Help needed for NEMA -23 Stepper Motor with Stepper Driver TB600 and Arduino

Dear Group Members,

I have written an Arduino Program for a NEMA-23 Stepper Motor, that uses two Push Buttons to run CCW/CW directions and two Limit Switches to get to the end Positions.

Goal: Programme should be reliable ! -should be able to move between limit switches, when corresponding Push Buttons are kept pressed (not one time Press and Release - rather pressed until motor runs till end position and stops itself with limit switches).

Speed = 90°/ 2sec
1 Step = 0,1176°
Max. Current per Phase = 2,8A
Motor Driver = TB600 (Toshiba TB6600HG based)
Motor has three states:

  1. standby: waiting for input
  2. moveForward: moving CCW
  3. moveBackward: moving CW

So far, I am satisfied with the code except two queries, which I want to share with you people.

  1. For the debouncing of both Push Buttons, the “debounce example of Arduino” is not working anymore. Few days before, it was working, when my goal was to press push button only once to start motor from any position and stop at end switch. Since I changed my Program so that button has to be kept pressed, this “debounce” Function never returns switch HIGH. Not working code has been greyed in both int readFwdPin() and int readRevPin() functions in my attached code.

  2. Second problem is more sophisticated => When I keep pressing and releasing both push buttons (forward Button and Reverse Button in code) very fast one after the another (to ceck unexpected behavior of Program), there is one moment where stepper moves considerably faster than the normal set speed to one of the limit switches or even maybe ~40° roughly, and then comes back to the original speed set by me, given that button is still pressed. I can’t explain it to me if it is because of Arduino or TB6600 driver (because frequency stored in the interrupt register should not get changed). I try to connect Oscilloscope to see Pulses from Arduino, but can’t find something extra ordinary there than mere pulses.

I am sorry in advance for any unclarity that I leave. I am a beginner Hardware Developer and have not alot of experience with programming and motors.

The motor speed is set in my program by way of an Interrupt timer, which triggers every 382Hz. The controller can then generate pulses depending on cuurent operating mode of a stepper motor.

Thank you folk.

Stepper_Daimler_8_dualPress_Counter.ino (7.28 KB)

Which Arduino?

/*
 * Sicherheit variante 1:

this program runs the motor in forward and reverse direction depedning on choice of button.

Once the motor starts running, it stops with release of a push button.

On reaching Limit Switch in direction of movement, motor will stop.

this program lets the Interrupt triggered, however in ISR Pulse signal is only then generated, when program is in moveForward or moveBackward mode.
otherwise, Interrupts are still there, but nothing is executed in ISR

maxSteps counts the maximum Steps which motor is allowed to take in case any of limit switch should get broken
*/

//********************************* Pins and Variables Declaration *********************************
// Input Pin Definitions for User Interface

const int fwdButtonPin = 2; 
const int revButtonPin = 3;
const int fwdLimitSwitchPin= 4;
const int revLimitSwitchPin= 5;

// Containers for storing the states of Input Pins

int fwdButton = LOW;
int revButton = LOW;
int fwdLimitSwitch = HIGH;
int revLimitSwitch = HIGH;

//***variables needed for debouncing**********************
int revButtonState;
int revLastButtonState = LOW;

unsigned long revLastDebounceTime = 0;
unsigned long revDebounceDelay = 100; // debounce delay is 100ms


//**variables needed for debouncing***********************
int fwdButtonState;
int fwdLastButtonState = LOW;

unsigned long fwdLastDebounceTime = 0;
unsigned long fwdDebounceDelay = 100; // debounce delay is 100ms
//****************************************

// Motor Interface Output Pins

int motorStep = 8;
int motorDir = 9;
int motorEN = 10;

// Variable to count steps of a motor

int maxSteps = 0; // this variable adjust maximum rotation of +/-100° or +/-851 Steps (1 Step = 0,1176°)

// Different States of Stepper

enum state_t { standby, moveForward, moveBackward };
state_t motorState_t = standby;

// maximum timer count

#define TIMER_COUNT 5228

//************************ Routines Declaration *****************************************************

void setup()
{
  // setup input pins

  pinMode(fwdButtonPin, INPUT);
  pinMode(revButtonPin, INPUT);
  pinMode(fwdLimitSwitchPin, INPUT);
  pinMode(revLimitSwitchPin, INPUT);

  // setup output pins

  pinMode(motorStep, OUTPUT);
  pinMode(motorDir, OUTPUT);
  pinMode(motorEN, OUTPUT);

  digitalWrite(motorStep, LOW); // to be sure that step is not yet high
  
  // motorEN is active LOW !!!! 
  digitalWrite(motorEN, HIGH); // to be sure that motor is not enable

  digitalWrite(motorDir, LOW); // CW

  // setup timer1 to Interrupt at a frequency of 382,65Hz

  cli(); // stops system interrupts => google.it
  TCCR1A = 0; // Set entire register TCCR1A to 0
  TCCR1B = 0; // Set entire register TCCR1B to 0
  TCNT1 = 0; // initialize counter value with 0

  // set counter for Interrupts at 328,5Hz

  OCR1A = TIMER_COUNT; // uC clock frequency / [ (Pre- Scaler * Frequency_needed) - 1 ]
                       // we had to use Timer1 because Timer 0 and 2 can't count more than 255
  TCCR1B |= ( 1<<WGM12 ); // turn on Counter Compare Mode (CTC)

  //**** set bits for timer Pre- scaler 8 ****

  // TCCR1B |= ( 0<<CS10 ); // sets cs11 to 1 => Not needed, because we already have set this register bits to 0
  TCCR1B |= ( 1<<CS11 ); // sets CS11 bit of this register to 1 => Check timer1 clock select register table
  // TCCR1B |= ( 0<<CS12 ); // sets cs11 to 1 => Not needed, because we already have set this register bits to 0

  TIMSK1 = 0;
  TIMSK1 |= ( 1<<OCIE1A ); // enables timer compare interrupt = interrupt at compared point
  sei();

  // open up serial port to monitor steps counted by motor
  Serial.begin(9600);
}

// **** Interrupt Handler Function: Interrupt Service Routine **********

ISR (TIMER1_COMPA_vect)
{
  // perfom one step of a motor
 if(motorState_t == moveForward) // generate Pulses only when motor is active
 {
 digitalWrite(motorStep, HIGH);
 delayMicroseconds(10); // needs at least 2,2us High Time and 2,2us Low Time
 digitalWrite(motorStep, LOW);
 maxSteps++; // increament Total Steps
 }

 // perfom one step of a motor
 if(motorState_t == moveBackward) // generate Pulses only when motor is active
 {
 digitalWrite(motorStep, HIGH);
 delayMicroseconds(10); // needs at least 2,2us High Time and 2,2us Low Time
 digitalWrite(motorStep, LOW);
 maxSteps--; // decreament Steps
 }
 
}

//***************new Rev Debouncing Function**************************************
int readRevPin()
{
  int reading = digitalRead(revButtonPin);
  
  if(reading != revLastButtonState && millis() - revLastDebounceTime > revDebounceDelay)
  {
    revLastButtonState = reading;
    revLastDebounceTime = millis ();
  }

  return revLastButtonState;

/*  if( (millis() - revLastDebounceTime) > revDebounceDelay ) // 1
  {
    
    if(reading != revButtonState) //2
    {
      revButtonState = reading;

      if(revButtonState == HIGH) // 3
      {
        return HIGH;
      } // 3
          
    } // 2

  } // 1

revLastButtonState = reading;

return LOW;
*/
}

//***************new Rev Debouncing Function**************************************
int readFwdPin()
{
  int reading = digitalRead(fwdButtonPin);
  
  if(reading != fwdLastButtonState && millis() - fwdLastDebounceTime > fwdDebounceDelay)
  {
    fwdLastButtonState = reading;
    fwdLastDebounceTime = millis ();
  }

  return fwdLastButtonState;

/*  if( (millis() - fwdLastDebounceTime) > fwdDebounceDelay ) // 1
  {
    
    if(reading != fwdButtonState) //2
    {
      fwdButtonState = reading;

      if(fwdButtonState == HIGH) // 3
      {
        return HIGH;
      } // 3
          
    } // 2

  } // 1

fwdLastButtonState = reading;

return LOW;
*/
}

//*************************************************************************************

// ********** Function tracks User Inputs and decides a suitable motor state based on input values *************

void loop()
{
    // read all user inputs
  fwdButton = readFwdPin();
  revButton = readRevPin();
  fwdLimitSwitch = digitalRead(fwdLimitSwitchPin);
  revLimitSwitch = digitalRead(revLimitSwitchPin);

  // State Machine Implementation

  if( maxSteps<-1000 || maxSteps>1000 ) // if limit Switches are broken, stop !
  {
    digitalWrite(motorEN, HIGH); // stop the motor
    motorState_t = standby;
    digitalWrite(motorStep, LOW);
    digitalWrite(motorDir, LOW);
    Serial.println(maxSteps);
  }
  
  else if(fwdButton == HIGH && revButton == HIGH)
  {
    digitalWrite(motorEN, HIGH); // stop the motor
    motorState_t = standby;
    digitalWrite(motorStep, LOW);
    digitalWrite(motorDir, LOW);
    Serial.println(maxSteps);
  }

  else if(fwdButton == HIGH && fwdLimitSwitch != HIGH)
  {
    digitalWrite(motorDir, HIGH); // run the motor forward (CCW)
    motorState_t = moveForward;
    digitalWrite(motorEN, LOW);
  }

  else if(revButton == HIGH && revLimitSwitch != HIGH)
  {
    digitalWrite(motorDir, LOW); // run the motor reverse (CW)
    motorState_t = moveBackward;
    digitalWrite(motorEN, LOW);
  }

  else
  {
    digitalWrite(motorEN, HIGH); // stop the motor in anyother case => e.g. Limit Switch is reached
    motorState_t = standby;
    digitalWrite(motorStep, LOW);
    digitalWrite(motorDir, LOW);
   }
}

Hello,

Thank you.

It is Arduino Uno R3 with Atmega 328P.

If you just want a program that works while a button is pressed all you need to avoid switch bounce is a short interval (perhaps 50millisecs) between successive calls to digitalRead(fwdButtonPin); There should be no need to check for a change in the state of the button. Look at the readButton() function in Several Things at a Time

Unfortunately a lot of Forum comments combine debouncing with change-of-state without explaining their different purposes.

Checking for change of state is generally only needed when one button is required to do two different things - such as move fwd with the first press and move rev with the second press.

...R