PicoBoy Color - Neues Projekt
RPi PicoBoy Color und
Magnetometer MMC56X3
Projekte und Anleitung in CircuitPython 9.x.x
Bildbox 1 (klick hier)
Andere PicoBoy-Color Projekte:
PicoBoy-Color vorgestellt
Hardware des PicoBoy - Color und Inbetriebnahme (1 - Display)
Hardware des PicoBoy - Color: Benutzung Joystick, Tasten und LED
Projekt mit PicoBoy - Color: Temperatur und Luftdruck messen
Projekt mit PicoBoy - Color: Neopixelring
Bewegte Bilder auf dem PicoBoy-Color - Spiele mit Sprites
Projekt mit PicoBoy - Color als Compass
PicoBoy Color - Neues Projekt
RPi PicoBoy Color und
Magnetometer MMC56X3
Projekte und Anleitung in CircuitPython 9.x.x





Bildbox 1 (klick hier)
In dieser neuen Anleitung wird mit Hilfe eines Magnetometers MMC56X3 von Adafruit eine Compassanwendung auf dem PicoBoy-Color dargestellt. Der Chip wird am I2C-Bus
des PicoBoys betrieben und an den Lötpads der GPIO 20 und 21 angeschlossen.
Hardware
- PicoBoy-Color (z.B. von hier )
- USB-A zu USB-C Kabel
- Magnetometer MMC56X3 von Adafruit (z.B. von hier )
Software
- aktuelle Firmeware CircuitPython z.B. 9.x
- library adafruit_mmc5656x3.mpy aus dem CircuitPython-Bundle zur Firmewareversion
- library adafruit_st7789.mpy aus dem CircuitPython-Bundle zur Firmewareversion
- Ordner adafruit_imageload aus dem CircuitPython-Bundle zur Firmewareversion
- Ordner adafruit_register aus dem CircuitPython-Bundle zur Firmewareversion
- Ordner adafruit_display_text aus dem CircuitPython-Bundle zur Firmewareversion
Los gehts
Da der PicoBoy-Color nicht über eine Stemma QT-Buchse verfügt, wie das Magnetometer MMC56x3 von Adafruit, müssen vier
Kabel an den Lötpads des PicoBoy-Color angelötet werden. Falls Sie ein Qwiic-Kabel 'spendieren', können Sie den Stecker auf einer Seite
abschneiden und wie im Foto gezeigt, an den Lötpads anlöten. Oder Sie verbinden das Magnetometer mit dem PicoBoy-Color über vier
Kabel, wie im Foto unten dargestellt. Damit bei den Tests reproduzierbare Werte entstehen, habe ich das Magnetometer-Board auf der
Unterseite des PicoBoy-Color fixiert (siehe Bild 2 in Bildbox 1). In einem späteren Gehäuse wird es dann einen geeigneten Platz
bekommen.

Wenn das erledigt ist, kann das Magnetometer in betrieb genommen werden. Adafruit beschreibt in seinen Anleitungen einen ersten s.g. 'simpletest.py', der im unteren Kasten gezeigt ist. Beachten Sie, dass sich die Bibliothek adafruit_mmc5656x3.mpy im 'lib-Ordner' befindet.
1 # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 # SPDX-License-Identifier: MIT 3 4 # Simple demo of the MMC56x3 magnetometer. 5 # Will print the magnetometer values every second. 6 import time 7 import board 8 import busio 9 import adafruit_mmc56x3 10 11 # Initialize I2C bus and sensor. 12 i2c = busio.I2C(board.GP21, board.GP20) 13 # i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller 14 sensor = adafruit_mmc56x3.MMC5603(i2c) 15 16 # values every second and print them out. 17 while True: 18 mag_x, mag_y, mag_z = sensor.magnetic 19 temp = sensor.temperature 20 # Print values. 21 print( 22 "Magnetometer (gauss): ({0:0.3f},{1:0.3f},{2:0.3f})".format(mag_x, mag_y, mag_z) 23 ) 24 print("Temperature: {0:0.3f}C".format(temp)) 25 # Delay for a second. 26 time.sleep(1.0)
Wenn Sie das Programm starten und den PicoBoy-Color auf einer flachen Unterlage etwas hin- und herbewegen, werden in der
Console der Thonny-IDE entsprechende Werte ausgegeben:
Bildbox 2 (klick hier)
Was die Werte bedeuten und wie sie genutzt werden können, wird nachfolgend erklärt. Dass der Chip auch die Temperatur erfasst, sei hier nur am
Rande erwähnt und wird nicht weiter verfolgt.
Notwendigkeit zum Kalibrieren des Sensors:
Magnetometer können verwendet werden, um die Orientierung in Bezug auf das Erdmagnetfeld zu ermitteln. Im Grunde wie ein Kompass!
Beim Kompass richtet sich eine Magnetnadel in Richtung des Erdmagnetfeldes aus und zeigt zum magnetischen Nordpol. So können wir sagen,
wo Norden ist. Aber Magnetometer müssen in einer Welt voller Magnete (Motoren, Spulen, Stromleitungen, Maschinen aus Eisen/Stahl u.s.w.)
ein sehr kleines Magnetfeld von 35-65 µTesla messen. Deshalb müssen sie kalibriert werden. Durch eine s.g. Hard-Iron-Offset-Berechnung
werden starke Offsetwerte ausgeschlossen. So können sie den magnetischen Norden finden.
Methode zum Kalibrieren des Sensors:
Eine einfache Methode zur Kalibrierung verwendet das Aufzeichnen von Werten, um die minimalen und maximalen Messwerte auf allen drei Achsen zu
erfassen. Während Sie die Aufzeichnung ausführen, drehen Sie das Modul mehrmals langsam in allen drei Achsen. Das Ziel besteht darin,
die absoluten Minima und Maxima für jede Achse aufzuzeichnen. Je mehr Sie es also drehen, desto wahrscheinlicher ist es, dass Sie den absoluten
Spitzenwert erfassen.
Das Programm im folgenden Kasten bestimmt diese Minimal- und Maximalwerte und schreibt sie in ein Array, welches im späteren Compass-Programm
genutzt wird.

Bildbox 2 (klick hier)
1 # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 # SPDX-License-Identifier: MIT 3 4 """ Calibrate the magnetometer and print out the hard-iron calibrations """ 5 6 import time 7 import board 8 import busio 9 import adafruit_mmc56x3 10 11 # Initialize I2C bus and sensor. 12 i2c = busio.I2C(board.GP21, board.GP20) 13 magnetometer = adafruit_mmc56x3.MMC5603(i2c) 14 15 # calibration for magnetometer X (min, max), Y and Z 16 hardiron_calibration = [[1000, -1000], [1000, -1000], [1000, -1000]] 17 18 def calibrate(): 19 start_time = time.monotonic() 20 # Update the high and low extremes 21 while time.monotonic() - start_time < 15.0: 22 magval = magnetometer.magnetic 23 print("Calibrating - X:{0:10.2f}, Y:{1:10.2f}, Z:{2:10.2f} uT".format(*magval)) 24 for i, axis in enumerate(magval): 25 hardiron_calibration[i][0] = min(hardiron_calibration[i][0], axis) 26 hardiron_calibration[i][1] = max(hardiron_calibration[i][1], axis) 27 print("Calibration complete:") 28 print("hardiron_calibration =", hardiron_calibration) 29 30 print("Prepare to calibrate! Twist the magnetometer around in 3D in...") 31 print("3...") 32 time.sleep(1) 33 print("2...") 34 time.sleep(1) 35 print("1...") 36 time.sleep(1) 37 38 calibrate()
Wenn Sie das Programm starten und den PicoBoy-Color langsam in verschiedene Richtungen bewegen, werden in der
Console der Thonny-IDE entsprechende Werte ausgegeben:
Bildbox 3 (klick hier)
Entscheidend ist die letzte Zeile in der Kommandozeile:
hardiron_calibration = [[14.8625, 69.6], [-40.6875, 31.3062], [-56.4312, -11.0562]]
Hier sind die Minimal- und Maximalwerte für die X, Y und Z Richtung enthalten. Speichern Sie die komplette Zeile in die Zwischenablage, um sie
später in das Compass-Programm einzusetzen.
Damit sind wir so weit, um ein erstes kurzes Programm mit der Kompassrichtung zu testen. Auf dem Kompass ist eine Scheibe mit einer im
Uhrzeigersinn aufgetragenen 360-Grad-Einteilung angebracht (Kompassrose). Die vier Himmelsrichtungen Norden, Osten, Süden und Westen
entsprechen 0°, 90°, 180° und 270°. Der Sensor des Magnetometers gibt uns die Werte des Magnetfeldes der Erde in µTesla
an. Zur Berechnung benutzen wir die x- und y-Richtung des Sensors. Um die Mikrotesla-Werte in eine Kompassrichtung von 0-360 Grad umzuwandeln,
können wir die Funktion atan2() verwenden. Das Ergebnis wird in Radiant angegeben, also multiplizieren wir es mit 180 Grad und dividieren
durch Pi, um es in Grad umzuwandeln. Im unteren Kasten finden Sie dafür den Quellcode, wie ihn Adafruit für eine Vielzahl seiner
Magnetometer vorschlägt:

Bildbox 3 (klick hier)
1 # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries 2 # SPDX-License-Identifier: MIT 3 4 """ Display compass heading data from a calibrated magnetometer """ 5 6 import time 7 import math 8 import board 9 import busio 10 import adafruit_mmc56x3 11 12 # Initialize I2C bus and sensor. 13 i2c = busio.I2C(board.GP21, board.GP20) 14 sensor = adafruit_mmc56x3.MMC5603(i2c) 15 16 # You need t copy your own value for hardiron_calibration from the output and paste it 17 # into this script here: 18 hardiron_calibration = [[14.8625, 69.6], [-40.6875, 31.3062], [-56.4312, -11.0562]] 19 20 # This will take the magnetometer values, adjust them with the calibrations 21 # and return a new array with the XYZ values ranging from -100 to 100 22 def normalize(_magvals): 23 ret = [0, 0, 0] 24 for i, axis in enumerate(_magvals): 25 minv, maxv = hardiron_calibration[i] 26 axis = min(max(minv, axis), maxv) # keep within min/max calibration 27 ret[i] = (axis - minv) * 200 / (maxv - minv) + -100 28 return ret 29 30 31 while True: 32 magvals = sensor.magnetic 33 normvals = normalize(magvals) 34 35 # we will only use X and Y for the compass calculations, so hold it level! 36 compass_heading = int(math.atan2(normvals[1], normvals[0]) * 180 / math.pi) 37 # compass_heading is between -180 and +180 since atan2 returns -pi to +pi 38 # this translates it to be between 0 and 360 39 if compass_heading < 0: 40 compass_heading += 360 41 42 print("Heading:", compass_heading) 43 time.sleep(1)
Was bedeuten die Anzeigen?
- Richtung: 0° Norden
- Richtung: 90° Osten
- Richtung: 180° Süden
- Richtung: 270° Westen
Nun wäre es natürlich schön, wenn die Werte nicht nur in der Console der Thonny-IDE angezeigt würden.
Deshalb folgt hier noch ein Vorschlag, wie eine Kompassrose auf dem Display des PicoBoy-Color dargestellt wird, die sich
bei Bewegung des PicoBoy's dreht und immer nach Norden ausrichtet.
Bildbox 4 (klick hier)
Bevor Sie den Quellcode aus dem unteren Kasten ausprobieren, erinnere ich noch einmal an die unter 'Software' genannten Bibliotheken und
Bibliotheksordner, die sich jetzt alle im 'lib-Ordner' befinden müssen. Ausserdem wird die Bitmap-Datei 'compass.bmp'
in einem Ordner 'images' benötigt. Legen Sie den Ordner auf dem PicoBoy Laufwerk an,
downloaden die Bilddatei von hier
und speichern sie im Ordner 'images'.


Bildbox 4 (klick hier)
1 # SPDX-FileCopyrightText : 2025 Detlef Gebhardt, written for CircuitPython 9.1.4 2 # SPDX-FileCopyrightText : Copyright (c) 2025 Detlef Gebhardt 3 # SPDX-Filename : PicoBoy-Color Compass 4 # SPDX-License-Identifier: https://dgebhardt.de 5 import time 6 import board 7 from adafruit_display_text.bitmap_label import Label 8 from displayio import Group 9 import busio 10 import displayio 11 import terminalio 12 import adafruit_imageload 13 import bitmaptools 14 from adafruit_st7789 import ST7789 15 import adafruit_mmc56x3 16 import math 17 18 # 1,69 Zoll 240x280 Pixel ST7789 Display 19 # SPI-Bus, in Portrait format 20 dc=board.GP8 21 reset=board.GP9 22 cs=board.GP10 23 sck=board.GP18 24 mosi=board.GP19 25 bl=board.GP26 26 # Release any resources currently in use for the displays 27 displayio.release_displays() 28 spi = busio.SPI(sck, mosi) 29 display_bus = displayio.FourWire(spi, command=dc, chip_select=cs, reset=reset) 30 display = ST7789(display_bus, rotation=0, width=240, height=280, backlight_pin=bl, rowstart=20, colstart=0) 31 display.brightness = 1 32 # create a main_group to hold anything we want to show on the display. 33 main_group = Group() 34 35 # Bitmap-Dateien fuer Hintergrund und Zeiger 36 zifferblatt = "/images/compass.bmp" 37 ## Compassnadel 240x240 Hintergrund 38 bg_bitmap, bg_pal = adafruit_imageload.load(zifferblatt, bitmap=displayio.Bitmap,palette=displayio.Palette) 39 bg_pal.make_transparent(0) 40 bg_bitmap_scribble = displayio.Bitmap(display.width, display.height, len(bg_pal)) 41 bg_tile_grid = displayio.TileGrid(bg_bitmap_scribble, pixel_shader=bg_pal) 42 main_group.append(bg_tile_grid) 43 bitmaptools.rotozoom( bg_bitmap_scribble, bg_bitmap, angle = 0) 44 45 # Initialize I2C bus and sensor. 46 i2c = busio.I2C(board.GP21, board.GP20) 47 sensor = adafruit_mmc56x3.MMC5603(i2c) 48 49 # set the main_group as the root_group of the built-in DISPLAY 50 display.root_group = main_group 51 52 sensor.data_rate = 10 # in Hz, from 1-255 or 1000 53 sensor.continuous_mode = True 54 55 #my values 56 hardiron_calibration = [[32.0, 62.0], [-22.0, 7.5], [-18.0, -12.0]] 57 58 # This will take the magnetometer values, adjust them with the calibrations 59 # and return a new array with the XYZ values ranging from -100 to 100 60 def normalize(_magvals): 61 ret = [0, 0, 0] 62 for i, axis in enumerate(_magvals): 63 minv, maxv = hardiron_calibration[i] 64 axis = min(max(minv, axis), maxv) # keep within min/max calibration 65 ret[i] = (axis - minv) * 200 / (maxv - minv) + -100 66 return ret 67 68 # begin main loop 69 while True: 70 magvals = sensor.magnetic 71 normvals = normalize(magvals) 72 # we will only use X and Y for the compass calculations 73 compass_heading = math.atan2(normvals[1], normvals[0]) * 30 / math.pi 74 # this translates it to be between 0 and 60 75 if compass_heading < 0: 76 compass_heading += 60 77 #print("Kurswinkel: ", 6*int(compass_heading + 0.5)) 78 bitmaptools.rotozoom( bg_bitmap_scribble, bg_bitmap, angle = math.pi/30 * (1 - compass_heading)) 79 time.sleep(0.3)
Zum Abschluss noch ein paar Erläuterungen zum Programm:
Die Zeilen 1- 34 importieren die benötigten Bibliotheken und Module und initialisieren das Display. In den Zeilen 35
bis 43 wird eine Tile_Grid mit der Bilddatei als Hintergrundbild angelegt und mit Hilfe von 'bitmaptools.rotozoom' (43) als
drehbar definiert. Die Zeilen 45 bis 72 entsprechen im Wesentlichen den vorangegangenen Tests. Die Angabe des Winkels für die
Kompassrichtung in Zeile 73 habe ich zwischen 0 und 60 gewählt. So kann ich in Zeile 78 die Ausrichtung der 'Nadel' ähnlich
den Sekunden auf dem Zifferblatt einer Uhr vornehmen. D.h. wenn der Zeiger senkrecht nach oben zeigt, wie in Bild 2 von Bildbox 4, wäre
die Venedigkarte 'eingenordet'. Ansonsten findet man Norden bei beliebiger Lage des PicoBoy-Color, da der Zeiger immer
in diese Richtung zeigt (siehe Bild 1 Bildbox 4).
Viel Spass und Erfolg beim Ausprobieren.
