Einstieg in Codesys: benutzung von SHL

Andrax

Level-1
Beiträge
84
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Morgen zusammen,

ich bin gerade dabei mich in Codesys auf dem Raspberry einzuarbeiten.
Dazu will ich nach und nach meine Python-scripte in SCL umsetzen.
Jetzt will ich folgenden Code umsetzen:

Python:
data = sdp810.read_i2c_block_data(SDP810_I2C_ADDRESS, 0, 9)

    press = twos_comp((256 * data[0] + data[1]), 16) / 240.0
    return press

def twos_comp(val, bits):
    if (val & (1 << (bits - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255#
        val = val - (1 << bits)        # compute negative value
    return val

Ich habe es jetzt mit folgenden Code versucht:
Code:
METHOD AfterReadInputs : INT
VAR
    Buffer : ARRAY[0..9] OF BYTE;
    len: DINT :=1;   
END_VAR


IF _iState = 10 THEN
    timer(IN:=TRUE);
    IF timer.Q THEN   
        len := Read(ADR(Buffer), 9);
        IF len = 9 THEN
            
            pressure :=(256 * Buffer[0] + Buffer[1])/240.0;
            IF pressure AND SHL(len, 15) <> 0 THEN
                pressure := pressure - SHL(len,16);
            END_IF
            xValid := TRUE;
            xNewMeasurement := TRUE;
        ELSE
        .....

Pressure ist vom Typ LREAL.
Ich bekomme immer den Fehler
" C0032: Typ 'LREAL' kann nicht in Typ 'ANY_BIT' konvertiert werden"
" C0032: Typ 'LREAL' kann nicht in Typ 'Bool' konvertiert werden"
" C0032: Typ 'Bool' kann nicht in Typ 'LREAL' konvertiert werden"

Was mache ich falsch?


Grüße

Andre
 
Moin,

Du versuchst eine IF-Abfrage (Bool) mit einem LREAL-Wert.
Du mußt den LREAL-Wert auf etwas vergleichen, um einen boolschen Ausdruck zu bekommen.
Die drei Meldungen besagen, daß der Compiler irgendwie versucht durch Typwandlungen an ein boolsches Ergebnis zu kommen und dabei scheitert.

Zu Deinem Problem:
Du versuchst ein bitweises UND. Das funktioniert nur mit Datentypen wie Byte, Word, DWord.
Ein Real oder LReal kannst Du nicht bitweise verUNDen, weil es kein BIT-Datentyp ist: Kann nicht in ANY_BIT konvertiert werden.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Datentyp pressure ist ? Datentypen sind in codesys bequem, man kanns aber auch ein Bisschen übertreiben
und warum ein dint 15 stellen nach links schieben ? len.0 benutzen?
und : (256 * byte + weiteres byte )/real ... ja das Ergebniss ist real aber ....
und ein Byte mal 256 um das aufs höherwertige Byte zu legen ... kopieren oder ein Union verwenden .. und kommentiere was 256 mal byte als datentyp ergibt (hilft Dir auch dauernd im Gedächtnis zu behalten in welchem Bereich du gerade bist).. in 10 Jahren braucht man ein paar nutzlose Minuten um das zu erarbeiten
Kannst du in 10 Jahren das wirklich nochmal auf Anhieb lesen ? (stimmt das mal dann gibts auch im "jetzt" keine Probleme mit Datentypen auch ohne alles explizit zu konvertieren)
 
Zuletzt bearbeitet:
Also, es handelt sich um einen Differenzdrucksensor.
Nach der Initalisierung werden vom Sensor 9 Register @16Bit abgerufen und in eine Liste gespeichert.
Danach erfolgt die Berechnung >>press = twos_comp((256 * data[0] + data[1]), 16) / 240.0
Danach würd geprüft, welches Vorzeichenbit gesetzt ist, und entsprechend geschoben.
Der Wert "pressure" wird ausgegeben.
Der Datentyp "pressure" ist in python nicht angegeben.
 
Bin erst mal einen Schritt weiter.
Der Code lässt sich ohne Fehler übersetzen und läuft auch.
Die Bitverschiebung hab ich erst mal raus geworfen.
In der library habe ich folgendes Stehen:

Code:
FUNCTION_BLOCK Test_SDP810 EXTENDS i2c
VAR_INPUT
END_VAR
VAR_OUTPUT
    pressure : LREAL; // Druck
END_VAR
VAR
    timer: ton := (IN:=TRUE, pt:=T#200MS);
    Buffer : ARRAY[0..8] OF BYTE;
    len: DINT;
END_VAR

SUPER^();

CASE _iState OF
0:
    IF usiAddress = 0 THEN
        usiAddress := 16#25;
    END_IF
    IF SUPER^.init() THEN
        _iState := 5;
    END_IF   

5:   
    write8(16#3F, 16#F9); // stopp messung
    write8(16#36, 16#1E); // setze Diferentialmessung time=0.5ms 0x36 + 0x1E = 0x361E
    _iState := 10;
    timer(IN := TRUE);   

END_CASE

In der Funktion AfterReadInputs steht folgendes:
Code:
METHOD AfterReadInputs : INT
VAR
    
END_VAR

SUPER^.AfterReadInputs();

IF _iState = 10 THEN
    timer();
timer(IN := TRUE);   
    IF timer.Q THEN   
        //timer(IN := FALSE);
        //timer(IN := TRUE);
        
        len := Readregister(0, ADR(Buffer), 9);
        IF len = 9 THEN
            pressure :=(256 * BYTE_TO_LREAL(Buffer[0]) + BYTE_TO_LREAL(Buffer[1]))/240.0;
        END_IF
        timer(IN:=FALSE);
    END_IF

END_IF

Problem, obwohl pt:=T#200MS steht, wird online immer pt:=T#10MS angezeigt.
Der Timer läuft nicht los.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ich bin gerade dabei mich in Codesys auf dem Raspberry einzuarbeiten.
Dazu will ich nach und nach meine Python-scripte in SCL umsetzen.
Ich will dir ja nicht zu nahe treten aber bevor du dich mit Vererbung, Methoden usw. beschäftigst wären die Grundlagen erstmal wichtiger.
z.B. Timer - Aufruf, mehrfach Aufruf, Bedeutung der Parameter, Funktionsweise eines Timer's

So wie du das programmiert hast, funktioniert es nicht.
 
ja der Timer war nicht korrekt instanziert.
VAR
timer1: TON;
los: BOOL := FALSE;
END_VAR
timer1 (IN:=los, pt:=T#100MS);
los := TRUE;
IF timer1.Q THEN
...
...
...
los := FALSE;

Problem: Im PLC_PRG läuft der Timer, im Funktionbaustein nicht.
Ursache hab ich mittlerweile auch schon gefunden. Ich komme nicht bei _istate über 0:, da ich bei SUPER^.init() hängen bleibe.
 
Zurück
Oben