I'm using a Python program to send some message over serial port to Arduino. This message contains the pin number of the pin and whether it should be HIGH
or LOW
. Eg: Sending 2H\n
should set pin 2 to HIGH
.
pins
array maps the pin numbers in the messages to the actual pin number of arduino. 1H
corresponds to pin 22 on Arduinio Mega.
When manually sending one message at a time, things work fine. However when Python sends a series of 30 such messages one after the other in a loop with no delays, pin 1 is always stuck at whichever value it is set to on the first series of messages.
Example:
1L\n
2H\n
3H\n
4H\n
5H\n
...
followed by
1H\n
2H\n
3H\n
4H\n
5H\n
...
will cause pin 1 to be stuck at LOW
when it should be high.
On arduino, this is the code that parse the message and sets the pin values.
void setPinValues(String message) {
for(int i = 1; i <= sizeof(pins) / sizeof(pins[0]); i++ ) {
String pinNumber = String(i);
if( message == pinNumber + "H\n" ) {
pinValues[i] = HIGH;
}
if( message == pinNumber + "L\n" ) {
pinValues[i] = LOW;
}
}
}
void loop(){
if( Serial.available() > 0 ) {
received = Serial.read();
message += received;
if(received == '\n') {
// Set pin values
setPinValues(message);
// Write to pins
for (int i = 1; i <= sizeof(pins) / sizeof(pins[0]); i++) {
digitalWrite(pins[i], pinValues[i]);
}
// Clear buffer
message = "";
}
}
}
Arduino Mega communicates with Windows 8 x64 system over USB using a baud rate of 57600. When using a lower baud rate of 9600, this problem is not seen.
Furthermore, at baud rate of 57600, if I were to replace setPinValues
with the following code, pin 1 is properly switched on and off.
void setPinValues(String message) {
for(int i = 1; i <= sizeof(pins) / sizeof(pins[0]); i++ ) {
if( message == String(1) + "H\n" ) {
pinValues[1] = HIGH;
}
if( message == String(1) + "L\n" ) {
pinValues[1] = LOW;
}
if( message == String(2) + "H\n" ) {
pinValues[2] = HIGH;
}
if( message == String(2) + "L\n" ) {
pinValues[2] = LOW;
}
if( message == String(3) + "H\n" ) {
pinValues[3] = HIGH;
}
if( message == String(3) + "L\n" ) {
pinValues[3] = LOW;
}
}
}
Doesnt both versions of setPinValues
do the same? Why does lowering the baud rate prevent the problem? I cannot use a lower baud rate because the USB buffer gets filled up and things slow to a crawl.
To compare the last char H
or L
:
String pinValueString = message.substring(message.length() - 1);
char pinValueBuffer[2];
pinValueString.toCharArray(pinValueBuffer,2);
if(pinValueBuffer[0] == 'H') {
digitalWrite(pins[pinNumber], HIGH);
}
Serial.available()
andSerial.read()
are just wrappers around the serial buffer attached to the interrupt by Arduino when callingSerial.begin()
, so he's actually already doing what you suggest :) The problem probably lies in the 128-byte buffer filling and dropping bytes due to the very slow processing. \$\endgroup\$