SOLIS Mini 1000 4G über Modbus auslesen

Gast #6311853
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:
1
#include <SoftwareSerial.h>
2
#include <Wire.h>
3
#include <LiquidCrystal_I2C.h>
4

5
#define rxPin 2
6
#define txPin 3
7
#define DataEnablePin A0
8

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

14
float dataReceived = 0.00;
15

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

19
LiquidCrystal_I2C lcd(0x3F, 20, 4);
20

21
void setup() {
22
  pinMode(DataEnablePin, OUTPUT);
23
  digitalWrite(DataEnablePin, LOW);
24
  mySerial.begin(9600);
25
  Serial.begin(115200);
26
  lcd.begin();
27
  lcd.backlight();
28

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

31
}
32

33
void loop() {
34
  uint8_t modArr[9];
35

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

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

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

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

49
  digitalWrite(DataEnablePin, HIGH);
50
  delayMicroseconds(20);
51
  mySerial.write(modArr, FRAMESIZE - 1);
52
  mySerial.flush();
53
  delayMicroseconds(10);
54
  digitalWrite(DataEnablePin, LOW);
55

56

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

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

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

68
  lcd.print("F:");
69
  lcd.setCursor(3,0);
70
  lcd.print(dataReceived);
71
  lcd.setCursor(10,0);
72
  lcd.print("Hz");
73
  lcd.home();
74

75
  delay(2500);
76

77
}
78

79
uint16_t calculateCRC(uint8_t *array, uint8_t num) {
80
  uint16_t _crc, _flag;
81
  _crc = 0xFFFF;
82
  for (uint8_t i = 0; i < num; i++) {
83
    _crc = _crc ^ array[i];
84
    for (uint8_t j = 8; j; j--) {
85
      _flag = _crc & 0x0001;
86
      _crc >>= 1;
87
      if (_flag)
88
        _crc ^= 0xA001;
89
    }
90
  }
91
  return _crc;
92
}


[1] 
https://www.scss.tcd.ie/coghlan/Elios4you/RS485_MODBUS-Hybrid-BACoghlan-201811228-1854.pdf
https://github.com/RobertSmart/ginlong_RS485
Angehängte Dateien:
#6311963
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
Gast #6312711
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
Angehängte Dateien:
#6313663
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren