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


von TR.0LL (Gast)


Angehängte Dateien:

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

von Ulrich K. (elektromechanikus)


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)


Lesenswert?

Hallo, Ulrich

vielen Dank für deine Antwort.

von TR.0LL (Gast)


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:

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)


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)


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/

von TR.0LL (Gast)


Lesenswert?

Kennt niemand eine Lösung?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.