Das unsigned byte Problem in Java

Seit letztem Wochenende habe ich ein nettes kleines Spielzeug zu Hause, mit dem ich gerade ein wenig herumexperimentiere. Es handelt sich um ein nRF51 Sensor Tag. Diese 3 cm. kleine Platine enthält einen BLE Chip mit nRF51822QFAA (Cortex-M0, 16kB RAM, 256kb Flash, SPI, I2C, UART, etc.), zwei Taster, RGB LED, MPU6050 3-Achsen-Gyroskop + 3-Achsen-Beschleunigungssensor, AP3216C Licht Sensor, BMP180 Luftdruck und Temperatur Sensor. Der Stromverbrauch ist extrem niedrig und daher reicht eine CR2023 Knopfzelle aus um die Elektronik mit Strom zu versorgen.

N51822 Bluetooth 4 0 BLE SOC Temperatur Atmosphärendruck Beschleunigung Sensor Modul Gyroskop Licht Sensor MPU6050 AP3216 in N51822 Bluetooth 4 0 BLE SOC Temperatur Atmosphärendruck Beschleunigung Sensor Modul Gyro

Die Elektronik habe ich durch Zufall im Internet entdeckt und für unter 10€ direkt in China bei aliexpress.com bestellt. Die Hardware ist nun da und ich habe nun eine kleine Android App zusammengedengelt, mit der die Sensordaten ausgelesen werden können. Die Daten der unterschiedlichen Sensoren werden als Byte-Array in der App verarbeitet, was mich auch direkt zum eigentlichen Problem führt.

Die Sensordaten des MPU6050 werden in 2 Datenpaketen von jeweils 6 Bytes übertragen. Darin sind dann wiederum 3 Sensorwerte mit einer Länge von 2 Byte enthalten.

Also z.B.

0xC0447A4E0234 (Beschleunigung X,Y und Z Achse) und 0xE4F53278A2C0 (Rotation X,Y und Z Achse)

Die Werte kann man nun wie folgt aufsplitten:

Beschleunigung X = {0xC0, 0x44}

Beschleunigung Y = {0x7A, 0x4E}

Beschleunigung Z = {0x02, 0x34}

Rotation X = {0xE4, 0xF5}

Rotation Y = {0x32, 0x78}

Rotation Z = {0xA2, 0xC0}

Um nun z.B. die Beschleunigung X zu ermitteln habe ich einfach den Wert 0xC0 mit 256 multipliziert und den Wert 0x44 addiert. Gibt man das so in den Taschenrechner ein ergibt das:

Hex: 0xC044

Dec: 49220

Leider ist ein Java byte vorzeichenbehaftet und entspricht nicht den Werten von 0 – 255 sondern von -128 bis 127. Das kann man mit dem folgenden kleinen Java Programm selber ausprobieren.

package com.jentsch.unsignedbyte.test;

public class Main {

        public static void main(String[] args) {

                for (int i = 0; i < 256; i++) {

                        byte b = (byte)i;

                        int value = b;

                        System.out.println (“Int: ” + i + ” Byte:” + b + ” Result: ” + value);

                }

        }

}

Das Ergebnis sieht dann wie folgt aus:

Int: 0 Byte:0 Result: 0

Int: 1 Byte:1 Result: 1

Int: 2 Byte:2 Result: 2

Int: 125 Byte:125 Result: 125

Int: 126 Byte:126 Result: 126

Int: 127 Byte:127 Result: 127

Int: 128 Byte:-128 Result: -128

Int: 129 Byte:-127 Result: -127

Int: 130 Byte:-126 Result: -126

Int: 253 Byte:-3 Result: -3

Int: 254 Byte:-2 Result: -2

Int: 255 Byte:-1 Result: -1

Schade, denn die kleine aber feine Methode, die ich verwende um aus den beiden Bytes mein Sensorwert zu erzeugen sieht wie folgt aus und würde mit einem unsigned byte ganz wunderbar funktionieren.

        public static long getLongValue(byte bh, byte bl) {

            long ret = bh * 0x100;

            ret += bl;

            return ret;

        }

Warum einfach, wenn es auch kompliziert geht.

Durch die Vorzeichen ergeben sich hier Werte, die nicht mehr zu gebrauchen sind. Also muss eine bessere Lösung her. Die einfachste Lösung, die ich gefunden habe sieht dann wie folgt aus:

        public static long getLongValue(byte bh, byte bl) {

                int ih = bh & 0xff;

            int il = bl & 0xff;

            long ret = ih * 0x100;

            ret += il;

            return ret;

        }

Eine kurze Probe mit dem folgenden Java Programm zeigt, dass es funktioniert.

package com.jentsch.unsignedbyte.test;

public class Main {

        public static void main(String[] args) {

                long val;

                long lastval = 0;

                for (int i = 0; i < 256; i++) {

                        for (int j = 0; j < 256; j++) {

                                byte bi = (byte)i;

                                byte bj = (byte)j;

                                val = getLongValue(bi,bj);

                                System.out.println (“Byte:” + bi + ” ” + bj + ” Result: ” + val);

                                if (lastval > val) {

                                       throw new RuntimeException (“Something went wrong here”);

                                }

                                lastval = val;

                        }

                }

        }

        public static long getLongValue(byte bh, byte bl) {

                int ih = bh & 0xff;

            int il = bl & 0xff;

            long ret = ih * 0x100;

            ret += il;

            return ret;

        }

}

So weit so gut. Also dann weiter. Mal sehen, was der nRF51 Sensor Tag so drauf hat 😊

Meine Apps im Google Play-Strore Jetzt bei Google Play