array dismay!

I’m a mega-noobie with arrays, but trying to use one to run 2 stepper motors simultaneously with Easydriver. I keep getting this error:

"In function ‘void loop)’:
error: name lookup of ‘i’ changed for new ISO ‘for’ scoping At global scope…

maybe there’s something about the relationship of my for{} and if/else{} statements that’s gummed up

can anyone help? (I’m sure I’ve just done something obviously dumb)
thanks!!

Here’s the code so far: (**** indicates location of error)

define num 2

int dirStateNum = 0;

int dirPin[num] = {3,9};
int stepPin[num] = {4,8};
int distance[num] = {0,0};
long previousMillis[num] = {0,0};
long interval[num] = {0,0};

void setup() {

pinMode(dirPin[0], OUTPUT);
pinMode(dirPin[1], OUTPUT);
pinMode(stepPin[0], OUTPUT);
pinMode(stepPin[1], OUTPUT);

}
void loop(){

dirStateNum = int(random(0,1));
for(int i=0; i<=num; i++);{

if(dirStateNum = 0)
{
digitalWrite(dirPin_, LOW);}*******_

  • else{*
    _ digitalWrite(dirPin*, HIGH);}_
    _
    }_
    _
    }_
    _
    delay(100);_
    _
    }*_

The last semicolon on this line is terminating the for loop, so when you try to refer to ‘i’ it’s out of scope.

  for(int i=0; i<=num; i++);{

… should become …

  for(int i=0; i<=num; i++){

In your for loop, you're setting up what is called a Local Variable, can only be used inside that For Loop.

Try putting int i; at the top of your sketch, above the Setup, and instead of setting it up as an Int inside the For loop (int x = 0;) just use x = 0; That should enable you to use it anywhere.

Also, something else I noticed, right after that:

if(dirStateNum = 0) { // this is incorrect, as you're saying dirStateNum equals 0

Instead, use: if(dirStateNum == 0){ // '==' means "Is Equal To" rather than just "Equals" like '='

http://arduino.cc/en/Reference/If Explains down, little bit past halfway.

And yes.... I didn't even notice that ; after the For... lol I miss out on the important stuff! :P

oh! Thank you thankyou!! Error is gone...on to bigger problems! :D

hharp,

There’s another error in your sketch that could cause problems. Your for loop says for(int i=0; i<=num; i++)Since you set ‘num’ to 2, this will loop three times, setting i to 0, 1, and 2. Your arrays have only two elements in them: [0] and [1]. If you reference the [2] element of any of your arrays, you are going past the end of that array. It’s hard to predict what will happen when you do that, but I can tell you that nothing good will come of it. Don’t ask me how I know. :slight_smile:

I think you want your statement to say: for(int i=0; i < num; i++)

Regards,

-Mike

Thank you for clarifying that. I'm a little confused about that because I thought that when I assigned 2 to num at the top of the code, it indicated a number that contained one more than one things, but I do understand that when it comes to arrays, zero is the first number and when I'm iterating through it goes 0,1,0,1,0,1, which is two things...It sounds like what you're saying is that in this case 2 means a number that's one more than two....right? :-?

The problem isn’t the array declaration or assignment. The problem is the for loop.

The for loop iterates as long as the middle statement evaluates to true. In this code:

for(int i=0; i<=num; i++)

i is 0 on the first pass through the loop. At the end of the loop, i is incremented, to 1. 1 is less than or equal 2, so the loop body is executed again. At the end, i is incremented, to 2. The loop condition is evaluated again, and 2 is less than or equal 2 (it’s obviously equal), so the loop body is executed. At the end of the loop, i is incremented to 3. This time, when the loop condition is evaluated, 3 is not less than or equal 2, so the body is not executed, and control passes to the next statement.

It’s that third time through the body of the code, when i equals 2 that causes a problem, when you use dirPin*. Remember that i equals 2, which refers to the third position in the array (0, 1, 2, …) that only has 2 positions.*

Thanks, sorry to be such a noob. so if I say
for (int i=0; i<num; i++)
it’s all good?

Not always. But, in this case, yes. You want to make sure that the loop condition does not allow an index to exceed the size of the array being referenced.

I think this program may be getting close to working, but I’m uncertain about the nested for/while loops, which are generating an error about the scope of my variables (****) any insight is very much appreciated.

////////////////////////////////////////////////////////
// Stepper Motor skecth for use with the EasyDriver 3.1
////////////////////////////////////////////////////////

// Dan Thompson 2008
//
// Inpired by the code and chat on this thread.
// http://forum.sparkfun.com/viewtopic.php?t=10378&highlight=easydriver
//
// Use this code at your own risk.
// For all the product details visit http://greta.dhs.org/EasyDriver/
// For the full tutorial visit http://danthompsonsblog.blogspot.com/

#define pink 2//for some reason we need a constant # of 2 for num???why I don’t know

int dirStateNum = 0;//a variable to hold whether we’re going forward or backwards

int dirPin = {3,9};//the pins that assign direction
int stepPin = {4,8};//the pins that step
int interval = 60;//the variable to hold the pause between steps
int distance = 100;//the amount of the iteration of steps
long previousMillis = {0,0};//a variable to hold the last time

int minGo = 100;
int maxGo = 4000;
int minWait = 60;
int maxWait = 200;

void setup() {

pinMode(dirPin[0], OUTPUT);
pinMode(dirPin[1], OUTPUT);
pinMode(stepPin[0], OUTPUT);
pinMode(stepPin[1], OUTPUT);// set the pinModes

}
void loop(){

dirStateNum = int(random(0,1)); //randomly choose between 1 and 0 for the direction
for(int i=0; i<pink; i++){//assign this direction to each motor

if(dirStateNum = 0)//use the randomly assigned 0 or 1 to set the pin either high or low
{
digitalWrite(dirPin*, LOW);}*

  • else{*
    _ digitalWrite(dirPin*, HIGH);}_
    _
    }_
    _
    delay(100);//this delay seems to be necessary for some reason*_

_ for (i = 0; i<pink; i++) // Iterate for a number of microsteps set by the distance variable******
* {*
* distance = r(minGo, maxGo);*
while (n = 0; n<distance; n++)_
_
{
_
_ previousMillis = millis(); //set the variable previousMillis to the time right now
digitalWrite(stepPin, LOW); // This LOW to HIGH change is what creates the

interval = r(minWait, maxWait);

while (millis() - previousMillis <= interval){//set the stepPin to HIGH and wait an interval before moving on
digitalWrite(stepPin*, HIGH); // “Rising Edge” so the easydriver knows to when to step.
}
}
}
}*_

According to the documentation for the random function:

Parameters

min - lower bound of the random value, inclusive (optional)

max - upper bound of the random value, exclusive

Returns

long - a random number between min and max - 1

So, your "random" number will always be 0. How random is that?

The #define statement is defining a constant. How does pink relate to 2?

dirStateNum is an int. Random returns a long. To get the long to fit into an int, you should cast it properly:

dirStateNum = (int)random(0,2);

This statment:

if(dirStateNum = 0)//use the randomly assigned 0 or 1 to set the pin either high or low

first sets dirStateNum to 0 and then tests for the truth or falseness of that assignment. The dirStateNum = 0 assignment actually returns a value. It does this so a statement like

a = b = c = 12;

will work. The c = 12 assignment occurs first, and returns a value of 12. That value is assigned to b, resulting in a return value of 12, which is assigned to a.

You actually want

if(dirStateNum == 0)//use the randomly assigned 0 or 1 to set the pin either high or low

which evaluates whether dirStateNum is 0, or not, without affecting its value.

The delay statement is necessary because steppers motors, while they are fast, are not instantaneous. You need to wait for the motor to step.

The while statement syntax is wrong. You are mixing up the for and while statements. The while statement requires one clause that evaluates to true or false. The for statement takes 3 clauses - an initialization clause, a conditional clause, and an increment clause.

Thank you thank you for all the help, especially the succinct explanation of the difference between for and while. I’ve made suggested changes and still getting an error message about my loop function:

error: name lookup of ‘i’ changed for new ISO ‘for’ scoping

////////////////////////////////////////////////////////
// Stepper Motor skecth for use with the EasyDriver 3.1
////////////////////////////////////////////////////////

// Dan Thompson 2008
//
// Inpired by the code and chat on this thread.
// http://forum.sparkfun.com/viewtopic.php?t=10378&highlight=easydriver
//
// Use this code at your own risk.
// For all the product details visit http://greta.dhs.org/EasyDriver/
// For the full tutorial visit http://danthompsonsblog.blogspot.com/

#define pink 2//for some reason we need a constant # of 2 for num???why I don’t know

int dirStateNum = 0;//a variable to hold whether we’re going forward or backwards

int dirPin = {3,9};//the pins that assign direction
int stepPin = {4,8};//the pins that step
int interval = 60;//the variable to hold the pause between steps
int distance = 100;//the amount of the iteration of steps
long previousMillis = {0,0};//a variable to hold the last time

int minGo = 100;
int maxGo = 4000;
int minWait = 60;
int maxWait = 200;

void setup() {

pinMode(dirPin[0], OUTPUT);
pinMode(dirPin[1], OUTPUT);
pinMode(stepPin[0], OUTPUT);
pinMode(stepPin[1], OUTPUT);// set the pinModes

}
void loop(){

dirStateNum = (int)random(0,2); //randomly choose between 1 and 0 for the direction
for(int i=0; i<pink; i++){//assign this direction to each motor

if(dirStateNum==0)//use the randomly assigned 0 or 1 to set the pin either high or low
{
digitalWrite(dirPin*, LOW);}*

  • else{*
    _ digitalWrite(dirPin*, HIGH);}_
    _
    }_
    _
    delay(100);//this delay seems to be necessary for some reason*_

* for (i = 0; i<pink; i++) // Iterate for a number of microsteps set by the distance variable*
* {*
* distance = (int)random(minGo, maxGo);*
* while ( n<=distance){*
_ previousMillis = millis(); //set the variable previousMillis to the time right now
digitalWrite(stepPin*, LOW); // This LOW to HIGH change is what creates the*
* interval = r(minWait, maxWait);
while (millis() - previousMillis <= interval){//set the stepPin to HIGH and wait an interval before moving on
digitalWrite(stepPin, HIGH); // “Rising Edge” so the easydriver knows to when to step.
}
}
}
}*_

Ignore that last post, I figured it out. Thanks again for all the help!! Once I test this with my motors, I’ll let you know if it really works.

////////////////////////////////////////////////////////
// Stepper Motor skecth for use with the EasyDriver 3.1
////////////////////////////////////////////////////////

// Dan Thompson 2008
//
// Inpired by the code and chat on this thread.
// http://forum.sparkfun.com/viewtopic.php?t=10378&highlight=easydriver
//
// Use this code at your own risk.
// For all the product details visit http://greta.dhs.org/EasyDriver/
// For the full tutorial visit http://danthompsonsblog.blogspot.com/

#define pink 2//for some reason we need a constant # of 2 for num???why I don’t know

int dirStateNum = 0;//a variable to hold whether we’re going forward or backwards

int dirPin = {3,9};//the pins that assign direction
int stepPin = {4,8};//the pins that step
int interval = 60;//the variable to hold the pause between steps
int distance = 100;//the amount of the iteration of steps
long previousMillis = {0,0};//a variable to hold the last time

int minGo = 100;
int maxGo = 4000;
int minWait = 60;
int maxWait = 200;

void setup() {

pinMode(dirPin[0], OUTPUT);
pinMode(dirPin[1], OUTPUT);
pinMode(stepPin[0], OUTPUT);
pinMode(stepPin[1], OUTPUT);// set the pinModes

}
void loop(){

dirStateNum = (int)random(0,2); //randomly choose between 1 and 0 for the direction
for(int i=0; i<pink; i++){//assign this direction to each motor

if(dirStateNum==0)//use the randomly assigned 0 or 1 to set the pin either high or low
{
digitalWrite(dirPin*, LOW);}*

  • else{*
    _ digitalWrite(dirPin*, HIGH);}_
    _
    }_
    _
    delay(100);//this delay is necessary because stepper motors are fast but not instantaneous*_

* for (int p = 0; p<pink; p++) // Iterate for a number of microsteps set by the distance variable*
* {*
* distance = (int)random(minGo, maxGo);*
* for (int n; n<=distance; n++){*
* previousMillis[p] = millis(); //set the variable previousMillis to the time right now*
* digitalWrite(stepPin[p], LOW); // This LOW to HIGH change is what creates the*
* interval = (int)random(minWait, maxWait);*
* while (millis() - previousMillis[p] <= interval){//set the stepPin to HIGH and wait an interval before moving on*
* digitalWrite(stepPin[p], HIGH); // “Rising Edge” so the easydriver knows to when to step.*
* }*
* }*
* }*
}

The code compiles but as I try to control my motors with it nothing happens. I can see by connecting to LEDs and using Serial.print that it’s simply not executing the second part of the the main loop. the two nested “for” functions are simply not happening…

help? :-X
////////////////////////////////////////////////////////
// Stepper Motor skecth for use with the EasyDriver 3.1
////////////////////////////////////////////////////////

// Dan Thompson 2008
//
// Inpired by the code and chat on this thread.
// http://forum.sparkfun.com/viewtopic.php?t=10378&highlight=easydriver
//
// Use this code at your own risk.
// For all the product details visit http://greta.dhs.org/EasyDriver/
// For the full tutorial visit http://danthompsonsblog.blogspot.com/

#define pink 2//for some reason we need a constant # of 2 for num???why I don’t know

int dirStateNum = 0;//a variable to hold whether we’re going forward or backwards

int dirPin = {3,9};//the pins that assign direction
int stepPin = {4,8};//the pins that step
int interval = 60;//the variable to hold the pause between steps
int distance = 100;//the amount of the iteration of steps
long previousMillis = {0,0};//a variable to hold the last time

int minGo = 1000;
int maxGo = 40000;
int minWait = 600;
int maxWait = 2000;

void setup() {

Serial.begin(9600);
pinMode(dirPin[0], OUTPUT);
pinMode(dirPin[1], OUTPUT);
pinMode(stepPin[0], OUTPUT);
pinMode(stepPin[1], OUTPUT);// set the pinModes

}
void loop(){

dirStateNum = (int)random(0,2); //randomly choose between 1 and 0 for the direction
for(int i=0; i<pink; i++){//assign this direction to each motor
Serial.println("i: ");
Serial.println (i);
if(dirStateNum==0)//use the randomly assigned 0 or 1 to set the pin either high or low
{
digitalWrite(dirPin*, LOW);}*

  • else{*
    _ digitalWrite(dirPin*, HIGH);}_
    _
    }_
    _
    delay(100);//this delay is necessary because stepper motors are fast but not instantaneous*_

* for (int p = 0; p<pink; p++) // Iterate for through the different motors*
* {*
* distance = (int)random(minGo, maxGo);*
* for (int n; n<=distance; n++){*
* previousMillis[p] = millis(); //set the variable previousMillis to the time right now*
* digitalWrite(stepPin[p], LOW); // This LOW to HIGH change is what creates the*
* interval = (int)random(minWait, maxWait);*
* while (millis() - previousMillis[p] <= interval){//set the stepPin to HIGH and wait an interval before moving on*
* digitalWrite(stepPin[p], HIGH); // “Rising Edge” so the easydriver knows to when to step.*
* Serial.print("distance: ");*
* Serial.println(distance);*
* Serial.print("interval: ");*
* Serial.println(interval);*
* }*
* }*
* }*
}

First, when posting code, please use the # button. This generates tags in the post that cause the software to display your code in a scrollable window. It makes it take up a lot less space in the page.

In loop, do you see the “i: n” lines in the Serial Monitor?

If so, is i 0 then 1?

You assign a value to dirStateNum; either a 0 or a 1. Then, you only write to the pins if dirStateNum is 0. I think that what you want to do is write to the pin every time. The value to write to the pin (the 2nd argument) is dirStateNum (LOW is 0, HIGH is 1).

There is no need to the delay after setting the direction. The delay is needed after stepping.

This statement:

for (int n; n<=distance; n++)

does not assign a value to n, initially. Add " = 0" after “int n”.

Thank you for your help and the lesson on how to use the forum (note improved use of html buttons below)

This statement:
Code:
for (int n; n<=distance; n++)

does not assign a value to n, initially. Add " = 0" after “int n”.

I made this correction as you’ll see in the code below and the behavior of the program changed dramatically. Now my Serial window and LEDs show that the distance and interval numbers are changing and being sent through stepPin, however I’m no longer getting the change to the dirPin and no mention of “i” in my Serial window.

In loop, do you see the “i: n” lines in the Serial Monitor?

If so, is i 0 then 1?

You assign a value to dirStateNum; either a 0 or a 1. Then, you only write to the pins if dirStateNum is 0. I think that what you want to do is write to the pin every time. The value to write to the pin (the 2nd argument) is dirStateNum (LOW is 0, HIGH is 1).

Before the above change “i” was randomly switching between 0 and 1, although this was happening on both pins simultaneously, not independently as I desired, which was my reason for wading into the muddy waters of arrays in the first place.

There is no need to the delay after setting the direction. The delay is needed after stepping.

My intention is to use the “interval” variable to set changing delays after the step, thus not using the delay function, which would interfere with simultaneous operation of steppers…

////////////////////////////////////////////////////////
// Stepper Motor skecth for use with the EasyDriver 3.1 
////////////////////////////////////////////////////////

// Dan Thompson 2008
//
// Inpired by the code and chat on this thread.
// http://forum.sparkfun.com/viewtopic.php?t=10378&highlight=easydriver
//
// Use this code at your own risk.
// For all the product details visit http://greta.dhs.org/EasyDriver/
// For the full tutorial visit http://danthompsonsblog.blogspot.com/

#define pink 2//for some reason we need a constant # of 2 for num???why I don't know


int dirStateNum = 0;//a variable to hold whether we're going forward or backwards


int dirPin[pink] = {3,9};//the pins that assign direction
int stepPin[pink]  = {4,8};//the pins that step
int interval = 60;//the variable to hold the pause between steps
int distance = 100;//the amount of the iteration of steps
long previousMillis[pink]  = {0,0};//a variable to hold the last time

int minGo = 100;
int maxGo = 4000;
int minWait = 60;
int maxWait = 200;

void setup() {

Serial.begin(9600);
pinMode(dirPin[0], OUTPUT);
pinMode(dirPin[1], OUTPUT);
pinMode(stepPin[0], OUTPUT);
pinMode(stepPin[1], OUTPUT);// set the pinModes

}
 void loop(){
   
   dirStateNum = (int)random(0,2); //randomly choose between 1 and 0 for the direction
   for(int i=0; i<pink; i++){//assign this direction to each motor
   Serial.println("i:  ");
    Serial.println (i); 
  if(dirStateNum==0)//use the randomly assigned 0 or 1 to set the pin either high or low
   { 
     digitalWrite(dirPin[i], LOW);}
    else{
       digitalWrite(dirPin[i], HIGH);}
   }
   delay(100);//this delay is necessary because stepper motors are fast but not instantaneous

 
  for (int p = 0; p<pink; p++)       // Iterate for through the different motors
  {
    distance = (int)random(minGo, maxGo);
    for (int n=0; n<=distance; n++){
    previousMillis[p] = millis(); //set the variable previousMillis to the time right now
    digitalWrite(stepPin[p], LOW);  // This LOW to HIGH change is what creates the
    interval = (int)random(minWait, maxWait);
     while (millis() - previousMillis[p] <= interval){//set the stepPin to HIGH and wait an interval before moving on
    digitalWrite(stepPin[p], HIGH); // "Rising Edge" so the easydriver knows to when to step.
    Serial.print("distance:  ");
    Serial.println(distance);
    Serial.print("interval:  ");
    Serial.println(interval);
     }
    }
  }
 }

This posts looks a lot better. Thanks.

The state change is happening on both pins because that’s what you coded. If you want to randomly choose a direction for each motor, try this:

for(int i=0; i<pink; i++)
{
   digitalWrite(dirPin[i], (int)random(0, 2)); // For each pin, randomly
                                                                // set a direction
}

Try this for the whole loop function:

void loop()
{
   for(int i=0; i<pink; i++)
   {
      digitalWrite(dirPin[i], (int)random(0, 2)); // For each pin,
                                                                   // randomly
                                                                   // set a direction
   }

   for (int p = 0; p<pink; p++)       // Iterate for through the motors
   {
      distance = (int)random(minGo, maxGo);
      Serial.print("distance:  ");
      Serial.println(distance);

      for (int n=0; n<=distance; n++)
      {
         previousMillis[p] = millis(); //set the variable previousMillis to
                                                  // the time right now
         interval = (int)random(minWait, maxWait);
         Serial.print("interval:  ");
         Serial.println(interval);

         // I think that you need to set the pin low, then set the pin
         // high, to cause the motor to step
         digitalWrite(stepPin[p], LOW);  
         digitalWrite(stepPin[p], HIGH); // "Rising Edge" 

         // Then, wait some time before stepping again
         while (millis() - previousMillis[p] <= interval)
         {
            // Do nothing for a little while
         }
      }
   }
}

Although, I must confess that I don’t understand why you want to wait a different amount of time between steps. This will result in jerky movements. Perhaps what you wanted was to pick a random amount of time to wait after each step, and wait that amount of time after each step?