Arduino to PC Serial Communication Challenges

MRL runs on a JVM and can communication to the Arduino micro-controller through a serial port.  MRL controls the Arduino through a serial protocol.  

MRL to Arduino uses a 3 byte command set

msg[0] = METHOD
msg[1] = PARAM1
msg[2] = PARAM2

The first byte is indicates which method to execute on the Arduino.  For example when msg[0] == 0 then the Arduino should do a digitalWrite .  When msg[0] == 2 the Arduino will do a analogWrite .

The Arduino can send information back to the MRL.  It has a 4 byte protocol

msg[0] = PIN
msg[1] = METHOD
msg[2] = HIGHBYTE
msg[3] = LOWBYTE

When the Arduino is reading data from an analog pin, it will send analogRead value back in this return message.  Since analogReads can be a value between 0 - 1023 the data will need 2 bytes (HIGHBYTE & LOWBYTE)

All of this works very well, until the serial messages get out of sync.  Typically this error is caused by electrical noise on the system.  The really bad part, is that once the data stream becomes out of sync, it (rarely) gets back in sync.

There are a couple of strategies in order to correct this issue.  There is the CRC (cyclical redundancy check) - where a number is computed from the data bytes and sent in another byte.  The other side does the same calculation and if the calculated value equals the byte sent, all is good.  If not, then we know we have garbage.

I chose a simpler implementation.  At the beginning of each message I send a MAGIC_NUMBER.  I chose the value 170 ( 10101010 in binary) which I thought would be one of the most fragile (electrically) to start each message.  Now if MRL or the Arduino do not get the MAGIC_NUMBER at the beginning they throw the message away.  This will not guarantee your data is not corrupted, however, when there is corruption it will attempt to recover by throwing everything out, until it finds the MAGIC_NUMBER again.


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
pauloSouza's picture

Arduino Serial Comm

Hey GroG,

I have a lot of questions:

1- Can I use the SensorMonitor with a Arduino Mega? How can I reference more than 19 pins?

2- How can I read a pin status (in Python)? I didn't see a digitalRead() neither an AnalogicRead(). How could I read serial data sent by the arduino?

3- Is it possible in MRL use more than one sensor with I2C bus?

Thanks for your time with my dummy questions.

Paulo

GroG's picture

Hi pauloSouza,1. The sensor

Hi pauloSouza,

1. The sensor monitor can be used with the Arduino Mega.  You would need to reference the programmatically.  Do you want to view the values like a oscope or trigger an event?

2. If you are using MRLComm.ino  - then reading is done registering for PublishPin events

I don't have an Arduino at the moment but this script might get you there...

from time import sleep
from org.myrobotlab.service import Arduino
 
# variables dependent on your setup
boardType = "atmega2560"  # atmega168 | atmega328p | atmega2560 | atmega1280 | atmega32u4
comPort = "COM9"
readAnalogPin = 17
readDigitalPin = 13
 
arduino = Runtime.createAndStart("arduino","Arduino")
arduino.connect(comPort)
 
 
def input():
    # print 'python object is ', msg_arduino_publishPin
    print 'python data is ', msg_arduino_publishPin.data[0]
 
 
arduino.addListener("publishPin", python.name, "publishPin"); 
 
# start the analog pin sample to display
# in the oscope
arduino.analogReadPollingStart(readAnalogPin)
 
3. Yes MRL can use more than one I2C device on the bus - but there needs to be some form of driver to make the data meaningul.