Forum: PC-Programmierung RS485 Modbus per Libmodbus im Raspberry PI auslesen


von Peter B. (mallert)


Lesenswert?

Hallo,

ich bin zurzeit an der Auswertung eines Smart Meters per Raspberry PI. 
Leider beruhen meine C + Bus Kentnisse eher im Tryn Error Bereich.

Der Smartmeter (Janitza UMG104) soll per RS485 Modbus ausgelesen werden.
Dazu habe ich ein biliigen RS485-USB Umsetzer am Pi. Als Software habe 
ich die Bibilothek Libmodbus dazugezogen (www.libmodbus.org bzw die 
Dokumentation unter http://libmodbus.org/docs/v3.0.6/)

Die Anbindung - connect scheinen soweit zu funktionieren (bei 
abgezogegen USB erhalte ich die entsprechenden Fehlermeldungen)

Bei dem eigentlichen auslesen als Master komme ich leider nicht weiter.

Fragen:
-Wie muss das auslesen mit dem Aufruf modbus_mapping_new() korrekt 
entstehen? Ich komme mit der Dokumentation nicht weiter- Als Beispiel 
würde ich gerne das Register 19000 auslesen (das ist die Spannung - 
müsste also um die 230 liegen)

-Sollte als Anfänger eher eine andere Bibilothek/ andereren Weg genommen 
werden?

Danke!

p.S: Ziel des Projektes sind die Daten in den Volkszähler (Server 
bereits aktiv) zu laden.

Aktueller Code - while Schleife zurzeit auskommentiert:
1
#include <iostream>
2
#include <string.h>
3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <stdint.h>
6
#include <errno.h>
7
8
#include "modbus.h"
9
10
using namespace std;
11
12
int main(void)
13
{
14
  
15
int test=-1;            //Variable zur Testabfrage
16
modbus_mapping_t *mb_mapping;
17
18
19
cout << "Modbus Master Programm startet..." << endl;
20
cout << "libmodbus Version:" LIBMODBUS_VERSION_STRING << endl;
21
22
modbus_t *ctx;
23
24
  ctx = modbus_new_rtu ("/dev/ttyUSB0", 9600, 'N', 8, 2);
25
    if (ctx == NULL) 
26
    {
27
    cout<<"Fehler ABBRUCH \n";
28
    return -1;
29
    }
30
    else
31
    {
32
    cout<<"Parameter der Verbindung:\n";
33
    cout<<"BAUD:      9600\n";
34
    cout<<"Parity:      none\n";
35
    cout<<"Bits:       8\n";
36
    cout<<"Stop-Bit:    2\n";
37
    cout<<"Stop-Bit:    1\n\n";
38
    }
39
    
40
modbus_set_slave(ctx , 1);
41
cout<<"Slave Adresse:  1\n";
42
43
test = modbus_connect(ctx);
44
  if (test == -1) 
45
  {
46
  cout<<"Verbindung inaktiv ABBRUCH \n";
47
  return -1;
48
  }
49
  else
50
  {
51
  cout<<"Verbindung aktiv\n";
52
  }
53
54
/*
55
while(1)
56
{
57
58
mb_mapping = modbus_mapping_new(0,0,0,0); 
59
//(int nb_bits, int nb_input_bits, int nb_registers, int nb_input_registers);*
60
61
  if (mb_mapping == NULL)
62
  {
63
  cout<<"Verbindung inaktiv ABBRUCH \n";
64
  return -1;
65
  }
66
  else
67
  {
68
  cout<<"Verbindung aktiv\n";
69
  }
70
71
}    
72
*/
73
74
  cout<<"Ausserhalb der Schleife, Verbindungen werden geschlossen";  
75
  
76
  modbus_close(ctx);
77
  modbus_free(ctx);
78
  
79
  return 0;
80
}

: Bearbeitet durch User
von Stephan (Gast)


Lesenswert?

Hi,
ich bin nicht sicher ob ich verstanden habe was du willst aber ich 
versuchs mal:

>Sollte als Anfänger eher eine andere Bibilothek/ andereren Weg genommen
>werden?
Das passt schon. :-)
Was ich dir noch mitgeben kann, such dir einen MB-Monitor, damit kannst 
du die Kommunikation testen. Es gibt viele freie im Netz.
z.B.: http://www.chipkin.com hat einen. (es gibt mehrere Versionen, such 
die neuste)

>Bei dem eigentlichen auslesen als Master komme ich leider nicht weiter.
Master stellt nur Daten zur Verfügung!
Also der Janitza UMG104 ist der Master, du (dein PC) ist der Slave, der 
muß arbeiten und die Daten abholen!(abfragen)

>Wie muss das auslesen mit dem Aufruf modbus_mapping_new() korrekt
>entstehen? Ich komme mit der Dokumentation nicht weiter- Als Beispiel
>würde ich gerne das Register 19000 auslesen (das ist die Spannung -
>müsste also um die 230 liegen)
modbus_mapping_new ist für die Erstellung eines Masters!
Hier generierst du den Platzhalter für die Register(Informationen) die 
von Außen gelesen werden können(auch write möglich).
1
mb_mapping = modbus_mapping_new(
2
0, // keine Bits (Coils (RW))
3
0, // keine Input-Coils (nur Read-Only)
4
0, // keine Holding-Register (RW)
5
0  // keine Inputregister (nur Read-Only)
6
); 
7
// irgendwas mußte aber erstellen
8
mb_mapping = modbus_mapping_new(
9
0, // keine Bits (Coils (RW))
10
0, // keine Input-Coils (nur Read-Only)
11
REGISTERS_ADDRESS + 100, // 100 Holding-Register (RW)
12
0  // keine Inputregister (nur Read-Only)
13
);
Im 2 Fall könnte jetzt einer deine 100 H-Register lesen.
Schau bitte im Code nach was der Wert für REGISTERS_ADDRESS ist, den 
konnte ich nicht in der Doku finden.

Dieser Satz in der Doku ist für MB wichtig:
1
/* The fist value of each array is accessible from the 0 address. */
leider konnte ich in der Doku zum UMG104 nichts finden!!!
Also im Zweifel die Registeradressen um +- 1 verändern!

Eigentlich willst du doch deinen UMG104 auslesen, oder?
Dazu kannst du das aus der Doku verwenden:
1
modbus_t *ctx;
2
uint16_t tab_reg[64];  // <- hier die Registerwerte reinschreiben
3
int rc;
4
int i;
5
int MyMBStartAdr= 19000;
6
int MyMBAdrLen= 6; // alle Spannungen von L1 L2 L3
7
8
rc = modbus_read_registers(ctx, MyMBStartAdr, MyMBAdrLen, tab_reg);
9
if (rc == -1) {
10
    fprintf(stderr, "%s\n", modbus_strerror(errno));
11
    return -1;
12
}
13
14
for (i=0; i < rc; i++) {
15
    printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
16
}

Zum Anfang mehr als 1 Register lesen, wegen den Offset von 1!!!
Hat mir immer sehr geholfen :-)

von Peter B. (mallert)


Angehängte Dateien:

Lesenswert?

Hallo Stephan,

erstmal Danke für die Antwort- ich probiere es gleich mal den Vorschlag 
mit modbus_read_registers.

Aber gleich mal eine Verständnisfrage:
Der Modbus Master ist mein PC (in dem Fall ein RPI) der die Slaves 
(Umg104 Adresse 1) nach den Registern fragt?
Siehe http://de.wikipedia.org/wiki/Modbus und der Zeichnung anbei
Oder habe ich hier ein gernelles Verständnisproblem?
Weil der Befehl modbus_read_registers liegt bei der Dokumentation unter 
clients (slaves)

Danke

Gruß
Peter

von Stephan (Gast)


Lesenswert?

Hi,
hab nochmal nach gesehen:
http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf
Seite 4: (auch 2 Bilder)
1
The MODBUS application data unit is built by the client that initiates a MODBUS transaction.
2
The function indicates to the server what kind of action to perform. 
3
The MODBUS application protocol establishes the format of a request initiated by a client.

Für mich ist der Master(Server), der der die Daten hat.
Der Slave(Client) muß für sein Geld arbeiten, die Daten abholen.

Das Master / Slave kommt eigentlich von der Kundenseite.
Als ich das diesen Erklärt habe, hab ich es auch so rum erzählt.
Ist einfacher zu verstehen. Der Master fragt die Werte an und der Slave 
hat zu antworten.

Wenn du dir aber heute, Web Seiten anschaust, die Daten liegen auf dem 
Server und die Clients holen sie sich ab!
Vielleicht sollte man(n) heute nur noch von 'MB-Clients' und 'MB-Server' 
reden. (neu modischer ;-) )

Ist es besser?

PS: Besser als wiki ist
http://www.modbus.org/specs.php

von Stephan (Gast)


Lesenswert?

Master / Slave

schau mal hier:
http://www.modbus.org/docs/Modbus_over_serial_line_V1_02.pdf

Seite 7 (Bilder mit Master / Slave)
1
The MODBUS Serial Line protocol is a Master-Slaves protocol. Only one master (at the same time) is connected 
2
to the bus, and one or several (247 maximum number) slaves nodes are also connected to the same serial bus. 
3
A MODBUS communication is always initiated by the master. The slave nodes will never transmit data without 
4
receiving a request from the master node. The slave nodes will never 
5
communicate with each other. The master node initiates only one MODBUS transaction at the same time.

Das Master / Slave bezieht sich mehr auf die Übertragung.

Aber aus Modbus-Daten Sicht....(andersherum)
Ist halt schwer zu erklären. Sorry.

von Peter B. (mallert)


Lesenswert?

Hallo,

nach ein bisschen probieren (lezendlich hat ein Abschlussiwderstand 
gefehlt -bei 30cm Kabel.. naja) habe ich eine Ausgabe :)

Modbus Master Programm startet...
libmodbus Version:3.0.3
Parameter der Verbindung:
BAUD:      9600
Parity:      none
Bits:       8
Stop-Bit:    2
Slave Adresse:    200
Verbindung aktiv
weiter mit 00
in der Schleife
Register gelesen
017258
146344
217258
355525
417258
58426
Ausserhalb der Schleife, Verbindungen werden geschlossen

------------------
(program exited with code: 0)
Press return to continue

Was ich da überhaupt ausgelesen habe und was die Zahlen sagen forsche 
ich morgen bei einem Kaffe nach :)

Vielen Dank Stephan mit dem richtigen Hinweis!

Gruß
Peter

von Mathias O. (m-obi)


Lesenswert?

Ich weiß der letzte Post ist schon ein 3/4 Jahr her. Aber bevor Andere 
über diesen Thread stolpern, möchte ich gerne was richtigstellen.

Zu einem Server kann man auch Slave sagen. Er stellt Daten bereit und 
antwortet auf Anfragen vom Client bzw. Master. Der Client/Master hat die 
Oberhand, deswegen auch Master. Bzw. auch Client, da ein Client Anfragen 
stellt und Daten haben möchte.

Und das ist nicht nur bei Modbus so.

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.