1

I'm working on a project for school. I'm trying to rotate a servo by writing the letter that identify the servo and then the angle.

the problem is that sometimes the last number of the angle is lost or the whole angle all together. for example i want to rotate servo "a" 50 degrees. i enter a50 this works most of the time but sometimes i only get a 5 without the zero and sometimes i just get a zero. can anyone help, thanks.

please keep in mind i only did computer science in high school and intro to c++ in college. go easy on me please.

attached is the code and an image illustrating my problem.

#include <Servo.h>

Servo servo1;  
Servo servo2;
Servo servo3;

String angle1="";
String angle2="";

char serialbuffer[4];
int index=0;
int charcount=0;

int lastangle;
int dif;


void setup() {
  servo3.attach(3);  // attaches the servo on pin 9 to the servo object

  Serial.begin(9600);

  serialbuffer[0]='0';
  serialbuffer[1]='0';
  serialbuffer[2]='0';
  serialbuffer[3]='0';
}

void loop() {


       charcount=0;
       index=0;
       serialbuffer[0]=99;

   while (Serial.available() > 0) {

      char charbuffer = Serial.read();
       if(charbuffer=='\n'){
          index=0; 
        }
        else{

           serialbuffer[index]=charbuffer;
           index++;
           charcount++;
          }

      }

  angle1="";    
  if(serialbuffer[0]=='a'){

      for(int i=1;i<charcount;i++){
         angle1+=serialbuffer[i];
      }
      move_servo3(angle1);
      index=0;
      serialbuffer[0]=99;
    }
  delay(15);
}

void move_servo3(String angle2){


   Serial.println(angle2.toInt());   
   servo3.write(angle2.toInt()); 

  }

enter image description here

1

Are you hand-typing the commands? It is pretty difficult to do that consistently. I ask because your code collects data from the serial buffer until the buffer is empty - i.e. when you pause even slightly in your typing - and tries to act on whatever it has collected so far. That may be (probably will be!) an incomplete command. Even if your terminal uses line-by-line entry, there is still the risk that your code could notice an empty buffer between characters within a line.

Try collecting characters until it sees a newline, instead. That is probably what you intended, and it will be immune to your typing speed. You'll still need to test for .available, but that should only allow the code to collect more characters. Keep collecting until it sees a newline.

What (I think) is happening now is called a race-condition. That means that the program's behavior is dependent on which of two (or more) events happens first, and the order of their occurrence is indeterminate. Race conditions are especially hard to find when the order of two events is almost always the one you expected. Notice the "gotcha" word in that sentence? :)

| improve this answer | |
  • thanks for your answer. for future viewers, i ended up adding a last latter to determine the end of the message and then sending the whole thing to the servo. – sudo name Jul 15 '16 at 21:53
0

I don't understand why the problem is being caused, your code looks OK, but this is too big for a comment.

  • I think it would be better if you initialised you serialbuffer with NULL rather than '0'. This way angle2.ToInt() will just read the number you have typed, rather than what was in there last time. Try entering a111 and then a2. You will get a211 second time. NULL is the end of a string.
  • In loop() change your while loop to this:

    char charBuffer = Serial.read();
    while (charBuffer != '\n' && index < 4) // Index < 4 stops a buffer overflow.
    {
      serialbuffer[index++] = charBuffer;
      charCount++;
      charBuffer = Serial.read();
    }
    

This will keep reading until it sees a new line, which I think is what you want.

  • You don't need the delay statement now, the speed is controlled by how fast you can type.

  • The for statement could be changed to:

    for (int i = 0; i < 4 && serialbuffer[i] != NULL; ++i)
    

If you make these changes I think it might help see the problem. Also printing the number that has been typed in before the for loop might help, it will print now because you have initialised it to NULL.

| improve this answer | |

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.