0

I've connected two stepper through two uln2003 chip. And wrote a small class to control them. The class works perfectly and I'm able to control the steppers (rotate the CW and CCW).

My main code looks like this :

#include "StepperControl.h"

StepperControl myStepperControls[2];

void setup() {
    delay(1000);
    myStepperControls[0].init(6,5,4,3);
    myStepperControls[1].init(11,10,9,8);

    delay(1000);
    for (int i = 0; i < 2; i++)
    {
        myStepperControls[i].DelayBetweenSteps = 1200;
        myStepperControls[i].StepCCWDegree(90);
        myStepperControls[i].StepCWDegree(51);
    }
}
int moveNumber = 0;
void loop(){
    int stepperNumber = moveNumber / 2;
    bool cw = ((moveNumber % 2)  == 0);
    moveNumber = (moveNumber + 1) % 4;
}

As you can see I:

  • Init both instances of the class to different pins.
  • Set the Delay between the steps (in microseconds).
  • Rotate myStepperControls[0] counter clock wise and then clock wise.
  • Same for myStepperControls[1]

This doesn't work correctly, one of the motors doesn't move clock wise.

It is not always the same motor !! For the last hour the problem appeared only in myStepperControls[0], now it is only in myStepperControls[1].

I'm 100% sure it is not a wiring/electrical problem because:

  1. If I'll delete the content of the loop (which runs after setup) it will fix the problem.
  2. If I'll make the delay between steps 2000 it will fix the problems.
  3. As I've mentioned the problem was only in myStepperControls[0] for an hour, in that hour i switch the pins of the motors and still the motor that was connected to myStepperControls[0] was not able to rotate CW.

Any suggestions to how to investigate the problem will be appriciated

Here is my library code:

// StepperControl.h

#ifndef _STEPPERCONTROL_h
#define _STEPPERCONTROL_h

#if defined(ARDUINO) && ARDUINO >= 100
    #include "arduino.h"
#else
    #include "WProgram.h"
#endif

class StepperControl
{
 public:
    StepperControl();
    void init(byte blue, byte pink, byte yellow, byte orange);
    void StepCW(int steps);
    void StepCCW(int steps);
    void StepCWDegree(float degrees);
    void StepCCWDegree(float degrees);
    const int StepsPerFullRotation = 4076;
    int DelayBetweenSteps;
 private:

    void setPinsState(byte step);

    byte m_currentState;
    byte m_pinValuelookup[9];

    byte m_bluePin; // = 11;    // Blue   - 28BYJ48 pin 1
    byte m_pinkPin; // = 10;    // Pink   - 28BYJ48 pin 2
    byte m_yellowPin; // = 9;    // Yellow - 28BYJ48 pin 3
    byte m_orangePin; // = 8;    // Orange - 28BYJ48 pin 4
                            // Red    - 28BYJ48 pin 5 (VCC)

};

#endif

here is the cpp file :

#include "StepperControl.h"

StepperControl::StepperControl() : m_pinValuelookup{B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001, B00000}, DelayBetweenSteps(1100), m_currentState(0)
{
}

void StepperControl::init(byte blue, byte pink, byte yellow, byte orange)
{
    m_bluePin = blue;
    m_pinkPin = pink;
    m_yellowPin = yellow;
    m_orangePin = orange;

    pinMode(m_bluePin, OUTPUT);
    pinMode(m_pinkPin, OUTPUT);
    pinMode(m_yellowPin, OUTPUT);
    pinMode(m_orangePin, OUTPUT);
    delayMicroseconds(DelayBetweenSteps);
    setPinsState(8);
    delayMicroseconds(DelayBetweenSteps);
}

void StepperControl::StepCW(int steps)
{ 
    for(int i = 0; i < steps; i++)
    {
        m_currentState = (m_currentState - 1) % 8;
        setPinsState(m_currentState);
        delayMicroseconds(DelayBetweenSteps);
    }
    setPinsState(8);
}

void StepperControl::StepCCW(int steps)
{
    for(int i = 0; i < steps; i++)
    {
        m_currentState = (m_currentState + 1) % 8;
        setPinsState(m_currentState);
        delayMicroseconds(DelayBetweenSteps);
    }
    setPinsState(8);
}

void StepperControl::StepCWDegree(float degrees)
{
    float steps = degrees * (float)StepsPerFullRotation / 360.0f;
    StepCW((int)steps);
}

void StepperControl::StepCCWDegree(float degrees)
{
    float steps = degrees * (float)StepsPerFullRotation / 360.0f;
    StepCCW((int)steps);
}

void StepperControl::setPinsState(byte step)
{
  digitalWrite(m_bluePin, bitRead(m_pinValuelookup[step], 0));
  digitalWrite(m_pinkPin, bitRead(m_pinValuelookup[step], 1));
  digitalWrite(m_yellowPin, bitRead(m_pinValuelookup[step], 2));
  digitalWrite(m_orangePin, bitRead(m_pinValuelookup[step], 3));
}
1

You found the solution yourself. I am posting this answer anyway just to give some background on the problem.

I must say you were somewhat unlucky: you have just hit a couple of the least intuitive features of the C and C++ languages: integral promotion and signed division.

  1. Integral promotion: C does not know how to perform arithmetic on anything smaller than an int. When you write m_currentState - 1, the variable m_currentState is automatically promoted to int. Note that this promotion has converted an unsigned type (byte is unsigned) into a signed integer. Then, (byte) 0 - 1 is (int) -1 instead of (byte) 255.

  2. Signed division: When dividing a negative number by a positive one, the quotient is rounded towards zero and, conversely, the rest is negative. Then, -1 % 8 is -1 instead of 7.

There are several ways around these problems. One is to replace the modulo operation % 8 by a bitwise and: & 7. This is an optimization the compiler would have done anyway if dealing with unsigned integers. The option I prefer is to simply undo the integral promotion by an explicit cast:

m_currentState = (byte) (m_currentState - 1) % 8;

This way, if m_currentState is zero, (byte) (m_currentState - 1) is 255 and the result is, as expected, 7. Also, the compiler optimizes the unsigned modulo operation into a bitwise and: the whole lines compiles very efficiently into just two single-cycle instructions:

subi r24, 0x01  ; subtract 1
andi r24, 0x07  ; bitwise and with 7

It is worth noting that nothing of this would have happened if m_currentState was an unsigned int, as there would have been no integral promotion in the first place.

0

Some one helped me in the Arduino forums, and I felt obligated to add the answer here :

The : m_currentState = (m_currentState - 1) % 8; is the bug. I accidentally assumed that doing % on -1 will jump to 7.

Somehow this caused the strange behavior I had.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.