Modbus Zähler auslesen mit Arduino UNO

Hallo,
ich möchte einen ModbusZähler von Finder mit Modbus Schnittstelle auslesen. Modbus ist per Software Serial an den Arduino angeschlossen, Lib = ModbusMaster.h, verwendet wir dein Max485;

Mein Problem, ich bekomme keine Daten vom Zähler geschickt, soweit ich es beurteilen kann, liegt das Problem im Bereich des MAX485;

soweit ich dass mit einem Oszi messen kann, sind auf dem Bus zum Zähler Daten unterwegs, und wenn die ID des Zählers vorhanden ist, kommen auf dem Bus sofort nach den Senden eine Antwort zurück. Auf der TTL Seite des MAX ist auf TX-Leitung im sec. Takt eine Anfrage zu sehen, auf der RX kommt jedoch keine Antwort mehr an. ? Ich denke das Problem liegt an den RE/DO Pins , diese sind parallel geschaltet an Pin 3 des Uno's; Signal ist dauerhaft high; soweit ich den Bus bislang verstanden hab sollte high für senden und low für empfangen stehen,
aber wieso schaltet der Uno die Steuerleitung nicht um?
Was mir komisch vorkommt, im Code ist nirgends definiert an welchem Pin die Steuerleitung angeschlossen ist. ist dieser evtl. fest in der ModBusMaster.h definiert und ich die Steuerleitung an einem falschen Pin angeschlossen? oder mache ich sonst etwas falsch? ?

Ich hab mit Modbus (RS485) bislang überhaupt keine Erfahrung, ist mein erstes Projekt mit Modbus.

Eigentliche Aufgabe sollte sein:
3 Drehstromzähler (Finder 7M.38 Modbus') auszulesen, damit ich die jeweilige aktuelle Gesamtleistung in W je Zähler bekomme. Die Werte möchte ich dann verrechnen und entsprechend meinen Pufferspeicher beheizen, also eine Art Nulleinspeise-PV Steuerung aufbauen. Die Laststeuerung an sich steht soweit schon fest, die Heizkörper werden in 26 Schaltstufen '(reihe, parallell, gemischt) verschaltet und heizen dann je nach möglicher Leistung; Restliche Leistung wird als Überschuss ins Netz eingespeist.

Mein Problem ist aktuell das Auslesen der Zähler;
Geräteadresse ist 33, 8N1; 19200Baud;
der gewünschte Wert liegt in 30140 und 30141;

Ich denke das Senden funktioniert, da auf dem Bus wenn ich ID33 anspreche auch eine Antwort zu sehen ist, welche bei anderen Id's fehlt, den Inhalt der Antwort kann ich aktuell jedoch nicht sagen.

Ich hoffe hier ist ein Spezialist für Modbus unterwegs der mir helfen kann .. komme nicht weiter..

Hier der Code den ich für die ersten Tests verwendet hab:
er sollte die beiden Register auslesen und den Inhalt einfach anzeigen.



#include <ModbusMaster.h>    // Modbus Master Library
#include <SoftwareSerial.h>  // SoftwareSerial Library

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
}

void loop() {
  uint16_t registerValue;
  uint8_t result;

  // Senden einer Modbus-Anfrage an Slave-Adresse 33, Funktion 04, 
Register 30140 (2 Register lesen)
  result = node.readInputRegisters(30140, 2);  // Lesen von 2 
Input-Registern ab Adresse 30140

  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
}

ich denke mein primäres Problem liegt in der Steuerung der Datenrichtung RE/DO Pin's;
Auf der TX Leitung des Unos sind die Daten da, auf der RX ist nicht zu sehen.

Vielen Dank!

Und wo wird der Pin3 geschaltet?

schau dir noch mal die Beispiele der ModbusMaster Library an,
da gibt es je eine callback funktion preTransmission und postTransmission in der der RE/DO pin geschaltet wird. Im Setup werden die Callback Funktionen dem Objekt bekannt gegeben.

Für die Lesbarkeit deines Sketches ... drück mal STRG-T in der IDE.

Ja, ich hab vml. diesen Pin nicht deklariert, daher funktioniert die Umschaltung lesen / schreiben nicht.
Ich finde jedoch nirgends wie wie dies gemacht wird, und wie die Umschaltung gesteuert wird.
Ich schaue mir heute Abend das Beispiel nochmal an.

So habe ich das gemacht, hier wird PV Anlage ausgelesen, der Prinzip ist bis void loop ist gleich

#include <ModbusMaster.h>

#define MAX485_DE 2 //  Pin Anpassen 
#define MAX485_RE_NEG  2 
// instantiate ModbusMaster object
ModbusMaster node;
void preTransmission()
{
  digitalWrite(MAX485_RE_NEG, 1);// 1 =High
  digitalWrite(MAX485_DE, 1);
}
void postTransmission()
{
  digitalWrite(MAX485_RE_NEG, 0); //0=Low
  digitalWrite(MAX485_DE, 0);
}


void setup() {
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  // Init in receive mode
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
  // Modbus communication runs at 115200 baud
  // // Modbus slave ID 1 = Tracer Adresse
  node.begin(1, Serial);
  // Callbacks allow us to configure the RS485 transceiver correctly
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
}

void loop() {
/*  result = node.readInputRegisters(0x3100, 16);// 16 Stellen im Register 3100 auslesen
  //PV Daten
  if (result == node.ku8MBSuccess)
  {
    float pvVolt = node.getResponseBuffer(0x00) / 100.0f; //Tracer PV Volt
  }
*/
}

man kann es schon auch kompliziert machen.

ich würd's so machen:

constexpr uint8_t modbusEnablePin = 5;           // The GPIO used to control the MAX485 TX pin. Set to 255 if you are not using RS485 or a selfsensing adapter

// this function will be called before the client transmits data
void preTransmission() {
  digitalWrite(modbusEnablePin, HIGH);
}

// this function will be called after the transmission
void postTransmission()  {
  digitalWrite(modbusEnablePin, LOW);
}

Ok. RE, und DE hatten vor erst eigne Pins am Nano (10 und 11) erst bei umschreiben auf ESP8266 habe RE und DE auf einen Pin gesetzt.
@noiasca vor 2J hast du mir dabei geholfen :wink:

Dort habe ich die RE und DE nicht angeklemmt bzw. falsch verdrahtet :wink:
Sind ja fast 2J .

darum wird der Code von mir auch nicht laufen, bin erst abends wieder daheim und teste es nochmal wie oben beschrieben.

gibts es irgendwo eine Beschreibung über die Funktionen der Lib Modbus?

Vielen Dank für die viele Hilfe!

ich hab jetzt einen Code der mir die Spannung ausliest..
Problem war tatsächlich der nicht deklarierte EnablePin und noch weitere kleinere Sachen.

Aktuell lese ich Register 30111 und 30112 aus
Wert 30111 : 65280 <- sagt mir aktuell nichts
Wert 30112 : 2219 <- ist die Spannung an L3 221,9V

Was mir noch nicht klar ist ist der Inhalt des jeweils höheren Registers 65280,

ich muss jetzt noch die beiden Register zusammensetzen und das Programm erweitern damit ich auch die aktuelle Gesamtleistung in Watt auslesen kann. Die Werte liegen in 30140 und 30141; hier muss ich dann die beiden Register zusammensetzten da ein Register vml nicht für den Messbereich des Zählers ausreicht.

Wichtig beim Auslesen der Register ist diese nicht mit 30111 anzusprechen sondern lediglich 111,
hier muss ein Offset von 30000 abgezogen werden (diesen Tipp habe ich im microcontroller.net Forum erhalten! Danke!)

#include <ModbusMaster.h>    // Modbus Master Library
#include <SoftwareSerial.h>  // SoftwareSerial Library

SoftwareSerial modbusSerial(4, 5);  // RX, TX for Modbus
ModbusMaster node;                  // ModbusMaster Objekt

constexpr uint8_t modbusEnablePin = 2;           // The GPIO used to control the MAX485 TX pin. Set to 255 if you are not using RS485 or a selfsensing adapter


void setup() {

  pinMode (modbusEnablePin, OUTPUT); //Max485 Steuerpin als Ausgang.

  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

  //für die ModbusLib zur Steuerung der ModbusEnablePins!
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
}

// this function will be called before the client transmits data
void preTransmission() {
  digitalWrite(modbusEnablePin, HIGH);
}

// this function will be called after the transmission
void postTransmission()  {
  digitalWrite(modbusEnablePin, LOW);
}


void loop() {
  uint16_t registerValue0;
  uint16_t registerValue1;
  uint8_t result;


  // Senden einer Modbus-Anfrage an Slave-Adresse 33, Funktion 04, Register 30111 (2 Register lesen)


  result = node.readInputRegisters(111, 2);  // Lesen von 2 Input-Registern ab Adresse 30111


  if (result == node.ku8MBSuccess) {  // Überprüfen, ob das Lesen erfolgreich war
    registerValue0 = node.getResponseBuffer(0);  // Wert des ersten Registers in der Antwort
    Serial.print("Register 30111: ");
    Serial.println(registerValue0);
    registerValue1 = node.getResponseBuffer(1);  // Wert des zweiten Registers in der Antwort
    Serial.print("Register 30112: ");
    Serial.println(registerValue1);


  } else {
    Serial.println("Fehler beim Lesen der Register!");
  }

  delay(1000);  // Wartezeit zwischen den Anfragen
}

eines der Register auf 32bit casten und um 16bit shiften, das andere Register addieren.
Am besten im Datenblatt nachsehen was wohin gehört.

Im anderen Forum bescheid geben, dass es hier weitergeht - oder hier bescheid geben, dass dir wo anders geholfen wird.
Die Frage an zwei Ecken abkippen und doppelt arbeiten lassen, ist - zumindest hier - nicht gern gesehen. Stichwort Crosspost.

ich mach schon hier weiter!

die Register zusammenführen
uint32_t Volt = (registerValue0 << 16) | registerValue1; // beiden Registerwerte zu einem 32-Bit
float U_L3 = ((float)&Volt); // Interpretiere den 32-Bit Integer als Float-Zahl
und dann sollte die Spannung rauskommen,

Was mich etwas verwundert:
ich bekomme per Bus übermittelt
Reg 30111 : 65280
Reg 30112 : 2205

der Wert in 30111 irritiert mich etwas,
der Wert in 20112 entspricht der Spannung an L3 = 220,5V

Was erwartest Du denn da?
Vielleicht liegt es ja einfach auch nur daran, das der Gültigkeitsbereich der Variablen für Reg 30111 nicht passt? Oder vielleicht der Wert nur ein 16bit-Inhalt hat, das was Du erwartest aber 32bittig sein soll?

https://www.mikrocontroller.net/topic/553664#new

da sich der passende Wert im Reg30112 befindet würde ich eigentlich erwarten dass Reg30111 leer ist.

In @Moko's Link findet sich auch:

Register 30111 ist Hex 0xFF00 So einen Wert finde ich immer verdächtig.

Allerdings kann ich mir nicht vorstellen, wofür man mehr als 16 Bit für einen Wert mit der Einheit 0,1V in einem normalen Drehstromzähler braucht.

ja, evtl. sind ja für jeden Wert generell 2 Register reserviert, wenn nicht benötigt bleibts unbenutzt?

Finder selbst kann zum Modbus nichts sagen, was nicht im Datenblatt steht...

Finder Stromzähler auswerten ModBus - IP-Symcon 4.x/5.x/6.x - IP-Symcon Community schon gesehen?

nein kannte ich bislang noch nicht.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.