Raspberry PI Modbus TCP/IP Server

Hallo,

ich habe gerade etwas gebastelt. Im Anhang ist der Source für einen Raspberry Pi Modbus Client.
Damit lassen sich 8 GPIOs des Raspberry Pi mittels der IPS Modbus Funktionen steuern (momentan nur Ausgaenge).

Eingaenge und eventuell 1wire Temperaturen sind geplant.

Folgende Abhaengigkeiten werden benötigt.

sudo apt-get install libmodbus-dev

dann noch hier der Anleitung folgen:
https://projects.drogon.net/raspberry-pi/wiringpi/download-and-install/

mb.zip (2.35 KB) entpacken und:


make
sudo ./mb

Der Server lauscht nun:


pi@pidev ~/mbtest $ sudo ./mb 
GPIO Init
Init Done!
modbus init
waiting for connection!
connected!

Die GPIOs liegen auf Modbus (Bit) Adresse 0-7 (die gruenen: http://elinux.org/File:GPIOs.png, beginnend mit GPIO4)

Zum 230V schalten nutze ich ein Sainsmart 8 Channel 5V Solid State Relay Module Board. Google hilft.

Gruss, Michael

Servus

hab das mal ausprobiert und hat auf Anhieb funktioniert.
Er hört aber auf Port 1502 und nicht wie in der Modbus Wiki angegeben auf 502. Nach einem Blick in die Source wars wars Problem schnell gefunden.

Hast du bzg. lesen der GPIO schon was weitergebastelt, oder kannst was zur Stabilität sagen ?
Das wäre nämlich eine gute Gelegenheit mein zickendes Velleman Board zu ersetzen.

1Wire Unterstützung klingt auch gut. Die Sache per Modbus zu erledigen hat irgendwie mehr Charme als die sonst verwendete Variante mit parsen der OW-Server Webseite.

schöne Grüße,
bb

Hmm, hab mich da grad ein wenig eingelesen.

Verstehe ich das richtig das IPS nur ein MODBUS Client sein kann.

d.h. ich kann nicht aktiv einen Status vom PI zu IPS senden.
IPS müßte demnach immer pollen ? Bähhh.

gruß
bb

Ja, es wird gepollt. Finde ich aber nicht schlimm. Die paar bytes extra im Netz stören mich nicht.
Ich bevorzuge native Funktionen (Modbus Instanz) und verzichte auf extra Skripte.

Es wäre aber auch easy den GPIO Status bei Aenderung an einen IPS Client Socket zu schicken.

Bzgl. der stabilitaet. Ich hab ein paar Tage per IPS Script eine LED togglen lassen. Keine Probleme.

Zwischenzeitlich hab ich mal einen 1wire Sensor angeschlossen (http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/temperature/)

Hier mal etwas C code zum auslesen und umrechnen:

/*
 * Copyright (C) 2013, Michael Buhr, micbuh@googlemail.com
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 * 
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	FILE *ptr_file;
	char buf[100];
	char *p;
        double temp;

	ptr_file = fopen("/sys/bus/w1/devices/10-0008019c9a57/w1_slave", "r");

	if (!ptr_file)
        return 1;

	while (fgets(buf,100, ptr_file)!=NULL)
	{};//printf("%s",buf);

	p = strstr(buf, "t=") + 2;
	p[strlen(p)-1] = 0;		//remove new line char

	temp = atof(p)/1000;		//cast to float


	printf("
 Temp: %f 
", temp);	

	fclose(ptr_file);
	return 0;
}

Bei Gelegenheit werde ich das in den Modbus code einbauen.

Gruss, Michael

Aus Netzwerksicht ist mir das auch egal.
Soweit ich das verstehe müßte aber doch trotzdem ein IPS Script trotzdem dauernd pollen. Oder liege ich da falsch ?
Das fände ich in Bezug auf schnelle Antwortzeiten blöde.

Verstehe, du bindest 1Wire über OWFS an, und ließt die von OWFS angelegte Verzeichnisstruktur aus.

Hier sehe ich echt Potential. Man damit ja eine gute und billige 1Wire-Wlan/Lan Bridge. Genau das will ich mir schon lange bauen um meine Haus-externen 1Wire potentialfrei an IPS anzubinden. Hinsichtlich Blitzschutz hab ich da zzt. nämlich eine ganz schlechtes Gewissen.

Als ich vor einigen Jahren meine Linux Rechner und Server auf Win umgestellt habe hatte ich von X eigentlich die Nase gestrichen voll. Scheint das es mir nun durch die Hintertür doch wieder reinkommt.

Meine Linux Kenntnisse waren nie besonders gut und sind nun noch mehr eingerostet, bin aber durchaus interessiert daran dieses Projekt zu unterstützen.

gruß
bb

Super Idee!

hast du es schon geschaft?

Ich würde mich brennend dafür interessieren

Hi,

Schon gesehen?

Da gibt es auch SW zum Modul.

Macht nebenher auch Funk FS20 etc.

http://busware.de/tiki-index.php?page=COC

Gruss

Andre

Gesendet von meinem B1-A71 mit Tapatalk 2

Hi Michael,

teste gerade auch mit dem RASPBERRY.
Mit Arduino habe ich mir eine eigene Kommunikation geschrieben, würde aber lieber beim RASPBERRY auf MODBUS gehen - bist Du schon weiter oder kann mir jemand eine gescheite Erkläung der modbus.h senden?

Hallo,

ich habe hier die Datei von mibu angepasst, 8Ausgänge (-1), 8 Eingänge und 1-Wire Temperaturen einlesen DS18B20).

Ich habe vor über 20Jahren das letzte mal C++ gesehen - also bitte nicht über den CODE meckern ;-)))

Installation und alles wie bei mibu, zum 1-Wire steht etwas im File.

Viel Spass

herbertf

mb_v_1_4.zip (2.9 KB)

Nette Idee :wink:

Die modbuslib ist echt gut ich verwende sie auch, relativ einfach zu benutzen…aber ich Programmieren in C.

Ich habe immer gern eine MYSQL Datenbank dazwischen also:

InputScript -> MYSQL -> Modbus OutputScript

Die Installation des Programmes hat auf dem Raspi gleich funktioniert.
In IPS habe ich eine ModBus Instanz angelegt, der Raspi zeigt verbunden.

Was muss ich nun anlegen um die 1wire Temperatursensoren abzufragen.
Wie ist eine Zuordnung möglich?

Danke
Manfred

Also wenn Du meine Files genommen hast - siehe Anhang. Die 5 Sekuenden sind natürlich nur experimentell - will soviel Daten nicht haben ;-))) Praktisch hierbei ist allerdings, dass IPS nur bei Änderungen loggt.
DEr Befehlsausgang ist analog zum 1-WIRE: 1Bit Adresse: Lese 1, Schreib: 1 - hier darf nur Lesen natürlich nicht angewählt sein
Die Eingänge (binär): ab 1Bit Adresse: Lese 8, Schreib: 8 - hier muss nur Lesen natürlich angewählt sein

Guten Morgen,

ich habe meine I/O-Schnittstellen am RASPBERRY-PI um zwei I2C-Bausteine (8Eingänge bzw. 8 Ausgänge) erweitert.

Verbunden mit der Möglichkeit über 1-Wire-Temperaturen auszulesen und alles über Modbus an IPS einzubinden ist der Raspberry für mich hausautomationstauglich ;-)))

Schönes WE

mb.zip (3.28 KB)

Ich habe nach der Anleitung Modbus auf Raspberry installiert. Möchte über Modbus Poll die Register bzw ausgänge gpio lesen/schreiben. Welche Adresse und Funktionscode muss ich bei Modbus Poll geben damit ich auslesen kann.Ich habe mit Slave ID 1 und fast alle funktionscode durchgegangen, dennoch kommt die Fehlermeldung „illegale data adress“.

Ich bedanke mich schonmal für die Antworten. MfG:confused:

Hi RxCet,

gleich als ersten IPS-Eintrag eine doch eher komplexe Schnittstelle.

Nun gut. Sieh Dir bitte den Quelltext mb.c an, von Zeile 220 bis 235 werden die GPIOs definiert (Input oder Output).

Du solltest versuchen die mb.c als Anregung zu verstehen und Dir den für Dich optimalen CODE entwerfen. Die Fehleranalyse ist mittels putty auf der Konsole des Raspberry eigentlich in Ordnung (für solch triviale Analysen). So kannst Du auch die für Dich notwendigen GPIO-Ports oder auch die beschriebenen I2C-IO-Karten einbinden.

Hier nun zwei IPS-Beispiele einmal für nur Lesen und einmal für Schreiben und Lesen, da ich mittlerweile die Rückmeldung eines Befehls (aus meiner Sicht konsequenterweise) im Raspberry-Programm erzeuge wenn der Befehl tatsächlich ausgeführt wurde (logische Trennung Befehl und Rückmeldung).

Ciao Herbert

Hallo Herbert danke erstmal für dein Antwort. Kannst du mir viellecht ein Code beispiel geben wie ich am GPIO 17 ein LED ansteuern kann. Ich verstehe das nicht so richtig.


int gpio_init(void)
{
  int n;
  printf ("GPIO Init
") ;
  if (wiringPiSetup () == -1)
    return 1 ;
  //GPIO2 (PIN3) für I2C = SDA
  //GPIO3 (PIN5) für I2C = SCL 
  //GPIO4 (PIN7) für 1-Wire  
  /*uebrige GPIOs set GPIOs to OUTPUT*/
  for(n=0;n<=7;n++) pinMode(gpio[n], OUTPUT);	//GPIO4=1-Wire in IPS Adressen 0-7 1bit 
  /*set GPIOs to INTPUT*/
  //for(n=1;n<5;n++) pinMode(gpio[n], INPUT);	//GPIO4=1-Wire in IPS Adressen 8-15 1bit nur lesen
  for(n=8;n<=15;n++) pinMode(gpio[n], OUTPUT); //HW-Adressen theoretisch als Input nutzbar 
  printf ("Init Done!
") ;
  //int wiringPiI2CSetup (int devId) ;

Und über welchen Register kann ich das auslesen bzw schreiben. Welchen fuktionscode muss ich dafür benutzen auf der Modbus seite 05, 06, 15 oder 16 ?

Hi RXCet,

am Anfang habe ich auch ein paar Tage gebraucht.

Folgende Empfehlung:

  1. Du öffnest zwei Putty-Session
  2. In der 1. machst Du ein sudo killall mb (um den laufenden Prozess zu beenden), machst dann die jeweiligen Änderungen an der mb.c, dann jeweils ein make und startest dann mittels sudo ./mb.c (wie in einem der ersten Threads beschrieben)
  3. in der 2.Putty-Session machst Du ein gpio readall und siehst Dir die Aus-bzw. Eingänge an (im ersten Schritt muss dies gehen, die LED kommt danach)

Hier werden die Typen dekliniert:
for(n=0;n<8;n++) pinMode(gpio[n], OUTPUT); //GPIO4=1-Wire in IPS Adressen 0-7 1bit
/set GPIOs to INTPUT/
for(n=8;n<16;n++) pinMode(gpio[n], INPUT); //GPIO4=1-Wire in IPS Adressen 8-15 1bit nur lesen

Hier schreibst Du einen Port:
for(n=0;n<8;n++) digitalWrite(gpio[n], mb_mapping->tab_bits[n]);

Wenn Du also Pin3 (Bit3) schreiben willst, musst Du in meinem Snapshot (Heizungspumpe (vor zwei Threads)) statt der Adresse 21 die 3 einsetzen. Als Rückmeldeadresse würde ich im ersten Schritt auch die 3 nehmen.

Dazu mittels „gpio readall“ in der 2. Session Erfolg kontrollieren - mehr ist nicht …

Ciao Herbert

Hier werden die Typen dekliniert:
for(n=0;n<8;n++) pinMode(gpio[n], OUTPUT); //GPIO4=1-Wire in IPS Adressen 0-7 1bit // ist das jetzt nur für GPIO 4 ?
/set GPIOs to INTPUT/
for(n=8;n<16;n++) pinMode(gpio[n], INPUT); //GPIO4=1-Wire in IPS Adressen 8-15 1bit nur lesen//

Hier schreibst Du einen Port:
for(n=0;n<8;n++) digitalWrite(gpio[n], mb_mapping->tab_bits[n]); // Was muss ich hier genau Schreiben ?

Danke nochmal für deine Unterstützung,
Ich habe keine IPS. Ich versuche über ein Modbus Poll (z.B Simply Modbus) die GPIO`s zu steuern und ich krieges nicht hin.Auch mit Putty nicht. Kannst du mir bitte nochmal erklären wie bei einem erstklässler.

Also wenn Du kein IPS hast, macht das hier keinen Sinn.

Da musst Du am besten ins deutsche Raspberry-Forum …

Ich würde Dir dann empfehlen die GPIOs über ein WebInterface auf dem Raspberry zu steuern, MODBUS-TCP ist dann sicher für Dich das Falsche

Über web mache ich das schon. Mir gings nur über Modbus tcp register auslesen bzw. schreiben. Aber danke nochmal für deine Hilfen.