Can I use integers in this way?

Hi Arduino community,

I’m working on the sketch posted below. I used the following integers and I was hoping that the integer GoSteps would return a value that i can use to drive a stepper motor a certain amount of steps.

int NumStepsC
int NumStepsN
int GoSteps = NumStepsN+(-NumStepsC);

As you can see ,in the printscreen from the serial monitor, this is not working. It would be much appreciated if someone could point out what i’m doing wrong.

// parts of this sketch are from this tutorial: Arduino Stepper Motor Tutorial! Widget46
//https://www.youtube.com/watch?v=KbDPgxHpgAA&t=186s
// thanks NYC CNC

#define PUSH_PIN1    2   // pin  2 connected to push button1
#define PUSH_PIN2    3   // pin  3 connected to push button2
#define PUSH_PIN3    4   // pin  4 connected to push button3
#define PUSH_PIN4    5   // pin  5 connected to push button4
#define STEP_PIN    11   // pin 11 connected to step pin easydriver
#define DIR_PIN     12   // pin 12 connected to dir pin easydriver
#define SLEEP_PIN   13   // pin 13 connected to sleep pin easydriver         
#define MS1_PIN     14   // pin 14 connected to MS1 pin easydriver
#define MS2_PIN     15   // pin 15 connected to MS2 pin easydriver

int Distance = 0;   // how far we've traveled
int Speed = 500;    // control how fast to ''step'' the motor
int ButtonState1 = 0;  // stores status of button1
int ButtonState2 = 0;  // stores status of button2
int ButtonState3 = 0;  // stores status of button3
int ButtonState4 = 0;  // stores status of button4
int OnOrOffState1 = 0; // should the motor be running or should it be turened off

int NumStepsC = 1000;   // position the stepper is currently at
int NumStepsN = 1000;   // position the stepper needs to go
int GoSteps = NumStepsN+(-NumStepsC); ///CURRENt postion + (-NEW postion)

 void setup() {
  Serial.begin(9600);
  pinMode(SLEEP_PIN,OUTPUT);
  pinMode(DIR_PIN,OUTPUT);
  pinMode(STEP_PIN,OUTPUT);
  pinMode(MS1_PIN, OUTPUT);
  pinMode(MS2_PIN,OUTPUT);
  pinMode(PUSH_PIN1,INPUT_PULLUP);  // push botton1
  pinMode(PUSH_PIN2,INPUT_PULLUP);  // push botton2 
  pinMode(PUSH_PIN3,INPUT_PULLUP);  // push botton3
  pinMode(PUSH_PIN4,INPUT_PULLUP);  // push botton4
  digitalWrite(DIR_PIN,LOW);    // set motor to clockwise direction
  digitalWrite(STEP_PIN,LOW);   // dont let the stepper motor rotate
  digitalWrite(MS1_PIN,HIGH);    // LOW LOW = full stepp    HIGH LOW = half stepp    LOW HIGH = quarter step     HIGH HIGH = eight step
  digitalWrite(MS2_PIN, HIGH); 
  digitalWrite(SLEEP_PIN, HIGH);  // Wake up EasyDriver
  delay(5);  // Wait for EasyDriver wake up
}

 void loop() {
  
  ButtonState1 = digitalRead(PUSH_PIN1);
    if (ButtonState1 == LOW){                //LOW means that the button has been pushed
      NumStepsN = 1000;                 
      }
  ButtonState2 = digitalRead(PUSH_PIN2);
    if (ButtonState2 == LOW){                //LOW means that the button has been pushed
      NumStepsN = 2000;                      // set NumSteps to 1000 > puts the valve in position 1 
      }
  ButtonState3 = digitalRead(PUSH_PIN3);
    if (ButtonState3 == LOW){                //LOW means that the button has been pushed
      NumStepsN = 3000;                      // set NumSteps to 1000 > puts the valve in position 1 
      }
  ButtonState4 = digitalRead(PUSH_PIN4);
    if (ButtonState4 == LOW){                //LOW means that the button has been pushed
      NumStepsN = 4000;                      // set NumSteps to 1000 > puts the valve in position 1 
      }
                          
   Serial.println();
  Serial.print("NumStepsN"); 
  Serial.print("  ");   
  Serial.print(NumStepsN);
  delay(0);

  Serial.println();
  Serial.print("NumStepsC"); 
  Serial.print("  ");   
  Serial.print(NumStepsC);
  delay(0);
  
  Serial.println();
  Serial.print("GoSteps"); 
  Serial.print("  ");   
  Serial.print(GoSteps);
  delay(0);
  
    Serial.println();
  Serial.print("OnOrOffState1"); 
  Serial.print("  ");   
  Serial.print(OnOrOffState1);
  delay(1000);

  }

thanks,

Martijn

No, GoSteps is not a macro.

You can place that line in loop() before you start printing and it will work.

I was hoping that the integer GoSteps would return a value that i can use to drive a stepper motor a certain amount of steps.

The value held in a variable is not updated unless you specifically do it

int GoSteps = NumStepsN + (-NumStepsC);Declares and initialises the global GoSteps variable but subsequently changing the value of NumStepsN or NumStepsC will not change the value of GoSteps.

when you define a variable through a formula that's a one-off. it's not evaluated every time you call that variable. if you want to re-evalutate the formula you need to tell the compiler to do it

int a = 2;
int b = a + 3

;

a

is now 2 and

b

is 5

if you do

a = 4;

then

a

is now 4 but

b

did not change, it's still 5.

if you want

b

to change you need to re-do the computation every time you change

a

like

a = 4;
b = a + 3;

makes sense?

alternatively if you use a macro

#define b ((a)+3)

that instruct the compiler to replace all successive occurrences of

b

with

((a)+3)

so every time you use b in the code, that will take the current value of a into consideration

macro can lead to disappointment though..

if you do were to do

a = (++a) + b;

the pre-processor / compiler will replace and evaluate this as

a = (++a) [b]+[/b] ((a)+3)

and then it's unclear what ends up in

a

at the end because you don't know the order of evaluation of the addition

J-M-L:
if you do were to do

a = (++a) + b;

...you would be guilty of the obfuscation of a+b+1 IMHO.

aarg:
...you would be guilty of the obfuscation of a+b+1 IMHO.

No... you would be guilty of very poor coding.... a = a++ is always a bad idea :slight_smile:

that's why I wrote that in red..

Is it possible to show an example of incorrect macro expansion that isn't also an example of poor coding? Otherwise it would seem like you wouldn't ever have problems with macros as long as you obey good coding rules...

Macro expansion are always correct... it's just that often it's not the developer's intent

#define b a+3

int a = 10
int c = b * 2;

missing parenthesis is often a problem

more subtle

#define NB_MILLISECONDS_IN_ONE_SECOND 1000

...

delay(40* NB_MILLISECONDS_IN_ONE_SECOND);

(the compiler will warn you about the mistake on standard arduino such as UNO)

The advice given here is all very well, but from the thread title it may well be that the OP does not understand what an int really is otherwise he would have asked whether he could use a variable in this way.

I await his return with bated breath.

The key thing is to understand the difference between

int GoSteps = NumStepsN+(-NumStepsC);

which happens once
and

int GoSteps()
{ return  NumStepsN+(-NumStepsC); }

which can happen whenever GoSteps() is called.

The first names a value
the second names a calculation.

sterretje:
No, GoSteps is not a macro.

You can place that line in loop() before you start printing and it will work.

Yes that did the trick!

UKHeliBob:
The value held in a variable is not updated unless you specifically do it

int GoSteps = NumStepsN + (-NumStepsC);Declares and initialises the global GoSteps variable but subsequently changing the value of NumStepsN or NumStepsC will not change the value of GoSteps.

This was the reason my sketch wasn't working! Updating GoSteps,NumStepsC and NumStepsN at the end of the loop turned out to be the solution.

J-M-L:
when you define a variable through a formula that's a one-off. it's not evaluated every time you call that variable. if you want to re-evalutate the formula you need to tell the compiler to do it

int a = 2;

int b = a + 3


;



a


is now 2 and 

b


is 5

if you do 



a = 4;




then 

a


is now 4 but 

b


did not change, it's still 5.

if you want 

b


to change you need to re-do the computation every time you change 

a


like



a = 4;
b = a + 3;




makes sense?

alternatively if you use a macro


#define b ((a)+3)



that instruct the compiler to replace all successive occurrences of 

b


with 

((a)+3)


so every time you use b in the code, that will take the current value of a into consideration

macro can lead to disappointment though..

if you do were to do 


a = (++a) + b;




the pre-processor / compiler will replace and evaluate this as 


a = (++a) + ((a)+3)



and then it's unclear what ends up in 

a


at the end because you don't know the order of evaluation of the addition

makes perfect sense now. Excellent explanation!

// parts of this sketch are from this tutorial: Arduino Stepper Motor Tutorial! Widget46
//https://www.youtube.com/watch?v=KbDPgxHpgAA&t=186s
//parts of this sketch are from this tutorial: How to "Home" Stepper Motors using Limit Switches - Tutorial using Arduino and Easy Driver
//https://www.youtube.com/watch?v=3odRT6zdzqk&t=3s
//Thanks NYC CNC & Brainy-Bits

#define PUSH_PIN1    2   // pin  2 connected to push button1
#define PUSH_PIN2    3   // pin  3 connected to push button2
#define PUSH_PIN3    4   // pin  4 connected to push button3
#define PUSH_PIN4    5   // pin  5 connected to push button4
#define HOME_SWITCH 10   // pin 10 connected to home switch
#define STEP_PIN    11   // pin 11 connected to step pin easydriver
#define DIR_PIN     12   // pin 12 connected to dir pin easydriver
#define SLEEP_PIN   13   // pin 13 connected to sleep pin easydriver         
#define MS1_PIN     14   // pin 14 connected to MS1 pin easydriver
#define MS2_PIN     15   // pin 15 connected to MS2 pin easydriver


int Distance = 0;   // how far we've traveled
int Speed = 500;    // control how fast to ''step'' the motor
int ButtonState1 = 0;  // stores status of button1
int ButtonState2 = 0;  // stores status of button2
int ButtonState3 = 0;  // stores status of button3
int ButtonState4 = 0;  // stores status of button4
int OnOrOffState = 0; // should the motor be running or should it be turened off

int NumStepsC = 1000;   // position the stepper is currently at
int NumStepsN = 1000;   // position the stepper needs to go


 void setup() {
  pinMode(SLEEP_PIN,OUTPUT);
  pinMode(DIR_PIN,OUTPUT);
  pinMode(STEP_PIN,OUTPUT);
  pinMode(MS1_PIN, OUTPUT);
  pinMode(MS2_PIN,OUTPUT);
  pinMode(PUSH_PIN1,INPUT_PULLUP);  // push botton1
  pinMode(PUSH_PIN2,INPUT_PULLUP);  // push botton2 
  pinMode(PUSH_PIN3,INPUT_PULLUP);  // push botton3
  pinMode(PUSH_PIN4,INPUT_PULLUP);  // push botton4
  pinMode(HOME_SWITCH,INPUT_PULLUP);
  digitalWrite(DIR_PIN,LOW);    // set motor to clockwise direction
  digitalWrite(STEP_PIN,LOW);   // dont let the stepper motor rotate
  digitalWrite(MS1_PIN,HIGH);    // LOW LOW = full stepp    HIGH LOW = half stepp    LOW HIGH = quarter step     HIGH HIGH = eight step
  digitalWrite(MS2_PIN, HIGH); 
  digitalWrite(SLEEP_PIN, HIGH);  // Wake up EasyDriver
  delay(5);  // Wait for EasyDriver wake up


  // Start Homing procedure of Stepper Motor at startup

  while (digitalRead(HOME_SWITCH)) {  // Do this until the switch is activated   
    digitalWrite(DIR_PIN, HIGH);      
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(1000);                      
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(1000);   
}

 while (!digitalRead(HOME_SWITCH)) { // Do this until the switch is not activated
    digitalWrite(DIR_PIN, LOW);      
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(1000);                     
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(1000);   
  }

}

 void loop() {

int GoSteps=((NumStepsN)+(-NumStepsC));
  
  ButtonState1 = digitalRead(PUSH_PIN1);
    if (ButtonState1 == LOW){                //LOW means that the button has been pushed
      NumStepsN = 1000;                 
      }
  ButtonState2 = digitalRead(PUSH_PIN2);
    if (ButtonState2 == LOW){                //LOW means that the button has been pushed
      NumStepsN = 2000;                     
      }
  ButtonState3 = digitalRead(PUSH_PIN3);
    if (ButtonState3 == LOW){                //LOW means that the button has been pushed
      NumStepsN = 3000;                     
      }
  ButtonState4 = digitalRead(PUSH_PIN4);
    if (ButtonState4 == LOW){                //LOW means that the button has been pushed
      NumStepsN = 4000;                       
      }
   


    if (GoSteps > 0){               
      OnOrOffState=1;
      digitalWrite(DIR_PIN,LOW);        // this statement lets the stepper turn clockwise when GoSteps > 0
    }
 
    if (GoSteps < 0){
      OnOrOffState=1;
      digitalWrite(DIR_PIN,HIGH);       // this statement lets the stepper turn counter-clockwise when GoSteps < 0
      GoSteps=GoSteps*-1;               // *-1 to make GoSteps a positive value again
    }

     while(OnOrOffState == 1){         
      digitalWrite (STEP_PIN,HIGH);
      delayMicroseconds(Speed);
      digitalWrite (STEP_PIN,LOW);
      delayMicroseconds(Speed);         // this statement lets the stepper turn while the OnOrOffState is 1
      Distance = Distance + 1;          // whit everey step the distance gets a +1

      if (Distance == GoSteps)  {       // when the distance is equal to GoSteps
      OnOrOffState = 0;                 // OnOrOffState is set to 0 
      NumStepsC=NumStepsN;
      Distance=0;
      GoSteps=0 ;                           //((NumStepsN)+(-NumStepsC));
      }
      
     }
     }

This is the final sketch. I want to thank everybody for the input.

Have a great day,

MB

great follow up :slight_smile:

a few constructive notes:


int GoSteps=((NumStepsN)+(-NumStepsC)); can simply be written int GoSteps = NumStepsN - NumStepsC; no need for all the parenthesis, makes it easier to read


int Distance = 0;   // how far we've traveled
int Speed = 500;    // control how fast to ''step'' the motor

aren't those always positive or null? you might want to use unsigned int instead of int


int ButtonState1 = 0;  // stores status of button1
int ButtonState2 = 0;  // stores status of button2
int ButtonState3 = 0;  // stores status of button3
int ButtonState4 = 0;  // stores status of button4

those will be HIGH or LOW, right? so a byte is the right storage size, no need for an integer, and use HIGH and LOW when initializing or checking to simplify code reading.


int OnOrOffState = 0; // should the motor be running or should it be turened offthat sounds like a boolean to me... no need for an int and use true or false instead of 0 and 1, will make code easier to read and understand. (I would also call that onState so that you know if it's true it means on and if it's false you know it means off)


  // Start Homing procedure of Stepper Motor at startup

  while (digitalRead(HOME_SWITCH)) {  // Do this until the switch is activated   
    digitalWrite(DIR_PIN, HIGH);      
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(1000);                      
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(1000);   
}

 while (!digitalRead(HOME_SWITCH)) { // Do this until the switch is not activated
    digitalWrite(DIR_PIN, LOW);      
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(1000);                     
    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(1000);   
  }

Looks like what you want to do there is if the motor is not @ home, then start your motor and wait until the HOME_SWITCH is triggered and then move a bit off the home switch. There is no need to keep asking the motor to move in the while and you might want to wait a small bit to avoid bouncing form the limit switch before testing if you've moved off the button.

// Start Homing procedure of Stepper Motor at startup

if (digitalRead(HOME_SWITCH) != LOW) { // INPUT_PULLUP, switch LOW when not active
    // start moving
    digitalWrite(DIR_PIN, HIGH);      
    digitalWrite(STEP_PIN, HIGH);
}
while (digitalRead(HOME_SWITCH) != LOW) ; // wait until you hit the switch
digitalWrite(STEP_PIN, LOW); // stop the motor
delay(15); // give a chance to absorb bounces of the end switched and motor inertia

digitalWrite(DIR_PIN, LOW);   // reverse direction
digitalWrite(STEP_PIN, HIGH); // start moving
while (digitalRead(HOME_SWITCH) == LOW) ; // wait until you have left the switch
digitalWrite(STEP_PIN, LOW); // stop the motor

    if (GoSteps > 0){               
      OnOrOffState=1;
      digitalWrite(DIR_PIN,LOW);        // this statement lets the stepper turn clockwise when GoSteps > 0
    }
 
    if (GoSteps < 0){...

as you are testing the opposite condition (and not changing GoSteps in the first if) you don't need to do another test if you entered the first if --> you could use an else statement

    if (GoSteps > 0){               
      OnOrOffState=1;
      digitalWrite(DIR_PIN,LOW);        // this statement lets the stepper turn clockwise when GoSteps > 0
    } else {...

 GoSteps=GoSteps*-1;

multiplications are slower than additions or subtraction so doing GoSteps=-GoSteps;will likely perform faster (probably caught and optimized by the compiler for you though)


Distance = Distance + 1;is usually written asDistance++;The compiler will catch that for you though nowadays.


if (Distance == GoSteps)  {when you do testing, although it should never happen, it's a good practice to test with "greater than or equal to", this way if you have a bug in your code for whatsoever reason and Distance has been incremented by 2 and miss the GoSteps target then you'll still catch the condition. if your case it's easy so there is no risk, but that's a good habit to take.if (Distance >= GoSteps)  {


putting both previous comments together, you can help the compiler (which will likely do that for you) be a bit more optimal and instead of doing

Distance = Distance + 1;          // whit everey step the distance gets a +1
if (Distance == GoSteps)  {       // when the distance is equal to GoSteps

you could doif (++Distance >= GoSteps)  {      // with everey step the distance gets a +1 and  when the distance reaches GoSteps

J-M-L:

int OnOrOffState = 0; // should the motor be running or should it be turened off

that sounds like a boolean to me... no need for an int and use true or false instead of 0 and 1, will make code easier to read and understand. (I would also call that onState so that you know if it's true it means on and if it's false you know it means off)

Very true. Take it one step further, make it "motorState" so you know what it is the on state of.

aarg:
Very true. Take it one step further, make it "motorState" so you know what it is the on state of.

well make it motorIsOn then because motorState being true does not tell you much.

ie I can very easily understand if (motorIsOn) {...} else {...}whereas if (motorState) {...} else {...}is kinda not intuitive

J-M-L:
well make it motorIsOn then because motorState being true does not tell you much.

ie I can very easily understand if (motorIsOn) {...} else {...}whereas if (motorState) {...} else {...}is kinda not intuitive

True. It is kind of controversial, but you can also:

if (motorState == ON) {...} else {...}

as the other decision you have to make is whether

motorState = OFF;

or

motorIsOn = false;

is more intuitive.

sure that would be readable but ON is not a standard keyword and so you would have to declare

#define ON true
#define OFF false

kinda defeats the idea of a boolean (a logic value)

An enum would have the advantage of make it type safe.

enum motorState { ON, OFF };
motorState stepperState = OFF;
[...]
if (stepperState == ON) {...} else {...}

sure that works too but I would call that over engineered if your motor has only 2 states. an enum will create an int to store the state and you go back to allocating and handling more memory than necessary (1 byte ought to be enough)

J-M-L:
sure that works too but I would call that over engineered if your motor has only 2 states. an enum will create an int to store the state and you go back to allocating and handling more memory than necessary (1 byte ought to be enough)

Interesting. The OP should also take note that they have over-engineered by making their variable an int. I believe that the bool type is also implemented in a byte in AVR-GCC IIRC, and arduino.h defines boolean as bool.

that's why I'm suggesting a boolean :slight_smile:

every byte of RAM counts on small microprocessors and on a 8 bit processor asking the CPU to handle 16 or 32 bits operations is slower than 8 bit operations... so when you can stick to bytes and when things are constant, tell the compiler, it will use that to optimize code too.