how can I improve Arduino connection reliability in MRL?

As frequent shoutboxer know I do not stop  moaning about unreliable Arduino connections at startup. I came up with this improvement but it is also not working as I expected. What could be improved on my connection script?

# try and retry to connect the arduinos
 
def connectArduinos():
 
  left = Runtime.createAndStart("i01.left", "Arduino")
  left.setBoardMega()
  left.connect(leftPort)
  sleep(0.5)
  for i in range(0,2):
    if not left.isConnected():
      left.disconnect()
      sleep(0.5)
      left.connect(leftPort)
      sleep(0.5)
    else:
      break
    
  sleep(1)
 
  right = Runtime.createAndStart("i01.right", "Arduino")
  right.setBoardMega()
  right.connect(rightPort)
  sleep(0.5)
  for i in range(0,2):
  if not right.isConnected():
    right.disconnect()
    sleep(0.5)
    right.connect(rightPort)
    sleep(0.5)
  else:
    break
moz4r's picture

Hi juerg, goal is this worky

Hi juerg, goal is this worky without errors

  left = Runtime.createAndStart("i01.left", "Arduino")
  left.connect(leftPort)
 
what errors you have with it
juerg's picture

hi moz4r you can see the log

hi moz4r

you can see the log and the errors in my latest noworky (I think 16.12.2017)

I looks to me that I am not able to get a correct "connected" state as it tries to reconnect also when it is actually connected and my script should only try to reconnect if it is not already connected?

And the problem remains that in most cases I have to connect manually using the swing gui. Running the message monitor I see sent out version request but no answer from the arduino.

Another issue is that once mrl gets data back from the arduino the messages get interpreted at the wrong position (not with the first byte of the message), leading to wrong length assumptions (as it interpretes one of the message content bytes as the length byte) therefore throwing wrong structure messages. This however looks to resync with time with the proper message start interpretation.

 

calamity's picture

Hi juergOn power up, the

Hi juerg

On power up, the arduino serial output buffer is always filled with some wierd content. If you use the arduino serial monitor, you will see those message as wierd caracter at the begining.

The only way to clear those caracter is to send them, and when it's caugh by MRL, they are not reconized and trigger an error. then the connection process restart and is usually fine.

So it show an error, but there is nothing we can do about it and it's usually of no consequences.

The problem is on the arduino side, and there is nothing we can do other than to get around it

juerg's picture

Hi Calamity I think I can

Hi Calamity

I think I can follow your arguments. It's just things in the buffer of the Arduino and I do not have a problem with that as it syncs after some choking.

However, my initial problem is still there - I sometimes do not get anything from the Arduino when trying to connect. Had another look at the "isConnected" function and I see that it includes the check of having gotten a correct version number from the Arduino - however that does not match my observation that the serial monitor does not show any values received from the Arduino. In addition my code should only retry connection when "isConnected" returns false so there should not be any drop and retry of connection happening?

juerg's picture

I still have problems with my

I still have problems with my Arduino's:

This is the most simple setup I can imagine and my results:

Deleted myrobotlab.log, fresh restart of myrobotlab.jar, version 2671:

i01 = Runtime.createAndStart("i01","InMoov")
 
left = Runtime.createAndStart("i01.left", "Arduino")
left.connect("COM3")
 
right = Runtime.createAndStart("i01.right", "Arduino")
right.connect("COM4")
 
noworky sent 21.12.2017, 11:44
GroG's picture

Ya, Mrl is reporting the

Ya, Mrl is reporting the Arduino is not sending it data - Both Arduino's didn't respond.

11:43:48.499 [i01.left] ERROR c.m.a.Msg [Msg.java:2284] Ack not received
11:43:48.689 [python.interpreter.3] INFO c.m.f.Service [Arduino.java:490] waited 4501 ms for Arduino i01.right to say hello
11:43:48.690 [python.interpreter.3] ERROR c.m.f.Service [Service.java:2056] i01.right error COM4 did not get response from arduino....
11:43:50.501 [i01.left] ERROR c.m.a.Msg [Msg.java:2284] Ack not received

I think your idea of simplifying too is a good one, as it might actually lead to the root cause.  You said this is the simplest script, but it certainly is not.  The simplest script is just connecting to an Arduino, and doing a couple of commands.

arduino = Runtime.start("arduino", "Arduino")
arduino.connect("COM5")

sleep(5)

print(arduino.getBoardInfo())

This is my log after the above connect.

05:57:23.132 [python.interpreter.7] INFO  class org.myrobotlab.service.Serial - setParams 115200 8 1 0
05:57:23.133 [arduino] INFO  c.myrobotlab.framework.Service - arduino info arduino connected to COM5
05:57:23.133 [arduino.serial] INFO  c.myrobotlab.framework.Service - arduino.serial info arduino.serial connected to COM5
05:57:23.135 [COM5.portListener 1] INFO  c.myrobotlab.framework.Service - arduino warn Arduino->MRL error - bad magic number 10 - 1 rx errors
05:57:23.136 [COM5.portListener 1] INFO  c.myrobotlab.framework.Service - arduino warn Arduino->MRL error - bad magic number 19 - 2 rx errors
05:57:23.137 [COM5.portListener 1] INFO  c.myrobotlab.framework.Service - arduino warn Arduino->MRL error - bad magic number 8 - 3 rx errors
05:57:23.138 [COM5.portListener 1] INFO  c.myrobotlab.framework.Service - arduino warn Arduino->MRL error - bad magic number 0 - 4 rx errors
05:57:23.138 [COM5.portListener 1] INFO  c.myrobotlab.framework.Service - arduino warn Arduino->MRL error - bad magic number 12 - 5 rx errors
05:57:23.139 [python.interpreter.7] WARN  c.myrobotlab.framework.Service - already have active task "getBoardInfo"
05:57:23.141 [python.interpreter.7] INFO  c.myrobotlab.framework.Service - waiting for boardInfo lock..........
05:57:23.159 [AWT-EventQueue-0] INFO  c.myrobotlab.swing.ServiceGui - onConnect - COM5
05:57:23.181 [AWT-EventQueue-0] INFO  c.myrobotlab.swing.ServiceGui - onConnect - COM5
05:57:24.184 [python.interpreter.7] INFO  c.myrobotlab.framework.Service - waited 1043 ms for Arduino arduino to say hello
05:57:24.187 [python.interpreter.7] ERROR c.myrobotlab.framework.Service - arduino error MrlComm.ino responded with version 56 expected version is 57
05:57:27.137 [arduino] ERROR class org.myrobotlab.arduino.Msg - Ack not received
 
As you can see I got the buffered garbage errors too - but it quickly cleans of the serial, and gets a version.  In my case I don't have the latest MrlComm.
 
Uploaded the latest release and I get the following...
 
06:04:31.374 [arduino] INFO  c.myrobotlab.framework.Service - arduino.serial info connect to port COM5 115200|8|1|0
06:04:31.378 [arduino] INFO  class org.myrobotlab.serial.Port - here
06:04:31.379 [arduino] INFO  c.myrobotlab.framework.Service - arduino.serial info arduino.serial publishConnect COM5
06:04:31.379 [COM5.portListener 2] INFO  class org.myrobotlab.serial.Port - listening on port COM5
06:04:31.379 [arduino] INFO  class org.myrobotlab.service.Serial - setParams 115200 8 1 0
06:04:31.380 [arduino.serial] INFO  c.myrobotlab.framework.Service - arduino.serial info arduino.serial connected to COM5
06:04:31.384 [arduino] INFO  c.myrobotlab.framework.Service - waiting for boardInfo lock..........
06:04:31.408 [AWT-EventQueue-0] INFO  c.myrobotlab.swing.ServiceGui - onConnect - COM5
06:04:32.431 [COM5.portListener 2] ERROR c.myrobotlab.framework.Service - 9��

06:04:32.432 [arduino] INFO  c.myrobotlab.framework.Service - waited 1047 ms for Arduino arduino to say hello
06:04:32.434 [arduino] INFO  c.myrobotlab.framework.Service - arduino info arduino.serial connected on COM5 responded version 57 ... goodtimes...
06:04:32.434 [arduino] INFO  c.myrobotlab.framework.Service - arduino info arduino connected to COM5
06:04:32.434 [arduino] WARN  c.myrobotlab.framework.Service - already have active task "getBoardInfo"
06:04:32.498 [AWT-EventQueue-0] INFO  c.myrobotlab.swing.ServiceGui - onConnect - COM5
06:06:55.329 [python] INFO  class org.myrobotlab.service.Python - exec(String) 
print(arduino.getBoardInfo())
 
As you can see, I always get garbage initially in the buffer as well, however after 1047 ms I got a "hello" from Arduino.  And the print(arduino.getVersionInfo()) returns 
 
version 57 load 9 heartbeat 4 sram 927 devices 0
 
I would recommend experimenting with an even more simple script, like the one I used, until the root cause of your issue is resolved.

 

juerg's picture

@Grog, thanks for coming back

@Grog, thanks for coming back on this. Good to know that we have an even simpler script for seeing the problems I sometimes encounter.

Did many tries (always restarting mrl) with COM3 only and I did not encounter any "no ack received" with it.

Added then the second arduino and on the second run it showed the "did not get response for the arduino" again for the COM4 connection.

Sent an noworky again with that result (dec-21-2017, 18:03 swiss time)

Looks like this is a more robust approach anyway - so how do I first start the arduinos and after that add them to the i01 InMoov instance?

Regards, Juerg

GroG's picture

I looked at the

I looked at the noWorky.
COM3 - looks "normal"

Mrl connects, garbage is sent back, but @ 905 ms later .. goodtimes ...

17:52:16.082 [python.interpreter.3] INFO c.m.f.Service [Arduino.java:490]
waited 905 ms for Arduino arduinoL to say hello
COM4 however, "nothing" happens, no garbage, no goodtimes, no nothing..
which alway in the past got down to a hardware issue.
Some things you might consider :

* Is there enough power ?
* How noisy is the power.
* What brand are these Arduino's your using ?
* Will the Monitor open COM4 now ?
* Is this the latest drivers ?
* What drivers are you using ?

From the Mrl side it seems we successfully open the COM4 port..

Hmm, here's a good experiment. Perhaps its wired up such that the connect
is not doing the reset we expect. A way to test that is ""AFTER" COM4 has
been opened (which is the state you left your system in when you sent the
noWorky) - hit reset on the COM4 Arduino ...

If thtat's the case the reset signal on port connect may be not working
properly on your boards.

Let us know how the experiment goes - and of course another noWorky...

juerg's picture

Hi Grog Looks like we are on

Hi Grog
Looks like we are on the right track now. Repeated my arduino script several times (murphy was with me and had them connect like a charm a few times) but then I ran into the "no response" error.

Manually resetting the arduino then startet the messages to be delivered to MRL.

So it looks to be an issue with my arduinos. purchased them from china, so far had no issues with them. they are about 3-4 years old.

The arduinos are powered by usb from my windows laptop and for my trials the laptop was connected to the power. Assume this is not the cause.

Driver - it shows the arduinos in the device manager as Arduino Mega 2560, Driver Provider is Arduino LLC, driver date 24-Nov-15, Version 1.2.3.0

 

GroG's picture

Well, It looks like your

Well,
It looks like your boards are "not to specification" of how they are supposed to handle a port connection. 

It might be beneficial if you read the following link :

The article is about how to "disable" the way a "standard" Arduino behaves.

https://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection 

Perhaps, the connection should be re-evaluated in the future, where Mrl-Java generates a request instead of relying on the hardware to send the mesage.  We did this in the past, but found the port would not open in a predictable time.  The delay varied on different boards.  The result was, the message from mrl-Java, would get lost and we would be in the same state with standard boards.

Having Mrl-Comm send a series of messages on connect appeared to solve this problem, but it relies on the hardware working correctly.

Perhaps a "smarter" way would be for both sides attempt to connect, and sync.  But I don't see any of that happening pre-manticore release.

juerg's picture

Thanks Grog, so I must have

Thanks Grog, so I must have ended up with slightly incompatible Arduinos with the attempt to get the cheapest stuff from whereever!

What I still struggle a bit is the behaviour of my code sequence:

In my loop I do a connect(), then I use isConnected() to decide on a retry.

In the logs I however see that it tries to reconnect albeit it had had a connection. Thought that disconnect() is not clearing out the (old) version information but trying to follow the code (once again - its zig-zagging much too much for me to be able to follow the path confidently) a disconnect shoud set the version to null? At least the comment says so.

So my question remains - how can I see reconnect tries with my script int the log after it had a successful connection with goodtimes?

juerg's picture

tried to come up with this

tried to come up with this script but now I am blocked I assume with the ear in case I run the "softReset" on my Arduino? It starts my Head but not the rest and the log shows "micNotListening"

 
# try and retry to connect the arduinos


def connectArduinos():

  left = Runtime.createAndStart("i01.left", "Arduino")
  left.setBoardMega()

  while True:
    left.connect(leftPort)
    sleep(5)

    if left.isConnected():
      break

    left.softReset()
    left.disconnect()
    sleep(1)

  sleep(1)

  right = Runtime.createAndStart("i01.right", "Arduino")
  right.setBoardMega()

  while True:
    right.connect(rightPort)
    sleep(5)

    if right.isConnected():
      break

    right.softReset()
    right.disconnect()
    sleep(1)

 

juerg's picture

always connecting after softReset()

Was missled in my last post, an AIML issue had caused my script to stop, not calling the softReset() for the Arduinos.

So with my last posted "connectArduinos()" script I see sometimes a few retries but so far I always got finally a connection to both Arduinos with it.

Thanks for all your help