Matlab funktion in python funktion umschreiben (bitshift)

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
python48
User
Beiträge: 18
Registriert: Donnerstag 19. März 2015, 14:58

Hallo,

ich bräuchte mal wieder eure Hilfe.
Eine Funktion, die in Matlab funktioniert und die ich in Python umgeschrieben habe,
funktioniert leider nicht so wie sie soll in python.
Ich habe schon einiges ausprobiert aber komme einfach nicht weiter.
Im Folgenden habe ich die funktionierende Matlab funktion eingefügt und die nicht
funktionierende python funktion.
Womöglich könnt ihr mir gleich einen Hinweis geben woran es liegen könnte.
Mit dieser Funktion werden sensoren ausgelesen (analogwerte). Normalerweise
sollten im ruhezustand immer werte im Bereich 20-80 angezeigt werden, was in der
Matlab funktion auch klappt. In der python funktion scheinen die ersten beiden werte
korrekt und die 2 nachfolgenden sind im bereich von 3000-40000.
Den bitshift habe ich ja genau wie in der Matlabfunktion übernommen also kann es
daran eigentlich nicht liegen aber trozdem sieht es nach eine shift oder konvertierungsfehler aus.
Kann es was mit der integerinterpretation von python zu tun haben?
Muss ich die werte zuerst in ein anderes format casten? (unsigned integer wie in der matlab funktion?)
Komme hier einfach nicht weiter und hoffe dass mir der ein oder andere einen hinweis geben kann! :)

Code: Alles auswählen

function [ data ] = analogreaddistancel()
%Die Bodensensoren werden ausgelesen
       a = [234,4,6,1];
       x = serialwriteread(a);

       b = uint16(x(2));
       c = uint16(x(3));
       g = uint16(x(4));
       e = uint16(x(5));
       f = uint16(x(6));
       
       d(2) = bitshift(b,2) + bitshift(c,-6);
       d(3) = bitshift(bitshift(c,10),-6) + bitshift(g,-4);
       d(4) = bitshift(bitshift(g,12),-6) + bitshift(e,-2);
       d(5) = bitshift(bitshift(e,14),-6) + f;
      
       data = [d(2),d(3),d(4),d(5),];
       
   end
end

Code: Alles auswählen

def analogreaddistanceleft():  
            order = [234, 4, 6, 1]
            data_response = []
            response = serial_write_read(order)

            response_2 = int(response[2])
            response_3 = int(response[3])
            response_4 = int(response[4])
            response_5 = int(response[5])
            response_6 = int(response[6])

            shift_tmp_1 = (response_2 << 2) + (response_3 >> 6)
            shift_tmp_2 = ((response_3 << 10) >> 6) + (response_4 >> 4)
            shift_tmp_3 = ((response_4 << 12) >> 6) + (response_5 >> 2)
            shift_tmp_4 = ((response_5 << 14) >> 6) + response_6

            data_response.append(shift_tmp_1)
            data_response.append(shift_tmp_2)
            data_response.append(shift_tmp_3)
            data_response.append(shift_tmp_4)

            return data_response
Vielen Dank schon mal! :)
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@python48: für mich sieht das so aus, als ob Du 5 Bytes in 4 10bit-Werte konvertieren willst:

Code: Alles auswählen

def analogreaddistanceleft():  
    order = [234, 4, 6, 1]
    _, b, c, g, e, f = serial_write_read(order)
    a = (((b * 256 + c) * 256 + g) * 256 + e) * 256 + f
    a, a4 = divmod(a, 1024)
    a, a3 = divmod(a, 1024)
    a1, a2 = divmod(a, 1024)
    return a1, a2, a3, a4
BlackJack

@python48: Also der Fehler dürfte sein das in Matlab anscheinend 16-Bit-Zahlen benutzt werden wo Bits die man ”links raus schiebt” einfach verschwinden, während die in Python erhalten bleiben weil `int` in Python keine Grössenbeschränkung haben. Da müsste man dann das Ergebnis vom jeweiligen links-schieben mit ``& 0xffff`` auf 16 Bit beschränken. Oder den schöneren Weg von Sirius3 nehmen. :-)
python48
User
Beiträge: 18
Registriert: Donnerstag 19. März 2015, 14:58

vielen lieben dank für deine schnelle hilfe! :)

Wenn ich deinen code ausprobiere bekomme ich jedoch eine fehlermeldung:

Code: Alles auswählen

_, b, c, g, e, f = serial_write_read(order)
ValueError: too many values to unpack
Also der Fehler dürfte sein das in Matlab anscheinend 16-Bit-Zahlen benutzt werden wo Bits die man ”links raus schiebt” einfach verschwinden, während die in Python erhalten bleiben weil `int` in Python keine Grössenbeschränkung haben.
Ah, das erscheint logisch... Vielen Dank, daran habe ich jetzt nicht gedacht :P
BlackJack

@python48: Dann liefert `serial_write_read()` mehr als die 6 Bytes. Da könnte man mit Slicing arbeiten: ``a, b, c, d, e = map(int, serial_write_read(order)[1:6])``
python48
User
Beiträge: 18
Registriert: Donnerstag 19. März 2015, 14:58

@BlackJack: Ich habe den Wertebereich jetzt noch mit der entsprechenden Bitmask verundet/begrenzt
und es funktioniert jetzt einwandfrei! Vielen Dank für den Hinweis mit der Größenbeschränkung! :)

@Sirius: Danke dir, ich hätte jedoch noch 2 Fragen zu deinem code:
1. Wieso nimmst du immer mal 256? Da stehe ich bei mir grad aufm Schlauch...

Code: Alles auswählen

a = (((b * 256 + c) * 256 + g) * 256 + e) * 256 + f

2. Hat der Unterstrich am Anfang der Zeile eine besondere Bedeutung in python oder wird das
einfach als eine normale variable interpretiert?

Code: Alles auswählen

_, b, c, g, e, f = serial_write_read(order)
Danke euch! :)
BlackJack

@python48: ``n << e`` ist äquivalent zu ``n * 2**e``, also ist ``n << 8`` das gleiche wie ``n * 256``. Der Unterstrich ist ein an sich normaler Name, wird in Quelltext aber per Konvention für Stellen verwendet wo man syntaktisch einen Namen schreiben muss, wo einem der Wert aber egal ist.
python48
User
Beiträge: 18
Registriert: Donnerstag 19. März 2015, 14:58

Vielen Dank für die Hilfe, hat mich ein ganzes stück weitergebracht! :)

Gruß, python48.
Antworten