Hallo, hab ein Problem mit Modbus, zugegeben Modbus ist nicht mein ding.. ich bin eher in der Leistungselektronik zuhause..
Vorhaben: im Endausbau sollen 3 Zähler Type Finder 7M.38.8.400.0212 per Modbus mit einem µC ausgelesen werden.
Aktuell spiele ich mit einem Zähler und einem Arduino UNO als test.
Zähler ist eingestellt auf ID 33, 19200Baud, 8N1;
lt. Anleitung sollte in Adresse 30111 und 30112 die Spannung an L3 auszulesen sein.
Ich habe die Schaltung aufgebaut, lt. Oszi werden Daten auf dem Bus gesendet, und der Zähler sollte auch antworten, da ich immer 2 Datenpakete sehen. Wenn ich die Zähleradresse ändere, ist nur 1 Paket sichtbar, ich gehe also davon aus dass der Bus an sich OK sein sollte, (Buslänge 30cm).
SoftwareSerial modbusSerial(4, 5); // RX, TX for Modbus
ModbusMaster node; // ModbusMaster Objekt
void setup() {
Serial.begin(9600); // Serielle Kommunikation mit der Baudrate 9600 für Debugging
modbusSerial.begin(19200); // Serielle Kommunikation mit der Baudrate 19200 für Modbus
node.begin(33, modbusSerial); // ModbusSlave ID und Serielle Objekt initialisieren
}
// Senden einer Modbus-Anfrage an Slave-Adresse 33, Funktion 04, Register 30111 (2 Register lesen)
result = node.readInputRegisters(30111, 2); // Lesen von 2 Input-Registern ab Adresse 30111
if (result == node.ku8MBSuccess) { // Überprüfen, ob das Lesen erfolgreich war
registerValue = node.getResponseBuffer(0); // Wert des ersten Registers in der Antwort
Serial.print("Register 30111: ");
Serial.println(registerValue);
registerValue = node.getResponseBuffer(1); // Wert des zweiten Registers in der Antwort
Serial.print("Register 30112: ");
Serial.println(registerValue);
} else {
Serial.println("Fehler beim Lesen der Register!");
}
delay(1000); // Wartezeit zwischen den Anfragen
}
evtl. kann mir jemand helfen, mit Bussystemen bin ich nicht wirklich vertraut, wo liegt mein Fehler?
Irgendein Schwachkopf ist mal auf die Idee gekommen, beim Modbus-Protokoll in den Registernummern zusätzlich die Art des Zugriffs (Input Register, Holding Register, Coil, Input State) zu codieren, und dazu zur /eigentlichen/ Registernummer einen willkürlichen Offset von entweder 10000, 30000 oder 40000 zu addieren.
Das ist komplett bescheuert, weil es einseits nichts mit dem zu tun hat, was der Modbus /tatsächlich/ macht, und weil es andererseits völlig sinnlos die Anzahl der verfügbaren Register reduziert.
Tatsächlich aber werden auf dem Modbus /je Typ/ 65536 Register unterstützt, die von 0 an aufsteigend durchnumeriert werden.
Betrachtet man Dein Beispiel (findermodbus.png), so werden dort zwei Register ausgelesen, beginnend bei 0x6b (107).
Der erläuternde Text in Deinem Bild nennt dieses Register 30107.
Also ändere Dein Programm dahingehend, daß der schwachsinnige Pseudo-Offset weggelassen wird:
1
result=node.readInputRegisters(111,2);// Lesen von 2
Ja, Treiber IC MAX485 ist vorhanden, Abschlusswiderstände sind vorhanden,
Der Bus sollte funktionieren, wenn ich mit den Oszi schauen kommt wenn ich die
Adresse 33 anspreche nach dem senden sofort eine Antwort, wenn ich eine andere Adresse anspreche, welche es nicht gibt, kommt keine Antwort.
Kann mich leider immer nur abends hinsetzen, denk evtl. liegt es am Code..
Ich habe gerade etwas rumgemessen, dabei viel mir auf:
die Umschaltung lesen/schreiben läuft nicht, DE/RE sind im High, damit sollte schreiben möglich sein, jedoch kein lesen.
Mit dem Oszi kann ich auf TX daten sehen welche auch nach dem Max485 vorhanden sind, auf der Busleitung kommt auch eine Antwort, diese wird jedoch nicht am RX weiter zum Arduino gegeben, da DE/RE immer auf high sind.
beide Pins sind an Pin2 des Arduinos angeschlossen, jedoch werden diese im im Programm nirgends deklariert/initiert,
Ich kenne mich mit Modbus nicht aus, macht die ModBusmaster - LIB die Umschaltung schreiben/lesen nicht automatisch im Hintergrund mit?
Welchen Pin du für Rx/Tx nimmst kannst du frei entscheiden.
Du musst schon vor den senden den Port setzen und danach zurück. (Je nach Polarität des RE/TE deines RS485 Transceivers.
Danke für die Antworten,
ich hab jetzt einen Code der läuft und die Spannung aus den beiden Registern ausliest,
Fehler waren:
DE/RE-Pin des Max485 funktionierten nicht und auch die Registeradressen
stimmen so nicht wie im Datenblatt angegeben,
Spannung L3 (REG 30111 und 30112) müssen wie oben von Harald K. geschrieben um den Wert von jeweils 10000/20000/30000 reduziert werden, dann kommen die Wert..
Ich muss mich jetzt noch mit den zusammensetzten der beiden Register zu einem Spannungswert beschäftigen, aber soweit läuft der Code aktuell..
Ja, die 220 Stimmen schon, Zähler ist aktuell an einem Regeltrenntrafo angeschlossen, im Display wird auch der gleiche Wert angezeigt , wie im Datenstrom, Werte ändern sich auch beide wenn ich die Spannung ändere
evtl. sind ja für jeden Parameter der verarbeitet wird generell 2
Register reserviert und das höhere Register bleibt dann leer?
Nein. In der Tabelle ab S. 34 steht das alles fein säuberlich drin, in der Spalte "Data" steht, wie der Wert zu interpretieren ist (für R.30111 steht da T5), und in den ersten beiden Spalten steht, ob ein oder zwei Register gelesen werden müssen.
Bei 30111 steht in der zweiten Spalte 30112, also ist logisch, daß die beiden Werte zu kombinieren und dann nach der Typbeschreibung T5 zu interpretieren sind.
Ich habe schon deutlich schlechtere Modbus-Dokumentationen gesehen.
Ok ich glaub jetzt hab ich verstanden.
REG 111 REG 112
FF00 2205
FF = Exponent-1 00 2205 Messwert
FE = Exponent-2
FD = Exponent -3
Um den eigentlichen Wert zu ermitteln darf ich nicht direkt beide Register kpl. verknüpfen, da ich dann ja das FF (beiden höchsten stellen) mit verrechne.