Energiezähler mit Modbus aulesen

Hallo! Ich habe ein Problem mit den Werten, ausgelesen von einem Energiezähler SDM630-Modbus mit Hilfe eines UNO's.
Die Kommunikation steht, es wurde alles so aufgebaut wie hier beschrieben: https://www.ob121.com/doku.php?id=de:project:modbus_rtu_uno_master_sw_serial
Wenn ich nun jedoch das Register "POWERTOTAL 0x0034 //W" auslese, dann bekomme ich bei Null Last eine 0 zurück, was ja auch stimmt. Bei 24 Watt Last jedoch den Wert 16830. Ich sitze nun schon seit Stunden und finde den Fehler nicht. Wo könnte der liegen? Anbei mein Testprogramm (Beispiel aus public domain - angepasst an meine Bedürfnisse):

#include <ModbusRtu.h>
#include <SoftwareSerial.h>

// data array for modbus network sharing
uint16_t au16data[16];
uint8_t u8state;
#define SSerialTxControl 10

SoftwareSerial mySerial(2, 3);//Create a SoftwareSerial object so that we can use software serial. Search "software serial" on Arduino.cc to find out more details.

/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  port : serial port
 *  u8txenpin : 0 for RS-232 and USB-FTDI 
 *               or any pin number > 1 for RS-485
 */
Modbus master(0); // this is master and RS-232 or USB-FTDI via software serial

/**
 * This is an structe which contains a query to an slave device
 */
modbus_t telegram;

unsigned long u32wait;

void setup() {
  Serial.begin(9600);//use the hardware serial if you want to connect to your computer via usb cable, etc.
  master.begin( &mySerial, 9600, SSerialTxControl );
  master.setTimeOut( 2000 ); // if there is no answer in 2000 ms, roll over
  u32wait = millis() + 1000;
  u8state = 0; 
}

void loop() {
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1: 
    telegram.u8id = 1; // slave address
    telegram.u8fct = 4; // function code (this one is registers read)
    telegram.u16RegAdd = 0x0034; // start address in slave
    telegram.u16CoilsNo = 1; // number of elements (coils or registers) to read
    telegram.au16reg = au16data; // pointer to a memory array in the Arduino

    master.query( telegram ); // send query (only once)
    u8state++;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 2000; 
     
        Serial.println(au16data[0]); //Or do something else!
        Serial.println("----------------------");
        delay(2000);
       
    }
    break;
  }
}

Danke für Eure Unterstützung!
LG, M

Das sind Fließkommawerte, keine Ganzzahlen. Wenn du deine 16830 in hexadezimalen Zahlen schreibst, ist das 0x41BE. Das ist der erste Teil einer IEEE754-float-Darstellung. Du musst noch ein weiteres Register lesen, um auf die vollen 32 Bit zu kommen. Nehmen wir an, da stünden nur Nullen drin, bekommst du 0x41BE0000, und das ist die Darstellung des Wertes 23,75.

1 Like

Danke für die schnelle Antwort!
Da ich ein Arduino - Neuling bin, kannst du mir bitte verraten wie ich das mache?
Wenn ich also zwei Registerwerte habe, zum Beispiel au16data[0] und au16data[1],
wie bekomme ich da meinen Wert ? Danke und Sorry ...

Das kommt ein bisschen auf die Reihenfolge der Bytes an, die der Server schickt.

Der schlichteste Versuch wäre "wird schon stimmen" - dann könntest Du

union {
  float wert;
  uint16_t words[2];
} overlay;
overlay.words[0] = au16data[0];
overlay.words[1] = au16data[1];
Serial.printf("%8.2f\n", overlay.wert);

schreiben. Wenn Du Pech hast, musst Du die Worte 0 und 1 vertauschen, und wenn noch mehr Pech, auch die Bytes innerhalb der Worte :laughing:

1 Like

Wow! Du bist ja schnell unterwegs!
Wie gesagt, bin ich ein kompletter Anfänger ....
Was mache ich mit dieser Fehlermeldung:

C:\Users\meki01\Documents\Arduino\Strommessung_MODBUS_ORIG\Strommessung_MODBUS_ORIG.ino: In function 'void loop()':
Strommessung_MODBUS_ORIG:93:8: error: 'class HardwareSerial' has no member named 'printf'; did you mean 'print'?
 Serial.printf("%8.2f\n", overlay.wert);
        ^~~~~~
        print
exit status 1
'class HardwareSerial' has no member named 'printf'; did you mean 'print'?

Arduino... :roll_eyes:
Versuche mal Serial.println(overlay.wert); stattdessen.

Nimmst du auch Aufträge an?
Wenn ich dir den Zähler schicke und du mir ein passendes Programm für einenn UNO oder NANO schreibst .... Was würde mich das kosten?
LG, M

Das hat er geschluckt .... Es kommt aber als Wert immer 0.00 Ich spiel mal ein wenig rum, vielleicht wird's ja noch was .... Danke vorerst!

Druck' mal das ganze au16data-Array in Hexadezimal aus und poste es hier (Serial.print(au16data[i], HEX);).

Und Aufträge - nein, ich habe schon genug Spaß! :wink:

Habe jetzt words[0] und words[1] vertauscht. So funktioniert es nun - Super!

      union {
  float wert;
  uint16_t words[2];
} overlay;
overlay.words[0] = au16data[1];
overlay.words[1] = au16data[0];
Serial.println(overlay.wert);

Danke dir! Ich schau mal wie weit ich komme mit meinem Projekt. Darf ich mich bei Problemen wieder melden?

Der Post "au16data-Array in Hexadezimal" kommt in Kürze.

Bei 162 Watt lese ich folgendes aus (letzter Wert ist der gewünschte)

12:02:52.302 -> Register 0x0C :17186
12:02:52.302 -> Register 0x01 :0
12:02:52.336 -> Register 0x02 :0
12:02:52.336 -> Register 0x03 :0
12:02:52.370 -> Register 0x04 :0
12:02:52.370 -> Register 0x05 :0
12:02:52.404 -> Register 0x06 :0
12:02:52.437 -> Register 0x07 :0
12:02:52.437 -> Register 0x08 :0
12:02:52.471 -> Register 0x09 :0
12:02:52.471 -> 162.00
12:02:52.471 -> 4322
------------------

Bei Null Watt sind es folgende Werte:

12:04:28.745 -> Register 0x0C :0
12:04:28.745 -> Register 0x01 :0
12:04:28.779 -> Register 0x02 :0
12:04:28.779 -> Register 0x03 :0
12:04:28.813 -> Register 0x04 :0
12:04:28.813 -> Register 0x05 :0
12:04:28.847 -> Register 0x06 :0
12:04:28.847 -> Register 0x07 :0
12:04:28.881 -> Register 0x08 :0
12:04:28.915 -> Register 0x09 :0
12:04:28.915 -> 0.00
12:04:28.915 -> 0

Bei ca. 24 Watt (jetzt mit dem richtigen Register - Total System Power)

12:16:24.347 -> Register 0x34 :16836
12:16:24.347 -> Register 0x01 :0
12:16:24.347 -> 24.50
12:16:24.347 -> 41C4

Auch Einspeisung funktioniert :slight_smile:

2:28:04.496 -> Register 0x34 :50032
12:28:04.496 -> Register 0x01 :0
12:28:04.530 -> -240.00
12:28:04.530 -> C370

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