I try to communicate from a Java process to the M4 and a daisy chained Mega. After a couple of sends the input on the M4 seems to get garbled (nonsense) and if I try to re-load code via the Arduino IDE the IDE responds with the dreaded M4 Sketch Stop (or Start) failed. I started out with a baud rate of 115200 and have dropped to 9600, but it doesn't make a difference. I also have had this problem before I chained another Mega. Can data be sent too quick? Should a different setup be done on the port? Does the string handling become a problem? In Java I have created with the help of the GNU rxtx library the following code to communicate with the M4 from the i.MX6: Code: private static SerialPort openPort(CommPortIdentifier identifier, int block) throws PortInUseException { if (identifier.getPortType() == CommPortIdentifier.PORT_SERIAL) { SerialPort port = (SerialPort)identifier.open(SerialComm.class.getName(), block); try { port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); // port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); port.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT); port.setOutputBufferSize(3 * 80); port.setInputBufferSize(3 * 80); } catch (UnsupportedCommOperationException e) { throw new AssertionError(String.format("Cannot configure serial port %s", identifier.getName())); } return port; } throw new IllegalArgumentException(String.format("Port %s is not a serial port", identifier.getName())); } public void println(String identifier, String value) { try { if (writeLock.tryLock(50, TimeUnit.MILLISECONDS)) { try { System.out.println(identifier + ":" + value); out.write(identifier.getBytes(StandardCharsets.US_ASCII)); out.write(':'); out.write(value.getBytes(StandardCharsets.US_ASCII)); out.write('\r'); out.flush(); } finally { writeLock.unlock(); } } } catch (Exception e) { e.printStackTrace(); } } The lock and the System.out are attempts at debugging.... On the M4 I read the code in the following way: Code: void loop() { const unsigned long now = millis(); static String imxInput; static String megaInput; if (checkSerial(imxSerial, imxInput)) { megaSerial.println(imxInput); imxSerial.println(imxInput); dispatchCommand(imxInput); imxInput = ""; } if (checkSerial(megaSerial, megaInput)) { imxSerial.println(megaInput); megaInput = ""; } for (Module **mpp = modules; *mpp; mpp++) { (*mpp)->loop(now, imxSerial); } } void dispatchCommand(String command) { int index = command.indexOf(':'); if (index > 0) { String id = command.substring(0, index); String data = command.substring(index + 1); for (Module **mpp = modules; *mpp; mpp++) { if ((*mpp)->isModule(id)) { (*mpp)->processCommand(data); break; } } } } bool checkSerial(Stream& stream, String& string) { int incoming = stream.read(); if (incoming > 0 && incoming != '\n' && incoming != '\r') { string += (char)incoming; } return incoming == '\r'; } On the Arduino I have the following: Code: HardwareSerial& neoSerial = Serial1; void setup() { neoSerial.begin(57600); Serial.begin(9600); for (Module **mpp = modules; *mpp; mpp++) { (*mpp)->begin(); } } void loop() { const unsigned long now = millis(); static String neoInput(80); if (checkSerial(neoSerial, neoInput)) { dispatchCommand(neoInput); neoInput = ""; } for (Module **mpp = modules; *mpp; mpp++) { (*mpp)->loop(now, neoSerial); } } void dispatchCommand(String command) { Serial.print("dispatch command "); Serial.println(command); int index = command.indexOf(':'); if (index > 0) { String id = command.substring(0, index); String data = command.substring(index + 1); for (Module **mpp = modules; *mpp; mpp++) { if ((*mpp)->isModule(id)) { (*mpp)->processCommand(data); break; } } } } bool checkSerial(Stream& stream, String& string) { int incoming = stream.read(); if (incoming > 0 && incoming != '\n' && incoming != '\r') { string += (char)incoming; } return incoming == '\r'; }
Between what devices starts the garbling? mega-m4? m4-a9? What if you use minicom -D /dev/ttyMCC to monitor the m4-a9 communication?
Yes, I have a level shifter in between. In my test I have the LCD connected to the Mega, and after a few commands for the LCD the data received is incorrect. In my tests with minicom I did not encounter a problem. I'll add some debugging tomorrow.
@waltervl I am fairly sure it is the Neo M4 crashing. Just tried some quick things and the Neo M4 seems not to keep up, and then fails to work as I get a stop or start failed error. @Andrea Rovai, is my assumption correct?
I tried to keep reading the serial input faster, but it doesn't help. By faster I meant, as long as there is input: Code: QueueArray<String> commands; while(checkSerial(imxSerial, imxInput)) { commands.enqueue(imxInput); imxInput = ""; } if (!commands.isEmpty()) { String command = commands.dequeue(); megaSerial.println(command); imxSerial.println(command); dispatchCommand(command); } This is the output on the Mega serial showing that it fairly quickly goes wrong (already after the first three): LCD received: 'PRINTAT0,0:i = 1 ' LCD received: 'PRINTAT0,0:i = 2 ' LCD received: 'PRINTAT0,0:i = 3 LCDLCDLCDRINTAT0,0:i = 24 RINTAT0,0:i = 25 ' LCD received: 'PRINTAT0,0:i = 26 ' LCD received: 'PRINTAT0,0:i = 27 ' LCD received: 'PRINTAT0,0:i = 34 ' LCD received: 'PRINTAT0,0:i = 50 LCD' LCD received: 'PRINTAT0,0:i = 66 ' LCD received: 'PRINTAT0,0:i = 67 ' LCD received: 'PRINTAT0,0:i = 68 LCDLCDRINTAT0,0:i = 74 LCD:RINTAT0,0:i = 82 ' LCD received: 'PRINTAT0,0:i = 86 ' LCD received: 'PRINTAT0,0:i = 87 LCDRINTAT0,0:i = 96 LCT0,0:i = 127 ' Edit: I think this is a flow control problem. However, I do not know if Arduino or Neo provides any flow control. I haven't found examples that do.
When I was working on my tutorial about the webpage control I saw also that after the first reading of lines from /dev/ttyMCC the output was not correct but it stayed fine further on. If you think it is flow control perhaps put some small delays (couple of ms) in between println messages to see if it stabilises the output. If it does we can work on that further.
I can't see how you declared/defined megaSerial and imxSerial but normally they are named Serial and Serial0. What if you just use these names? Perhaps your way of declaring changes some hidden settings.
I've done some experimenting and the communication is ok if I stay above 75ms between each message. This confirms to me that it is a flow control problem. However, I do not know if the Neo implements flow control signals with RTS/CTS. At least, configuring the ports with a RTS/CTS flow didn't seem to help. Who has a more in depth explanation and, hopefully, a better solution than 'just wait a few milliseconds'...? Code: lcd.clear(); Runnable command = () -> { lcd.print(0, 0, "Message " + (++i)); }; executor.scheduleAtFixedRate(command, 1, 75, TimeUnit.MILLISECONDS); @waltervl, the megaSerial and imxSerial are defined as follows: Code: HardwareSerial& imxSerial = Serial; HardwareSerial& megaSerial = Serial0;
Yes, I think I have to switch to XON/XOFF flow control. I have done a test with a delayed send queue, but I saw that even with the delay an error occurred after a while. Too fragile for my liking. Do you happen know an example of implementing XON/XOFF?