<< Summary

Raspberry PI reads data from Arduino, in Java Raspberry PI

As the Arduino is a real-time processor, and as the Raspberry PI is not, it could make some sense to have both those guys connected to each other.

Description:
In this example, we will have the Arduino to read analog data from a light-sensor (photo resistor), and send those values to the Raspberry PI, through a USB Serial port.

The Arduino sketch


  /*
   * Reads a light-resistor (pin A0).
   * See circuit in the book, p63.
   * "Getting started with Arduino"
   * Generates NMEA-like messages, emitted on the Serial port
   * A Raspberry PI is at the other end of the serial cable.
   */
  void setup()
  {
    Serial.begin(9600);
  }

  int val      = 0, 
      previous = 0;

  const String PREFIX = "OS";  // Device Prefix
  const String ID     = "MSG"; // Sentence ID

  void loop()
  {
    val = analogRead(A0);
    if (val != previous)
    {
      String payload = "LR," + String(val); // LR: Light Resistor
      String nmea = generateNMEAString(payload, PREFIX, ID);
      Serial.println(nmea);
    }
    previous = val;
    delay(250);
  }

  int checksum(String s)
  {
    int cs = 0;
    int len = s.length() + 1; // Yes, +1
    char ca[len];
    s.toCharArray(ca, len);
    for (int i=0; i<len; i++)
      cs ^= ca[i]; // XOR
    return cs;
  }

  String generateNMEAString(String payload, String prefix, String id)
  {
    String nmea = "";
    if (prefix.length() != 2)
      return nmea; // ("Bad prefix [" + prefix + "], must be 2 character long.");
    if (id.length() != 3)
      return nmea; // ("Bad ID [" + id + "], must be 3 character long.");
    nmea = prefix + id + "," + payload;
    int cs = checksum(nmea);
    String cks = String(cs, HEX);
    cks.toUpperCase();
    if (cks.length() < 2) // lpad '0'
      cks = "0" + cks;
    nmea += ("*" + cks);  // *00
    return "$" + nmea;    // Prefixed with $
  }

        
As you can see in the loop method, the photo resistor value is read from pin A0 every 250ms, and sent on the serial port if the value is different from the one previously read, in an NMEA-like format.

Validating the received data

In order to make sure there is no data alteration between the Arduino and the Raspberry PI, we use an NMEA-like protocol, with a checksum.
The idea is not to be burdened with invalid sentences, that would have been damaged during the transport through the serial port.
This way, the receiver of the data can tell if they are valid or not, before parsing them. In the sketch above, this is what the checksum and generateNMEAString are for.
Example:

 $OSMSG,LR,178*65
 || |   |     |
 || |   |     Checksum
 || |   Message
 || Sentence ID
 |Device prefix
 $ 
      

The Java code on the Raspberry PI

It's all about resading the right serial port. Here, it is /dev/ttyACM0.
See in the script named arduino:

 JAVA_OPTIONS=""
 JAVA_OPTIONS="-Dserial.port=/dev/ttyACM0"
 sudo java $JAVA_OPTIONS -cp $CP arduino.raspberrypi.SerialReader

      
The main method of the arduino.raspberrypi.SerialReader.java class opens the serial port, and creates a serial listener that will take care of displaying the valid sentences received from trhe Arduino.

$OSMSG,LR,35*5D
$OSMSG,LR,27*5E
$OSMSG,LR,31*59
$OSMSG,LR,27*5E
$OSMSG,LR,33*5B
$OSMSG,L]
        Oops! Invalid String [R,27*5E
$OSMSG,LR,31*59
$OSMSG,LR,27*5E
$OSMSG,LR,32*5A
$OSMSG,LR,28*51
$OSMSG,LR,32*5A
$OSM]
        Oops! Invalid String [SG,LR,27*5E
$OSMSG,LR,32*5A
$OSMSG,LR,28*51
$OSMSG,LR,32*5A
$OSMSG,LR,28*51
$OSMSG,LR,32*5A
$OSMS]
        Oops! Invalid String [G,LR,27*5E
$OSMSG,LR,32*5A
$OSMSG,LR,28*51
$OSMSG,LR,32*5A
$OSMSG,LR,28*51
$OSMSG,LR,32*5A
$OSMS]
        Oops! Invalid String [G,LR,28*51
$OSMSG,LR,32*5A
$OSMSG,LR,28*51

      

The NMEA sentences arrive one by one, they are parsed if valid (notice the invalid ones) to extract the value we are interested in.

Wiring

The only wiring on the the Raspberry PI is the USB connection with the Arduino.
On the Arduino:

Click to enlarge


Oliv did it