Go Down

Topic: Multiple Servos with XBee & Arduino (Read 1 time) previous topic - next topic

Ty Huffman

Does anyone have any idea why this works? If the Serial.print command in Receiver is removed it breaks, why is that?? I tried changing to int but that had no effect, Serial.print makes this work. I think this is a bug, that just happens to make something work.

Code: [Select]

#######  Sender #########
// SENDER connected to first PC

void setup()
{
Serial.begin(9600); // used to be 19200
}

void loop()
{
int ana1 = analogRead(1);
delay(10);
int ana2 = analogRead(2); // read the analog values in
delay(10);
int val1 = map(ana1, 0, 1023, 0, 179);
int val2 = map(ana2, 0, 1023, 0, 179); // assign maped values to val1 & val2

Serial.print(254, BYTE);
Serial.print(val1, BYTE);

Serial.print(253, BYTE);
Serial.print(val2, BYTE);

delay(5);

}


######### Receiver ##########

// RECIEVER connected to second PC

#include <Servo.h>
byte serv, ana1, ana2;
Servo myservo1;
Servo myservo2;
void setup()
{
myservo1.attach(12);
myservo2.attach(13);
Serial.begin(9600); // used to be 19200
}

void loop() {
 if (Serial.available()) {
   serv = Serial.read();

   Serial.println(int(serv));
   
    if ((int(serv) == 254)) {
    byte ana1;
    ana1 = Serial.read();
    // Serial.println(int(serv)); // To check if data is received
    // Serial.println(int(ana1)); // To check if data is received
     myservo1.write(ana1);
   }
   
   if ((int(serv) == 253)) {
    byte ana2;
    ana2 = Serial.read();
    // Serial.println(int(serv)); // To check if data is received
    // Serial.println(int(ana2)); // To check if data is received
     myservo2.write(ana2);
   }
 }
}



Ty

PaulS

I've seen this before, too. It appears as though Serial::read is a non-blocking function. In effect, it starts the read process and then returns, before the read operation is complete.

The Serial::print function is also non-blocking, but it doesn't return until the write operation begins, which can't happen until the read operation has completed.

At that time, serv contains data that can be used (and printed). Without the print function call, you are trying to access the serv value before the read operation has completed.

A short delay (a few microseconds) after the Serial::read call achieves the same result. That is, the read operation is done before the value is used.

It looks like a bug to me, but, as you've observed, during debugging the problem doesn't exist.

Ty Huffman

Thanks for the info, when you say a few microseconds, is that a Delay(3), or more like a Delay(20)? I'm afraid of delaying into the transmission timing and creating bigger problems on down the road, as more Servos are added.

What is the shortest Delay() you have used and had this work?

How do I go about escalating this issue, or have I done my part by reporting this to the forum??

Ty

PaulS

I used delay(10); successfully. You may be able to go with a smaller value. Try it, and see.

Imahilus

delayMicroseconds(1) is sufficient for me.
Delay goes by miliseconds, a thousand microseconds go in a milisecond, so delay(10) is immense overkill, according to my experiences ;)

PaulS

Well, a 10 millisecond delay was not causing me any problems. So, I didn't have a need to find what value was required. I'm happy to know that a much shorter delay is all that's required.

Ty Huffman

I just attempted to use the delayMicroseconds and it did NOT work !! Adding the SerialPrint command back in and it does work. Could someone load the code I posted and verify?? The first read is the only one that has problems, not the second read, look at the receive code. Definitely a bug and a nasty one at that, seeing as only the Serial command makes it work, and that it only break the first test not the second test.

Go Up