Raspberry Pi Pico

Het Raspberry Pi project is begonnen met de Raspberry Pi 1, de '$35 Linux computer'. Oorspronkelijk opgezet om kinderen weer in aanraking te laten komen met'echte computers' in plaats van kant-en-klare kastjes is dit project wereldwijd in de belangstelling gekomen, en gegroeid tot een ideaal low-cost hobby-platform.

Pagina is nog onder constructie! Heb hem nog maar net binnen...

Raspberri Pi Pico binnen
Binnen (11 feb 2021)...
Raspberri Pi Pico!

Nu (februari 2021) ook de Raspberry Pi Pico!!! Geen Linux, maar een '$4' embedded processor vergelijkbaar met de Arduino Nano (maar dan veelkrachtiger). Heeft een door Raspberry Pi ontworpen RP2040 microcontroller chip met dual-core ARM M0+ op 133 MHz, plus dual-core PIO: simpele cores voor allerlei real-time I/O zoals NeoPixel (WS2812) LEDs. De $4 is zonder BTW, verzendkosten etc, maar heb er twee gekocht, kosten me €7.50 per stuk; goed te doen. Zie ook de vergelijkingspagina hoe dit vergelijkt met andere bordjes.

Eerste stappen

Vandaag binnengekregen en getest: in mijn Ubuntu systeem geprikt (microUSB), MicroPython er op gekopieerd, een terminal window geopend naar de USB poort (minicom -b 115200 -o -c on -D /dev/ttyACM0), en de Pico meldt zich met de Python prompt '>>>'. Met control-d kan je de MicroPython resetten, dan krijg je het MicroPython versienummer te zien, zie het scherm hieronder.

MicroPython in de terminal

Boot, en MicroPython direct op de Raspberry Pico draaiend...

Timer en Thread

Met wat regels Python (hieronder) op de Pico knippert de on-board LED via een onafhankelijke timer-taak; je kan dus ondertussen gewoon verder met Python.

from machine import Pin, Timer
led = Pin(25, Pin.OUT)   # object voor de ingebouwde LED
mytimer = Timer()        # en een timer-object
def tick(timer):
    global led
    led.toggle()

mytimer.init(freq=2.5, mode=Timer.PERIODIC, callback=tick)

En de LED knippert! Schrijf dit als een file 'main.py' naar het MicroPython file systeem op de Pico (b.v. met Thonny, zie verderop), en iedere keer dat je de Pico van stroom voorziet start dit script en knippert de LED. Wil je de main.py kwijt? Op de Pico: import os; os.remove("main.py") en een soft-reset (^d): ledje is uit :-). Meer LEDs bij 'projecten'...

Het voorbeeld boven draait als een timer-taak op de eerste core (core0). Je kan het ook als aparte thread op de tweede core draaien. Helaas, zijn maar twee cores, dus slechts twee threads tegelijk. Voor meer moet je toch iets van een RTOS/kernel hebben; microPython helpt je hier niet (de M0+ cores kunnen het op zich makkelijk aan). Maar, hier dus als aparte thread, met een extra externe LED op GPIO pin 0 (ondertussen loopt bovenstaande timer-taak op de ingebouwde LED ook nog steeds):

import _thread, time

def task(n, delay):       # deze functie gaat als taak draaien
    led2 = machine.Pin(25, machine.Pin.OUT)
    for i in range(n):
        led2.toggle()
        time.sleep(delay) # niet als timer, moeten zelf de delay in de gaten houden
    print('done')         # (als timer is dus eigenlijk hier veel handiger)

_thread.start_new_thread(task, (50, 0.5))  # starten als aparte taak op de tweede core

Simpel... En terwijl dit drasait kan je op de command line gewoon verder werken: dit loopt tenslotte op de tweede core, de eerste is weer vrij. Type maar in "1+1", wordt netjes uitgerekend. Probeer je de taak (terwijl de eerste nog loopt) nog een keer te starten, dan krijg je een foutmelding "OSError: core1 in use". En zo hoort het ook hier.

Het bordje

MicroPython in de terminal

Het printje, ongeveer 2 bij 5 cm

Het bordje (Pico documentatie) ziet er leeg uit... Een teken dat het Raspberry Pi team goed heeft nagedacht wat er allemaal in de chip moest; weinig extra onderdelen nodig. De belangrijkste punten op een rijtje (van de RPI Pico web site, waar je ook heel goede documentatie van zowel het bordje als de chip vind):

  • 40 pin 21x51 mm 'DIP' PCB met 0.1" through-hole gaten
    • printje geschikt voor pinnen (voor breadboard) of om direct op een andere PCB te solderen (castellated module, met helemaal vlakke onderzijde)
  • Speciaal door Raspberry Pi ontwikkelde microcontroller, de RP2040 (RP2040 datasheet)
    • Dual-core Arm Cortex M0+ processor, instelbare klok tot 133 MHz
    • Accelerated floating-point libraries en bootloader in on-chip 16 KB boot ROM
    • USB 1.1 met device en host support
    • 264KB SRAM
    • 8 × Programmable I/O (PIO) state machines voor custom peripheral support
  • 2MB on-board Flash memory
  • Drag-and-drop programming via mass storage over USB via de bootloader in ROM
  • Programmeerbaar in MicroPython (direct op de Pico) of in C/C++ (in een ontwikkelomgeving b.v. Eclipse, maar de Arduino-omgeving komt ook vast wel)
  • 26 × multi-function GPIO pins
    • 2 × SPI, 2 × I2C, 2 × UART, 3 × 12-bit ADC
    • 16 × controllable 16-bit PWM channels (8 groepen van 2)

Is wel een boot-knop, maar geen reset: soms niet handig als je vaak nieuwe programma's test. Is makkelijk zelf toe te voegen, of kies een kant-en-klare oplossing: de 'Resetti'.

De voeding

Wel mooi dat er een geschakelde voeding op zit; hierdoor kan het zowel met batterijen als met USB gevoed worden: voeding van 1.8 Volt tot 5.5 Volt: dus twee normale of NiMH batterijen, een Li-Ion batterij, .... Nadeel is dat de ruststroom misschien wat groter is.

De pinout

Hieronder de pinout van het bordje. Alle GPIO pinnen zijn 3,3 Volt (1,8 Volt compatible, maar niet geschikt voor 5 Volt)! Een high-res versie van de pin-out is te vinden op de RPi Pico web site.

Raspberri Pi Pico binnen

<meer uitleg>

De Processor

Of eigenlijk, de RP2040 microcontroller (met daarin 2x een ARM M0+ processor core). Best gewaagd, je eigen chip ontwerpen in plaats van een bestaande van een grote fabrikant te nemen! Zitten dan ook een aantal mooie features in voor hobbyisten. Goed over nagedacht! Moet natuurlijk altijd afwegingen maken (prijs moet goed blijven, en dat is gekoppeld aan het oppervlak van de chip). Vooral de PIO lijkt me een mooie uitbreiding.

<meer uitleg>

De PIO

PIO (Programmable I/O): twee extra 'cores' om real-time low-level I/O (bit-banging) overbodig te maken, en de echte ARM cores hiervan te ontlasten. Eigenlijk twee groepen van ieder 4 state machines, programmeerbaar in een soort microcode. Kan DMA en interrupts gebruiken, en GPIO lijnen aansturen; en heeft ieder 2x4 FIFO's voor interne communicatie-buffering. Krachtig en neemt je het real-time aansturen van pinnen voor bijvoorbeeld seriële LEDs uit handen (bijvoorbeeld voor WS2812B LED aansturing, die nogal nauw komt qua timing op 800 kHz). Ook voor andere protocollen als I2S, VGAS video output, 6800/8080 bus emulatie, ...

<meer uitleg>

Ontwikkelomgeving

MicroPython

MicroPython is een gestripte versie van Python 3, passend gemaakt voor microcontrollers. Als volledig Python: een interpreter/compiler waarbij je direct en interactief op de Pico kan programmeren; je hoeft niet eerst als bij C/C++ op je PC te compileren maar kan direct op het bord commando's uitvoeren.

De beschikbare MicroPython (documentatie) draait dus direct op de Pico. Eenmalig de goede UF2 installatiefile naar je Pico slepen; terminal er aan, en je kan programmeren (zie voorbeeld bovenaan de pagina). Alternatief is er ook een (wat beperkte) ontwikkelomgeving 'Thonny' voor op je normale computer beschikbaar, als je dat makkelijker vind typen. Hiervanuit kan je je programma direct naar de Pico downloaden. Debugging lijkt nog niet te werken, of is daar een uitbreiding voor nodig? En er zullen nog wel meer omgevingen volgen. Installatie op Ubuntu: sudo apt-get install thonny

CircuitPython van Adafruits is een uitbreiding op MicroPython, met meer support voor allerlei I/O devices (150+ device libraries). Nog niet geprobeerd.

<meer uitleg>

C/C++

C/C++ programmeren geeft meer mogelijkheden maar is ook complexer (documentatie). De standaard-omgeving ... GCC/CGB... Eclipse... (documentatie). Debug mogelijkheden...

Er schijnt ook nog een Arduino-variant te volgen. Maar, werkt mogelijk alleen met de Arduino-print (in ontwikkeling, met WiFi and Bluetooth?) met de RP2040.

<meer uitleg>

Projecten

LEDs aansturen

Al even wat gespeeld met de PIO (voorbeeldcode): zoals aansturen van WS2812B LEDS aan de hand van dit voorbeeld in MicroPython. Werkt gelijk. Wel jammer dat in MicroPython de transfers niet via DMA gaan; de moeilijke timing wordt met de PIO opgelost, maar nog steeds moet de processor wachten tot er weer plek in de FIFO is voor de volgende 3 bytes (op te lossen met DMA in C++, maar wil liever in Python). Nu mijn eigen draai aan de LEDs geven...

Maar, eigenlijk is de Pico bedoeld voor mijn PWM-geregelde LED's: op dit moment aangestuurd met een ATtiny2313, maar deze heeft maar 2 PWM kanalen van 16-bit, de rest is 8 bit. Ik heb er meer nodig; het menselijk oog is (vooral 's nachts) erg gevoelig en niet lineair, en stappen van 1/256 zijn bij lage helderheid te grof. De Pico (in microPython) kan 16-bit op alle PWM-kanalen. Als eerste zet: het voorbeeld van de knipperende LED uit 'eerste stappen' is makkelijk aan te passen om van PWM gebruik te maken. Door de stappen kwadratisch te maken lijkt de fade-in/fade-out voor het oog juist mooi gelijkmatig. Teller i van 0 tot 255; pwm-waarde dan pwm.duty_u16(i * i)... Download voorbeeld-file hier (gebaseerd op de niet op de timer gebaseerde Raspberry voorbeeldcode). Draait dus ook weer helemaal als 'achtergrond-taak' (timer callback); je kan live op de prompt gewoon doorgaan, als spelen met de pwm-frequentie: probeer maar eens pwm.freq(10).

<meer uitleg>