ModbusRTU Startadresse

Seit langem wieder an dem Haus Projekt.
Hab in den letzten Tagen fast nur daran gesessen, herauszufinden warum, wieso weshalb....

Nutze >>diese<< Library

#include <ModbusRtu.h>
#define ID   1 //Slave ID

Modbus slave(ID, 1, 2); // this is slave ID and RS-232 or USB-FTDI
Modbus slave0(ID, 0,0);

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

void setup() {
  slave.begin( 19200 );
  slave0.begin( 19200 );
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(20, OUTPUT);
  pinMode(8, INPUT);
  pinMode(9, INPUT);
  pinMode(13, OUTPUT);

  digitalWrite(3, HIGH );
  digitalWrite(4, LOW ); 
  digitalWrite(5, HIGH );
  digitalWrite(6, LOW );
  digitalWrite(20, HIGH );
  digitalWrite(13, HIGH );
}

void loop() {
  slave.poll( au16data, 2 );
  slave0.poll( au16data, 2 );
  // get digital inputs -> au16data[0]
  bitWrite( au16data[0], 0, digitalRead( 8 ));
  bitWrite( au16data[0], 1, digitalRead( 9 ));

  // set digital outputs -> au16data[1]
  digitalWrite( 3, bitRead( au16data[1], 0 ));
  digitalWrite( 4, bitRead( au16data[1], 1 ));
  digitalWrite( 5, bitRead( au16data[1], 2 ));
  digitalWrite( 6, bitRead( au16data[1], 3 ));
 digitalWrite( 20, bitRead( au16data[1], 4 ));
 digitalWrite( 13, bitRead( au16data[1], 5 ));
}

In openHAB muss ich die Startadresse 16 (modbus:serial.slave2.start=16) angeben, warum ausgerechnet 16?
Wie kann man es berechnen oder wovon hängt es ab?

openhab.cfg

############################### Modbus Binding ########################################
#
# sets refresh interval to Modbus polling service. 
# Value in milliseconds (optional, defaults to 200)
modbus:poll=1000

# Arduino Eingänge
modbus:serial.slave1.connection=/dev/ttyUSB0:19200:8:none:2:rtu
modbus:serial.slave1.id=1
modbus:serial.slave1.start=0
modbus:serial.slave1.length=2
modbus:serial.slave1.type=discrete

# Arduino Ausgänge
modbus:serial.slave2.connection=/dev/ttyUSB0:19200:8:none:2:rtu
modbus:serial.slave2.id=1
modbus:serial.slave2.start=16
modbus:serial.slave2.length=6
modbus:serial.slave2.type=coil

demo.items

Contact MB_DT0		"DT0 PIN8 [MAP(en.map):%s]"	{modbus="slave1:0"}
Contact MB_DT1		"DT1 PIN9 [MAP(en.map):%s]"	{modbus="slave1:1"}
Switch  MB_CL16		"MB_CL16 PIN3"  {modbus="slave2:0"}
Switch  MB_CL17		"MB_CL17 PIN4" 	{modbus="slave2:1"}
Switch  MB_CL18		"MB_CL18 PIN5" 	{modbus="slave2:2"}
Switch  MB_CL19 	"MB_CL19 PIN6" 	{modbus="slave2:3"}
Switch  MB_CL20 	"MB_CL20 PIN20"	{modbus="slave2:4"}
Switch  MB_CL21		"MB_CL21 PIN13" {modbus="slave2:5"}

demo.sitemap

sitemap demo label="Main Menu"
{

    Frame {
        Text item= MB_DT0
        Text item= MB_DT1
        Switch item= MB_CL16
        Switch item= MB_CL17
        Switch item= MB_CL18
        Switch item= MB_CL19
        Switch item= MB_CL20
        Switch item= MB_CL21
    }

}

Hier noch ein Tutorial, für alle die es lesen können:
Как подружить OpenHAB и Arduino
Arduino & Modbus
Arduino & OpenHAB

Bin kein Modbus Crack aber durch meine HMI Geschichte habe ich mich ein bisschen eingearbeitet.

Modbus ist byte Basiert es gibt unterschiedliche "Arten" >HIER<
Du arbeitest hier im Bereich Discrete Output Coils wobei man auch die Output-Daten als Input nutzen kann also du nutzt nur den Datenbereich 0-9999 entspricht der Adress 0X0- 0x270E

modbus:serial.slave1.length=2
modbus:serial.slave1.type=discrete

Dort nutzt du den Bereich discrete coils ( jeweils ein Byte) also die Adresse 0-15
in dem zweiten Arduino bist du also ab Adresse 16 und den zustand von 6 Bits
Hier:

modbus:serial.slave2.start=16
modbus:serial.slave2.length=6
modbus:serial.slave2.type=coil

Schau mal auf der Seite nach die ich oben verlinkt habe dannach wird dir einiges klarer.
Gruß
DerDani

Auch wenn ich nur dies stehen hab, gehts erst ab startadresse 16

# Arduino Ausgänge
modbus:serial.slave2.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.slave2.id=2
modbus:serial.slave2.start=16
modbus:serial.slave2.length=1
modbus:serial.slave2.type=coil
#include <ModbusRtu.h>
#define ID   2 //Slave ID
#define DATEN 2 // data array 

Modbus slave(ID, 1, 2); // this is slave ID and RS-232 or USB-FTDI
Modbus slave0(ID, 0,0);
uint16_t au16data[DATEN];


void setup() {
  slave.begin( 19200 );
  slave0.begin( 19200 );
  // define i/o


    pinMode(A0, OUTPUT);
  
}

void loop() {
  slave.poll( au16data, DATEN );
  slave0.poll( au16data, DATEN );

  // set digital outputs -> au16data[1]
  digitalWrite( A0, bitRead( au16data[1], 0 ));

}

Die Seite ausm Link hab ich zich mal gelesen/gesehen,wie auch andere dieser Art.
Discrete Inputs 1 Bit lesen
Coils 1 Bit schreiben/lesen
Input Registers 16 Bit lesen
Holding Registers 16 Bit schreiben/lesen

Da ich hier nur Coils nutze, schreibt/liest der nur mit 1 Bit, richtig?
Oder liest der nur 1 Bit aber schreibt 16?

Das ist doch die Config aus openHAB und wenn du die 16 änderst in 0?
Muss man was neu compilieren für openHAB? Ich kenn mich mit der HAB sache absolut nicht aus. Mit der ModbusRTU Lib kannst du das alles so machen so war es auch bei meiner HMI Sache.
Gruß
DerDani

Ja... und wenn ich die config von penHAB ändere, muss ich openHAB neu starten.

Mit CAD Modbus Scanner gescannt:

Auf Adresse 00001 wird geschrieben.
modbus:serial.slave2.start=0
modbus:serial.slave2.length=1
digitalWrite( A0, bitRead( au16data[1], 0 ));
LED auf A0 wird nicht geschaltet.

modbus:serial.slave2.start=0
modbus:serial.slave2.length=1
digitalWrite( A0, bitRead( au16data[0], 0 ));
LED auf A0 wird geschaltet.

Auf Adresse 00002 wird geschrieben.
modbus:serial.slave2.start=1
modbus:serial.slave2.length=1
digitalWrite( A0, bitRead( au16data[1], 0 ));
LED auf A0 wird nicht geschaltet.

modbus:serial.slave2.start=1
modbus:serial.slave2.length=1
digitalWrite( A0, bitRead( au16data[0], 1 ));
LED auf A0 wird geschaltet.

modbus:serial.slave2.start=1
modbus:serial.slave2.length=2
digitalWrite( A0, bitRead( au16data[1], 0 ));
LED auf A0 wird nicht geschaltet.

modbus:serial.slave2.start=1
modbus:serial.slave2.length=2
digitalWrite( A0, bitRead( au16data[0], 1 ));
LED auf A0 wird geschaltet.

Wie du siehst, führen viele Wege nach Rom, welcher ist der richtige? :smiley:
Ich will es halt nur verstehen wie es funktioniert, ohne erst raten zu müssen.

Auf Adresse 00009 wird geschrieben.

modbus:serial.slave2.start=0
modbus:serial.slave2.length=1
digitalWrite( A0, bitRead( au16data[1], 0 ));
LED auf A0 wird nicht geschaltet.

Probier das mal mit der 9 dann dürfte die LED angehen.
Gruß
Daniel

modbus:serial.slave2.start=9
modbus:serial.slave2.length=1
digitalWrite( A0, bitRead( au16data[1], 0 ));
LED auf A0 wird nicht geschaltet.

modbus:serial.slave2.start=8
modbus:serial.slave2.length=1
digitalWrite( A0, bitRead( au16data[1], 0 ));
LED auf A0 wird nicht geschaltet.

Den den Start bei 0 lassen und auf Adresse 9 schreiben meinte ich.
Gruß
DerDani

modbus:serial.slave2.length=2
oder
modbus:serial.slave2.length=1

#include <ModbusRtu.h>
#define ID   2 //Slave ID
#define DATEN 2 // data array 

Modbus slave(ID, 1, 2); // this is slave ID and RS-232 or USB-FTDI
Modbus slave0(ID, 0,0);
uint16_t au16data[DATEN];


void setup() {
  slave.begin( 19200 );
  slave0.begin( 19200 );
  // define i/o


    pinMode(A0, OUTPUT);
  
}

void loop() {
  slave.poll( au16data, DATEN );
  slave0.poll( au16data, DATEN );

  // set digital outputs -> au16data[1]
  digitalWrite( A0, bitRead( au16data[9], 0 ));

}
# Arduino Ausgänge
modbus:serial.slave2.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.slave2.id=2
modbus:serial.slave2.start=0
modbus:serial.slave2.length=1
modbus:serial.slave2.type=coil

getestet mit:
#define DATEN 1 // data array
#define DATEN 2 // data array
digitalWrite( A0, bitRead( au16data[0], 9 ));
digitalWrite( A0, bitRead( au16data[9], 0 ));

LED auf A0 wird nicht geschaltet.

Ich fange mal anders an.
Du initialisierst zwei int (2 Bytes => 16Bits) in einem Array au16data.
Das sieht dann so aus

au16data[0]= BIN0000 0000 0000 0000;
au16data[1]= BIN0000 0000 0000 0000;

mit

modbus:serial.slave2.start=0
modbus:serial.slave2.length=1

startest du beim rechten Bit. Schreibst du jetzt Coil 1 steht im
au16data[0]= BIN 0000 0000 0000 0001
Coil 2
au16data[0]= BIN 0000 0000 0000 0010
etc
mit bit Read liest du dann die einzelnen Bits aus an den Stellen.

zu meinem Beispiel meinte ich

Auf Adresse 00009 soll geschrieben.

modbus:serial.slave2.start=0
modbus:serial.slave2.length=2
digitalWrite( A0, bitRead( au16data[0], 8 ));

Dann sollte die led angehen. In
au16data[0] stehen die Coils 16=>1
au16data[1] stehen die Coils 32=>17
Gruß
DerDani

LED auf A0 wird nicht geschaltet.
Achtung bitRead startr mit Index 0 während coil mit Index 1