Haussteuerung mit Modbus erstellen

Hallo,

ich bin seit einigen Tagen dabei eine eigene Haussteuerung zu erstellen.

Hintergrund ist das ich gerade ein neues Haus baue und dort gerne einiges automatisieren/steuern würde.
In meinem alten Haus hatte ich die Homematic verbaut (Teilweise Wired, teilweise Funk).
Habe aber gemerkt das dieses System mittlerweile einiges an wünschen offen lässt vorallem im Kabelgebundenen bereich. Und so kam ich Anfang des Jahres zum Arduino und jetzt will ich halt gerne alles damit machen.

Nun zum eigentlichen Problem.

Ich hatte schon mal auf dem Breadboard 2 Slaves (NANO mit MAX485) und 1 Master (Mega mit MAX485) aufgebaut und das ganze auch eigentlich gut am laufen.

Als Protokoll habe ich die Lib von Nick Gammon genommen. Nur leider war mir selbst nach ein bisschen Tuning in der Lib selbst immer noch die abfrage der Taster und das ansteuern der LED's viel zu langsam und hackelig.

Jetzt würde ich gerne den Modbus ausprobieren, der ist meiner Meinung nach sowieso besser für sowas ausgelegt und etwas flexibler/kompatibler.

Nur leider hänge ich beim Master.

Wie soll ich meinen Code gestalten um nacheinander möglichst schnell ca 25-30 Slaves abzufragen und für jeden ein Array anzulegen mit dem mitgeteilten werten.

Es gibt ja sehr viele Beispiele für Slaves die meisten konnte ich auch schnell und gut nachvollziehen,
aber bei Master komme ich nicht voran.

Als Lib wollte ich den Simple Modbus Nehmen.

Aber wie frage ich die Register im Slave ab und vorallem welches Register muss ich abfragen.

Ich will hier keine vorgekauten codes von euch ein Denkanstoß wäre schon ganz Nett.

Es gibt ja hier schon einpaar Leute die sich mit dem ganzen Thema auseinander gesetzt haben vielleicht könnte ich mich mit meinen Ideen auch in ein bestehendes Projekt einklinken.

Wenn ich den Modbus gebändigt habe, dann werde ich mal nen Prototyp vom ersten Slave bauen damit ihr was sehen könnt.

Er soll jeweils in jedem Raum eingebaut werden und erstmal folgendes können

  1. 4 Taster Inputs (z.b. Licht oder Rollläden)
  2. 3 Reedkontakt Inputs (Auf, Kipp und Sabotagekontakt)
  3. 2 Relais Kontakte der Gira Rauchmelder abfragen
  4. 1 DHT22 zur Erfassung der Temp und LF

Das wäre dann erstmal Beta 1

Der Master soll eigentlich nur die Slaves abfragen und die jeweiligen Koppelrelais für licht oder andere Stromkreise schalten.
außerdem soll er in Zukunft auch als Schnittstelle in das Netzwerk fungieren um Daten weiter zureichen oder auch um Anweisung aus dem Netzwerk durchzuführen z.B. über MQTT.

freue mich auf eure antworten

Gruß Enrico

Hast du dir meine 2 Versionen von den Platinen angeschaut? Das eine Busankoppler ( ca 8 Platinen hab ich noch liegen ) das andere Taster für haus-bus.de.
Willst du wirklich für jedes Zimmer ein Kabel für Licht ziehen? Mal daran gedacht was passiert wenn dein gebastel nicht funktioniert? Deswegen nutze ich Relais in UP Dosen, kann man beim Haus verkaufen alles rausschmeißen und keiner weiß was du da hattest.

Ich bleib bei OpenHab. Dein IOBroker ist mir zu unsicher.
Also....
OpenHab auf dem Raspi ( Master )
Der rest ist alles Slave:
Mega entweder durch usb oder RS485 mit dem Raspi verbunden, sitzt im Schaltschrank und schaltet Relais.
Andere Slaves kannste entweder am Mega oder wieder am Raspberry anklemmen durch zweiten RS485.
Ich hab in meinen Threads auch Beispiele dazu, Link dazu müsstest du schon haben.
Ich hoffe es wird nicht wieder so ein hoffnungsloser Thread wie die meisten was das Thema angeht, keiner bringts zuende.

skorpi08:
Hast du dir meine 2 Versionen von den Platinen angeschaut? ...

Könntest Du mit Links dienen? Vom Modbus habe ich keine Ahnung, aber da ich mich die letzte Zeit mit I²C beschäftigt habe, interessiert mich das Thema.

skorpi08:
... Ich hoffe es wird nicht wieder so ein hoffnungsloser Thread wie die meisten was das Thema angeht, keiner bringts zuende.

Wo ist denn ein Anfang?

Gruß

Gregor

Anfang ist jeder neue Thread.
Der Kollege hier ist nebenbei am bauen, da hätte er mit der Elektronik früher anfangen sollen. Man hat nie zeit für was anderes. Immer schnell.... schnelll..... schnellller....

Wenn du keine Ahnung hast, dann such einfach nach alles mögliche zum Thema, dann stolperst du auch über meine Beiträge :wink:

Macht dir mal um meinen Bau Fortschritt und meine Zeit keine sorgen wenn es ums Bauen geht weiß ich genau was ich tue. Außerdem habe ich für alles immer nen Plan B.

Aber hier geht's jetzt um den modbus alles andere können wir dann aus diskutieren wenn mein Master den slave Interviewt hat :smiley:

Habs heut endlich geschafft Mac OS zu installieren dass Sound und Internet läuft.
Demnächst kann ich dir dann mit Code etc weiterhelfen soweit ich kann/weiß.

Was war deine Frage nochmal? :smiley:
Was klappt nicht?

Am Wochenende habe ich mal 3 Tage Urlaub hoffe das ich WLAN im Hotelzimmer habe dann werde ich mal nen slave Sketch schreiben und wir können ihn hier nach und nach durch gehen.

Das wichtigste war mir eigentlich das abfragen der Register im slave.

Gruß Enrico

Hier gregor:
Ganz durchlesen
http://forum.arduino.cc/index.php?topic=267979.5

http://forum.arduino.cc/index.php?topic=258332.5

Hier das Deutsche Forum für OpenHab

http://knx-user-forum.de/forum/supportforen/openhab/38546-via-modbus-komma-werte-übertragen

http://forum.arduino.cc/index.php?topic=343536

http://forum.arduino.cc/index.php?topic=344311.0

https://forum.arduino.cc/index.php?topic=347263.0

http://forum.arduino.cc/index.php?topic=268101.10

Mein test Sketch von früher, wo ich noch mit dieser Lib rumhantierte, mittlerweile hab ich ne andere weil hier eine Funktion nicht unterstützt wird die openhab brauch.

#include <SimpleModbusSlave.h>
#include <OneWire.h>
OneWire  ds(A3);  // on pin 10
#define PIN_TASTER       9

// Für Bistabiles Relais werden 2 Pins gebraucht.
#define ON  8
#define OFF 7

#define INTERVAL 1000 
#define BUTTON_DEBOUNCE_DELAY 20
long lastDebounceTime = 0;
long previousMillis = 0;
#define MB_TXENPIN   A2
#define MB_SLAVE_ID  2
#define MB_BAUDRATE  9600
#define MB_PARITY  SERIAL_8N2
enum 
{     
  LICHT,
  CELSIUS,
  HOLDING_REGS_SIZE // immer stehen lassen, brauch die Library.
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; 
void setup()
{
    // configure pins
  pinMode(PIN_TASTER, INPUT);
  pinMode(ON, OUTPUT);  
  pinMode(OFF, OUTPUT); 
  
  modbus_configure(&Serial, MB_BAUDRATE, MB_PARITY, MB_SLAVE_ID, MB_TXENPIN, HOLDING_REGS_SIZE, holdingRegs);
  modbus_update_comms(MB_BAUDRATE, MB_PARITY, MB_SLAVE_ID);

}

void loop()
{  
  
    modbus_update();
//Code für den DS18B20 Temperatursensor
  byte i;
  byte present = 0;
  byte type_s =0;
  byte data[12];
  byte addr[8] = {0x28, 0x97, 0xCC, 0x84, 0x04, 0x00, 0x00, 0x60};
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // start conversion, with parasite power on at the end

  if(millis() - previousMillis < INTERVAL) return;
    previousMillis = millis();   
 present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad
  Serial.print(present,HEX);
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
  }

  // convert the data to actual temperature
  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms

  }
holdingRegs[CELSIUS] = raw*625L/1000;  // Zwischenrechnung ist long, Ergebnis passt in int
  
  //Wenn Taster Zustand geändert wird, ändert sich die Variable LICHT und wird direkt an Master übertragen. Im Master könntest du dann mit Serial.println (LICHT); abfragen.
   if ((digitalRead(PIN_TASTER) == HIGH) && ((millis() - lastDebounceTime) > BUTTON_DEBOUNCE_DELAY))
  {
    // invert LED state
    holdingRegs[LICHT] = !holdingRegs[LICHT];

    lastDebounceTime = millis();
  }
//Wenn Taster gedrückt wurde, also der Zustand auf HIGH/1 dann wird das Relais geschaltet. Dass machste dann auf dem Master.
    if (holdingRegs[LICHT]==1){
      // ON //
  digitalWrite(ON,1);
  digitalWrite(OFF,0);
  delay(10);
  digitalWrite(ON,0);
  digitalWrite(OFF,0);
} 
  else{
    // OFF //
  digitalWrite(ON,0);
  digitalWrite(OFF,1);
  delay(10);
  digitalWrite(ON,0);
  digitalWrite(OFF,0); 
}

}

Passiert wohl nicht mehr viel hier

Ich habe doch gesagt ich bin noch im Urlaub und ohne computer kann ich hier nicht viel machen.

Heute abend mache ich eventuell mal den slave Sketch fertig wenn meine Kinder mich lassen.

Gruß Enrico

Du kannst auch sagen was du in dem Slave Sketch haben willst und andere versuchen dir dabei zu helfen.

Nabend,

so also habe mal etwas probiert.

Als Master lief das hier auf dem Mega

#include <SimpleModbusMaster.h>

#define baud 9600
#define timeout 1000
#define polling 200 
#define retry_count 5
#define TxEnablePin 3 


enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS 
};

Packet packets[TOTAL_NO_OF_PACKETS];

unsigned int readRegs[1];

void setup()
{
  Serial.begin(9600);
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 1, 0);
  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, readRegs);
  pinMode(LED, OUTPUT);
}

void loop()
{
  modbus_update();
  Serial.println(readRegs[0]);
  Serial.println(readRegs[1]);
  Serial.println(readRegs[2]);
}

Eigentlich sollte im Serial monitor einmal die 1 stehen und bei drücken auf den Taster zur 0 werden.

Der Slave (Nano) bekam das hier:

#include <SimpleModbusSlave.h>

enum 
{     
    VAL,     
         HOLDING_REGS_SIZE 
};

unsigned int holdingRegs[HOLDING_REGS_SIZE];


void setup()
{
 pinMode(2, INPUT_PULLUP);
  Serial.begin(9600);
  
  modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 3, HOLDING_REGS_SIZE, holdingRegs);

  
  modbus_update_comms(9600, SERIAL_8N2, 1);
  
  
}

void loop()
{
 
  
  modbus_update();
  
  holdingRegs[VAL] = digitalRead(2); 
  Serial.print(holdingRegs[VAL]);
    

}

Im Serial Monitor am Master kam nur:

769
0
0

Jetzt habe ich aber für morgen noch eine Sache die ich testen möchte.
und zwar habe ich das ganze ja noch aufm Breadboard gesteckt und die Bus Widerstände weg gespart.
Das hatte bei meinem letzten versuch auch funktioniert, aber vielleicht braucht der Modbus es dringender.

Wie habt ihr das Terminiert ?

ich werde morgen mal das Probieren.

gruß Enrico

So Jetzt läuft es.

Lag aber nicht am widerstand sondern an meiner eigenen Blödheit...

Habe bei meinen ersten versuchen mit der Lib von Nick Gammon

immer 11 und 12 als RX und TX Pins gewählt.

Bei Simple Modbus muss man ja Pin 0 und 1 nehmen.

Ausserdem habe ich ja versucht mir was auf dem Serial Monitor anzuzeigen...
Als ich das aus dem Sketch entfernt hatte leuchtet nach dem Hochladen dann plötzlich meine LED am Master und beim Druck auf den Taster war sie aus....wie durch ein Wunder.

Aber trotzdem hätte ich gerne eure vorschläge zum Widerstand.

Gruß Enrico

Widerstand brauchste aufm Tisch nicht unbedingt.
Dass mit den Pin 11, 12, 0 und 1.....
Du hattest sicher SoftwareSerial Library verwendet und die Pins 11/12 genommen, ist ja auch ok, würde hier auch funktionieren.

Pin 0/1 wird von Modbus und Serial Monitor verwendet, das geht nicht beides gleichzeitig.
Du kannst auf dem Mega 0/1 für Serial Monitor nehmen und Serial 2 ( Pins weiß ich grad nicht, irgendwas über 20) für Modbus.
Mega hat ja 3 Serial Ports zur Verfügung, wobei auf dem Serial Monitor nur was angezeigt wird wenn du Serial.print verwendest. Serial2.print wird also nicht angezeigt.

Moin,

ich habe mal die ersten versuche starten können und bin angenehm überrascht.

Habe am Slave 4 Taster, ein Poti und einen DHT22
Alles wird übertragen und das auch recht flott.

Hatte erst wieder so meine Start problem aber das Problem war wieder zwischen Stuhl und Tastertur.
Nach dem beheben lief alles wie gewünscht.

Habe auch ein kleines video gemacht damit ihr was zu gucken habt :smiley:

Hatte im Video mal 57600 probiert fande aber das es auf 9600 fast besser lief mit den Tastern.
Das Dimmen kann man nicht so gut erkennen aber es dimmt.

als nächstes werde ich mal versuchen das etwas schön zu verpacken und nen 2ten Slave ins spiel bringen.

Gute Nacht

Sicher dass es über Modbus geht? Sieht mir so aus als obs nur ein Arduino ist der nix verschickt.
Was ist nun der nächste Schritt?

Denke das das wohl ein scherz war....

Als nächstes wird das auf ne Platine verstaut und dann werde ich einen weiteren slave einbinden.

Danach muss noch der master mit meinem Server Daten austauschen.

Mal sehen ob auch über modbus oder mqtt.

Wie mache ich eigentlich ein neues Array für den nächsten slave?

Oder liest er alle slaves nach und nach in readregs[] ein.

Bei den alten Versionen von simple modbus konnte man ja im modbus_construct ein Array angeben.

Bei den alten Versionen von simple modbus konnte man ja im modbus_construct ein Array angeben.

kannst du dass jetzt nicht?

Nein es geht nicht.

Habe es jetzt so gelöst

enum
{
  PACKET1,
  PACKET2,
  TOTAL_NO_OF_PACKETS 
};

Packet packets[TOTAL_NO_OF_PACKETS];

unsigned int readRegs[7];
unsigned int readRegs2[7];

void setup()
{
 Ethernet.begin(mac, ip);
  server.begin();
  
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 7, 0);
  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, readRegs);
  modbus_construct(&packets[PACKET2], 2, READ_HOLDING_REGISTERS, 0, 7, 0);
  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, readRegs2);

Es scheint auch zu Funktionieren ich habe den Slave testweise auf ID2 gestellt und es hat genau so geklappt wie zuvor.

Habe auch noch mal schnell einen Webserver mit in den Master gepackt so konnte ich im Browser ein paar Werte anzeigen. LF und Temp werden auch übertragen.

scheint alles zu funktionieren jetzt muss ich nur mal ein paar Slaves fertig bauen zum test mit mehren.

Gruß
Enrico

Und was geht hier so ab?