Light Sensor on Arduino over modbus

Hello,

how i can read data from arduino light sensor and see in openhab2 ?
I have node on arduino with sketch:

#include <ModbusRtu.h>

// data array for modbus network sharing
uint16_t au16data[3];


Modbus slave(1,0,2);
void setup() {
  pinMode(11, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(A1, INPUT);
  digitalWrite(11, LOW );
  digitalWrite(13, LOW );
  Serial.begin(19200);
  slave.begin( 19200 ); // baud-rate at 19200
  au16data[0] = 0;
}

void loop() {
if (slave.poll( au16data, 0 ))
{
  digitalWrite( 11, bitRead( au16data[0], 0 ));
  digitalWrite( 13, bitRead( au16data[0], 1 ));
  au16data[1] = analogRead(A1);  // fotoregistor
}
}

modbus.cfg

modbus:poll=5000
modbus:serial.slave1.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.slave1.type=coil
modbus:serial.slave1.id=1
modbus:serial.slave1.start=0
modbus:serial.slave1.length=5

modbus:serial.slave2.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.slave2.type=coil
modbus:serial.slave2.id=2
modbus:serial.slave2.start=0
modbus:serial.slave2.length=5

modbus:serial.slave3.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.slave3.type=discrete
modbus:serial.slave3.id=1
modbus:serial.slave3.start=2
modbus:serial.slave3.length=2
modbus:serial.slave3.valuetype=uint16


item:

Switch Slave1 { modbus="slave1:0" }
Switch Slave1r { modbus="slave1:1" }
Number LightSensor  "Light Sensor  [%.1f LUX]" {modbus="slave3:2"}
Switch Slave2 { modbus="slave2:0" }

switchs on pin 11 and 13 works fine but a can’t read data from analogRead(A1), please help.

Nobody do not know where is the problem ?

Not a discrete (bit), you want a 16-bit register type, probably input or holding. For a single 16-bit register, length = 1

I think you might need to review the other id, start, and length parameters as well. I would expect your Arduino to have only one id.

OK works !!!
On the same node i have slave1 and slave3, my comfiguration with light sensor:

modbus:poll=1000
modbus:serial.slave1.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.slave1.type=coil
modbus:serial.slave1.id=1
modbus:serial.slave1.start=0
modbus:serial.slave1.length=2

modbus:serial.slave2.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.slave2.type=coil
modbus:serial.slave2.id=2
modbus:serial.slave2.start=0
modbus:serial.slave2.length=1

modbus:serial.slave3.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.slave3.type=holding
modbus:serial.slave3.id=1
modbus:serial.slave3.start=1
modbus:serial.slave3.length=1

item:

Switch Slave1 { modbus="slave1:0" }
Switch Slave1r { modbus="slave1:1" }
Number LightSensor  "Light Sensor [%d LUX]" {modbus="slave3:0"}
Switch Slave2 { modbus="slave2:0" }

Next will be DS18B20.

OK ds18b20 working fine, this is configuration
modbus.cfg

modbus:poll=1000

# NODE 1
#LEDs
modbus:serial.slave1.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.slave1.type=coil
modbus:serial.slave1.id=1
modbus:serial.slave1.start=0
modbus:serial.slave1.length=2

#LightSensor && Temperature
modbus:serial.slave2.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.slave2.type=holding
modbus:serial.slave2.id=1
modbus:serial.slave2.start=1
modbus:serial.slave2.length=2

#NODE 2
#LED
modbus:serial.slave3.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.slave3.type=coil
modbus:serial.slave3.id=2
modbus:serial.slave3.start=0
modbus:serial.slave3.length=1

item:

Switch Slave1 { modbus="slave1:0" }
Switch Slave1r { modbus="slave1:1" }
Switch Slave2 { modbus="slave3:0" }
Number LightSensor  "Light Sensor [%d LUX]" { modbus="slave2:0" }
Number Temperature  "Temperature [%.1f °C]" { modbus="slave2:1" }

and all the thinks are saved in mysql database without installing JDBC olny MYSQL-persi…
and:
Instaling MYSQL:

sudo apt-get install mysql-server-5.5

and login

mysql -u root -p

and create new database:

create database openhab2;

and new user with all privilage to this db:

CREATE USER 'openhab'@'localhost' IDENTIFIED BY 'openhab';
GRANT ALL PRIVILEGES ON openhab2.* TO 'openhab'@'localhost';
quit;

and add new file to openhab2 dir:

sudo nano /opt/openhab/configurations/persistence/mysql.persist

with:

Strategies {
    default = everyChange
}

Items {
    * : strategy = default, restoreOnStartup
}

and mysql.cfg

chart:provider=default
persistence:default=mysql
org.eclipse.smarthome.persistence:default=mysql
mysql:url=jdbc:mysql://127.0.0.1:3306/openhab2
mysql:user=username
mysql:password=password
mysql:sqltype.string=VARCHAR(20000)

and thats all :slight_smile: its working all changes are saved in db and value from all sensors in my case ligghtsensor and temperature and turon on and off for switches.

I forgot, i use DS18B20 9bit and its need 93ms (eg. 20,5 C) (for 12bit 750ms 20,5000C) to read or conversion data and on this time blocking node even is on multitasking, i use:

sensors.setWaitForConversion(false);

this is complite shetch for node 1:

#include <Timers.h>
#include <ModbusRtu.h>
#include <OneWire.h>
#include <DallasTemperature.h>

Timers <3> akcja;
// data array for modbus network sharing
//uint16_t au16data[16] = {
//  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, -1 };
uint16_t au16data[4];

/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI 
 *               or any pin number > 1 for RS-485
 */
//beg_lightsensor
#define photoPin A1         // Fotorezystor
volatile int lastLightLevel;
//end_lightsensor

//beg_temp
#define COMPARE_TEMP 1 // Wysyłaj temperaturę jeśli się zmieni? 1 = YES 0 = NO
#define MAX_ATTACHED_DS18B20 1
#define ONE_WIRE_BUS 7
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress;
int  resolution = 9;
unsigned long lastTempRequest = 0;
int  delayInMillis = 0;
volatile float lastTemperature[MAX_ATTACHED_DS18B20];
//end_temp

Modbus slave(1,0,2);

void setup() {
//Temp_beg 
  sensors.begin();
  sensors.getAddress(tempDeviceAddress, 0);
  sensors.setResolution(tempDeviceAddress, resolution);
  sensors.setWaitForConversion(false);
  
  delayInMillis = 750 / (1 << (12 - resolution)); 
  lastTempRequest = millis();
//Temp_end  
  pinMode(11, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(photoPin, INPUT);
  digitalWrite(11, LOW );
  digitalWrite(13, LOW );
  slave.begin( 19200 ); // baud-rate at 19200
  au16data[0] = 0;
  akcja.attach(0, 1, modbus); // Komunikacja modbus
  akcja.attach(1, 300119, lightLevel); // Poziom natezenia swiatla co 5 min
  akcja.attach(2, 309469, CheckTemp); // Odczyt temperatury co 5 min
  
}

void loop()
{
akcja.process();

}

void modbus()
{
 if (slave.poll( au16data, 4 ))
{
  digitalWrite( 11, bitRead( au16data[0], 0 ));
  digitalWrite( 13, bitRead( au16data[0], 1 ));
  au16data[1] = lastLightLevel;
  au16data[2] = lastTemperature[0];
}
}

void lightLevel()
{
  int lightLevel = (analogRead(photoPin)); 
  if (lightLevel != lastLightLevel) {
       lastLightLevel = lightLevel;
  }
}

void CheckTemp()
{
  
 if (millis() - lastTempRequest >= delayInMillis) // waited long enough??
  {
 sensors.requestTemperatures();
 float temperature = sensors.getTempCByIndex(0);
  
    int i=0;
    #if COMPARE_TEMP == 1
    if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) {
    #else
    if (temperature != -127.00 && temperature != 85.00) {
    #endif     
      // Send in the new temperature
      //temp = sensors.getTempCByIndex(i);
      // Save new temperatures for next compare
      lastTemperature[i]=temperature;
    }
    lastTempRequest = millis();
  }  
}

Next will be button to turn on and off on the led in node.

Somebady is reading this ??? :)))

OK button works fine !!!
In openhab2 we change nothing.
Sketch for Arduino:

#include <Timers.h>
#include <ModbusRtu.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Bounce2.h>

Timers <4> akcja;
// data array for modbus network sharing
//uint16_t au16data[16] = {
//  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, -1 };
uint16_t au16data[4];

//beg_bounce
#define BUTTON_PIN 4
Bounce debouncer = Bounce();
int ledState = LOW;
volatile byte button_state = 0;
//end_bounce

//beg_lightsensor
#define photoPin A1         // Fotorezystor
volatile int lastLightLevel;
//end_lightsensor

//beg_temp
#define COMPARE_TEMP 1 // Wysyłaj temperaturę jeśli się zmieni? 1 = YES 0 = NO
#define MAX_ATTACHED_DS18B20 1
#define ONE_WIRE_BUS 7
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress;
int  resolution = 9;
unsigned long lastTempRequest = 0;
int  delayInMillis = 0;
volatile float lastTemperature[MAX_ATTACHED_DS18B20];
//end_temp
/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI 
 *               or any pin number > 1 for RS-485
 */
Modbus slave(1,0,2);

void setup() {

//beg_bounce
pinMode(BUTTON_PIN, INPUT_PULLUP);
debouncer.attach(BUTTON_PIN);
debouncer.interval(5);
//end_bounce

//Temp_beg 
  sensors.begin();
  sensors.getAddress(tempDeviceAddress, 0);
  sensors.setResolution(tempDeviceAddress, resolution);
  sensors.setWaitForConversion(false); 
  delayInMillis = 750 / (1 << (12 - resolution)); 
  lastTempRequest = millis();
//Temp_end

  pinMode(11, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(photoPin, INPUT);
  digitalWrite(11, LOW );
  digitalWrite(13, LOW );
  slave.begin( 19200 ); // baud-rate at 19200
  au16data[0] = 0;
  akcja.attach(0, 1, modbus); // Komunikacja modbus
  akcja.attach(1, 300119, lightLevel); // Poziom natezenia swiatla co 5 min
  akcja.attach(2, 309469, CheckTemp); // Odczyt temperatury co 5 min
  akcja.attach(3, 2, CheckButtonState); // Odczyt buttona co 3ms
}

void loop()
{
akcja.process();
}

void CheckButtonState()
{
boolean stateChanged = debouncer.update();
int valueB = debouncer.read();
if (stateChanged &&  valueB == LOW) {
         ledState = digitalRead(11);
       if ( ledState == LOW ) {ledState = HIGH;} else {ledState = LOW;}
            digitalWrite(11,ledState);
            bitWrite( au16data[0], 0, digitalRead( 11 ));
            }
              
}

void modbus()
{
 if (slave.poll( au16data, 4 ))
{  
// set
  digitalWrite( 11, bitRead( au16data[0], 0 ));
  digitalWrite( 13, bitRead( au16data[0], 1 ));
  
// get  
  au16data[1] = lastLightLevel;
  au16data[2] = lastTemperature[0];
}
}

void lightLevel()
{
  int lightLevel = (analogRead(photoPin)); 
  if (lightLevel != lastLightLevel) {
       lastLightLevel = lightLevel;
  }
}

void CheckTemp()
{
  
 if (millis() - lastTempRequest >= delayInMillis) // waited long enough??
  {
 sensors.requestTemperatures();
 float temperature = sensors.getTempCByIndex(0);
  
    int i=0;
    #if COMPARE_TEMP == 1
    if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) {
    #else
    if (temperature != -127.00 && temperature != 85.00) {
    #endif     
      // Send in the new temperature
      //temp = sensors.getTempCByIndex(i);
      // Save new temperatures for next compare
      lastTemperature[i]=temperature;
    }
    lastTempRequest = millis();
  }  
}

This sketch maby can optimalized if You can do it because i can not do this i m programer amator :slight_smile:

where can i change the modbus.cfg ??