Go Down

Topic: Arduino Freezes after a while of Serial. (Read 2752 times) previous topic - next topic

leelokhin

Mar 17, 2011, 09:35 am Last Edit: Mar 17, 2011, 09:37 am by Zephyrs Reason: 1
Code: [Select]
void setup() {
 Serial.begin(9600);
 pinMode(13, OUTPUT);
}

//Message sample <2X245> Which means motor 2, speed 245.
boolean ParseSerial(int &MotorNum, int &Speed){
 char SerialData[6]; //Reference paramter to modify. Read Pointers
 char Temp[4]; // X is an integer.
 
  //Strings must be null terminated
 if (Serial.read() == '<') {//If first Char = <
   int StartTime = millis();    // Wait for Serial Buffer
   while (millis() - StartTime < 200 && Serial.available() < 5){};
   if (Serial.available() < 5) return false; // Timeout
   for (int i = 0; i < 5; i++) {
     SerialData[i] = Serial.read();
     if (((int(SerialData[i]) - 48) > 9 || (int(SerialData[i]) - 48) < 0 )) return false;
   }

   MotorNum = int(SerialData[0]) - 48; //ASCII to Int
   
   strncpy(Temp, SerialData + 2, 3);
   Speed = atoi(Temp);
   Serial.flush();
   return true;  
 }
 return false;
}
   

void loop() {
 int LEDPin;
 int TEMP;
 int Speed;
 LEDPin = 13;
 TEMP = 11;
 //Serial.println(millis());
 if (ParseSerial(TEMP, Speed)) {
   analogWrite(TEMP, Speed);
 }
}

//PORTB = (PORTB & B11100111) | (bit3_value << 3) | (bit4_value << 4);



There's my arduino code.

There's data incoming from the serial RX pin every 20ms, in the form of <MxSSS>, where M is the pin number for a PWM output, and SSS is the duty cycle.

It works perfectly fine for around 3 minutes, then the waveform freezes, whatever I do. Tx also stops, if the led on the board is correct.
According to my oscilloscope, the serial data coming in from Rx is still changing fine, but Tx stops, and the waveform stops changing. I've tried pins 5,6 and 9.

Is there some sort of memory leak in the above stuff?

Oh, yes. It works fine if Serial.println(millis()); isn't commented out, and it will work for another 3 minutes if the arduino is restarted.

PaulS

Code: [Select]
    Serial.flush();
Throw away random amounts of data. Now, does that really seem like a good idea?

You are sending, you said, "<MxSSS>". But, you are reading the '<' and the next 5 characters. You assume that the 5 characters are valid. Bad assumption. You should read and store all the data after the '<', until the '>' arrives, and check that you have stored exactly 5 characters. Only then should you use the data.

Code: [Select]
    MotorNum = int(SerialData[0]) - 48; //ASCII to Int
This would be much more readable as:
Code: [Select]
    MotorNum = int(SerialData[0]) - '0'; //ASCII to Int

Quote
There's data incoming from the serial RX pin every 20ms

And yet your timeout is 200 milliseconds...

Search the forum for "started && ended" for an example I posted on how to read delimited serial data, as it becomes available. There is no need to have any timeout in the read function, because the function can simply read any unread data, doing something with the data only when a complete packet has arrived.
The art of getting good answers lies in asking good questions.

leelokhin

#2
Mar 18, 2011, 03:28 am Last Edit: Mar 18, 2011, 03:46 am by Zephyrs Reason: 1
The timeout is 200 ms, which is why I have Serial.flush. And its the timeout. In particular, this line of code
Code: [Select]
while (millis() - StartTime < 200 && Serial.available() < 5){};
means that once Serial.available is above 5, it quits the while loop.

This data is sent in a continuous stream, so it is no big deal if a few packets are lost here and there - the next one is incoming, as I said, in 20 ms.

Basiclaly, I have a program which reads a joystick and sends serial data continuously. Would it matter that a few packets are lost?

And wouldn't the program waiting until ">" comes along wait a while if > doesn't come?

EDIT: Took your suggestion about the '>'. Changed  code to
Code: [Select]
while (millis() - StartTime < 200 && Serial.available() < 6){};
and added
Code: [Select]
if (Serial.read() != '>') return false;

So if the sixth character isn't a '<', it'll return false.


Still have no idea why the arduino would freeze if it doesn't transmit Tx continuously, but it's fine if it does.



nickgammon

In your code, where does the 4th byte of Temp get set to zero? That is, Temp [3].

It starts off undefined, then you copy 3 bytes in with strncpy. Then you do atoi on it. So the results could be undefined, or wrong (no terminating 0x0 byte).

I'm inclined to agree with Paul. The Serial.flush isn't going to help, and you are doing Serial.read() without checking first if anything is there.

Quote

This data is sent in a continuous stream, so it is no big deal if a few packets are lost here and there - the next one is incoming, as I said, in 20 ms.


Well ... the data comes every 20 ms but you are waiting 200 ms? Plus, the UART chip buffers stuff (4 bytes from memory). So the available test isn't really guaranteed to be "recently received". I think I would rework it.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

Go Up