Previous posts for this project:

 

 

Introduction

 

This week's post is about getting sensor data from an Arduino in OpenHAB and sending commands from OpenHAB to Arduino. The post covers the different iterations my code went through in order to achieve the desired result, giving some insight on how I tackle a specific problem until the goal is reached.

 

This post is also submitted half a day earlier than usual, so it can still have a shot at winning Dave (Forget Me Not Challenge: Minion of the Week #1), as I won't have time to make elaborate posts in the next to weeks. I'm getting married next week, and let's say my Minion bride would not appreciate it if I dared to take my laptop along on our honeymoon (That's probably the kind of thing one could pull off after ten years of marriage, but perhaps not after one day ... Let's not try to find out.)

 

As doctorcdf pointed out, competition was indeed fierce this week, and this Minion is going all out one last time with this post

 

$(KGrHqUOKpYFJJQ1rC-HBSYGs6rljg~~60_35.JPG

ebay.com

 

Let's go!

 

Arduino to OpenHAB

 

Static values

 

In this first step, I'm trying to have string of data passed from the Arduino to OpenHAB. Once received in OpenHAB, it can be parsed and the values assigned to the corresponding items.

For this test, having the Arduino send a static string to OpenHAB is sufficient, as the focus is more on the reception and the parsing. In a second step, I'll be sending dynamic values, based on sensor data.

 

Serial data from Arduino to Raspberry Pi

 

First, the data from the Arduino needs to be sent to the Raspberry Pi. To do this, I plugged the Arduino in one of the USB ports of the Pi, after having configured it with the sketch below:

 

int weight = 125;
int temperature = 39;

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.print("weight:");
  Serial.print(weight);
  Serial.print("g_temperature:");
  Serial.print(temperature);
  Serial.println("C;");

  delay(10000);
}



































 

On the Pi, it is possible to verify the serial data is properly received, by listening with minicom:

 

pi@webserver ~ $ sudo minicom -b 9600 -o -D /dev/ttyACM0



































 

The screenshot shows the data from the Arduino is being received.

Screen Shot 2014-08-17 at 18.32.54.png

 

Serial data in OpenHAB

 

Just like with the EnOcean Pi, the OpenHAB "start.sh" script needs to be modified to be able to use this new serial interface.

 

pi@webserver ~ $ sudo nano /opt/openhab/start.sh





























 

... -Dgnu.io.rxtx.SerialPorts=/dev/ttyAMA0:/dev/ttyACM0 ...





























 

It is possible to define multiple serial ports, as long as they are delimited by ":".

 

The next step is to enable the serial binding by ensuring it is present in the addons folder:

 

pi@webserver ~ $ ls -l /opt/openhab/addons/*serial*
-rw-r--r-- 1 root root 10748 Jun 16 02:26 /opt/openhab/addons/org.openhab.binding.serial-1.5.0.jar





























 

Finally, we need an item to bind the data to:

 

String Arduino "Arduino [%s]" (arduino) {serial="/dev/ttyACM0"}





























 

To visualise the data, the item can also be added to the sitemap.

 

With all the necessary modifications done, I restarted OpenHAB and verified the events log:

 

pi@webserver ~ $ less /opt/openhab/logs/events.log
































 

2014-08-17 17:34:17 - Arduino state updated to weight:125g_temperature:39C;
2014-08-17 17:34:27 - Arduino state updated to weight:125g_temperature:39C;
2014-08-17 17:34:37 - Arduino state updated to weight:125g_temperature:39C;
2014-08-17 17:34:47 - Arduino state updated to weight:125g_temperature:39C;
2014-08-17 17:34:57 - Arduino state updated to weight:125g_temperature:39C;


































 

Data is coming in! Great!

 

Parsing serial data

 

Two additional items were created to assign the parsed data to:

 

String Arduino_weight "Weight [%s]"
String Arduino_temperature "Temperature [%s]"

































The Arduino string is parsed with a rule which then updates the weight and temperature items:

 

rule "Arduino"
 when 
      Item Arduino received update
 then
      var String ArduinoUpdate = Arduino.state.toString.trim

      var int weightStartsOn = ArduinoUpdate.indexOf("weight:") + "weight:".length
      var String weight = ArduinoUpdate.mid(weightStartsOn, ArduinoUpdate.indexOf('_')-weightStartsOn)

      Arduino_weight.postUpdate(weight)

      var int temperatureStartsOn = ArduinoUpdate.indexOf("temperature:") + "temperature:".length
      var String temperature = ArduinoUpdate.mid(temperatureStartsOn, ArduinoUpdate.indexOf(';')-temperatureStartsOn)

      Arduino_temperature.postUpdate(temperature)
end

































 

Checking the events log again, we can now see the weight and temperature being updated as well:

 

2014-08-17 18:47:58 - Arduino state updated to weight:125g_temperature:39C;
2014-08-17 18:47:58 - Arduino_weight state updated to 125g
2014-08-17 18:47:59 - Arduino_temperature state updated to 39C
































 

A quick look in OpenHAB shows the full string and the parsed items:

Screen Shot 2014-08-17 at 20.45.14.png

 

Dynamic values

 

With the parsing of static data working, it was time to move to dynamic data.

 

For this test, I connected potentiometers to two different analog inputs of the Arduino, in order to simulate sensor data.

To make it more visual, I also connected two LEDs.

 

The setup used is as follows:

Untitled Sketch_bb.pngIMG_4450.JPG

 

In the Arduino sketch, two sensors are simulated:

  • a weight sensor ranging from 0-250gr
  • a temperature sensor ranging from 0-50°C

 

These are just test values to demonstrate the functionality until the real sensors arrive and are hooked up.

 

The sensor data will only be transmitted if one of the two values changes. Later on, this could be fine tuned even more by only sending the changed data.

 

const int weightSensorPin = A0;
const int temperatureSensorPin = A1;

int previousWeightSensorValue = 0;
int previousTemperatureSensorValue = 0;
int currentWeightSensorValue = 0;
int currentTemperatureSensorValue = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  currentWeightSensorValue = analogRead(weightSensorPin);
  currentTemperatureSensorValue = analogRead(temperatureSensorPin);

  currentWeightSensorValue = map(currentWeightSensorValue, 0, 1023, 0, 250); // simulate 0-250g
  currentTemperatureSensorValue = map(currentTemperatureSensorValue, 0, 1023, 0, 50); // simulate 0-50°C

  if(currentWeightSensorValue != previousWeightSensorValue || currentTemperatureSensorValue != previousTemperatureSensorValue) {
    Serial.print("weight:");
    Serial.print(currentWeightSensorValue);
    Serial.print("g_temperature:");
    Serial.print(currentTemperatureSensorValue);
    Serial.println("C;");

    previousWeightSensorValue = currentWeightSensorValue;
    previousTemperatureSensorValue = currentTemperatureSensorValue;
  }

  delay(1000);
}


























 

 

I've made my very first video montage, specially for this blog post! I learned how to record my screen, create a picture-in-picture and how to add a title!

I manually tried to sync the two videos, and managed to get very close. Perhaps someone has additional tips on how to do this more accurately? (I'm using iMovie on Mac)

 

Anyway, here's the fancy demonstration:

 

 

 

Converting

 

In the above steps, the data was parsed as a string of text. In order to be able to do calculations, these need to be converted to numbers. To do this, I slightly modified the rule and the items.

 

The rule has been updated to:

  • drop the unit which was passed in the string, to only keep the numeric data
  • create a new variable which converts the String data to Double

 

rule "Arduino"
 when 
       Item Arduino received update
 then
      var String ArduinoUpdate = Arduino.state.toString.trim

      var int weightStartsOn = ArduinoUpdate.indexOf("weight:") + "weight:".length
      var String weight = ArduinoUpdate.mid(weightStartsOn, ArduinoUpdate.indexOf('g_')-weightStartsOn)
      var Double weightDouble = new Double(weight)

      Arduino_weight.postUpdate(weightDouble)

      var int temperatureStartsOn = ArduinoUpdate.indexOf("temperature:") + "temperature:".length
      var String temperature = ArduinoUpdate.mid(temperatureStartsOn, ArduinoUpdate.indexOf('C;')-temperatureStartsOn)
      var Double temperatureDouble = new Double(temperature)

      Arduino_temperature.postUpdate(temperatureDouble)
end





 

Then, I updated the items to have numeric data instead of a string, like so:

 

Number Arduino_weight "Food quantity [%.1f gr]" <bowl> (Dispenser_Chart)
NumberArduino_temperature"Water temperature [%.1f °C]" <temperature> (Dispenser_Chart)





 

Et voila. The data can now be used for calculations, charts, etc ...

 

2014-08-24 09:00:42 - Arduino_weight state updated to 57.0
2014-08-24 09:00:43 - Arduino_weight state updated to 180.0
2014-08-24 09:00:50 - Arduino_weight state updated to 73.0
2014-08-24 09:01:02 - Arduino_temperature state updated to 49.0
2014-08-24 09:01:02 - Arduino_temperature state updated to 8.0
2014-08-24 09:01:03 - Arduino_temperature state updated to 22.0





 

OpenHAB to Arduino

 

Time to do it the other way around.

 

In the first part of this blog post, the Arduino was sending data to OpenHAB, now OpenHAB will send data to the Arduino!

 

Arduino sketch

 

First, I modified my previous Arduino sketch to listen for incoming serial messages, in addition to what it was already doing.

 

I discovered  function called "SerialEvent" which is automatically executed at the end of every loop. Because of that, it is important to reduce the delays in the loop to a minimum, as this will delay the processing of the incoming serial messages. You can find more on SerialEvent here: Arduino - SerialEvent

 

My SerialEvent call looks like this:

 

String inputString = "";
boolean stringComplete = false;

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    inputString += inChar;

    if (inChar == '\n') {
      stringComplete = true;
    }
  }
  if(inputString == "light=OFF"){
    digitalWrite(13, LOW);
  }
  else if (inputString == "light=ON"){
    digitalWrite(13, HIGH);
  }
  inputString = "";
  stringComplete = false;
}










 

In short, it will expect incoming messages equal to "light=ON" or "light=OFF" and update the status of the onboard LED accordingly.

 

OpenHAB rule

 

In OpenHAB, I defined an item called "Arduino" earlier, making use of the serial binding. This same item can be used to send data back to the Arduino, via the same serial binding.

I added an additional switch, which is meant to turn a light on or off in order to increase visibility in the Pi camera.

 

All that is needed after that is a rule that will send the expected command to the Arduino, based on the switch's state.

 

rule "Video Light"
 when 
     Item camera_light changed
 then
      var state = camera_light.state as OnOffType
      sendCommand (Arduino , "light=" + state)
end










 

With Arduino and camera_light defined as follows in the items:

 

String Arduino "Arduino [%s]" (arduino) {serial="/dev/ttyACM0"}
Switch camera_light "Video lighting" <video>










 

Test

 

With everything set up, it's time for testing!

 

Reorganising the sitemap, this is the current structure I came up with for the food/water dispenser:

Screen Shot 2014-08-23 at 20.57.00.png

It's populated with dummy data generated by the Arduino, until the real sensors are hooked up. The button for the light has been put just above the video, as this seemed most practical.

 

In the video below, I demonstrate the action of turning the light on and off while the camera is filming the onboard LED of the Arduino. Later on, this can trigger an LED strip, white LEDs or even IR LEDs (in combination with Pi NoIR).

 

 

Conclusion

 

In the past weeks, I spent a lot of time exploring OpenHAB. I've played with domains such as data collection, persistence, video, etc ...

I can now start the actual build of the project, as the software side mechanisms have been figured out and found to be working!

 

Some blog posts have been prepared to be published during my absence in the coming two weeks. The focus will gradually be shifting to the hardware side of the project.

 

Until next time!