arduino
arduino copied to clipboard
Changing baud rate in Firmata Serial
Moved from https://github.com/jgautier/firmata/issues/104
My Scenario
Using an Arduino Uno and softwareSerial I'm trying to connect to a device that runs at 115200 baud by default. I know the Uno & softwareSerial cannot handle that baud rate reliably so the first thing I do is send a short command to change the device to 9600 baud, then close my connection and reopen at 9600.
Sample Arduino code
This sample works fine:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(11, 10); // RX, TX
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
mySerial.begin(115200);
// Send 32 byte command to change message type and baud rate
byte changeOpMode[] = {0xA0, 0xA2, 0x00, 0x18, 0x81, 0x02, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x05, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x25, 0x80, 0x01, 0x3A, 0xB0, 0xB3 };
mySerial.write(changeOpMode, sizeof(changeOpMode));
mySerial.end();
// Reopen connection at new baud rate
mySerial.begin(9600);
}
void loop() { // run over and over
if (mySerial.available()) {
Serial.write(mySerial.read());
}
if (Serial.available()) {
mySerial.write(Serial.read());
}
}
@soundanalogous wrote: The root of this issue is on the Arduino (c/c++) side, not the JavaScript side. I can see now based on your Arduino example above what is different from my implementation. I'm deallocating the pointer to the SoftwareSerial object when calling end(), then if the user tries to config again, a new SoftwareSerial instance is assigned to the pointer that must be breaking something (and could also lead to a heap and stack collision if done multiple times). Whereas in your example above you simply call end, then begin with a new baud rate.
I want to keep the ability to deallocate memory in case a serial port is no longer needed after a certain point in an application. What I could do is add a new message that enables the user to update the baud rate. This would essentially call end then begin with the new baud as in your example. The close would deallocate.
Can you run the same sketch on your Mega substituting Serial1 for SoftwareSerial and verify whether or not that works the same?
Protocol update: https://github.com/firmata/protocol/pull/46
It didn't at first but once I added a delay between end and begin it did.
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial1.begin(115200);
// Send 32 byte command to change message type and baud rate
byte changeOpMode[] = {0xA0, 0xA2, 0x00, 0x18, 0x81, 0x02, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x05, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x25, 0x80, 0x01, 0x3A, 0xB0, 0xB3 };
Serial1.write(changeOpMode, sizeof(changeOpMode));
Serial1.end();
delay(1000);
// Reopen connection at new baud rate
Serial1.begin(9600);
}
void loop() { // run over and over
if (Serial1.available()) {
Serial.write(Serial1.read());
}
if (Serial.available()) {
Serial1.write(Serial.read());
}
}
Is 1000ms the minimum delay or is that the only value you tried?
It was all I tried. Narrowed it down a bit... 50 did not work, 60 did
Thanks... lets say 100ms seems safe then.
Do you have an idea of what the API signature will look like? I think @rwaldron had expressed a preference for a second call to serialConfig like serialConfig({baud:9600}). The Tessel crew uses serialBaud(9600). I'm indifferent. I'm just curious because I will be mimicking it in tessel-io and imp-io.
I'd prefer serialBaud(9600) out of those 2 options and in the documentation indicating that it's for updating the baud rate of a serial object that is already configured. I should have probably kept baud out of the configuration in Firmata (Arduino). Would have probably scaled better to non-Arduino platforms.
Would have probably scaled better to non-Arduino platforms.
It's exactly the right thing for imp-io and tessel-io so I'm not sure what you mean. When would you not want to set the baud when configuring?
No need to answer, I'm just saying it seems okay to me.
Does either tessel or imp allow changing the baud rate on a configured serial port?
The Tessel 2 has serialBaud(9600) to change an already configured port's baud rate but to be honest I'm not sure what happens behind the scenes. It may close and reopen. I haven't found anything on the Electric Imp where anyone has tried it or talked about it.
@dtex please test: https://github.com/jgautier/firmata/pull/107/files. You will need to pull firmata/arduino and checkout the update-baud branch. Please test with both HW and SW serial with your GPS code.
Rodger dodger, I will get that done today/tonight.
Didn't forget about you. Just haven't been able to get it to work. Still plugging away, trying to confirm it's not something I'm doing wrong.
There was talk in the Arduino dev list recently about adding a method to change the buad rate. Currently it can only be done via the Serial constructor.