I am using a Nema 23 Stepper with a DM542T driver and it works fine on an Arduino Uno (spins both clockwise and counter-clockwise. However, when I use the same script on my Nodemcu it only spins one direction. What is the difference in the pins on the Uno vs the Nodemcu that would be causing this? I've also tried and ESP32 but have same issue. Is it something to do with attachinterrupt enabled on the Uno but not the Nodemcu? Here's the sketch:
#include <Stepper.h>
const int stepsPerRevolution = 200; // change this to fit the number of steps per revolution
// for your motor
// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 7, 6);
//Changing the pins to (stepsPerRevolution, D4, D3) on the Nodemcu only spins the motor in one direction.
void setup() {
// set the speed at 60 rpm:
myStepper.setSpeed(60);
// initialize the serial port:
Serial.begin(9600);
}
void loop() {
// step one revolution in one direction:
Serial.println("clockwise");
myStepper.step(stepsPerRevolution);
delay(500);
// step one revolution in the other direction:
Serial.println("counterclockwise");
myStepper.step(-stepsPerRevolution);
delay(500);
}
Th ESP8266 nodeMCU and ESP32 are 3,3V devices. It might be that this voltage is just not sufficient for the control-input of the driver.
Do you have the GND of the microcontroller connected to GND of the driver?
What IO-pins of the nodeMCU/ESP32 did you use? Some of them have pull-up / some of them do have a pull-down-resistor.
In the program the instance is created with three parameters
I assume creating it with three parameters tells stepper.h it is a pulse/dir-interface.
from where should the library know which are the third and forth IO-pin for direct phase-sequencing?
I don't think so. Check out the Stepper.h source code. When a two pin constructor is given, there is a step sequence of 4 with the two pins.
void Stepper::step(int steps_to_move)
{
int steps_left = abs(steps_to_move); // how many steps to take
// determine direction based on whether steps_to_mode is + or -:
if (steps_to_move > 0) { this->direction = 1; }
if (steps_to_move < 0) { this->direction = 0; }
// decrement the number of steps, moving one step each time:
while (steps_left > 0)
{
unsigned long now = micros();
// move only if the appropriate delay has passed:
if (now - this->last_step_time >= this->step_delay)
{
// get the timeStamp of when you stepped:
this->last_step_time = now;
// increment or decrement the step number,
// depending on direction:
if (this->direction == 1)
{
this->step_number++;
if (this->step_number == this->number_of_steps) {
this->step_number = 0;
}
}
else
{
if (this->step_number == 0) {
this->step_number = this->number_of_steps;
}
this->step_number--;
}
// decrement the steps left:
steps_left--;
// step the motor to step number 0, 1, ..., {3 or 10}
if (this->pin_count == 5)
stepMotor(this->step_number % 10);
else
stepMotor(this->step_number % 4);
}
}
}
void Stepper::stepMotor(int thisStep)
{
if (this->pin_count == 2) {
switch (thisStep) {
case 0: // 01
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, HIGH);
break;
case 1: // 11
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, HIGH);
break;
case 2: // 10
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, LOW);
break;
case 3: // 00
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, LOW);
break;
}
}
The ESP8266 nodeMCU and ESP32 are 3,3V devices. It might be that this voltage is just not sufficient for the control-input of the driver.
This is a very good point. The specs for the driver indicate that the pulse needs to be 4-5v.
What the code of the stepper.-library does show is:
it is not a step/direction interface because the two IO-pins are switched in a sequencing manner 01, 11, 10, 00
a step/direction-interface would just toggle the one single IO-pin (the step-pin) LOW/HIGH
Both IO-pins are switched LOW/HIGH
this is that part of the code that does the IO-pin switching.
For driving steppers I would recommend the MoBaTools-library
In contrast to a lot of other libraries the documentation of the mobatools is good
////////// Example 3 for MoToStepper - attaching a bipolar stepper with step/dir and enable ////////////
/* Example for the control of a bipolar stepper with 4 buttons and a potentiometer ( for the speed ).
In this example, besides the stepper class (MoToStepper), the classes MoToButtons and MoToTimebase
are also used.
The stepper current is switched off, if the stepper is not moving.
The buttons must switch to Gnd, no resistors are needed.
Button1: Rotates right as long as the button is pressed and held
Button2: Rotates left as long as the button is pressed and held
Button3: One turn to the right
Button4: One turn to the left
*/
/* Beispiel für die Ansteuerung eines bipolaren Steppers über 4 Taster und
ein Poti ( für die Geschwindigkeit )
In diesem Beispiel werden neben der Stepperklasse (MoToStepper), auch die MoToButtons
und der MoToTimebase genutzt.
Der Spulenstrom wird abgeschaltet, wenn der Stepper nicht läuft.
Die Taster müssen gegen Gnd schalten, es sind keine Widerstände notwendig
Button1: Dreht rechts, solange Taster gedrückt
Button2: Dreht links, solange Taster gedrückt
Button3: 1 Umdrehung rechts
Button4: 1 Umdrehung links
*/
#define MAX8BUTTONS // spart Speicher, da nur 4 Taster benötigt werden (saves RAM)
#include <MobaTools.h>
// Pindefinitions - change to your needs
const byte dirPin = 5;
const byte stepPin = 6;
const byte enaPin = 7;
const byte button1Pin = A1;
const byte button2Pin = A2;
const byte button3Pin = A3;
const byte button4Pin = A4;
const byte potPin = A0; // must be an analog input
const int STEPS_REVOLUTION = 800;
//Stepper einrichten ( 800 Schritte / Umdrehung - 1/4 Microstep )
MoToStepper myStepper( STEPS_REVOLUTION, STEPDIR ); // 800 Steps/ Umdrehung
// Taster einrichten
enum { Button1=0, Button2, Button3, Button4 } ; // Den Tasternamen die Indizes 0...3 zuordnen
const byte buttonPins[] = { button1Pin, button2Pin, button3Pin, button4Pin }; // muss als byte definiert sein, damit ein enfaches sizeof funktioniert
MoToButtons button( buttonPins, sizeof(buttonPins), 20, 500 );
MoToTimebase speedIntervall; // Zeitinterval zum Auslesen des Speedpotentiometers
// the speed pot ist read only every 'speedintervall' ms
int vspeed = 0; //Steppergeschwindigkeit in U/min*10
void setup()
{
myStepper.attach( stepPin, dirPin );
myStepper.attachEnable( enaPin, 10, LOW ); // Enable Pin aktivieren ( LOW=aktiv )
myStepper.setSpeed( 200 );
myStepper.setRampLen( 100 ); // Rampenlänge 100 Steps bei 20U/min
speedIntervall.setBasetime( 100 ); // 100ms Tickerzeit
}
void loop() {
button.processButtons(); // Taster einlesen und bearbeiten
// Speed alle 100ms neu einlesen und setzen
if ( speedIntervall.tick() ) {
// wird alle 100ms aufgerufen ( Tickerzeit = 100ms im setup() )
vspeed = map((analogRead(potPin)), 0, 1023, 20, 1800); //Poti mappen auf 2 ... 180 Umdr/Min
//min speed =2 and max speed =180 rpm
myStepper.setSpeed( vspeed );
}
// Drehen rechtsrum
if (button.pressed(Button1) ) {
//Taster1 gedrückt
myStepper.rotate( 1 ); // Stepper dreht vorwärts
}
if ( button.released(Button1) ) {
//Taster1 losgelassen
myStepper.rotate(0); // Stepper stoppt
}
//Drehen linksrum
if (button.pressed(Button2) ) {
//Taster2 gedrückt
myStepper.rotate( -1 ); // Stepper dreht rückwärts
}
if ( button.released(Button2) ) {
//Taster2 losgelassen
myStepper.rotate(0); // Stepper stoppt
}
// 1 Umdrehung rechts {
if (button.pressed(Button3) ) {
//Taster3 wurde gedrückt
myStepper.doSteps(STEPS_REVOLUTION);
}
// 1 Umdrehung links
if (button.pressed(Button4) ) {
//Taster4 wurde gedrückt
myStepper.doSteps(-STEPS_REVOLUTION);
}
}
To clarify, yes, the original code posted does turn the motor both directions when used with an Arduino Uno when Pul+ and Dir+ on the motor driver are connected to 5V and Pul- and Dir- are connected to 6 & 7 on the Uno.
I understand that Pul+ and Dir+ require 5v. So, I keep these pins connected to an Uno for power and switch the 6, 7 pins to an ESP8266 (D3, D4) but it only goes in one direction (clockwise) although it is turning. I have tried Robin2 script but still one direction. I have also tried connecting the ground of the DM542T to the ground on the ESP8266 as mentioned but that didn't work. I've also tried switching to other pins on the ESP8266 (D5, D6) for example, but regardless of what I do, I cannot get it to turn counter clockwise. I have also tried the AccelStepper library - it works well with the Uno only, but not with the ESP8266 or ESP32 - turns but only one direction.
the problem is the step-input and the dir-input of the driver need to see minimum 4V.
Any IO-pin of any ESP (ESP8266, ESP32 ) can "deliver" a maximum of 3.3V
These 3.3V are too less for the DM542T-driver-inputs to switch HIGH.
at 3.3V the DM542T still sees a LOW.
So you need a voltage-level converter 3.3V up to 5V
The minimum circuit for only outputting a signal looks like this
Thank you Stefan for the explanation. I have ordered these and will report back - DAOKI 2 Channel Logic Level Converter 3.3V to 5V TTL Bi-directional Module
This has AFAIK been a topic several times on this forum.
Connect the opto +5volt inputs of the drivers to 5volt,
and use transistors (2N2222 with 330 ohm base resistor) to switch the other side of the opto to ground.