<< Summary

Raspberry PI reads and writes data from Arduino, in Java Raspberry PI

This project is elaborated on top of the Raspberry PI reads data from Arduino. You should check it out first is case you've not done it yet. It gives details and explanations will will not repeat here.

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.
In addition to the previous project (Raspberry PI reads data from Arduino), we also have on the Arduino a Light Emitting Diode (led) that goes on if the value read from the light sensor drops below a certain threshold (40 by default, see the sketch).
The user can override this behavior from the Raspberry PI: if the Raspberry PI sends a '0' on the serial port, the led will go off. Any other character sent on the serial channel (like '1') will turn it on.
See in the sketch the code higlighted in bold in the loop method.
The intend here is to show how to use the same serial channel to read and write data. Data are here exchanged both ways between the Raspberry PI and the Arduino.

The Arduino sketch


  /*
   * Uses the Serial port to communicate with the Raspberry PI
   * Read from the Serial port
   * Write to the Serial port
   *
   * Send '0' to turn the led off.
   * Anything else will turn it on.
   *
   * One led on pin 13. Grounded with a 10k resistor
   * One photo resistor on pin A0.
   *
   * The led goes on when the photo-resistor goes below 40 (THRESHOLD).
   * It can be overriden by an input from the serial port 0 (off), or 1 (on).
   */
  const int LED = 13;
  const int THRESHOLD = 40;

  void setup()
  {
    pinMode(LED, OUTPUT);
    digitalWrite(LED, LOW); // turn it off by default
    Serial.begin(9600);
  }

  int val = 0, 
      previous = 0;
  const String PREFIX =  "OS"; // Device Prefix
  const String ID     = "MSG"; // Sentence ID

  void loop()
  {
    if (Serial.available())  
    {
      int fromRPI = Serial.read(); // Read one character
      fromRPI -= '0'; // Possibly comes from the key-pad connected to the RPi
      if (fromRPI == 0)
        digitalWrite(LED, LOW);
      else
        digitalWrite(LED, HIGH);
    }
    
    val = analogRead(A0);
    
    if (abs(previous - val) > 3)
    {
      String payload = "LR," + String(val); // LR: Light Resistor
      String nmea = generateNMEAString(payload, PREFIX, ID);
      Serial.println(nmea);
      
      if (val < THRESHOLD)
        digitalWrite(LED, HIGH);
      else
        digitalWrite(LED, LOW);
      previous = val;
    }
  }

  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);  // *FF
    return "$" + nmea;    // Prefixed with $
  }

        
Copy to Clipboard
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 new value is different from the one previously read by more that 3 units, in an NMEA-like format.

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.write:

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

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

  Serial Communication.
   ... connect using settings: 9600, N, 8, 1.
   ... data received on serial port should be displayed below.
  Hit 'Q' to quit.
  Hit 'V' to toggle verbose on/off.
  Hit [return] when ready to start.

  Opening port [/dev/ttyACM0:9600]
  Port is opened.
  So? >   Oops! Invalid String [$O5B
  $OSMSG,LR,29*50
  $OSMSG,LR,33*5B
  $OSMSG,LR,29*50
  $OSMSG,LR,35*5D
  $OSMSG,LR,29*50
  $ÿ34*5C
  $OSMSG,LR,29*50
  $OSMSG,LR,33*5B
  $OSMSG,LR,29*50
  $OSMSG,LR,33*5B
  $OSMSG,LR,29*50
  $OSMSG,LR,35*5D
  $OSMSG,LR,29*50
  $ÿ]
          Oops! Invalid String [$OSMSG,LR,30]
          Oops! Invalid String [*58
  $OSMSG,LR,34*5C
  $OSMSG,LR,28*51
  $OSMSG,LR,32*5A

  $OS]
  v
  So? > 1
          Writing [1] to the serial port...
  So? > 0
          Writing [0] to the serial port...
  So? > q
  Bye!

      

The NMEA sentences arrive one by one, they are parsed if valid, 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