I need help with Servo Code

Hello All,

I am trying to write code for a servo that will move in either CW or CCW motion from a random point and increase by +1 or decrease -1 from that point until it reaches either 0 or 180. Here is the code I have so far.

//Written painfully by Spaceman

#include <Servo.h>

Servo servo01;
int pos = 0;

void setup ()
{
  Serial.begin(9600);
  servo01.attach(9);
}

void loop()
{
 int OddEven = random(1, 3);
 int randNum = random(0, 180);

  void loop();
   Serial.print("OddEven");
   Serial.println(OddEven); // so I can see what value I get
   delay(250); //time to read
   Serial.print("randNum");
   Serial.println(randNum); // so I can see what value I get
   delay(250); //time to read
    if (OddEven = 1)
    {  
      for(pos = randNum; pos < 180; pos +=1)
         servo01.write(pos);
         Serial.print("Position");
         Serial.println(pos); // so I can see what value I get
         delay(250); //time to read
    }
    else if (OddEven = 2)
    {
      for(pos = randNum; pos < 180; pos -=1)
        servo01.write(pos);
       Serial.print("Position2");
       Serial.println(pos); // so I can see what value I get
       delay(250); //time to read
    }
    delay(500); //time to read
}

When I run the code, I can see that the direction (OddEven) random number is working and the random number to start the incremental positioning is working. It is the incremental/decremental 'for' statement that doesn't seem to work. It always stays at 180. Also, I never get to the 'else if' part of the loop.

I've been lurking in here for a while and thought I could figure this out on my own. I don't have much experience writing code and clearly I need help.

Any thought or hints would be appreciated.
Also, a little shout-out to those that run this place.... nice work!

Hi,

you want == not = in the if statements, == is a comparison operator which says 'is this equal to this', = is an assignment operator which says 'make this equal to this'

you could also just use just one for loop and change the name and purpose of oddEven to direction.

Something like this -

for(int pos; pos > 0 && pos < 180; pos+=direction)
{
if(pos <= 0)
{
direction = 1;
}
if(pos >= 180)
{
direction = -1;
}

...
}

Note, code not tested, in a rush to get out. Good luck

Duane B

rcarduino.blogspot.com

Why have you got a prototype for "loop()" inside "loop()"?

You also need to decide if you need {} braces around the body of your for loops. Your indentation is ignored by the compiler.

AWOL:
Why have you got a prototype for "loop()" inside "loop()"?

You also need to decide if you need {} braces around the body of your for loops. Your indentation is ignored by the compiler.

Not having any experience in programming, I'm not sure what any of the above means. I created the first loop to generate the direction var (OddEven) and the movement var (randNum). The second loop is to execute the direction and incremental change. Is that the wrong approach?

No, you have "void loop();" before the "Serial.print("OddEven");".
It serves no purpose, and should not be there.

    if (OddEven = 1)

You need to read up on the difference between = (the assignment operator) and == (the equality operator).

 int OddEven = random(1, 3);

This will limit the values that can be in OddEven to 1 or 2.

    else if (OddEven = 2)

If the value isn't 1, we wouldn't execute the else portion. Testing again that the value IS 2 is completely unnecessary.

Here my reasonings

AWOL:
No, you have "void loop();" before the "Serial.print("OddEven");".
It serves no purpose, and should not be there.

Don't I need the first loop to come back to the top and re-establish new OddEven/randNum numbers?

PaulS:

    if (OddEven = 1)

You need to read up on the difference between = (the assignment operator) and == (the equality operator).

so this should read if (OddEven == 1)

PaulS:

 int OddEven = random(1, 3);

This will limit the values that can be in OddEven to 1 or 2.

This is what I was trying to get. Either clockwise or counter clockwise

PaulS:

    else if (OddEven = 2)

If the value isn't 1, we wouldn't execute the else portion. Testing again that the value IS 2 is completely unnecessary.

so this should just be 'else'

What I'm trying to accomplish is get 4 servos moving in random directions for random distances continuously. I guess I'm not on the right track afterall.

I guess I'm not on the right track afterall.

Sure you are. Just not close (enough) to the station.

Don't I need the first loop to come back to the top and re-establish new OddEven/randNum numbers?

You need the loop function, yes. But you do not need (or want) that void loop statement in there. The loop function gets called in an endless loop without your "help" at all.

so this should read if (OddEven == 1)

Yes.

so this should just be 'else'

Yes.

I made some corrections and now have this:

//Written with alot of help by Spaceman

#include <Servo.h>

Servo servo01;
int pos = 0;

void setup ()
{
  Serial.begin(9600);
  servo01.attach(9);
}


void loop()

 {

  randomSeed(analogRead(0));
  int OddEven = random(1, 3);
  int randNum = random(0, 180);
   
Serial.print("OddEven");
Serial.println(OddEven); // so I can see what value I get
delay(250); //time to read
Serial.print("randNum");
Serial.println(randNum); // so I can see what value I get
delay(250); //time to read
 
   if (OddEven == 1)
    {  
      for(pos = randNum; pos < 180; pos +=1)
         servo01.write(pos);
         Serial.print("Position");
         Serial.println(pos); // so I can see what value I get
         delay(250); //time to read
    }
    else 
    {
      for(pos = randNum; pos < 180; pos -=1)
        servo01.write(pos);
       Serial.print("Position_2_");
       Serial.println(pos); // so I can see what value I get
       delay(250); //time to read
    }
    delay(500); //time to read
 }

As I watch the results in the serial monitor, I realize it is not doing what I expected. What I expected was to get either 1 or 2 for OddEven. That works. I expected to get a random number between 0 and 179 for randNum. That works too....yay! What isn't happening is the incremental change in either 'for' statements to move from the randNum to 180 in 'if' or 0 in 'else'. It simply flops between 0 and 180 regardless of the result of OddEven var.

So, pretending to be the code, here is what I hoped for:
int OddEven = random(1,3); answer 1
int randNum = random(0,180); answer 141

 if (OddEven == 1)
    {  
      for(pos = randNum; pos < 180; pos +=1)
         servo01.write(pos);

pos 141,142,143,144,145,146,147,148...etc 180

return to top of loop and get new random numbers.

int OddEven = random(1,3); answer 2
int randNum = random(0,180); answer 77

 else
    {  
      for(pos = randNum; pos < 180; pos -=1)
         servo01.write(pos);

pos 77,76,75,74,73,72,71...etc 0

return to top of loop and get new random numbers.

Please show what you think is the body of your for loop.

PaulS:
Please show what you think is the body of your for loop.

for(pos = randNum; pos < 180; pos +=1)
         servo01.write(pos);

and

 for(pos = randNum; pos>=1; pos -=1)
        servo01.write(pos);

...which takes virtually no time whatsoever to execute, regardless of the size of randNum

AWOL:
...which takes virtually no time whatsoever to execute, regardless of the size of randNum

but the servo doesn't move and the Serial Monitor results are either 0 or 180 for pos var.

but the servo doesn't move and the Serial Monitor results are either 0 or 180 for pos var.

You only print the value of pos after the for loop. At that point, it will be either 0 or 180.

As to why the servo does not move, you haven't assured us that it is wired correctly and that it is getting sufficient current. Have you tried the sweep example to verify that the servo works?

You only print the value of pos after the for loop. At that point, it will be either 0 or 180.

As to why the servo does not move, you haven't assured us that it is wired correctly and that it is getting sufficient current. Have you tried the sweep example to verify that the servo works?

I have the servo wired through a breadboard to a 6v supply and the ground from arduino is in common with the servo. The sweep example runs as it should.

I will reposition the serial output for pos during the loop and report back.

My advice, for what it's worth, is that every 'if', 'else', 'for', 'while' etc should always be followed by a compound statement, even if you only plan to have a single statement in it. In other words, put a '{' and '}' pair, each on separate lines please, and indented to the same amount. This avoids the type of bug that PaulS was hinting at when he asked his leading question.

My advice, for what it's worth, is that every 'if', 'else', 'for', 'while' etc should always be followed by a compound statement, even if you only plan to have a single statement in it. In other words, put a '{' and '}' pair, each on separate lines please, and indented to the same amount.

Agreed. At work, whenever I type if(someCondition), I put the open and close curly braces in without even thinking about what to do in the block. It's just become automatic. Then, I go back and put the code in the block. Visual Studio automatically does the indenting and outdenting so, I rarely have to deal with mismatched indent levels, except when copying and pasting a block of code. When I do that, the first thing I do after pasting is correct the indent level to match the braces.

Saves untold amounts of grief.

Well, because of all who have helped in this topic, I got it! Here is what it looks like:

//Written with alot of help by Spaceman

#include <Servo.h>

Servo servo01;
int pos = 0;

void setup ()
{
  Serial.begin(9600);
  servo01.attach(9);
}


void loop()
{
  randomSeed(analogRead(0));
  int OddEven = random(1, 3);
  int randNum = random(0, 180);
  
  if (OddEven ==1)
  {
    Serial.print("position_01");
    Serial.println(randNum);
    //delay(250); uncomment if you want to read slowly
    servo01.write(randNum);
      {
        for(pos = randNum; pos < 180; pos +=1)
          {
            servo01.write(pos);
            Serial.print("position_01_Next");
            Serial.println(pos);
            //delay(100); uncomment if you want to read slowly
          }
      }
  }      
  else
  {  
    Serial.print("position_02");
    Serial.println(randNum);
    //delay(250); uncomment if you want to read slowly
    servo01.write(randNum);
      {
        for(pos = randNum; pos>=1; pos -=1)
          {
            servo01.write(pos);
            Serial.print("position_02_Next");
            Serial.println(pos);
            //delay(100); uncomment if you want to read slowly
          }
      }
  }
}

PeterH:
My advice, for what it's worth, is that every 'if', 'else', 'for', 'while' etc should always be followed by a compound statement, even if you only plan to have a single statement in it. In other words, put a '{' and '}' pair, each on separate lines please, and indented to the same amount. This avoids the type of bug that PaulS was hinting at when he asked his leading question.

Not knowing much about programming, this is what made the difference. I'll follow this practice from now on!

Now to figure out how to apply this to 4 servos working at the same time. I saw somewhere in the forum about sketches. Does anyone have any hints?

The sketch is what you just posted.
Did you mean libraries, or even simply arrays?

I saw somewhere in the forum about sketches.

Sketches are everywhere on the forum. Perhaps you meant arrays.

Servo myServos[4];

myServo[0].attach(somePin);
myServo[1].attach(anotherPin);

for(int n=0; n<4; n++)
{
  int pos = random(0, 180);
  myServo[n].write(pos);
}

Moderator edit: Code tags added, subscript corrected.