Page 1 of 1

Python 2.7 Zugriff andre Bits im Offset

Posted: 05 Jan 2018, 09:39
by nseries
Hallo zusammen,

ich habe eine wahrscheinlich sehr einfache Frage zum Zugriff auf die Ein- und Ausgänge des ReviPI.

Ich habe mir die Videotutorials und auch die Downloads angesehen und folgendes Problem. Ich habe mir die folgende Funktion geschrieben (Python Python 2.7.9):

Code: Select all

#get Value from input or output
def getDriverValue(pOffset,pBit):
        driver.seek(pOffset);       #readValue offset 100
        i = driver.read(2);     #length 2
        s = struct.unpack('<H',i)       # this is the way which is possible with Python 2.7
        print i
        lValue = s[pBit]                            # because is is a list we have to restrict the access to the first element
        return lValue
Ich möchte gern der Funktion die nötigen Parameter übergeben um die bspw. digitale Eingänge zu lesen.
Zum test habe ich die folgenden benannt und addressiert:

Code: Select all

 piTest -r Input1
Bit value: 1
Bit value: 1

piTest -v Input1
variable name: Input1
       offset: 100
       length: 1
          bit: 0
         
 piTest -r Input2
Bit value: 0
Bit value: 0

piTest -v Input2
variable name: Input2
       offset: 100
       length: 1
          bit: 2
                   
Man sieht ich kann beide korrekt mit -r Auslesen. Der erste digitale Input steht auf 1 der zweite auf 0.

Wenn ich der Funktion oben als Offset 100 gebe, erhalte ich immer den Wert des ersten Inputs. Auch wenn ich bspw. 100.1 oder 100.2 übergebe.
Wo liegt mein Fehler? Wie kann ich der Funtion sagen nimm bitte den Wert offset 100 2. Bit?

PS.: aktuell übergebe ich als pBit der Funktion immer eine 0. Das war noch ein Test..

Danke und viele Grüße

:)

Re: Python 2.7 Zugriff andre Bits im Offset

Posted: 05 Jan 2018, 14:15
by volker
HI,
da sind in Deinem Code leider Dinge ein wenig durhceinander geraten. Dem Kommentarim Code entnehme ich, dass Du Du Teile davon aus "RunninLight.py" (aus "Code Beispiel aus Video Tutorial Nr. 16") hast. Dort wurde aber bei diesen zeilen kein Einzelbit abgefragt, sondern alle 14 Eingänge (also 2 Byte). Der Einzelzugriff auf Bits erfolgt auf 2 mögliche Weisen: Eintweder mit einem IOCTL-Aufruf (siehe RunningLight.py) oder aber beim Lesen durchaus auch einfacher durch Lesen aller 14/16 Eingänge und anschließendes maskieren des Bits und dann rechtsshift (=division durch 2er Potenz). Während bei IOCTL ein komplizietrer Parameter bestimmt und übergeben werden muss, ist dort allerdings dann auch die direkte Übergabe der Bit-Stelle möglich. Da es beim lesen wirklich egal ist (ja sogar performanter) ob Du gleich 16 Bits einliest, ist dies beim Schreiben natürlich nicht egal, weil man dann immer erst lesen muss, dann ein einzelnes Bit verändern und danach wieder Schreiben. In der Zwischenzeit könnten sich aber die anderen Bits schon verändert haben und dann entshet ein Problem daraus. Du brauchst beim Schrieben einen sogenannten "atomaren" Zugriff, der nur über den IOCTL-Aufruf gewährleistet ist. Beim Lesen ist das wie gesagt egal.
Daher kannst Du wie in Deinem Programm einfach mit

Code: Select all

i = driver.read(2);     #length 2
die beiden Bytes mit allen 14/16 Eingängen einlesen (je nach DIO oder DI Modul). Mit

Code: Select all

s = struct.unpack('<H',i)       # this is the way which is possible with Python 2.7
entpackst Du das beim read eingelesene Bytearray in eine Struktur, bei der das einzige Element eine Integerzahl mit allen Bits ist. Da die struct Funktion immer eine Struktur zurück gibt, auch wenn asl Ergebnis nur eine Zahl entsteht, muss so auf diese Zahl zugegriffen werden:

Code: Select all

lValue = s[0] 
In lValue steht nun die 16 bit Integerzahl. Nun musst Deine Funktion mit dem Parameter pBit daraus das einzelen Bit extrahieren und auf 1 oer 0 testen. Das geht z.B. so:

Code: Select all

mask  =  1<<pBit                                   # links shift un pBit entspricht der Funktion 2^pBit, also 0,2,4,8,16,32... für 0,1,2,3,4,5...
return (lValue & mask == mask)
Wenn in Deiner Software sehr viel mit solchen masken gearbeitet wird, dann kannst Du performanter statt x-mal einen linksshift durchzuführen auch gleich zu Beginn eine dictionary Struktur anlegen und darüber zugreifen:

Code: Select all

mask = {0:0,1:2,2:4,3:8,4:16,5:32,6:64,7:128,8:256,9:512,10:1024,11:2048,12:4096,13:8192}
return (lValue & mask[pBit]==mask[pBit])
Soweit die klassische Methode über Bit-Masken. Macht ja durchaus Sinn, dass Du Dich mit dieser Matherie mal in dieser Tiefe befasst. Wenn Du es einfacher haben willst, dann kannst Du natürlich auch auf Biliotheken zugreifen, die diese Arbeit für Dich erledigen:
https://revpimodio.org/
Aber in die muss man sich halt auch erst mal einlesen ;.)
Viel Erfolg und ruhig weiter fragen wenn Dinge noch unklar sind...