Serial > Arduino button + relay

Hello people, thank you for reading this.
I’m, like a lot of other people, just starting with openHAB. I have been reading the starting guides and documentation bit by bit to understand how it works and I think it is a assume platform. But I don’t yet totally grasp the workings of openHAB. Zo I have just started to tray a few things to learn it in practice to understand it better.

I’m planning to use quite a few Arduino based sensor’s and switches with MQTT and USB > serial in a later moment. I will eventually use a RPI but now I’m using my windows laptop as test setup. I’m first traying to send a switch input from the Arduino over USB - serial port to openHAB and then, with the help of a rule, send a command back to the Arduino to turn on a LED.

What I have done so far:

  • Instald openHAB on my PC
  • Installed “Serial Binding”
  • Created a serial.items file with:

Switch Button “SW_1” (Test) { serial=“COM5@9600,ON(sw_1_on\n),OFF(sw_1_off\n)” }
Switch Button “SW_2” (Test) { serial=“COM5@9600,ON(sw_2_on\n),OFF(sw_2_off\n)” }
Switch Button “SW_3” (Test) { serial=“COM5@9600,ON(sw_3_on\n),OFF(sw_3_off\n)” }

  • Uploaded a Arduino sketch:

#define led_1 2
#define led_2 3

#define sw_1 4
#define sw_2 5
#define sw_3 6

void setup() {
Serial.begin(9600);
pinMode(sw_1, INPUT_PULLUP);
pinMode(sw_2, INPUT_PULLUP);
pinMode(sw_3, INPUT_PULLUP);

pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
Serial.println(“start”);

}

void loop() {

if (digitalRead(sw_1) == LOW) {
Serial.println(“sw_1_on”);
}
else
{
digitalWrite (led_1, LOW);
Serial.println(“sw_1_off”);
}

//------------------------------------

if (digitalRead(sw_2) == LOW) {
Serial.println(“sw_2_on”);
}
else
{
digitalWrite (led_2, LOW);
}

//-----------------------------------

if (digitalRead(sw_3) == LOW) {
Serial.println(“sw_3_on”);
}
else
{
Serial.println(“sw_3_off”);
}
delay(500);
}

I also made a test.rules file. But only got a few errors.
I know of the existence of the MYSENSOR project and there serial bridge. But they are especially focused on wireless sensor’s and I’m traying to make everting wired. Also it looked simpler, more robust and more flexible to just send some data over a serial bus. And also learn some more from it.
Thank you for all your help

Greetings sander.

which errors?

Also, my suggestion for you is to use WiFi based ESP8266 ($2). You wont have to worry about serial since you can directly send commands and read states from/to OH via REST API or MQTT (pubsub client readily available in many github repos)

I also see no code where you read serial from the arduino itself. YOu would need to do a serial.read() in arduino to process commands and turn on/trigger your GPIOs

Thank you for you’re response.

I have thought about a ESP8266 but I need more pins and I wish to make every thing wired. Couse it’s more realible, I already have a big cat6 netwerk in my home and a ton of cat6 cabling left collecting dust. Also the control clossed with the aduino and All of the connection point is just have a meter away from eachother. (the other floor and our fuse box is a different storey. I’m planning to use mqtt there)

Yes, I was first trying to have the openHAB log giving me a “sw 1 prest” respond. So I could get it to work piece by piece.

I will post the rulles file I was trying tomorrow when I’m back at my computer.

Thank you for you’re help.
Greetings, Sander

How reliable do you need it to be? I have several esp8266-based sensors all over the house and many of them tied up to my security alarm system and I’ve never had any issues. You can try few, then see if it works for you. My house is laced with cat5e also. I have 2 independent wired networks. Every room has 2 cat5e cables, but I opted for Wifi on some areas, and devices that are on batteries/solar.

The system will eventually manage the security and a lot more. But I want to build it part by part. So I’m starting with a simple light switch. Also, I will need to run power to al the sensors and controllers. I don’t think that solar panels is a viable option for the indoor controllers.
So I will stay at the wired communication idea.

We just moved in to our new home and we did quite some construction and renovation beforehand. We also changed quite a lot in the electrical system. We opted to centralize as much as possible and changed everything to led. We made a office with storage from the garage. So we laid a lot of electrical piping to a central point with spare pipes for digital buttons and sensors.


This is when we were half way done, so there is a lot more now. This is only for the low-voltage of the office.

We have a server cabinet with our UPS, NAS, data servers and arrays and a big 48 port managed switch. We also do the network patching here. We will have one switch but 2 network. One for our internet and one without internet access for openHAB and the IPcameras that will be installed in the further. There is a RPI for openHAB in this cabinet. On the wall, on the place in the picture, about 1m from this cabinet there is a other cabinet with all the led drivers and switching hardware. And a Arduino mega where all the switching hardware and buttons and sensors are connected to the microcontroller. There is a usb cable that goes to the RPI in the server cabinet.

In the fuse box closet there is a other cabling cabinet for the living room and the kitchen.
On the other flour of the house there is a cabling cabinet for the bedrooms and the bathroom. These will be connected over the “secure” network with MQTT.

On this moment only the office is digital with a program directly in the Arduino. I also got it to work with demoticz but I after a lot of googling I concluded that I like the flexibility and the possibilities in openHAB.

This is the broadly the plan. But I am first trying to have openHAB detect a switch press from the Arduino over the USB connection

Even if I would abandon this plan I would wane now what I’m doing wrong.

Thank you for your idea and input,
Greetings Sander

Whel, I have made some steps. With a tutorial from here I can now send 2 button presses and switch 2 led’s from openHAB basicUI and from physical buttons.

items:

String  ArduinoData  "ArduinoData [%s]" (arduino)   {serial="COM5@250000"}
Number  ArduinoSW1  "SW1 [%.1f]" (arduino)
Number  ArduinoSW2  "SW2 [%.1f]" (arduino)
Number  ArduinoSW3  "SW3 [%.1f]" (arduino)

Switch  led1        "led1"       (arduino)
Switch  led2        "led2"       (arduino)

readrules:

rule "ArduinoRead"
when 

Item ArduinoData received update

then

var String ArduinoDataUpdate = ArduinoData.state.toString.trim

var int S1StartsOn = ArduinoDataUpdate.indexOf("S1:") + "S1:".length
var String S1 = ArduinoDataUpdate.mid(S1StartsOn, ArduinoDataUpdate.indexOf('_')-S1StartsOn)
var Double S1Double = new Double(S1)

ArduinoSW1.postUpdate(S1Double)

var int S2StartsOn = ArduinoDataUpdate.indexOf("S2:") + "S2:".length  
var String S2 = ArduinoDataUpdate.mid(S2StartsOn, ArduinoDataUpdate.indexOf(';')-S2StartsOn)  
var Double S2Double = new Double(S2)

ArduinoSW2.postUpdate(S2Double)


end

arduino wride:

rule "arduino2"  
 when  
     Item led1 changed
 then  
     var state = led1.state as OnOffType
     sendCommand (ArduinoData , "led1=" + state)  
 end  

  rule "arduino1"  
 when  
     Item led2 changed
 then  
     var state = led2.state as OnOffType
     sendCommand (ArduinoData , "led2=" + state)  
 end  

  rule "arduino3"
 when
        Item ArduinoSW1 changed from 0 to 1
 then
        sendCommand (ArduinoData , "led1=ON")
 end

   rule "arduino4"
 when
        Item ArduinoSW1 changed from 1 to 0
 then
        sendCommand (ArduinoData , "led1=OFF")
 end

   rule "arduino5"
 when
        Item ArduinoSW2 changed from 0 to 1
 then
        sendCommand (ArduinoData , "led2=ON")
 end

   rule "arduino6"
 when
        Item ArduinoSW2 changed from 1 to 0
 then
        sendCommand (ArduinoData , "led2=OFF")
 end

Arduino code:

#define led_1 2
#define led_2 3

#define sw_1 4
#define sw_2 5
#define sw_3 6

String inputString = "";
bool stringComplete = false;

bool S_1 = 0;
bool S_2 = 0;
bool S_3 = 0;

bool H_1 = 0;
bool H_2 = 0;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(250000);
  pinMode(sw_1, INPUT_PULLUP);
  pinMode(sw_2, INPUT_PULLUP);
  pinMode(sw_3, INPUT_PULLUP);

  pinMode(led_1, OUTPUT);
  pinMode(led_2, OUTPUT);
  digitalWrite(led_1, HIGH);
  digitalWrite(led_2, HIGH);
  delay(1000);
    digitalWrite(led_1, LOW);
  digitalWrite(led_2, LOW);

}

void loop() {
  // put your main code here, to run repeatedly:
  knoppen_lezen();
  zend();
  serialEvent();
  outputs();
  delay(150);

}

void knoppen_lezen() {
  if (digitalRead(sw_1) == LOW) {
    S_1 = 1;
  }
  else
  {
    S_1 = 0;
  }

  //------------------------------------
  if (digitalRead(sw_2) == LOW) {
    S_2 = 1;
  }
  else
  {
    S_2 = 0;
  }

  //-----------------------------------
  if (digitalRead(sw_3) == LOW) {
    S_3 = 1;
  }
  else
  {
    S_3 = 0;
  }
}

void zend() {
  Serial.print("S1:");
  Serial.print(S_1);
  Serial.print("_S2:");
  Serial.print(S_2);
  Serial.println(";");
}

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    inputString += inChar;
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}


void outputs() {
  if (inputString == "led1=ON") {
    digitalWrite(led_1, HIGH);
    //Serial.println("led 1 aan");
  }
  else if (inputString == "led1=OFF") {
    digitalWrite(led_1, LOW);
    //Serial.println("led 1 uit");
  }
  else if (inputString == "led2=ON") {
    digitalWrite(led_2, HIGH);
    //Serial.println("led 2 aan");
  }
  else if (inputString == "led2=OFF") {
    digitalWrite(led_2, LOW);
    //Serial.println("led 2 uit");
  }
  Serial.println(inputString);
  inputString = "";
  stringComplete = false;
  //delay(500);
}

But now I was attempting to add more than one variable from the Arduino to openHAB just by adding more switches like this.

  Serial.print("S1:");
  Serial.print(S_1);
  Serial.print("_S2:");
  Serial.print(S_2);
  Serial.print("_S3:");
  Serial.print(S_3);
  Serial.println(";");

and

rule "ArduinoRead"
when 

Item ArduinoData received update

then

var String ArduinoDataUpdate = ArduinoData.state.toString.trim

var int S1StartsOn = ArduinoDataUpdate.indexOf("S1:") + "S1:".length
var String S1 = ArduinoDataUpdate.mid(S1StartsOn, ArduinoDataUpdate.indexOf('_')-S1StartsOn)
var Double S1Double = new Double(S1)

ArduinoSW1.postUpdate(S1Double)

var int S2StartsOn = ArduinoDataUpdate.indexOf("S2:") + "S2:".length  
var String S2 = ArduinoDataUpdate.mid(S2StartsOn, ArduinoDataUpdate.indexOf('_')-S2StartsOn)  
var Double S2Double = new Double(S2)

ArduinoSW2.postUpdate(S2Double)

var int S3StartsOn = ArduinoDataUpdate.indexOf("S3:") + "S3:".length  
var String S3 = ArduinoDataUpdate.mid(S3StartsOn, ArduinoDataUpdate.indexOf(';')-S3StartsOn)  
var Double S3Double = new Double(S3)

ArduinoSW3.postUpdate(S3Double)

end

But I just get a lot of errors
image

What am I doing wrong? Can somebody point me in the right direction?

Thank you guys!

var int S1StartsOn = ArduinoDataUpdate.indexOf("S1:") + "S1:".length
var String S1 = ArduinoDataUpdate.mid(S1StartsOn, ArduinoDataUpdate.indexOf('_')-S1StartsOn)
var Double S1Double = new Double(S1)

If the string received is “_S2:” (Your third serial write) then ArduinoDataUpdate.indexOf("S1:") is empty… And so on
You need to check if ArduinoDataUpdate.Contains("S1:") before getting the index

I suggest that instead of use S1:… format, just use commas as delimiter. THen you can just string.split(",") the payload to make it easier for you to parse.

Example payload:

S1Value,S2Value,S3Value

or actually:

0,1,0

to parse:

...
var parts = payload.Split(",");
var s1 = parts[0];
var s2 = parts[1];
var s3 = parts[2];

To avoid exceptions,

if (parts.length==3)
{
    var s1 = ...
    ...
}

But for me, I’d rather use ArduinoJSON lib. Then you can use JSONPath transformation in OH

I will have a look in your JSON idea. Meanwhile I have something working. With 3 buttons, and in theorie it will still work when I add more. Now I have to go back and test if it communication from openHAB to the Arduino still works and if I can expand that.

This is what I have come up with.

rule "ArduinoRead"
when 

Item ArduinoData received update

then

var String ArduinoDataUpdate = ArduinoData.state.toString.trim

var int S1StartsOn = ArduinoDataUpdate.indexOf("S1:") + "S1:".length
var String S1 = ArduinoDataUpdate.mid(S1StartsOn, ArduinoDataUpdate.indexOf('_')-S1StartsOn)
var Double S1Double = new Double(S1)

ArduinoSW1.postUpdate(S1Double)

//--------------------------------------------------------------------------------------------------------

ArduinoDataUpdate = ArduinoDataUpdate.substring(ArduinoDataUpdate.indexOf('_')+1)

var int S2StartsOn = ArduinoDataUpdate.indexOf("S2:") + "S2:".length
var String S2 = ArduinoDataUpdate.mid(S2StartsOn, ArduinoDataUpdate.indexOf('_')-S2StartsOn)  
var Double S2Double = new Double(S2)

ArduinoSW2.postUpdate(S2Double)

//------------------------------------------------------------------------------------------------------------

ArduinoDataUpdate = ArduinoDataUpdate.substring(ArduinoDataUpdate.indexOf('_')+1)

var int S3StartsOn = ArduinoDataUpdate.indexOf("S3:") + "S3:".length  
var String S3 = ArduinoDataUpdate.mid(S3StartsOn, ArduinoDataUpdate.indexOf(';')-S3StartsOn)  
var Double S3Double = new Double(S3)

ArduinoSW3.postUpdate(S3Double)

ArduinoDataUpdate = ("")
end

I relies I could have erased a lot of stuff. But I wane keep the option to send variables and bigger prefix than S1.