Elsner Wetterstation mit e!Cockpit

eloee

Level-1
Beiträge
29
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

Versuche eine Elsner Wetterstation bzw. die ELTAKO Variante davon an meine PFC200 750-8202 zu bringen... das ganze allerdings mit e!Cockpit.
Für die 2.3 gibt es hier ja alles fertig, für e!Cockpit hab ich dazu allerdings noch nichts gefunden und mir fehlt hier auch irgendwie der Ansatz... :(
Hat das evtl. schon jemand erfolgreich am Laufen ?
Ich scheitere schon an der Konfiguration der, am 750-8202, integrierten RS232/485 Schnittstelle... wo wird das bei e!Cockpit gemacht ? Kann die überhaupt dazu verwendet werden ?

Viele liebe Grüße
Eloee
 
Hallo,
habe ich auch noch vor. Scheint leicht zu sein, da die Elsner anscheinend eine Bitschleuder ist und nicht mit irgendwelchen Steuersequenzen arbeitet. Ich muss mich aber noch im Detail einlesen. Wird dann an einer 750-652 hängen.

Ansatz:
Schnittstelle initialisieren,
Warten bis die Anzahl der Bytes reinkam
entweder direkt auswerten oder zwischenspeichern
Schnittstellenindex auf 0 und warten dass das nächste Telegramm reinkommt, dann geht es von vorne los.

Ich kann direkt auswerten empfehlen, da der Controller genug Power hat.
Ich habe erfolgreich 3 Serielle laufen, mit OnBoard, 750-0652 und 750-0650. Auf der anderen Seite werkeln ein ehz, Viessmann kw200 und 30x DS18B20. Alles sehr stabil und zuverlässig.
hier hast Du mal meine Initialsierungssequenz für den ehz, der ebenfalls eine Bitschleuder ist.
Code:
i_Schnittstelle := 2;  // Auswahl, die Schnittstelle ist COM2 für Zaehlerdaten
CASE i_Schnittstelle OF
        0: I_PORT := 0;    
        1: I_PORT := COM1; (* Onboard Schnittstelle *)
        2: I_PORT := COM2_Zaehler; (* 750-652 Schnittstelle *)
        3: I_PORT := COM3_Heizung; (* 750-650 Schnittstelle *)
    ELSE
        i_Schnittstelle := 0;
END_CASE

IF x_IsOpen = NOT TRUE THEN x_Open_01 := TRUE; // Schnittstelle oeffnen

(* SerCom Instanz *)
o_FbSerialInterface_cpt_01(
    oStatus=> , 
    xOpen:= x_Open_01, 
    xIsOpen=> x_IsOpen, 
    xIsIdle=> x_IsIdle, 
    xError=> x_Error, 
    xTxTrigger:= x_TxTrigger, 
    pTxBuffer:= ADR(s_TxBuffer), 
    udiTxNBytes:= INT_TO_UDINT(LEN(s_TxBuffer)), 
    pRxBuffer:= ADR(ab_RxBuffer), 
    udiRxBufferSize:= SIZEOF(ab_RxBuffer), 
    udiRxIndex:= udiRxIndex, 
    xRxBufferFull=>,
    xRxOverflow=> x_RxOverflow,
    xResetStatus:= x_ResetStatus,
    I_Port:= I_Port,
    udiBaudrate:= 9600,
    usiDataBits:= 8,
    eParity:= eTTYParity.None,
    eStopBits:= eTTYStopBits.One,
    eHandshake:= eTTYHandshake.None,
    ePhysical:= eTTYPhysicalLayer.RS232);

// Status der seriellen Schnittstelle anzeigen
    st_Status := o_FbSerialInterface_cpt_01.oStatus.GetDescription();    
ELSE
    // mit dem Minimum an Parametern aufrufen, damit Daten in den Receive Buffer eingetragen werden
 o_FbSerialInterface_cpt_01(
    xTxTrigger:= x_TxTrigger, 
    udiRxIndex:= udiRxIndex);
END_IF

IF o_FbSerialInterface_cpt_01.xRxBufferFull = TRUE THEN
    Zaehlerdaten_lesen.udiRxIndex := 0;
END_IF

must Du natürlich für deine Belange umbauen RS232/485/Schnittstellenparameter etc.

Gruß

Chris
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen Dank Chris,
habe das ganze nun mal angepasst und die Werte noch korrekt umgerechnet (ASCII) und es läuft einwandfrei!!
Will noch ein paar Sachen verbessern, dann lade ich meinen Code auch mal hoch :D

Würde nur noch ganz gerne einen Watchdog einbauen, sodass ein Verbindungsabbruch erkannt werden kann und das ganze dann wieder sauber loslaufen kann.
Wenn ich jetzt das Kabel kurz abziehe, werden die Daten zwar weitergeschrieben, aber um einige Byte verschoben im Empfangspuffer... habe das noch nicht anständig resetten können... :(

Wie genau liest du denn die DS18B20 aus ?

Schöne Grüße
Eloee
 
Hallo Eloee,
DS18B20: da gibt es eine Library von Rayk. Suche nach OWOS.LIB. Derzeit offiziell nur in Codesys 2.3 zu haben. Da der Quellcodes offen ist habe ich die mal nach 3.5 portiert. Rayk wollte es testen, ob alle Portierungen auch so laufen, da ich die notwendige Hardware nicht habe. Ansonsten braucht Du eine Serielle, einen DS2480 und x mal DS18B20. Wie gesagt, ich habe 30 Stück am Start und die laufen super.

Chris
 
Oh das hört sich auch interessant an... Das Projekt hab ich wohl übersehen, hab nämlich vor lauter Verzweiflung nen umsetzer 1wire auf Modbus TCP mit nem Arduino gebaut ;-)

Hast du den DS2480 als fertiges Modul gekauft oder was gebastelt? Wie hast du da die Topologie vom 1wire Bus?

Und hast du auch ne Visu im Einsatz? Bin irgendwie noch nicht so zufrieden mit der Wago eigenen bzw. Hab da auch noch keinen für mich passenden Bildschirm gefunden... :-(

Schöne Grüße Eloee
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe den 2480 mit einem RS232 Treiber auf Lochraster selber gebaut. Schaltbilder gibt es zu Hauf im Netz. RS232 hatte ich aus China im 10er-Pack für ein paar €. Quick and dirty, aber das sollen die am längsten laufenden Anlagen sein ;-) Meine Topologie natürlich alles parallel bei 4 Linien: 1.OG, EG, KG und draußen. Habe die einfache Webvisu. Wollte mal was mit html5 machen, aber da gibt es wenig Dokus und schon keine für Einsteiger. Sieht bei mir so aus, aber ich bin erst am Anfang:

Anhang anzeigen 30794Anhang anzeigen 30795
 
Leider gehen deine Bilder nicht... da ist wohl irgendwas schief gelaufen :(
Weisst du ob die Portierung für Codesys 3 bzw. e-Cockpit bald mal offiziell wird ? Habe mir die Hardware jetzt mal besorgt und würde das ganze gerne mal testen...

Schöne Grüße Eloee
 
Hallo,
tja irgendwann gingen sie mal. Welche Portierung meinst Du? Von Codesys 3 nach e!cockpit oder von 2x nach e!? Ich hatte meine Programme alle mit 2x exportiert und in 3 eingelesen. War relativ einfach. Nur mit dem Objekten (serielle,etc) haperte es am Anfang. Was hält dich eigentlich vom testen ab? Für e! gibt es ein Testversion, die 30 Programmiertage lauffähig ist, da bekommst Du schon einiges getan.

Chris
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi,
meinte die Portierung von 2.3 auf e!. Die Testversion hab ich, bin da ja auch schon kräftig im ausprobieren... hab das gestern dann auch mal selbst mit der Portierung versucht aber war noch nicht so erfolgreich, eben wegen der Bibliotheken die sich, wenn ich das richtig sehe, bei e! teilweise geändert haben bzw. nun andere Namen haben!? Du hattest aber auch in e! mal eine lauffähige Version?

Gruß Eloee
 
Hallo,
also eine direkte Portierung ist bei mit mit hunderten von Fehlermeldungen fehlgeschlagen. Aber war eh nur "just for fun". Der Ansatz bei e! ist jetzt ein anderer. Er ist jetzt objektorientiert. Schau dir z.B. die Serielle an. Ich habe klein angefangen. Zunächst habe ich versucht die Serielle in den Griff zu bekommen. Hat bei mir gut eine Woche gedauert, bis ich alles im Griff hatte. Wago's Hotline hat auch sehr kräftig geholfen. Aber irgendwann hat es auch bei mir geklickt. Bibliotheken sind vorhanden aber nur rudimentär. Z.B. fehlt eine Zeitschaltuhr. Mußte ich dann selber erstellen. Ich habe größe Hoffnungen, dass das angekündigte Update bezüglich der Bibliotheken einiges bringt.
Im übrigen ist Wago sehr kullant. Ich habe die Hotline angrufen, die gaben mir dann noch mal eine Verlängerung für weitere 30 Tage.

Chris
 
Hallo eloee,


hast Du den Code funktionsfähig und kannst ihn mal hochladen? (hattest es seinerzeit ja mal angeboten...)


@all:
Hat jemand die Wetterstation am laufen mit e!cockpit? Ich finde immer noch nichts brauchbares bei Wago, wie es z. B. für 2.3 existiert.


Fabian
 
Hast du die genaue Bezeichnung der Wetterstation.
Es Gab mal eine Wago und eine "andere".

Unterschied war damals, dass die Wago-Version so nur alle 5 Sekunden slebständig Daten gesendet hat.

Bei der 8202 hast schon viel BUMS.
Da könnte das auch passen.

EInfach mal testen.
 
Hier nun endlich mal der Code, falls ihn noch jemand braucht :)
Läuft seit einigen Jahren störungsfrei:

Code:
FUNCTION_BLOCK WetterStationV2
VAR_INPUT
    Windwarnung:INT;    // Ab wieviel m/s gibt der Baustein Windwarnung aus
    Windwarnung_Rueck:INT;    // Ab wieviel m/s wird die WIndwarnung zurückgesetzt
    Verz_Windwarnung:TIME;
    Verz_Windwarnung_Rueck:TIME;
    Hell_Schwelle:INT;        // Ab wieviel Lux ist es Hell genug für Verschattung
END_VAR
VAR_OUTPUT
    o_Temperatur:REAL;
    o_Sonne_Sued:INT; (*1-99klx*)
    o_Sonne_West:INT; (*1-99klx*)
    o_Sonne_Ost:INT; (*1-99klx*)
    o_Daemmerung:BOOL;
    o_Tageslicht:INT; (*1-999Lx*)
    o_Wind:REAL; (*m/s*)
    o_Regen:BOOL;
    o_Windwarnung:BOOL;
    o_Sonne_West_Hell:BOOL;
    o_Sonne_Ost_Hell:BOOL;
    o_Sonne_Sued_Hell:BOOL;
END_VAR
VAR
    sInterface:FbSerialInterface_cpt;
    x_Open: BOOL;
    x_IsOpen: BOOL;
    x_IsIdle: BOOL;
    x_Error: BOOL;
    x_TxTrigger: BOOL;
    x_TxBuffer: STRING;
    x_RxBuffer: ARRAY[1..40] OF BYTE;
    AsciiBuffer: ARRAY[1..40] OF STRING;
    udiRxIndex: UDINT;
    x_BufferFull: BOOL;
    x_RxOverflow: BOOL;
    x_ResetStatus: BOOL;


    st_Starus: STRING;
    Counter: INT;
    BufferIndex: INT;
    
    Watchdog:TON;
    Watchdog_Trigger: R_TRIG;
    close_status: WAGOAPPCOM.FbResult;
    close_error: BOOL;
    close_done: BOOL;
    close_busy: BOOL;
    
    ResetWatchdog: BOOL;
    falsch: BOOL;
    index: UDINT;
    SearchCounter: INT;
    DataBegin:INT; 
    DataEnd:INT;
    CorrectedIndex: INT;
    
    Windwarnung_Hoch_TON:TON;
    Windwarnung_Niedrig_TON:TON;
    Temp_Windwarnung_Hoch:BOOL;
    Temp_Windwarnung_Niedrig:BOOL;
    Windwarnung_Start:R_TRIG;
    Windwarnung_Stop:R_TRIG;
    tSonneWestHell:BOOL;
    tSonneOstHell:BOOL;
    tSonneSuedHell:BOOL;
    TOF_SonneWestHell:TOF;
    TOF_SonneOstHell:TOF;
    TOF_SonneSuedHell:TOF;
    
END_VAR




IF NOT x_IsOpen THEN
    
x_Open := TRUE;


sInterface(
    oStatus=> , 
    xOpen:= x_Open, 
    xIsOpen=> x_IsOpen, 
    xIsIdle=> x_IsIdle, 
    xError=> x_Error, 
    xTxTrigger:= x_TxTrigger, 
    pTxBuffer:= ADR(x_TxBuffer), 
    udiTxNBytes:= INT_TO_UDINT(LEN(x_TxBuffer)), 
    pRxBuffer:= ADR(x_RxBuffer), 
    udiRxBufferSize:= SIZEOF(x_RxBuffer), 
    udiRxIndex:= udiRxIndex, 
    xRxBufferFull=> x_BufferFull, 
    xRxOverflow=> x_RxOverflow, 
    xResetStatus:= x_ResetStatus, 
    I_Port:= COM1, 
    udiBaudrate:= 19200, 
    usiDataBits:= 8, 
    eParity:= eTTYParity.None, 
    eStopBits:= eTTYStopBits.One, 
    eHandshake:= eTTYHandshake.None, 
    ePhysical:= eTTYPhysicalLayer.RS485_HalfDuplex);
    
    st_Starus := sInterface.oStatus.GetDescription();
    
    ELSE
        sInterface(xTxTrigger := x_TxTrigger, udiRxIndex := udiRxIndex);
    END_IF
    
    IF udiRxIndex = 40 THEN BufferIndex := BufferIndex + 1; END_IF
    
    IF x_RxBuffer[udiRxIndex] = 87 THEN 
        index := udiRxIndex;
        //udiRxIndex := 0; 
    //    falsch := TRUE;
    END_IF
 
    
    // WAtchdog
    Watchdog_Trigger(CLK := (udiRxIndex = 40));    
    Watchdog(IN:=(x_IsOpen AND NOT Watchdog_Trigger.Q AND NOT ResetWatchdog), PT := T#5S);
    
    IF Watchdog.Q THEN    
        //sInterface.finish();
    //    x_Open := FALSE;
        //x_ResetStatus := TRUE;
    //    sInterface.I_Port.Close(ADR(PLC_PRG.Wetter2));
        ResetWatchdog := TRUE;
    ELSE     
        ResetWatchdog := FALSE;    
END_IF
    


    
// Wenn Puffer voll ist, werden die Werte ausgewertet...    
    IF sInterface.xRxBufferFull THEN
        
        // Suche Anfang und Ende des Puffers        
        FOR SearchCounter:= 1 TO SIZEOF(x_RxBuffer) DO
            IF x_RxBuffer[SearchCounter] = 87 THEN DataBegin := SearchCounter; END_IF
            IF x_RxBuffer[SearchCounter] = 3 THEN DataEnd := SearchCounter; END_IF
        END_FOR
    
        FOR Counter:= 1 TO SIZEOF(x_RxBuffer) DO
            CorrectedIndex := DataBegin + Counter - 1;
            IF CorrectedIndex > SIZEOF(x_RxBuffer) THEN CorrectedIndex := CorrectedIndex - SIZEOF(x_RxBuffer); END_IF    
        
            AsciiBuffer[Counter] :=  ASCIIByte_To_String(b:=x_RxBuffer[CorrectedIndex] );
        END_FOR
        
        // Boolsche Werte
        IF AsciiBuffer[13] = 'J' THEN o_Daemmerung := TRUE; ELSE o_Daemmerung := FALSE; END_IF
    
        IF AsciiBuffer[21] = 'J' THEN o_Regen := TRUE; ELSE o_Regen := FALSE; END_IF    
        
        // Real Werte
        // Temperatur
        o_Temperatur := (STRING_TO_INT(AsciiBuffer[3]) * 10) + STRING_TO_INT(AsciiBuffer[4]) + (STRING_TO_INT(AsciiBuffer[6]) * 0.1);
        IF AsciiBuffer[2] = '+' THEN o_Temperatur := o_Temperatur; ELSE o_Temperatur := o_Temperatur * -1; END_IF
        
        // Wind
        o_Wind := (STRING_TO_INT(AsciiBuffer[17]) * 10) + STRING_TO_INT(AsciiBuffer[18]) + (STRING_TO_INT(AsciiBuffer[20]) * 0.1);
    
        // Int Werte
        // Sonne Süden
        o_Sonne_Sued := (STRING_TO_INT(AsciiBuffer[7]) * 10) + STRING_TO_INT(AsciiBuffer[8]);
    
        // Sonne West
        o_Sonne_West := (STRING_TO_INT(AsciiBuffer[9]) * 10) + STRING_TO_INT(AsciiBuffer[10]);
    
        // Sonne Ost
        o_Sonne_Ost := (STRING_TO_INT(AsciiBuffer[11]) * 10) + STRING_TO_INT(AsciiBuffer[12]);
        
        // Tageslicht 
        o_Tageslicht := (STRING_TO_INT(AsciiBuffer[14]) * 100) + (STRING_TO_INT(AsciiBuffer[15]) * 10) + STRING_TO_INT(AsciiBuffer[16]);
        
        // und dann der Index wieder auf 0 zurückgesetzt
        udiRxIndex := 0;
    END_IF


// Überprüfung auf Windwarnung 
IF o_Wind > Windwarnung THEN Temp_Windwarnung_Hoch := TRUE;
    ELSE Temp_Windwarnung_Hoch := FALSE;
END_IF


// WIndwarnung setzen
Windwarnung_Hoch_TON(IN := Temp_Windwarnung_Hoch, PT := Verz_Windwarnung);
Windwarnung_Start(CLK := Windwarnung_Hoch_TON.Q);
IF Windwarnung_Start.Q THEN o_Windwarnung := TRUE; END_IF


IF o_Wind < Windwarnung_Rueck THEN Temp_Windwarnung_Niedrig := TRUE;
    ELSE Temp_Windwarnung_Niedrig := FALSE;
END_IF
    
Windwarnung_Niedrig_TON(IN := Temp_Windwarnung_Niedrig, PT := Verz_Windwarnung_Rueck);
Windwarnung_Stop(CLK := Windwarnung_Niedrig_TON.Q);


IF Windwarnung_Stop.Q THEN o_Windwarnung := FALSE; END_IF


IF o_Sonne_Ost > Hell_Schwelle THEN
    tSonneOstHell := TRUE;
    ELSE
        tSonneOstHell := FALSE;
END_IF




IF o_Sonne_West > Hell_Schwelle THEN
    tSonneWestHell := TRUE;
    ELSE
        tSonneWestHell := FALSE;
END_IF






IF o_Sonne_Sued > Hell_Schwelle THEN
    tSonneSuedHell := TRUE;
    ELSE
        tSonneSuedHell := FALSE;
END_IF


TOF_SonneWestHell(IN := tSonneWestHell, PT := T#15M, Q => o_Sonne_West_Hell);
TOF_SonneOstHell(IN := tSonneOstHell, PT := T#15M, Q => o_Sonne_Ost_Hell);
TOF_SonneSuedHell(IN := tSonneSuedHell, PT := T#15M,Q => o_Sonne_Sued_Hell);

Gruß Eloee
 
Zurück
Oben