Look for in our Blog. You will find multiple applications, solutions, code examples. Navigate using the tag cloud or search using specific criteria

Stepper motor speed control using an Arduino based PLC and a rotary encoder


Introduction

In this post we will control the speed of a stepper motor (Nema 17HS16-2004S) using a rotary encoder (LPD3806-600bm). For this we will also need a driver for the stepper motor that will be connected to our Arduino based PLC for the automation of the speed control. For the software, a pulses.h library is implemented (software without using pulses.h library is also attached).


Requirements

Ethernet PLC:   Ethernet PLC      

Nema 17 Bipolar 45Ncm 4 Wires  Stepper Motor:  Nema 17HS16-2004S Stepper Motor

LPD3806-600bm-g5 two phases 5-24 V 600 pulses Encoder:  LPD3806 Rotray Encoder

Microstep Driver TB6600 9 ~ 42V DC 4A:  Driver Microstep TB6600

Pulses.h (Tools40 library):   Pulses Library - Github Repository

Industrial Shields boards:  How to use the mapping pins of Industrial Shields boards

4,7 KΩ Resistors:             4K7 Pull-up resistor


Description

Nema 17 Bipolar 45Ncm 4 Wires Stepper motor:  

A stepper motor is an electro-mechanical device that converts a series of electrical impulses into discrete angular displacements, which means that it is capable of rotating a number of degrees (step or half a step) depending on its control inputs. The stepper motor behaves in the same way as a digital-analog converter (D / A) and can be governed by pulses from digital systems.

In the case of this post, the stepper motor used has the following electrical characteristics:

Electrical Specification
Bipolar/UnipolarBipolar
Holding Torque (Ncm)45
Holding Torque (oz.in)64
Inductance (mH)2.6
Phase Resistance (ohm)1.1
Rated Current (A)2
Step Angle (°)1.8


LDP3806 Rotary Encoder:  

Also called a shaft encoder, is an electro-mechanical device that converts the angular position or motion of a shaft or axle to analog or digital output signals.
Rotary encoders are used in a wide range of applications that require monitoring or control, or both, of mechanical systems.

In the case of this post, the LDP3806 Rotary Encoder is composed by a quadrature disc, and a LED/phototransistor module.

 

LDP3806 Rotray encoder main specifications:

  • 600 pulses/revolution for a single phase. Therefore, two-phase output leads to 2400 pulses/revolution

  • Maximum mechanical speed: 5000 Revolutions/minute

  • Response frequency: 0-20KHz 


Microstep Driver:

Generally speaking, specialized stepper motor driver boards only require two connections (plus GND) to the Arduino for step and direction signals. 

Normally specialized stepper motor driver boards have the ability to limit the current in the motor which allows them to drive it with higher voltages (up to 35v for the Pololu A4988) for better high speed performance.  Drivers usually have the ability to do microstepping. 


Connections


Stepper Motor - Driver connections:

Blue     -->      A-
Red      -->      A+
Black   -->      B-
Green  -->      B+ 

Ethernet PLC - Driver connections: 

Q0.0    -->  PUL + (pulses)      
Q0.1    -->  DIR+ (rotational direction)
Q0.2    -->  ENA+ (enable)                     
GND    --> PUL-, DIR -, ENA -

* Signals = 5Vdc
* Do not use Q0.5, Q0.6 or Q0.7, they are not pure digital outputs!

Encoder - Ethernet PLC Connections: 

+24Vdc               -->     Red  
Gnd                     -->     Black   
I0.5 (A Phase)  -->     Green 
I0.6 (B Phase)  -->     White


* I0.5 and I0.6 (Encoder Outputs) must have a pull-up resistor at 24Vdc (4,7kΩ resistors recomended). 

* Remember that the Ethernet PLC digital inputs must allow interruptions!


 Final Connection:



Software

Using this sketches you are able to control the speed of the stepper and direction by managing the acceleration pulses of rise and fall. 

Three different sketches have been programmed.

 

In this first sktech we will program the encoder to be able to control the acceleration of the stepper motor using interruption pins from the Arduino based PLC.
Find the code below:

/*

   Copyright (c) 2018 Boot&Work Corp., S.L. All rights reserved

   This program is free software: you can redistribute it and/or modify

   it under the terms of the GNU Lesser General Public License as published by

   the Free Software Foundation, either version 3 of the License, or

   (at your option) any later version.

   This program is distributed in the hope that it will be useful,

   but WITHOUT ANY WARRANTY; without even the implied warranty of

   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License

   along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */

#define PRINT_COUNTER 0

#define PIN_ENCODER_A 3

#define PIN_ENCODER_B 2

#define ENCODER_PULSES_PER_REV 600

int32_t counter_a = 0;

void count_a() {

  if (digitalRead(PIN_ENCODER_B)) {

    ++counter_a;

  } else {

    --counter_a;

  }

}

////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {

  Serial.begin(9600L);

  Serial.println("stepper started");

  pinMode(PIN_ENCODER_A, INPUT);

  pinMode(PIN_ENCODER_B, INPUT);

  attachInterrupt(digitalPinToInterrupt(PIN_ENCODER_A), count_a, RISING);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {

  static int32_t last_a = 0;

  if (counter_a != last_a) {

    last_a = counter_a;

    Serial.println(last_a);

  }

}

This second code controls by software the pulses of acceleration and deceleration.

/*

   Copyright (c) 2018 Boot&Work Corp., S.L. All rights reserved

   This program is free software: you can redistribute it and/or modify

   it under the terms of the GNU Lesser General Public License as published by

   the Free Software Foundation, either version 3 of the License, or

   (at your option) any later version.

   This program is distributed in the hope that it will be useful,

   but WITHOUT ANY WARRANTY; without even the implied warranty of

   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License

   along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */


#define PIN_STEPPER_PUL Q0_0

#define PIN_STEPPER_DIR Q0_1

#define PIN_STEPPER_EN  Q0_2

#define STEPPER_PULSES_PER_REV 400UL

#define FREQ (3000UL) // Hz

#define PERIOD (1000UL * 1000UL / (FREQ)) // us

#define NUM_REVOLUTIONS 10UL

#define STEPPER_STEPS ((NUM_REVOLUTIONS) * (STEPPER_PULSES_PER_REV))

#define RAMP_LEN 8

#define pulse(T) { \

  digitalWrite(PIN_STEPPER_PUL, HIGH); \

  delayMicroseconds((T) / 2); \

  digitalWrite(PIN_STEPPER_PUL, LOW); \

  delayMicroseconds((T) / 2); \

}

////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {

  pinMode(PIN_STEPPER_DIR, OUTPUT);

  pinMode(PIN_STEPPER_PUL, OUTPUT);

  pinMode(PIN_STEPPER_EN, OUTPUT);

  digitalWrite(PIN_STEPPER_DIR, HIGH);

  digitalWrite(PIN_STEPPER_EN, LOW);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {

  for (uint32_t i = RAMP_LEN; i > 0; --i) {

    pulse(PERIOD << i);

  }

  for (uint32_t i = 0; i < STEPPER_STEPS - (2 * RAMP_LEN); ++i) {

    pulse(PERIOD);

  }

  for (uint32_t i = 0; i < RAMP_LEN; ++i) {

    pulse(PERIOD << (i + 1));

  }

  delay(1000);

}



Finally, this third sketch also controls by software the treatment of acceleration and deceleration pulses, but in this case the pulses.h library available in the Tools40 repository is used.

* IMPORTANT: When use this sketch, the connections to the Ethernet PLC must be modified. We will use the pin3 of the MDuino instead of Q0.0 for the PUL entry of the driver (This modification allows us to use Timer 3 from the Arduino Mega).

If you click on this link, you will find a guide of the pulses.h library .

/*

   Copyright (c) 2018 Boot&Work Corp., S.L. All rights reserved


   This program is free software: you can redistribute it and/or modify

   it under the terms of the GNU Lesser General Public License as published by

   the Free Software Foundation, either version 3 of the License, or

   (at your option) any later version.


   This program is distributed in the hope that it will be useful,

   but WITHOUT ANY WARRANTY; without even the implied warranty of

   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

   GNU Lesser General Public License for more details.


   You should have received a copy of the GNU Lesser General Public License

   along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */


#define PIN_STEPPER_PUL 3

#define PIN_STEPPER_DIR Q0_1

#define PIN_STEPPER_ENA Q0_2

#define STEPPER_PULSES_PER_REV 400UL


#define FREQ (3000UL) // Hz

#define NUM_REVOLUTIONS 10UL

#define STEPPER_STEPS ((NUM_REVOLUTIONS) * (STEPPER_PULSES_PER_REV))


#include <Pulses.h>


volatile uint32_t stepsCnt = STEPPER_STEPS;

ISR(TIMER3_COMPA_vect) {

  if (stepsCnt) {

    --stepsCnt;

    if (stepsCnt == 0UL) {

      stopPulses(PIN_STEPPER_PUL);

    }

  }

}


////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {

  pinMode(PIN_STEPPER_DIR, OUTPUT);

  pinMode(PIN_STEPPER_PUL, OUTPUT);

  pinMode(PIN_STEPPER_ENA, OUTPUT);


  digitalWrite(PIN_STEPPER_DIR, HIGH);

  digitalWrite(PIN_STEPPER_ENA, LOW);


  // It depends on the PIN_STEPPER_PUL

  TIMSK3 |= 1 << OCIE3A;


  startPulses(PIN_STEPPER_PUL, FREQ, 3);

}


////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {


}