PicoBoy - Inbetriebnahme

technische Daten wie beim RPi Pico
MC RP2040 mit OLED-Display 128x64 Pixel

Anleitung für die Firmware CircuitPython 9.0.x



Hardware

- PicoBoy
- USB-A zu USB-C Kabel

Seit einiger Zeit ist ein weiterer Vertreter des Microcontrollers RP2040 mit dem Namen PicoBoy auf dem Markt. Es heißt, dass er von einem Informatiklehrer entwickelt wurde, damit seine Schüler das Programmieren erlernen. Ausgeliefert wird der PicoBoy allerdings mit einigen vorinstallierten Arcadederivaten von Tetris und Pacman, was einen heutigen Jugendlichen wohl gerade einmal dazu animiert, die Spiele im Briefmarkenformat auszuprobieren, bis die 3 V Knopfzelle leer ist. Was bei meinen Versuchen nach ca. 30 Minuten der Fall war.
Der PicoBoy wird also wie seine anderen Verwandten (Raspberry Pi, RPi Pico u.a.) seine Fangemeinde bei 'vorbelasteten' Programmierern (Profis u. Amateuren) finden, die bestimmte Projekte umsetzen wollen oder einfach zeigen, was mit Microcontrollern alles geht. Somit dürfte sich der lobenswerte Wunsch des Informatiklehrers wahrscheinlich nicht erfüllen. Immerhin bringt ihm der Verkauf der Platinen sicher ein paar Euro ein, was nicht verwerflich ist und hier nicht kritisiert wird.

Ich zähle mich zu den o.g. 'Vorbelasteten' und habe also zunächst einmal den PicoBoy "platt gemacht". D.h. den PicoBoy über ein USB-Kabel mit dem Rechner verbunden, die Boot-Taste gedrückt - diese gehalten - dann die Reset-Taste gedrückt - und nun beide losgelassen. Im Explorerfenster des Rechners erscheint daraufhin wie beim RPi-Pico ein Massenspeicher RPI-RP2 . Also gleiche Methode wie beim RPi-Pico. Dann mit der uf2-Datei flash-nuke.uf2 alles komplett löschen. Ich entscheide mich für das Betriebssystem CircuitPython und ziehe eine entsprechende, aktuelle uf2-Datei der Firmeware auf den Massenspeicher RPI-RP2. Nach dem Kopieren erscheint nun das Laufwerk 'CIRCUITPI' im Explorer. Bitte nicht wegklicken. Für den RPi-Pico habe ich die Schritte bei der Erstinstallation des runden LCD-Displays von Waveshare hier ausführlich beschrieben. Lesen Sie sich dort g.g.f. unter 'Los gehts' die entsprechenden Schritte durch und alles ist gut. Diejenigen, die sich schon auskennen, laden sich die aktuelle Firmeware 'CircuitPython' von hier: https://circuitpython.org/board/waveshare_rp2040_lcd_1_28/ herunter und installieren sie.


Los gehts

Nachdem 'CircuitPython' für den PicoBoy installiert ist, kann es weiter gehen. Als nächstes wird der Treiber für das Display gebraucht. Laut Hersteller handelt es sich um ein SH1106 1,3" s/w-OLED-Display mit 128 x 64 Pixeln. Unter CircuitPython gibt es dafür die Bibliothek adafruit_displayio_sh1106.mpy, die Sie in den 'lib'-Ordner auf das Laufwerk 'CIRCUITPI' kopieren. Bei dieser Gelegenheit kopieren Sie auch gleich die Bibliotheken für die Zeichenelemente ('adafruit_display_shapes') und den Text ('adafruit_display_text') in den 'lib'-Ordner. Ich habe festgestellt, dass beim Initialisieren des Displays am rechten Rand immer ein Streifen von Pixeln zu sehen war, der sich nicht überschreiben oder löschen ließ. Aufgrund eines Beitrags von Dan Halbert (CircuitPython core developer) auf github.com stieß ich darauf, dass die maximale Displaybreite 132 Pixel beträgt und konnte so das Problem beseitigen, indem ich für das Display bei 'width=132' eintrage .

Damit können wir einen ersten Test durchführen, um das Display in Betrieb zu nehmen:

  
  

1  import time
2  import board
3  import busio
4  import rtc
5  import displayio
6  import fourwire
7  import digitalio
8  import terminalio
9  from adafruit_display_text import label
10 from adafruit_display_shapes.rect import Rect
11 from adafruit_display_shapes.circle import Circle
12 import adafruit_displayio_sh1106
13 import pwmio
14
15 # Compatibility with both CircuitPython 8.x.x and 9.x.x.
16 # Remove after 8.x.x is no longer a supported release.
17 try:
18     from fourwire import FourWire
19 except ImportError:
20     from displayio import FourWire
21
22 #DC = board.GP8
23 #Reset = board.GP9
24 #CS = board.GP10
25 #SCK = board.GP18
26 #MOSI = board.GP19
27
28 # built-in a display
29 displayio.release_displays()
30 # Make the displayio SPI bus and the sh1106 display
31 spi = busio.SPI(board.GP18, board.GP19)
32 #
33 # Circuit 8.x.x
34 #display_bus = displayio.FourWire(spi, command=board.GP8, chip_select=board.GP10, reset=board.GP9, baudrate=1000000)
35 #display =adafruit_displayio_sh1106.SH1106(display_bus, width=132, height=64, rotation=0, brightness = 1)
36 #
37 # Circuit 9.x.x
38 display_bus = FourWire(spi, command=board.GP8, chip_select=board.GP10, reset=board.GP9, baudrate=1000000)
39 display =adafruit_displayio_sh1106.SH1106(display_bus, width=132, height=64, rotation=0, brightness = 1)
40
41 # Make the display contexts
42 splash = displayio.Group()
43 display.root_group = splash
44
45 # create the label
46 updating_text = label.Label(font=terminalio.FONT, text="it works", scale=2, color=0xffffff, line_spacing=1)
47 # set label position on the display
48 updating_text.anchor_point = (0, 0)
49 updating_text.anchored_position = (25, 20)
50 # add label to group that is showing on display
51 splash.append(updating_text)
52
  

Es folgen einige Erläuterungen:
In den Zeilen 1 bis 13 werden die Bibliotheken importiert. Einige werden zwar jetzt noch nicht benötigt, sind aber bei der späteren Programmerweiterung dann schon vorgesehen.
Die Zeilen 15 bis 20 stellen die Kompatibilität zwischen den Circuitversionen 8.x.x und 9.x.x sicher. Bei CircuitPython 8.x.x wurde 'Fourwire' in 'displayio' ausgeführt, was im Zuge der Weiterentwicklung von CircuitPython 9.x.x nicht mehr der Fall sein wird.
In den Zeilen 22 bis 26 sehen Sie, welche GPIO's das Display nutzt. Damit kann dann in den Zeilen 31 der 'spi-Bus' und in 38, 39 das Display initialisiert werden.
Die Zeilen 41 bis 51 sind schließlich für den Hintergrund und die einfache Textausgabe zuständig. In Zeile 43 sehen Sie, dass in CircuitPython 9.0.0 nicht mehr 'display.show(splash)' verwendet, sondern durch 'display.root_group = splash' ersetzt wird.


Für eine erste Uhrfunktion erweitern wir das Programm um die folgenden Zeilen:

  
  

53  updating_datum = label.Label(font=terminalio.FONT, text="", scale=1, color=0xffffff, line_spacing=1)
54  updating_datum.anchor_point = (0, 0)
55  updating_datum.anchored_position = (45, 3)
56  splash.append(updating_datum)
57
58  wotage = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"]
59
60  while True:
61      current_time = time.localtime()
62      hour = current_time.tm_hour
63      minute = current_time.tm_min
64      second = current_time.tm_sec
65      year = current_time.tm_year
66      month = current_time.tm_mon
67      day = current_time.tm_mday
68      tag = current_time.tm_wday
69      #datum = str(day) + "." + str(month) + "." + str(year)
70      datum = "{:02}.{:02}.{:04}".format(day,month,year)
71      zeit = "{:02}:{:02}:{:02}".format(hour,minute,second)
72      ## Datum und Zeit anzeigen
73      updating_text.text = zeit
74      updating_datum.text = wotage[tag] + "\n\n\n\n" + datum
  

Die Erläuterungen:
Die Zeilen 53 bis 56 legen ein weiteres Textlabel fest, mit dem der Wochentag und das Datum angezeigt werden. Dazu muss die Variable 'tag', welche aus 'current_time.tm_wday' als Zahl gewonnen wird einem String zugewiesen werden. Das geschieht mit Hilfe der Liste in Zeile 58. Die 'while-Scheife' ab Zeile 60 holt bei jedem Schleifendurchlauf die Variablen 'hour', 'minute', 'second' u.s.w. aus 'time.localtime()'. Diese wird ja beim Start des Microcontrollers am Rechner mit der aktuellen Zeit synchronisiert. Solange die Spannung nicht unterbrochen wird, arbeitet der Timer (ziemlich genau) weiter. Wird der Prossesor ohne Verbindung zum Rechner gestartet, beginnt der Timer mit 1.1.2020 um 00:00 Uhr zu zählen.

Aus diesem Grunde werden wir die PicoBoy-Uhr in den nächsten Beiträgen um eine Stell- und Weckfunktion erweitern, indem wir die vorhandenen LED's, den Lautsprecher (eigentlich ein 'Leisesprecher') und vor allem den Joystick nutzen. Bis dahin....


Viel Spass und Erfolg beim Ausprobieren.