Mit B&R Schnittstelle (RS485) auslesen?

Ruddy

Member
Beiträge
12
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo liebe Gemeinde!

Ich bin gerade am verzweifeln, wär also nett wenn ihr mir weiterhelfen könntet :)

Ich habe ein Projekt bei dem ich Daten mehrerer Regler über eine RS485- Schnittstelle auslesen muss.
Als Hardware habe ich ein Power-Panel, das über X2X-Link mit einem Kommunikationsmodul (X20CS1030) verbunden ist.
Die Regler sind untereinander über RS485 verbunden und die Leitung geht anschließend auf mein Kommunikationsmodul.

Leider hab ich es bis jetzt noch nicht geschafft, das mir ein Regler eine Antwort zurückschickt :( (bin auch noch Neuling auf dem Gebiet)
Zur Kommunikation verwende ich die "DVFrame"-Bibliothek. Nachstehend füge ich meinen Code und einen Auszug des Schnittstellenprotokolles der Regler ein, vielleicht fällt euch ja ein Lösungsansatz ein. Vielleicht mach ich auch grundsätzlich was falsch...

Ausschnitt aus dem Schnittstellen-Protokoll (E-Link):

=====================================================================================

  • Baudrate: 9600
  • Parität: Keine
  • Datenbits: 8
  • Stoppbits: 1



  • Für die Kommunikation steht das folgende Protokoll zur Verfügung:
  • <SOH> <Adr> <STX> <D1 D2 D3...Dn> <ETX> <Checksum> <EOT>
  • <SOH> = ^A (0x01)
  • <Adr> = 0x30 + Adresse des Gerätes von 0...78
  • <STX> = ^B (0x02)
  • D1 D2...Dn = Datenbereich (Abfrage= ? Programmierung = !, Bsp: Abfrage des Parameters 1000= ?1000
  • <ETX> = ^C (0x03)
  • Checksum = Checksumme: Adr xor D1 xor D2 xor D3...xorDn, Wenn Checkbyte <= 1: Checkbyte + 0x71
  • <EOT> = ^D (0x04)

Beispiel für die Abfrage aller Laufvariablen: ^A~^B?9000^CH^D
============================================================================================



Nun mein Code (zyklisch):
===================


CASE step OF


//WARTEN******************************************************************
0:

strcpy(ADR(Sendebuffer),ADR(''));

IF (Open) THEN
step := 1;
END_IF


//ÖFFNEN*******************************************************************
1:

FRM_xopen_0.enable := TRUE;
FRM_xopen_0.device := ADR('IF2.ST2.IF1');
FRM_xopen_0.mode := ADR('/PHY=RS485 /BD=9600 /DB=8 /PA=N /SB=1');
FRM_xopen_0.config := 0;
FRM_xopen_0.config := ADR(Schnittstellenparameter);

Schnittstellenparameter.idle := 1000;
Schnittstellenparameter.delimc := 1;
Schnittstellenparameter.delim[0] := 4; //<EOT>
Schnittstellenparameter.tx_cnt := 8;
Schnittstellenparameter.rx_cnt := 8;
Schnittstellenparameter.tx_len := 256;
Schnittstellenparameter.rx_len := 256;
Schnittstellenparameter.argc := 0;
Schnittstellenparameter.argv := 0;

FRM_xopen_0();

IF (FRM_xopen_0.status = 0) THEN
step := 2;
strcpy(ADR(Sendebuffer), ADR('^A~B?9000^CH^D'));
ELSIF (FRM_xopen_0.status = ERR_FUB_BUSY) THEN
step := 1;
ELSE
step := 255;
END_IF


//SENDEBUFFER ANFORDERN***************************************************
2:

FRM_gbuf_0.enable := TRUE;
FRM_gbuf_0.ident := FRM_xopen_0.ident;
FRM_gbuf_0();


IF (FRM_gbuf_0.status = 0) THEN
memset(FRM_gbuf_0.buffer, 0, FRM_gbuf_0.buflng);
strcpy(FRM_gbuf_0.buffer, ADR(Sendebuffer));
step := 3;
i := 0;
ELSIF (FRM_gbuf_0.status = ERR_FUB_BUSY) THEN
step := 2;
ELSE
step := 255;
END_IF


//SENDEN *****************************************************************
3:

FRM_write_0.enable := TRUE;
FRM_write_0.buffer := FRM_gbuf_0.buffer;
FRM_write_0.buflng := strlen(ADR(Sendebuffer));
FRM_write_0.ident := FRM_xopen_0.ident;
FRM_write_0();

IF (FRM_write_0.status = 0) THEN
step := 4;
ELSIF (FRM_write_0.status = ERR_FUB_BUSY) THEN
step := 3;
ELSE
step := 255;
END_IF


//LESEN ******************************************************************
4:

FRM_read_0.enable := TRUE;
FRM_read_0.ident := FRM_xopen_0.ident;
FRM_read_0();

IF (FRM_read_0.status = 0) THEN
step := 5;
ELSIF (FRM_read_0.status = frmERR_NOINPUT) THEN
step := 4;
ELSE
step := 255;
END_IF


//LESEBUFFER KOPIEREN ****************************************************
5:

memset(ADR(Readbuffer), 0, SIZEOF(Readbuffer));
memcpy(ADR(Readbuffer), FRM_read_0.buffer, FRM_read_0.buflng);
strcpy(ADR(ReceivBuffer),ADR(Readbuffer));

IF (FRM_read_0.buflng > 0) THEN

FRM_rbuf_0.enable := TRUE;
FRM_rbuf_0.ident := FRM_xopen_0.ident;
FRM_rbuf_0.buffer := FRM_read_0.buffer;
FRM_rbuf_0.buflng := FRM_read_0.buflng;
FRM_rbuf_0();


IF FRM_rbuf_0.status = 0 THEN
step := 0;
ELSIF FRM_rbuf_0.status = ERR_FUB_BUSY THEN
step := 5;
ELSIF FRM_rbuf_0.status = frmERR_INVALIDBUFFER THEN
step := 4;
ELSE
step := 255;
END_IF
ELSE
step := 6;
END_IF



//SCHLIESSEN*************************************************************
6:

FRM_close_0.enable := TRUE;
FRM_close_0.ident := FRM_xopen_0.ident;

FRM_close_0();

IF FRM_close_0.status = 0 THEN
step := 0;
ELSIF FRM_close_0.status = ERR_FUB_BUSY THEN
step := 6;
ELSE
step := 255;
END_IF

//************************************************************************
255:

//ERROR


END_CASE
 
Hi

hier vlt ein paar hilfreiche Fragen ;)

Wie sehen die Stais von den Bausteinen aus?
Kommt hier ein Fehler zurück? Wen ja an welchem FUB und welcher Fehlernummer?

Wie siehts an der LE Status an der CS Scheibe aus? Leuchtet die Tx beim Schreiben oder die Rx beim Lesen?

Hast du Abschlusswiderstand am Anfang und Ende drin? An der CS Scheibe kannst den Einschalten, dann sollte auch die LED T leuchten.
Verdrahtung ansonsten passt auch?
Welches Funktionsmodel hast du am Modul eingestellt? Stream wäre der Richtige.

Die Knotennummern der Slave sind eindeutig und richtig eingestellt?

So im Querflug hat der Code eigentlich gepasst, wobei ich Detail jetzt nicht alles angesehen habe.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi :)

Also nach dem Sendebefehl sendet der Baustein frmRead_0 den Status "frmERR_NOINPUT" zurück, die Schrittkette bleibt dann also im Leseschritt... Und das wars dann auch :p
die Tx- LED leuchtet kurz, die rx-LED leuchtet jedoch nicht auf... Der Abschlusswiderstand an der CS1030 ist eingeschaltet. Den Rest kontrolliere ich morgen, da ich heute keine Gelegenheit mehr dazu hab. Danke schonmal für deine Hilfe!
 
Hallo,
also ich könnte mir vorstellen das Problem liegt hier...

Code:
[COLOR=#333333]strcpy(ADR(Sendebuffer), ADR('^A~B?9000^CH^D'));[/COLOR]

Meiner Meinung nach müsste das so gehen

Code:
Sendebuffer[0] := $01
SendeBuffer[1] := $[COLOR=#3E3E3E]30 + Adresse des Gerätes von 0...78
[/COLOR]SendeBuffer[2] := $02
[COLOR=#333333]strcpy(ADR(Sendebuffer[3]), ADR('?9000'));
[/COLOR];
checksum berechnen
SendeBuffer[x] = checksum
SendeBuffer[x+1] = $04
Wenn du im String "^A" angibst sind das 2 Zeichen, also gänzlich unterschiedlich zu dem wie es sein soll.

Physikalisch scheint es lt. Beschreibung ja soweit OK zu sein. Wahrscheinlich verstehen die Regler schlicht und ergreifend einfach nicht was da kommt...

BG
BB
 
Danke für deine Antwort!

Klingt irgendwie logisch wie du das schreibst... Ich hätte dazu aber ein paar Fragen:


  1. Von welchem Datentyp muss das Array "SendeBuffer" sein?
  2. Kannst du mir erklären wie ich die Checksumme berechnen muss? Das versteh ich nicht...
  3. Wie übergebe ich dann den fertigen Sendebuffer an die Funktion? Das gesamte Array? (Funktion.buffer := ADR(SendeBuffer); Funktion.bufferlng := SIZEOF(SendeBuffer);

Sorry für die vielen Fragen, ich blick da nicht ganz durch...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für deine Antwort!

Klingt irgendwie logisch wie du das schreibst... Ich hätte dazu aber ein paar Fragen:


  1. Von welchem Datentyp muss das Array "SendeBuffer" sein?
  2. Kannst du mir erklären wie ich die Checksumme berechnen muss? Das versteh ich nicht...
  3. Wie übergebe ich dann den fertigen Sendebuffer an die Funktion? Das gesamte Array? (Funktion.buffer := ADR(SendeBuffer); Funktion.bufferlng := SIZEOF(SendeBuffer);

Sorry für die vielen Fragen, ich blick da nicht ganz durch...

Hallo Ruddy,

zu den Fragen

1) muss ein USINT-Array sein
2) ... siehe unten
3) so wie du es angegeben hast, mit strlen(Sendebuffer), allerdings musst du am Beginn - bevor du irgendwas in den Sendebuffer schreibst, alles mit
memset(adr(Sendebuffer), 0, sizeof(Sendebuffer)) initialisieren. Strlen gibt dann die Anzahl der Byte an von Beginn bis zur ersten 0 (null).

Die Checksum einfach in einer Schleife berechnen, bist du sicher dass STX nicht in die Checksum eingerechnet wird ? Das ist zumindest ungewöhnlich da ja index=1, Lücke (index =2) und dann weiter mit index = 3...

ACHTUNG: konnte das natürlich nicht testen, kannst du das mit Beispielen aus der Dokumentation des Gerätes verifizieren ?

Code:
    memset(ADR(SendeBuffer), 0, SIZEOF(SendeBuffer));
    SendeBuffer[0] := 1;
    SendeBuffer[1] := Dev_Adr + 16#30;
    SendeBuffer[2] := 16#2;
    strcpy(ADR(SendeBuffer[3]), ADR('?9000'));
    
    send_len := strlen(ADR(SendeBuffer));
    checksum := SendeBuffer[1];
    FOR index := 3 TO send_len-1 BY 1 DO
        checksum := checksum XOR SendeBuffer[index];
    END_FOR        
    IF (checksum <= 1) THEN
        checksum := checksum + 16#71;
    END_IF
    SendeBuffer[send_len] := checksum;
    SendeBuffer[send_len+1] := 16#04;


    send_len := strlen(ADR(SendeBuffer));


...

[COLOR=#3E3E3E][I]Funktion.buffer := ADR(SendeBuffer); 
Funktion.bufferlng := send_len[/I][/COLOR]

BG
BB
 
Hallo bits'bytes!

Ich bin dir sehr dankbar für deine Hilfe! Hab's jetzt hinbekommen, läuft mit einer kleinen Anpassung (Das "C" hat noch vor der checksumme gefehlt) nun einwandfrei :)

Ohne dich hätt ich wahrscheinlich den Hut drauf geworfen.
Danke nochmal!
 
Hallo Ruddy,
herzlichen Dank für das Feedback. Positives tut manchmal gut :p.!!

Das mit dem ^C hab ich total übersehen - gut dass dir das gleich aufgefallen ist.

Was ich noch sagen wollte - falls das bei dir zutrifft:

Wenn du mehrere Geräte hast brauchst du ja nicht auf die Antwort eines Gerätes zu warten und danach erst das Nächste adressieren usw.

In diesem Fall würde ich das ganze über ein entsprechendes Kommunikationsarray aufbauen (die Frame-Fubs brauchst du aber nur einmal, da nur eine Schnittstelle). Entsprechend viele Sende- und Empfangsbuffer und alle sonstigen Zwischenspeicher im Array unterbringen....

Viel Spass
BG
BB
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo :)
Ich habs bis jetzt so gemacht, das ich auf eine Antwort warte, und dann den nächsten Parameter oder Regler auslese... Ist also sicher noch ausbaufähig das ganze :p
ich muss jedoch nach nach den ersten 2 Reglern sowieso die Schnittstelle erneut öffnen, weil die darauffolgenden Regler andere Schnittstellenparameter haben...

LG, Rudi
 
Zurück
Oben