Most likely you're seeing the delayed startup of the Arduino. When you perform the open of the serial device per Tcl the Arduino is first reset, then waits about 2 seconds in its boot loader, then starts up and executes your program from its flashmemory. On the Tcl side use a "after 2000" right after the open, then proceed to normal communication. This might fix your issue.
HTH,
Christian
Hi All,arduino starts to respond normally.
My Tcl/Tk code for serial communication with Arduino is working but with a strange behavior.
I send a message through the serial port that calls a function in arduino and returns a message. The problem is that, at the beginning, I need to send the command 2 or 3 times before arduino start to respond. After the second or third attempt, the
The Tcl/Tk code is:
set serial_device [exec ls {*}[glob /dev/ttyACM*]]
set baud 9600
set parity n
set data_bit 8
set stop_bit 1
set id_serial_port [open $serial_device r+]
chan configure $id_serial_port -mode "$baud,$parity,$data_bit,$stop_bit" chan configure $id_serial_port -buffering line
chan configure $id_serial_port -blocking 0
chan configure $id_serial_port -encoding ascii
#To set the procedure (receiveReadout) to be called when serial port is readable
chan event $id_serial_port readable [list [self] receiveReadout $id_serial_port]
And the procedure receiveReadout
proc receiveReadout { id_serial_port } {
if { [eof $id_serial_port ] } {
puts "Closing $id_serial_port"
catch { close $id_serial_port }
return
}
#To read the response from Arduino
set serial_return [chan gets $id_serial_port]
}
And send the command to check the connection:
chan puts $id_serial_port checkConnection
And the Arduino code is: (adapted from http://www.gammon.com.au/forum/?id=11425)
void setup() {
Serial.begin(9600);
Serial.flush();
}
void processIncomingByte (const byte inByte) {
static char input_line[MAX_INPUT];
static unsigned int input_pos = 0;
switch (inByte)
{
case '\n': // end of text
input_line[input_pos] = 0; // terminating null byte
// terminator reached! process input_line here ...
process_data (input_line);
// reset buffer for next time
input_pos = 0;
break;
case '\r': // discard carriage return
break;
default:
// keep adding if not full ... allow for terminating null byte
if (input_pos < (MAX_INPUT - 1))
input_line[input_pos++] = inByte;
break;
} // end of switch
}// end of processIncomingByte
//Process_data to process incoming serial data after a terminator received void process_data (char *data) {
cmd = strtok(data, ";");
if ( (strcmp(cmd, "checkConnection") == 0) || (strcmp(cmd, "checkconnection") == 0) ) {
transaction_id = strtok(NULL, ";");
checkConnection( transaction_id );
} else {
Serial.print("#unknown command: ");
Serial.println(cmd);
} // end of if
}
//Send message "ACK" to to confirm the connection with the Arduino
void checkConnection(char *transaction_id ) {
Serial.print("ACK;");
Serial.println(transaction_id);
}
void loop() {
// if serial data available, process it
while (Serial.available () > 0)
processIncomingByte (Serial.read());
}
But as I said, to start receiving Arduino messages I need to send this command 2 or 3 times.
Please, any tips on how to resolve this?
Thank you,
Info Libera
Most likely you're seeing the delayed startup of the Arduino. When you perform the open of the serial device per Tcl the Arduino is first reset, then waits about 2 seconds in its boot loader, then starts up and executes your program from its flashmemory. On the Tcl side use a "after 2000" right after the open, then proceed to normal communication. This might fix your issue.
HTH,
Christian
Alternitively, use a "handshake protocol": my Bike Computer program sends a startup message:
Serial.println("BikeComputer 0.0");
in setup(), and then
does:
Serial.print(">>");
Serial.flush();
And after processing a command, it does:
Serial.print(">>");
Serial.flush();
The Tcl code waits for the prompt before sending a command.
That is, the Tcl code waits for the Arduino to get itself up to speed before asking it to do things.
At Wed, 25 Aug 2021 16:10:42 -0700 (PDT) Christian Werner <undro...@gmail.com> wrote:
--
Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
Deepwoods Software -- Custom Software Services
http://www.deepsoft.com/ -- Linux Administration Services hel...@deepsoft.com -- Webhosting Services
* Info Libera <liberi...@gmail.com>
| The Tcl/Tk code is:
| set serial_device [exec ls {*}[glob /dev/ttyACM*]]
What is this 'exec ls' supposed to achieve?
# use first serial device available or let glob err out if there are none set serial_device [lindex [glob /dev/ttyACM*] 0]Sorry for having summarized the text of the message too much so the text doesn't get too long.
| chan puts $id_serial_port checkConnection
Note that you don't send any ";" here...
| //Process_data to process incoming serial data after a terminator received | void process_data (char *data) {
| cmd = strtok(data, ";");
...yet you look for one here. If there is no ";" in the line received, strtok() will return NULL, and hence the strcmp() in the next line has undefined behaviour (crash, reboot arduino, send the ACK, whatever).
| if ( (strcmp(cmd, "checkConnection") == 0) || (strcmp(cmd, "checkconnection") == 0) ) {
| transaction_id = strtok(NULL, ";");
| checkConnection( transaction_id );
HTH
R'
Em quinta-feira, 26 de agosto de 2021 s 06:27:28 UTC-3, Ralf Fassel escreveu:
* Info Libera <liberi...@gmail.com>Dear Ralf,
| The Tcl/Tk code is:
| set serial_device [exec ls {*}[glob /dev/ttyACM*]]
What is this 'exec ls' supposed to achieve?
I used exec ls to list the device file of type tty/ACM corresponding
to the Arduino board.
It was a way to automate the device location. But it works if only
the board Arduino creates an ACM serial device.
Info Libera <liberi...@gmail.com> wrote:
Em quinta-feira, 26 de agosto de 2021 às 06:27:28 UTC-3, Ralf Fassel escreveu:
* Info Libera <liberi...@gmail.com>Dear Ralf,
| The Tcl/Tk code is:
| set serial_device [exec ls {*}[glob /dev/ttyACM*]]
What is this 'exec ls' supposed to achieve?
I used exec ls to list the device file of type tty/ACM corresponding
to the Arduino board.
It was a way to automate the device location. But it works if onlyYes, and you used Tcl's built in glob to first find the device files, passing the resulting filenames as parameters to ls, only to get them
the board Arduino creates an ACM serial device.
back from ls as ls's output.
[glob /dev/ttyACM*] would have done the exact same as your circuitus
exec ls call, without needing to fork an ls process to list filenames
that ls was given by Tcl's built in glob.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 296 |
Nodes: | 16 (2 / 14) |
Uptime: | 81:56:25 |
Calls: | 6,658 |
Calls today: | 4 |
Files: | 12,203 |
Messages: | 5,333,417 |
Posted today: | 1 |