Aktuelle Blinker für den Raspberry
Beim Raspberry ist alles im Fluss. Was letztes Jahr noch gültig war ist heute schon veraltet. Um wieder mal auf einen sauberen Stand zu kommen habe ich Blinkprogramme in diversen Sprachen realisiert.
Setup
Die Programme liefen auf einem Raspberry 4, mit einem frisch installierten Raspberry PI OS 32Bit.
An GPIO 18 waren ein 560 Ohm Widerstand in Serie mit einer LED gegen Masse angeschlossen.
Python
Mit der Standard-Installation kam ein Python 3.9. Das ist zwar nicht die aktuellste Version aber auch nicht extrem alt. Der Aufruf von python startet jetzt Python 3.
Es ist kein Wunder dass Python auf dem Raspberry so beliebt ist. Die Libraries sind bei der Standard-Installation schon dabei und die Scripts brauchen keine besonderen Rechte.
RPi.GPIO
Wird immer wieder als veraltet beschimpft, das Script lief aber auf Anhieb:
#!/usr/bin/env python3 from RPi import GPIO import time PIN = 18 GPIO.setmode( GPIO.BCM ) GPIO.setup( PIN, GPIO.OUT ) try: while True: GPIO.output( PIN, True ) time.sleep( 1 ) GPIO.output( PIN, False ) time.sleep( 1 ) except KeyboardInterrupt: pass finally: GPIO.setup( PIN, GPIO.IN ) GPIO.cleanup()
gpiozero
Soll die empfohlene Version sein. Auch diese Scripts liefen auf Anhieb:
#!/usr/bin/env python3 from gpiozero import LED import time led = LED( 18 ) try: while True: led.on() time.sleep( 1 ) led.off() time.sleep( 1 ) except KeyboardInterrupt: pass finally: led.close()
Es geht sogar noch einfacher:
#!/usr/bin/env python3 from gpiozero import LED import time led = LED( 18 ) try: led.blink( 1, 1, background=False ) except KeyboardInterrupt: pass finally: led.close()
bash
sysfs soll deprecated sein, aber auch dieses Script lief problemlos:
#!/bin/bash # Define the pin for the blinker PIN=18 # Handle ctrl-c function shutdown() { echo in > /sys/class/gpio/gpio$PIN/direction echo $PIN > /sys/class/gpio/unexport exit 0 } trap shutdown SIGINT # Export it echo $PIN > /sys/class/gpio/export sleep 0.2 # Set the pin as output echo out > /sys/class/gpio/gpio$PIN/direction # Loop forever while true do # Turn the LED on echo 1 > /sys/class/gpio/gpio$PIN/value sleep 1 # Turn the LED off echo 0 > /sys/class/gpio/gpio$PIN/value sleep 1 done
C/C++
Auf dem aktuellen OS fehlt wiringpi, und man findet nur noch veraltete Anleitungen zur Installation der Library. pigpio war installiert und deshalb wird es hier auch genutzt.
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> #include <pigpio.h> #define PIN 18 #define DELAY 1000 void cleanup( int ) { gpioSetMode( PIN, PI_INPUT ) ; gpioTerminate() ; exit( 1 ) ; } int main() { if( gpioInitialise() < 0 ) { printf( "Fehler beim Initialisieren von pigpio\n" ) ; return 1 ; } signal( SIGINT, cleanup ) ; gpioSetMode( PIN, PI_OUTPUT ) ; for( ;; ) { gpioWrite( PIN, PI_HIGH ) ; gpioSleep( PI_TIME_RELATIVE, 1, 0 ) ; gpioWrite( PIN, PI_LOW ) ; gpioSleep( PI_TIME_RELATIVE, 1, 0 ) ; } }
Go
Der Go-Compiler muss erst installiert werden, und für die GPIOs braucht es ein Package. Das Package wird automatisch geholt, da muss man sich gar nicht drum kümmern.
package main import ( "fmt" "time" "os" "os/signal" "github.com/stianeikeland/go-rpio" ) func main() { if err := rpio.Open(); err != nil { fmt.Println(err) os.Exit(1) } defer rpio.Close() pin := rpio.Pin(18) pin.Output() channel := make(chan os.Signal, 2) signal.Notify(channel,os.Interrupt) go func() { for _ = range channel { pin.Input() rpio.Close() os.Exit(1) } }() for { pin.High() time.Sleep(1*time.Second) pin.Low() time.Sleep(1*time.Second) } }
Java
Java stellte sich als mühsam heraus. Ein Java-Programm vom letzten Jahr musste fast vollständig neu geschrieben werden, obwohl es wie vorher pi4j verwendet. Eine Installationsanleitung für pi4j gibt es nicht mehr, das soll Gradle übernehmen.
Java und Gradle mussten erst installiert werden. Java scheint einigermassen aktuell zu sein, Gradle kam aber in der Version 4.4.1!
import com.pi4j.Pi4J; import com.pi4j.io.gpio.digital.DigitalOutput; import com.pi4j.io.gpio.digital.DigitalState; public class Blinker { private static final int PIN_LED = 18 ; public static void main( String[] args ) { // The 'Pi4J' static class includes a few helper context // creators for the most common use cases. The 'newAutoContext()' // method will automatically load all available Pi4J // extensions found in the application's classpath which // may include 'Platforms' and 'I/O Providers' var pi4j = Pi4J.newAutoContext() ; // Here we will create I/O interfaces for a (GPIO) digital output // pin. We define the 'provider' to use PiGpio to control // the GPIO. var ledConfig = DigitalOutput.newConfigBuilder( pi4j ) .id( "led" ) .name( "Blinker" ) .address( PIN_LED ) .shutdown( DigitalState.LOW ) .initial( DigitalState.LOW ) .provider( "pigpio-digital-output" ) ; var led = pi4j.create( ledConfig ) ; try { for( ;; ) { led.high() ; Thread.sleep( 1000 ) ; led.low() ; Thread.sleep( 1000 ) ; } } catch( Exception e ) { // Ignore all exceptions } // Shutdown Pi4J pi4j.shutdown() ; } }
JavaScript
node, npm und das Modul rpi-gpio mussten installiert werden weil sie auf dem Raspberry PI OS nicht vorhanden waren. Das Script läuft mit den normalen User-Privilegien.
const rpi = require( "rpi-gpio" ) const gpio = rpi.promise async function blinker() { const sleep = (sec) => new Promise( r => setTimeout(r,sec*1000) ) ; const PIN = 18 ; process.on( "SIGINT", async () => { await gpio.write( PIN, false ) ; await gpio.setup( PIN, gpio.DIR_IN ) ; process.exit( 1 ) ; } ) ; rpi.setMode( rpi.MODE_BCM ) ; await gpio.setup( PIN, gpio.DIR_OUT ) ; for( ;; ) { await gpio.write( PIN, true ) ; await sleep( 1 ) ; await gpio.write( PIN, false ) ; await sleep( 1 ) ; } } blinker() ;