Arduino Mudbus

Hallo,

bin mal ein wenig am Basteln und stehe vor einem kleinen Problem.
Ich will mein Arduino an IPS anbinden. Das ganze soll nun per Modbus erfolgen. Die Insperation hierfür habe ich von dieser Seite:

Nun habe ich mir die Library Mudbus besorgt:
https://code.google.com/p/mudbus/source/browse/Mudbus/Mudbus.h?r=8aaa42b5dccb5065ed02201af11b60b65135f039

Den ersten Sketch habe ich aufs Nötigste gekürzt:

#include <SPI.h>
#include <Ethernet.h>
#include "Mudbus.h"

Mudbus Mb;

void setup()
{
  uint8_t mac[]     = { 0x90, 0xA2, 0xDA, 0x00, 0x51, 0x06 };
  uint8_t ip[]      = { 192, 168, 178, 5 };
  uint8_t gateway[] = { 192, 168, 178, 1 };
  uint8_t subnet[]  = { 255, 255, 255, 0 };
  Ethernet.begin(mac, ip, gateway, subnet);
  //Avoid pins 4,10,11,12,13 when using ethernet shield

  delay(5000);
  Serial.begin(9600);
}

void loop()
{
  Mb.Run();
  
  //Analog inputs 0-1023
  Mb.R[1] = analogRead(A1);
}



Die Modbusfunktion habe ich mit folgendem Tool getestet:
https://oceancontrols.com.au/OCS-011.html

Nun die Konfiguration unter IPS…
Als erstes I/O Instanz mit der IP des Arduinos und den Port 52:
modbus1.PNG

Bis dahin scheint alles zu laufen. Der Arduino wird zumindest erkannt. Nun kommt der Spliter, diesen habe ich auf Modbus RTU over TCP gestellt und als Geräte-ID 0 gewählt. Die ID habe ich aus diesem Forum Eintrag rausgelesen:

modbus2.PNG

Nun habe ich, so wie im oben genanten Beitrag eine Modbusinstanz erstellt, die Einheit auf DWord (32Bit - Unsiged) gestellt, Die Leseadresse auf 1 und die Schreibeadresse auf 0. Ich nehme an das mit der Lese und schreibe Adresse das Register gemeint ist. Da ich den Wert erstmal nur auslesen möchte ist der „Nur Lesen“ Hacken aktiv. Das Intervall ist auf dem default Wert von 5000 gestellt.
modbus3.PNG

Trotz dieser Einstellung sehe ich nur dieses Traurige Bild:

Nun die große Frage… Was habe ich falsch gemacht?

Moin,

stell denn Splitter mal normal aus Modbus TCP. Dann warum liest du 32bit aus?

Nimm mal einen 16Bit wert. Die Modbus Register sind normal immer 16Bit groß.

Und ich weiß nocht mehr genau wie das war, aber lass den Hacken bei nur lesen mal weg.

Ok das Problem war wirklich der Splitter. Sobald der Modus auf „Modbus TCP“ stand, ging es sofort. Ein großen Dank an sallos.:smiley:

Bitte, aber warum ließt du 32Bit? Wie gesacht deine werde haben nur 16Bit.

Das scheint wohl kein unterschied zu machen, zumindest funktioniert es mit beiden Einträgen. Hast du eigentlich auch mal versucht einen Wert per Symcon an den Arduino zu übertragen? Habe nämlich doch noch ein Problem. Ich beschreibe es mal kurz:

Arduino Code:

#include <SPI.h>
#include <Ethernet.h>

#include "Mudbus.h"

Mudbus Mb;
//Function codes 1(read coils), 3(read registers), 5(write coil), 6(write register)
//signed int Mb.R[0 to 125] and bool Mb.C[0 to 128] MB_N_R MB_N_C
//Port 502 (defined in Mudbus.h) MB_PORT

void setup()
{
  uint8_t mac[]     = { 0x90, 0xA2, 0xDA, 0x00, 0x51, 0x06 };
  uint8_t ip[]      = { 192, 168, 178, 5 };
  uint8_t gateway[] = { 192, 168, 178, 1 };
  uint8_t subnet[]  = { 255, 255, 255, 0 };
  Ethernet.begin(mac, ip, gateway, subnet);
  //Avoid pins 4,10,11,12,13 when using ethernet shield

  delay(5000);
  Serial.begin(9600);
  
  pinMode(3, INPUT);
  pinMode(4, OUTPUT); 
}

void loop()
{
  Mb.Run();
  
  //Analog inputs 0-1023

  Mb.R[1] = analogRead(A1);


  //Analog outputs 0-255
  analogWrite(A2, Mb.R[2]); 

  //Digital inputs
  Mb.C[3] = digitalRead(3); 

  //Digital outputs
  digitalWrite(4, Mb.C[4]); 
}


Die konfiguration in Symcon ist gleichgeblieben. Die Modbus Instanz sieht so aus:
modbus5.PNG

Nun wollte ich die Variable auf true setzen und kriege die Meldung das die Variable auf nur lesen gesetzt ist. Wie man im Screen sieht, ist es aber nicht der Fall. Per Skript das gleich:
Warning: Variable wurde als „Nur-Lesen“ markiert und kann nicht verändert werden in C:\IP-Symcon\scripts\33773.ips.php on line 3
Hat jemand dazu noch eine Idee?

Ja, RTFM :wink:
http://www.ip-symcon.de/service/dokumentation/konzepte/variablen/
Michael

RTFM^^
ok so wie ich es verstehe handelt es sich dabei um eine „Status Variable“ aber warum habe ich dann die möglichkeit „Nur Lesen“ auszuwählen? Ist es überhaupt möglich Modbus Variablen mit der Musbus Library zu schreiben?

Alle StatusVariablen sind immer nur lesen. Das hat nicht direkt was mit dem Haken nur lesen in der Instanz zu tun.
Wenn du StatusVariablen beschreiben willst (und das auch geht) musst du den passenden Befehl auf die Instanz mit dem passenden Befehl ausführen.
Dadurch führt IPS im Hintergrund den Befehl aus und die Rückmeldung ist die Änderung bei der Statusvariable.
Wie in der Doku beschrieben, an der Tachonadel drehen heisst nicht das das Auto schneller wird, du musst schon eine Aktion ausführen :wink:
Z.B. ModBus_WriteRegisterDWord http://www.ip-symcon.de/service/dokumentation/modulreferenz/modbus-rtu-tcp/modbus-registerdword/
Michael

OK, ich hätte mich doch besser informieren sollen. Wusste bis dato nicht mal das es Modbus befehle gibt. Nun funktioniert auch das senden 1A. Danke noch mal an alle.

Moin,

ich habe das mit dem Bits auch mal versucht…war aber nicht ganz zufreiden es hat immer sehr lange gedauert und war nicht zuverlässig. Ich benutze jetzt nur noch INT16 und Wandel die dann in Bits um.

Ich bin noch am schreiben des Sketchs für den Arduino. Habe daher auch keine langzeit Erfahrung. Aber du hast recht, warum 32 bit belegen wenn es auch mit der hälfte geht.

[QUOTE=wowa371;236268]Hallo,

bin mal ein wenig am Basteln und stehe vor einem kleinen Problem.
Ich will mein Arduino an IPS anbinden. Das ganze soll nun per Modbus erfolgen. Die Insperation hierfür habe ich von dieser Seite:
Temperatur- und Verschlussüberwachung mittels Arduino | BPMedia

Nun habe ich mir die Library Mudbus besorgt:
https://code.google.com/p/mudbus/source/browse/Mudbus/Mudbus.h?r=8aaa42b5dccb5065ed02201af11b60b65135f039

Den ersten Sketch habe ich aufs Nötigste gekürzt:

#include <SPI.h>
#include <Ethernet.h>
#include "Mudbus.h"

Mudbus Mb;

void setup()
{
  uint8_t mac[]     = { 0x90, 0xA2, 0xDA, 0x00, 0x51, 0x06 };
  uint8_t ip[]      = { 192, 168, 178, 5 };
  uint8_t gateway[] = { 192, 168, 178, 1 };
  uint8_t subnet[]  = { 255, 255, 255, 0 };
  Ethernet.begin(mac, ip, gateway, subnet);
  //Avoid pins 4,10,11,12,13 when using ethernet shield

  delay(5000);
  Serial.begin(9600);
}

void loop()
{
  Mb.Run();
  
  //Analog inputs 0-1023
  Mb.R[1] = analogRead(A1);
}



Bei mir sagt er bei der Rot markierten stelle immer

sketch_dec28a:5: error: 'Mudbus' does not name a type
sketch_dec28a.ino: In function 'void loop()':
sketch_dec28a:22: error: 'Mb' was not declared in this scope

was für ein Arduino verwendest du denn.

Gruß
Stefan

hehe schön das mein gebastel den Weg ins Forum findet.

Stefan:
Der Include für das Mudbus sieht nicht gut aus.

Nutz mal: #include <Mudbus.h> anstatt #include „Mudbus.h“
Dann sollte es auch mit Mudbus Mb; funktionieren. Vorausgesetzt die Library wurde korrekt im Arduinoverzeichnis kopiert!

Hi, hatte nochmal ne andere Lib außem Netz gesucht, jetzt geht’s.
Danke schon mal für dein „gebastel“

Habe aber noch einige Fragen,
wenn ich beim Client Socket die IP des Arduino eingebe sagt er immer „Connect timed out“ ich kann den Arduino aber anpingen. modbus1.png

Wo finde ich das Modul ModBus RTU TCP modbus2.png

wie muß ich das schreiben wenn ich einen Ausgang schalten möchte oder wenn ich einen Wert in eine Variable ändern möchte?
Mb.R[1] = analogRead(A1);
Mb.R[1] = digitalRead(1); ???

[EDIT] hab ich in deinem anderen Beitrag gefunden [EDIT]

Danke schon mal für deine Antwort!

Gruß
Stefan

Hallo Stefan,

Siehe in der Dokumentation http://www.ip-symcon.de/service/dokumentation/modulreferenz/modbus-rtu-tcp/.

Wähle Modbus TCP und ID 1.

Wie bei PHP werden die Variablen von rechts nach links verarbeitet. Also

Mb.R[1] = digitalRead(1);

Mb.R[1] bekommt den Wert des PIN 1.

Wenn Du von IP-Symocn in den Arduino schreiben möchtest, muss das dann umgedreht werden.
Das würde dann bei einer Variablen so aussehen.

Variable = Mb.R[1]

Bei einem Pin brauchst du den Schaltbefehl z.B. digitalWrite(pinnummer,HIGH/LOW)
Siehe auch die Tutorials auf der Arduinoseite http://arduino.cc/en/Tutorial/Blink

Ich würde das so schreiben:


if (Mb.R[1] == 0){
digitalWirte(1,LOW);
} else {
digitalWrite(1,HIGH);
}

Evtl. könnte das auch gehen:

digitalWrite(1,Mb.R[1])

Weiß grad nicht ob die Funktion digitalWrite auch mit 0 und 1 anstatt LOW und HIGH umgehen kann.
//Nachtrag ja geht…http://forum.arduino.cc/index.php?topic=3068.0

Wichtig ist der pinMode(). Die Tutorials sind sehr gut auf der Seite! http://arduino.cc/en/Tutorial/DigitalPins

Achtung!!!
Wenn Du den Wert aus Mb.R[1] bidirektional nutzen möchtest. Also sowohl schreiben im Arduino als auch in IP-Symcon, musst Du dir Gedanke machen wer wann die Variable Mb.R[1] beschreiben darf. Anders als in PHP läuft der Arduino in einer Dauerschleife. Schreibst Du den READBefehl in den LOOP, dann wird dir die Variable immer durch den Arduino überschrieben. Evtl. könntest Du das mit einer weiteren BoolVariable lösen. So lange diese false ist (0) dann darf der Arduino die Mb.R[1] überschreiben Willst Du aus IP-Symocn schreiben und der Arduino soll die Variable verarbeiten dann sendest Du ein true. Für eine Variable ist das witzlos. Aber wenn du 10 Variablen bidirektional nutzen möchtest könnte das ganz gut funktionieren. Nur so als Idee.

Oh Super danke dir!

Jetzt muß ich erst mal eine Verbindung hin bekommen

Hab einen ModBus Gateway angelegt, ModBus RTU over TCP Geräte ID 1
bei Untergeordnete Instanz habe ich den Client Socket ausgewählt und beim
Client Socket hab ich die IP des Arduino und den Port 502 eingegeben wenn ich jetzt auf Übernehmen klicke
kommt die Meldung „No route to host.“, hab ich irgend etwas übersehen?

Gruß
Stefan

Ja Modbus RTU over TCP ist falsch…

Bildschirmfoto 2014-12-30 um 12.51.13.png

So muss das! RTU over TCP geht nicht!

Oh OK…hat aber leider nix gebracht

was mache ich falsch

hab nochmal grad die Netzwerkeinstellungen beim Arduino geändert auf

  uint8_t mac[]     = { 0x90, 0xA2, 0xDA, 0x00, 0x51, 0x06 };
  uint8_t ip[]      = { 192, 168, 3, 50 };
  uint8_t gateway[] = { 192, 168, 3, 1 };
  uint8_t subnet[]  = { 255, 255, 255, 0 };
  Ethernet.begin(mac, ip, gateway, subnet);
  //Avoid pins 4,10,11,12,13 when using ethernet shield

jetzt wechselt er immer zwischen Schnittstelle fehlerhaft markiert und Interface ist geöffnet

Das Du deinen PIN 4 für deine Wert nutzt ist Dir schon klar, dass das nicht funktioniert oder?


[b]//Avoid pins 4,10,11,12,13 when using ethernet shield[/b]
pinMode (4, OUTPUT);

Wenn ich mich nicht täusche nutzt das Ethernetshield den Pin.

Das könnte Deine Fehlermeldung erklären… das teilweise das Interface öffnet und teilweise nicht!

War leider nicht der Fehler.