I have a network of 20 Nanos all tied together on a serial bus (with a central 20-input NAND gate and bus drivers on the output). A master Nano sends out a token message and then the addressed remote unit replies. The token message is 4 bytes and reply messages can be 4-7 bytes long, with a maximum of 9 messages in one reply. At 9600 baud, a reply with 9 messages (a maximum of 60 bytes) should take 63 msec. To my consternation, it is taking 800 msec.
Here's the code from the responding remote unit. As you can see, the "send data" [S_data()] functions are adjacent lines of code and the S_data() function itself consists of immediately adjacent Serial.write() calls. I expect this code to be in blocking mode for 40-50 msec as the transmit buffer fills and empties, but the whole operation should take maybe 70-80 msec, with a little overhead for the function calls.
case 'K': { // token
if(Serial.read() == UID) { // for this unit?
S_data(T_Util) ;
S_data(T_Utilmax) ;
S_data(T_Utilmin) ;
S_data(T_Bflr) ;
S_data(T_Uflr) ;
S_data(T_Foot) ;
S_data(T_Footmax) ;
S_data(T_Footmin) ;
}
S_done() ; // send "I'm finished" msg
}
break ;
--------------------------------
// ----------- Send an Integer -------------------------
void S_data(byte b) {
Serial.write(0xAA) ; // start
Serial.write("N") ; // data (always an int)
Serial.write(UID) ; // from this unit
Serial.write(b) ; // index to data integer
Serial.write(lowByte(vars[b])) ; // get byte
Serial.write(highByte(vars[b])) ; // get byte
Serial.write(0x04) ; // end of msg
}
// ------------ Send Done Msg ----------------------------
void S_done() {
Serial.write(0xAA) ; // start
Serial.write("D") ; // done msg
Serial.write(UID) ; // from this unit
Serial.write(0x04) ; // end of msg
The result is quite different. I have Mega on the network that watches the serial line and then reports those messages via the IDE serial monitor. Here is what the Mega sees as unit #2 responds to its token:
08:41:22.807 -> --Token-- msg = --====-- 2 (this is a 4-byte message)
08:41:22.900 -> --Integer-- msg from 2 (this is a 7-byte message)
08:41:22.994 -> --Integer-- msg from 2
08:41:23.088 -> --Integer-- msg from 2
08:41:23.182 -> --Integer-- msg from 2
08:41:23.238 -> --Integer-- msg from 2
08:41:23.335 -> --Integer-- msg from 2
08:41:23.428 -> --Integer-- msg from 2
08:41:23.522 -> --Integer-- msg from 2
08:41:23.616 -> --Done-- 2 (this is a 4-byte message from unit #2)
08:41:23.616 -> Msec to Done = 792 (total time from the token msg to the "I'm done" msg)
This is about 90 msec per message, more than 10x the time it should take to transmit 7 bytes. The total time of 792 msec has some variation due to the housekeeping loop in the Mega, as well as the housekeeping loop in the remote unit, both of which take 45-60 msec. So worst case, housekeeping can account for maybe 100 msec.
Where is the extra time? Is it in the Serial library in the IDE or in the UART interface in the chip? Is there a way to stuff bytes into the UART buffer so that they are transmitted as one continuous serial message without 80 msec gaps between bytes?
Even when there is only one reply message from a unit, eg, "done," the typical time from when a remote unit sees its token to when it has the full "done" message on the net is 86 msec, of which only 6 msec is the message transmit time. This means it can take 3-5 seconds to poll all the units, when the theoretical limit is on the order of 0.2 seconds. What the heck?
Dr Quark