Forum: Haus & Smart Home SOLIS Mini 1000 4G über Modbus auslesen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von TR.0LL (Gast)


Angehängte Dateien:
  • wr.sr (998 Bytes, 9 Downloads)

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte einen SOLIS Mini 1000 4G Wechselrichter mit einem Arduino 
auslesen. Wenn ich ein Register (z.B.: 33094)[1] probiere Auszulesen 
bekomme ich "Error 2: Illegal data address" zurück (siehe response.png).

Die Anfrage scheint richtig zu sein (siehe request.png).

Kennt jemand eine Lösung?

Hier der Arduino Code:
#include <SoftwareSerial.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define rxPin 2
#define txPin 3
#define DataEnablePin A0

#define slaveID 0xA
#define regRequested 33050
#define numRegReq 0x1
#define FRAMESIZE  9                                   //size of out/in array

float dataReceived = 0.00;

SoftwareSerial mySerial (rxPin, txPin);
uint16_t calculateCRC(uint8_t *array, uint8_t num);

LiquidCrystal_I2C lcd(0x3F, 20, 4);

void setup() {
  pinMode(DataEnablePin, OUTPUT);
  digitalWrite(DataEnablePin, LOW);
  mySerial.begin(9600);
  Serial.begin(115200);
  lcd.begin();
  lcd.backlight();

  Serial.println("---- STARTING ----");

}

void loop() {
  uint8_t modArr[9];

  modArr[0] = slaveID; // Slave ID
  modArr[1] = 0x04;    // Object type

  modArr[2] = highByte(regRequested);
  modArr[3] = lowByte(regRequested);

  modArr[4] = highByte(numRegReq);
  modArr[5] = lowByte(numRegReq);

  uint16_t temp = calculateCRC(modArr, FRAMESIZE - 3);
  modArr[6] = lowByte(temp);
  modArr[7] = highByte(temp);

  digitalWrite(DataEnablePin, HIGH);
  delayMicroseconds(20);
  mySerial.write(modArr, FRAMESIZE - 1);
  mySerial.flush();
  delayMicroseconds(10);
  digitalWrite(DataEnablePin, LOW);


  if (mySerial.available() >= FRAMESIZE) {

    for (uint16_t n = 0; n < FRAMESIZE - 2; n++) {
      modArr[n] = mySerial.read();
    }
  }

  if (modArr[0] == slaveID) {
    dataReceived = word(modArr[3], modArr[4]) / 100.00f;
  }

  lcd.print("F:");
  lcd.setCursor(3,0);
  lcd.print(dataReceived);
  lcd.setCursor(10,0);
  lcd.print("Hz");
  lcd.home();

  delay(2500);

}

uint16_t calculateCRC(uint8_t *array, uint8_t num) {
  uint16_t _crc, _flag;
  _crc = 0xFFFF;
  for (uint8_t i = 0; i < num; i++) {
    _crc = _crc ^ array[i];
    for (uint8_t j = 8; j; j--) {
      _flag = _crc & 0x0001;
      _crc >>= 1;
      if (_flag)
        _crc ^= 0xA001;
    }
  }
  return _crc;
}


[1] 
https://www.scss.tcd.ie/coghlan/Elios4you/RS485_MODBUS-Hybrid-BACoghlan-201811228-1854.pdf
https://github.com/RobertSmart/ginlong_RS485

von Ulrich K. (elektromechanikus)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Tr.oll,

dein Modbus Request ist syntaktisch richtig. Du bekommst daher auch eine 
gültige Modbus Error Response zurück.
Der "Error 2: Illegal data address" ist eindeutig, deine aufgerufene 
Registeradresse existiert im angesprochenen Gerät nicht.

Grund ist die Codierung der Registeradressen im Function Code.
In deinem Fall greift Function Code 4 auf 3x Input Register zu, d.h. die 
3x sind implizit und deine gewünschte Adresse ist nur der Offset in 
diesen Bereich.

Aus der Modbus Bibel (Modicon Modbus Protocol Reference Guide 
PI–MBUS–300 Rev. J)   (http://modbus.org/docs/PI_MBUS_300.pdf):

Here is an example of a request to read register 30009 from slave device 
17:

Field Name               (Hex)
Slave Address             11
Function                  04
Starting Address Hi       00
Starting Address Lo       08
No. of Points Hi          00
No. of Points Lo          01
Error Check (LRC or CRC)  ––

Figure 16 Read Input Registers – Query

Du musst also 30000 von diener Zieladress abziehen.
Ei weiterer Knackpunkt ist die Zählweise der Register die in Geräten bei 
0 oder 1 anfangen kann. Modicon begann bei 1 und Register 30001 hat im 
Protokoll den Index 0 (siehe auch das Beispiel)

Ich hoffe das hilft dir weiter.

Gruß
Ulrich

von TR.0LL (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo, Ulrich

vielen Dank für deine Antwort.

von TR.0LL (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ulrich K. schrieb:
> Du musst also 30000 von diener Zieladress abziehen.

Jetzt bekomme ich keinen Fehler mehr, aber immer noch keine stimmenden 
Daten.

von TR.0LL (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt bekomme ich keinen Fehler mehr vom Wechselrichter (SOLIS Mini 1000 
4G) zurückgeliefert, sondern Werte die keinen sinn Ergeben. Wenn ich 
z.B.:  den Monat abfrage (Register 33023) bekomme ich immer eine 0x000B 
(11) zurück (Zeit und Datum sind am Wechselrichter richtig eingestellt.

Kennt jemand einen Weg, um an die echten Werte zu kommen (in dem Fall 
der Aktuelle Monat)?

Vielen Dank
TR.0LL

von Ulrich K. (elektromechanikus)


Bewertung
0 lesenswert
nicht lesenswert
Hallo TR.0LL

lade dir ein "modbus master tool" (Google) auf den PC.
Damit ist es einfach ganze Bereiche von Registern einzulesen und an Hand 
der Inhalte eine Orientierung über die Adressbereiche zu erhalten.
Plus/Minus eine Adresse Abweichung habe ich in meiner ersten Antwort 
schon erwähnt, liefert in deinem Beispiel aber auch keinen erkennbar 
sinnvollen Wert.

Gruß
Ulrich

von TR.0LL (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe es gerade eben mal mit einem ModbusMasterTool [1] probiert, 
bekomme aber immer noch keine Passenden Werte (z.B.: Register 33023 
liefert jetzt eine 3072 zurück.). Hat jemand eine Idee an was das liegen 
könnte?

Vieln Dank
TR.0LL

[1]http://users.telenet.be/modbus/

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.