Indietro

Raspberry Pi 4 e 5 nel browser — modalità base e modalità Linux, passo dopo passo

Un Raspberry Pi in Velxio è una scheda sulla canvas che esegue uno script Python sul circuito che costruisci attorno ad essa. Non c’è nulla da compilare. Scrivi lo script, premi Run, e uno dei due motori lo esegue:

Questo articolo costruisce due progetti, uno per modalità, e mostra ogni clic lungo il percorso. Il primo è una stazione d’allarme fatta di moduli Grove su un Raspberry Pi 5: un sensore di movimento, un interruttore a vibrazione e un DHT11 sul lato input, un buzzer, due LED e un relè con una ventola sul lato output. Il secondo è un setup di sensori su un Raspberry Pi 4 con tre dispositivi I2C. Entrambi gli script usano le librerie incluse in Raspberry Pi OS, quindi funzionano invariati su una scheda reale.

Prima di iniziare, due cose sull’accesso. Chiunque può posizionare un Raspberry Pi sulla canvas e cablare un circuito attorno ad esso. Eseguirlo richiede un account con accesso effettuato: ogni account gratuito riceve tre sessioni di prova di 15 minuti sulla famiglia Raspberry Pi, in entrambe le modalità, e qualsiasi piano a pagamento rimuove il limite. I dettagli sono nella sezione Quanto costa verso la fine.

Due modi per eseguire lo stesso script

Modalità baseModalità Linux
Dove viene eseguito lo scriptUn interprete Python nella scheda del tuo browserUn guest Alpine Linux sotto QEMU sui server di Velxio
Tempo di avvioPochi secondiCirca un minuto
GPIORPi.GPIO, gpiozero, Adafruit BlinkaGli stessi, più /dev/gpiochip0 e gli strumenti libgpiod
I2C, SPI, UART, 1-WireI veri smbus2, spidev, pyserial e w1thermsensor su file di dispositivo emulatiLe stesse librerie sui veri nodi di dispositivo del kernel
Una shell e un file systemNoSì, nel Serial Monitor
Pacchetti di terze partiDa un requirements.txtDa un requirements.txt, risolti offline prima che il guest si avvii
Ideale perQuasi tuttoStrumenti shell, sottoprocessi, file e qualsiasi cosa un tutorial faccia da un terminale

Il motore viene scelto per te. Uno script che richiede qualcosa che solo Linux può fare, come subprocess, viene inviato alla modalità Linux e un chip nella barra degli strumenti ti dice perché. Puoi anche forzare tu stesso la modalità Linux, ed è ciò che fa il secondo progetto.

Progetto 1: una stazione d’allarme Grove su un Raspberry Pi 5

I moduli Grove sono il modo più rapido per collegare sensori a un Pi: ogni modulo ha lo stesso connettore a quattro pin, e in Velxio ciascuno si collega all’header con tre fili, SIG, VCC e GND. Questa stazione sorveglia una stanza con un sensore di movimento PIR e un interruttore a vibrazione, legge l’aria con un DHT11, e risponde tramite un buzzer, un LED verde per “tutto tranquillo”, un LED blu per “allarme”, e un relè che aziona una ventola quando la stanza si scalda.

Passo 1: avvia un progetto sul Raspberry Pi 5

Apri velxio.dev/editor. La finestra Avvia un nuovo progetto si apre da sola. Scorri fino alla sezione Raspberry Pi e clicca sulla scheda Raspberry Pi 5. La scheda Raspberry Pi 4B funziona allo stesso modo: le due schede condividono l’header a 40 pin e le stesse librerie, quindi tutto quanto segue vale per entrambe.

La finestra Avvia un nuovo progetto con la sezione Raspberry Pi; la scheda Raspberry Pi 5 è evidenziata

Passo 2: aggiungi i componenti

Clicca il pulsante blu Aggiungi all’estremità destra della barra degli strumenti. Si apre il catalogo dei componenti.

La barra degli strumenti con il pulsante Aggiungi evidenziato

Digita un nome nel campo di ricerca e clicca sulla scheda per posizionare il componente sulla tela. I moduli Grove sono tutti elencati con i loro nomi Seeed, quindi “Grove PIR” o “Grove relay” li trova. Aggiungi questi otto componenti, uno alla volta:

  1. Grove - PIR Motion Sensor
  2. Grove - Vibration Sensor (SW-420)
  3. Grove - Temperature & Humidity Sensor (DHT11)
  4. Grove - Piezo Buzzer
  5. Grove - Green LED
  6. Grove - Blue LED
  7. Grove - Relay
  8. DC Motor / Fan

La finestra Aggiungi componente con Grove PIR digitato nel campo di ricerca e la scheda del sensore di movimento PIR evidenziata

I componenti possono essere trascinati ovunque sulla tela. Lasciare il Pi in basso e i moduli sopra il suo header mantiene i fili corti.

Passo 3: collega tutto

Per tracciare un filo, clicca su un pin, poi clicca sul pin all’altro capo. I nomi dei pin appaiono quando passi il mouse su un componente. Ogni modulo Grove richiede gli stessi tre fili: SIG a un GPIO, VCC a 3V3, GND a GND. Il relè è l’eccezione sul lato alimentazione, la sua bobina vuole 5 V.

ModuloSIGVCCGND
Sensore di movimento PIRGPIO173V3GND
Sensore di vibrazione (SW-420)GPIO273V3GND
DHT11GPIO43V3GND
BuzzerGPIO243V3GND
LED verdeGPIO53V3GND
LED bluGPIO63V3GND
RelèGPIO235VGND

La ventola non ha un filo di segnale proprio. Si trova sui contatti commutati del relè, come un carico su un banco di lavoro: l’alimentazione entra nel COM ed esce dal NO solo mentre la bobina è eccitata.

DaA
Raspberry Pi 5VRelè COM
Relè NOVentola +
Ventola -Raspberry Pi GND

La stazione cablata: il Raspberry Pi 5 in basso, il PIR, il sensore di vibrazione, il DHT11 e il buzzer in fila sopra il suo header, i due LED e il relè con la sua ventola sotto di essi, con richiami su ciascun modulo

Passo 4: lo script

L’esploratore di file a sinistra contiene già un file chiamato script.py con un breve script di lampeggio. Mantieni quel nome. La modalità base esegue il primo file .py che trova, ma la modalità Linux esegue specificamente script.py, quindi un progetto il cui file principale mantiene quel nome funziona in entrambe.

L'editor di codice con script.py selezionato nell'esploratore di file

Sostituisci il suo contenuto con questo script:

"""Grove alarm station on a Raspberry Pi 5.

A PIR sensor and a vibration switch watch the room, a DHT11 reads the air,
and the actuators answer: a buzzer and a blue LED for the alarm, a green LED
while all is quiet, and a relay that runs a fan when the room gets warm.
Every module hangs off the header with a Grove cable, one signal pin each.

Wiring, BCM numbers (VCC and GND of each module to 3V3 and GND):
    PIR motion sensor   SIG GPIO17   HIGH while motion is seen
    vibration SW-420    SIG GPIO27   LOW while shaking, HIGH at rest
    DHT11               SIG GPIO4
    buzzer              SIG GPIO24
    green LED GPIO5, blue LED GPIO6
    relay               SIG GPIO23, VCC on 5V; the contacts switch the fan:
                        5V to COM, NO to the fan's +, the fan's - to GND
"""
import time

import adafruit_dht
import board
from gpiozero import LED, Button, Buzzer, MotionSensor

FAN_ON_AT = 28   # degrees C
HOLD = 2.5       # seconds the alarm light stays on after the beeps

pir = MotionSensor(17)
shaker = Button(27, pull_up=True)   # the SW-420 pulls SIG low while it vibrates
dht = adafruit_dht.DHT11(board.D4, use_pulseio=False)
buzzer = Buzzer(24)
quiet_led = LED(5)
alarm_led = LED(6)
fan = LED(23)                        # the relay coil: on() closes COM to NO


def alarm(reason, beeps, beep_time):
    print(f"ALARM: {reason}")
    quiet_led.off()
    alarm_led.on()
    buzzer.beep(on_time=beep_time, off_time=0.1, n=beeps, background=False)
    time.sleep(HOLD)
    alarm_led.off()
    quiet_led.on()


quiet_led.on()
motion_seen = False
shaking = False
next_reading = 0
print("Station armed")

while True:
    if pir.motion_detected and not motion_seen:
        alarm("motion in the room", beeps=3, beep_time=0.15)
    motion_seen = pir.motion_detected

    if shaker.is_pressed and not shaking:
        alarm("vibration on the door", beeps=1, beep_time=0.6)
    shaking = shaker.is_pressed

    if time.monotonic() >= next_reading:
        next_reading = time.monotonic() + 2
        try:
            temperature, humidity = dht.temperature, dht.humidity
        except RuntimeError as err:   # a DHT11 misses a reading now and then
            print(f"DHT11: {err}")
        else:
            fan.value = temperature >= FAN_ON_AT
            print(f"{temperature:.0f} C  {humidity:.0f} %RH  fan {'on' if fan.value else 'off'}")

    time.sleep(0.1)

Tre cose al suo interno meritano uno sguardo, perché sono le stesse su hardware reale:

Passo 5: eseguilo

Sulla barra degli strumenti, clicca il triangolo verde per eseguire il progetto. Il Monitor Seriale si apre in basso e riporta cosa sta facendo il motore: carica il runtime Python, installa la libreria GPIO, e stampa una riga come [Velxio] ready in 6068 ms seguita dal nome dello script che sta eseguendo. Da quel momento in poi, ogni print() nello script finisce lì.

La barra degli strumenti con il pulsante Esegui evidenziato

Lo script stampa Station armed, poi una riga di temperatura e umidità ogni due secondi. Il DHT11 sulla tela parte da 31 C, quindi il relè si chiude subito e la ventola si avvia: il motore mostra una freccia di direzione e la sua velocità in rpm, e l’indicatore del relè si accende. Ora interagisci con i sensori:

La stazione in esecuzione in modalità base: la ventola gira dietro il relè, il LED blu è acceso dopo un clic sulla cupola del PIR, e il Monitor Seriale mostra le letture e la riga ALARM

Il quadrato rosso accanto al pulsante Esegui ferma lo script. Questa è la modalità base in tutto e per tutto: lo script gira nella tua scheda, i pin raggiungono la tela direttamente, e l’intero ciclo da Esegui a un circuito che reagisce richiede secondi.

Progetto 2: un banco di sensori I2C su un Raspberry Pi 4, poi la modalità Linux

Il secondo progetto mette tre dispositivi I2C sul bus dell’header e usa il vero smbus2 per comunicare con loro: un convertitore analogico-digitale Grove ADS1115 con due potenziometri, un sensore di temperatura e umidità Grove SHT31 e un OLED SSD1306. Un pulsante e un LED su GPIO semplice completano il quadro. Lo stesso circuito funziona su un Raspberry Pi 5 senza cambiare un filo o una riga: l’header è lo stesso.

L’ADS1115 è lì per un motivo che coglie molti di sorpresa: un Raspberry Pi non ha ingressi analogici. Un potenziometro collegato direttamente a un GPIO legge sempre e solo alto o basso, sulla scheda reale e in Velxio, quindi le manopole passano attraverso l’ADC.

Il circuito

Avvia un nuovo progetto sulla scheda Raspberry Pi 4B e aggiungi questi componenti dal catalogo:

Poi collegali. Tutti e tre i dispositivi I2C condividono GPIO2 (SDA) e GPIO3 (SCL):

Da (Raspberry Pi 4)A
GPIO2 (SDA)SDA dell’ADS1115, dell’SHT31 e dell’OLED
GPIO3 (SCL)SCL dell’ADS1115, dell’SHT31 e dell’OLED
3V3VCC dell’ADS1115, dell’SHT31, dell’OLED e di entrambi i potenziometri
GNDGND dell’ADS1115, dell’SHT31, dell’OLED e di entrambi i potenziometri
GPIO27Anodo del LED; catodo del LED verso 220 Ω, poi GND
GPIO22Pulsante; l’altro lato del pulsante verso GND
DaA
Potenziometro 1 SIGADS1115 A0
Potenziometro 2 SIGADS1115 A1

Il banco di sensori cablato: il Raspberry Pi 4 in basso, l'ADS1115 con due potenziometri, l'OLED e l'SHT31 sopra di esso, e il LED e il pulsante a destra, con richiami sui pin I2C e su ciascun dispositivo

Lo script

Salvalo come script.py. Prima chiede a ciascuno dei tre indirizzi se qualcuno risponde, poi entra in un ciclo: due canali ADC, temperatura e umidità, lo stato del pulsante sul LED e le letture sull’OLED tramite luma.oled.

"""Sensor rig check for a Raspberry Pi 4.

Probes the three I2C devices, then loops: two knobs through the ADS1115,
temperature and humidity from the SHT31, the readings on the OLED, and a
button that lights the LED. Everything here is what Raspberry Pi OS ships:
smbus2 for the bus, gpiozero for the LED and the button, luma.oled for
the display.

Wiring, on the 40-pin header:
    I2C   : ADS1115, SHT31 and OLED on GPIO2 (SDA) and GPIO3 (SCL), 3V3, GND
    ADC   : one potentiometer on ADS1115 A0, another on A1
    GPIO  : LED through 220 ohm on GPIO27, button between GPIO22 and GND
"""
import time

import smbus2
from gpiozero import LED, Button
from luma.core.interface.serial import i2c
from luma.core.render import canvas
from luma.oled.device import ssd1306

ADS1115, SHT31, OLED = 0x48, 0x44, 0x3C
NAMES = {ADS1115: "ADS1115", SHT31: "SHT31", OLED: "SSD1306 OLED"}

# ADS1115 config register, field by field (datasheet, table 8)
ADS_START = 0x8000       # OS: begin one conversion
ADS_MUX_SINGLE = 0x4000  # AINx against GND; the channel goes in bits 12 and 13
ADS_PGA_4V = 0x0200      # +/-4.096 V full scale
ADS_ONE_SHOT = 0x0100    # power down between conversions
ADS_128_SPS = 0x0080     # 128 samples per second
ADS_NO_COMP = 0x0003     # comparator off
ADS_LSB_VOLTS = 4.096 / 32768

bus = smbus2.SMBus(1)
led = LED(27)
button = Button(22, pull_up=True)


def present(address):
    """True when a device acknowledges its address on bus 1."""
    try:
        bus.write_quick(address)
        return True
    except OSError:
        return False


def read_ads1115(channel):
    """One single-shot conversion on AIN0..AIN3, returned in volts."""
    config = (ADS_START | ADS_MUX_SINGLE | (channel << 12)
              | ADS_PGA_4V | ADS_ONE_SHOT | ADS_128_SPS | ADS_NO_COMP)
    bus.write_i2c_block_data(ADS1115, 0x01, [config >> 8, config & 0xFF])
    time.sleep(0.01)
    hi, lo = bus.read_i2c_block_data(ADS1115, 0x00, 2)
    raw = (hi << 8) | lo
    if raw & 0x8000:
        raw -= 0x10000
    return raw * ADS_LSB_VOLTS


def read_sht31():
    """Single shot, high repeatability, no clock stretching (command 0x2400)."""
    bus.i2c_rdwr(smbus2.i2c_msg.write(SHT31, [0x24, 0x00]))
    time.sleep(0.02)
    reply = smbus2.i2c_msg.read(SHT31, 6)
    bus.i2c_rdwr(reply)
    d = list(reply)
    temperature = -45 + 175 * ((d[0] << 8) | d[1]) / 65535
    humidity = 100 * ((d[3] << 8) | d[4]) / 65535
    return temperature, humidity


print("I2C bus 1:")
for address, name in NAMES.items():
    print(f"  0x{address:02X}  {name}: {'found' if present(address) else 'missing'}")
print()

oled = ssd1306(i2c(port=1, address=OLED))

while True:
    knob_a = read_ads1115(0)
    knob_b = read_ads1115(1)
    temperature, humidity = read_sht31()
    pressed = button.is_pressed
    led.value = pressed
    print(f"A0 {knob_a:5.3f} V   A1 {knob_b:5.3f} V   {temperature:4.1f} C  {humidity:3.0f} %RH"
          + ("   button pressed" if pressed else ""))
    with canvas(oled) as draw:
        draw.text((0, 0), "Pi 4 sensor rig", fill="white")
        draw.text((0, 16), f"A0 {knob_a:.2f}V  A1 {knob_b:.2f}V", fill="white")
        draw.text((0, 32), f"{temperature:.1f} C   {humidity:.0f} %RH", fill="white")
        draw.text((0, 48), "button " + ("down" if pressed else "up"), fill="white")
    time.sleep(2)

Tre dettagli meritano uno sguardo. L’ADS1115 è configurato campo per campo, nel modo in cui il suo datasheet organizza il registro di configurazione, così ogni costante può essere verificata con la tabella 8 di quel documento. L’SHT31 viene letto con i2c_rdwr perché il suo comando di misurazione è di due byte senza indirizzo di registro, cosa che le normali chiamate SMBus non possono esprimere. E luma.oled è la stessa libreria di visualizzazione che i tutorial per Raspberry Pi installano con pip; qui è preinstallata, come smbus2 e gpiozero.

Esegui prima in modalità base

Premi Run. La sonda trova i tre chip, il ciclo stampa le letture e l’OLED le mostra. Gira un potenziometro e la tensione di A0 o A1 lo segue; clicca sull’SHT31 e puoi impostare la temperatura e l’umidità che riporta; tieni premuto il pulsante e il LED si accende.

Il banco di sensori in esecuzione in modalità base: l'OLED mostra le due tensioni, la temperatura e l'umidità e lo stato del pulsante, e il Serial Monitor mostra i tre dispositivi trovati e le letture

Tutto finora è stato eseguito nel browser. I prossimi passi eseguono lo stesso identico progetto su una macchina Linux.

Passa alla modalità Linux

  1. Se il Serial Monitor non è aperto, clicca su Serial nella barra degli strumenti.
  2. Nella barra del titolo del Serial Monitor, a destra, clicca su Linux terminal.

La barra del titolo del Serial Monitor con il pulsante Linux terminal evidenziato

  1. Una finestra di dialogo chiamata Advanced Linux mode spiega cosa sta per succedere: il progetto si riavvia, l’avvio richiede circa un minuto e tutto funziona più lentamente rispetto al browser. Clicca su Start Linux mode.

La finestra di dialogo Advanced Linux mode con il pulsante Start Linux mode evidenziato

Il guest si avvia nel Serial Monitor, che è diventato un vero terminale. Durante l’avvio, il chip accanto al selettore della scheda nella barra degli strumenti mostra Linux, e il suo tooltip dice che la modalità Linux è attiva per questo progetto.

La barra degli strumenti con il chip del motore che mostra Linux evidenziato

Quando appare il prompt, Velxio copia script.py nella directory home del guest e lo avvia. Su un server tranquillo il prompt compare dopo circa 20 secondi e le prime letture circa un minuto dopo aver cliccato il pulsante. L’output è lo stesso di prima, e l’OLED è pilotato dalla stessa chiamata luma.oled, ora dall’interno del guest attraverso /dev/i2c-1 del kernel.

Il banco di sensori in modalità Linux: il terminale mostra i tre dispositivi trovati e le letture, e l'OLED mostra gli stessi valori

Usa la shell

Ecco a cosa serve la modalità Linux. Clicca dentro il terminale, premi Ctrl+C per fermare lo script, e ti trovi a un prompt di root su un sistema Alpine Linux. Qualche riga da provare:

cat /etc/os-release | head -2
ls /dev/i2c* /dev/spidev* /dev/gpiochip*
gpioset gpiochip0 27=1
ls -la /home/pi

La seconda riga elenca i bus dell’header come nodi di dispositivo: /dev/i2c-0, /dev/i2c-1, /dev/spidev0.0, /dev/spidev0.1 e /dev/gpiochip0. Rispondono alle stesse chiamate di sistema che si usano su un Raspberry Pi, quindi una libreria che li apre da sola, un programma in C o il tuo codice ioctl comunicano con i componenti sulla tela.

La terza riga è il modo moderno di pilotare un pin dalla shell, con gli strumenti libgpiod che Raspberry Pi OS Bookworm include. Nel momento in cui premi Invio, il LED su GPIO27 si accende sulla tela. Il guest ha libgpiod versione 1, quindi il chip è un argomento posizionale, come scritto sopra, e la sintassi della versione 2 con --chip non viene riconosciuta.

La shell Linux dopo che lo script è stato interrotto: il comando gpioset è evidenziato e il LED sulla tela è acceso

Per eseguire di nuovo lo script a mano, digita python3 script.py. Per tornare al motore del browser, clicca su Exit Linux terminal nella stessa barra del titolo. La scelta non viene salvata con il progetto: riaprilo domani e Run tornerà alla modalità base.

La barra del titolo del Serial Monitor in modalità Linux con il pulsante Exit Linux terminal evidenziato

Cosa funziona in ciascuna modalità

La tabella qui sotto è la versione breve della pagina Raspberry Pi nella documentazione, misurata pezzo per pezzo sul prodotto live.

ModuloModalità baseModalità Linux
RPi.GPIO, gpiozeroPreinstallatiPreinstallati
smbus2, spidevPreinstallati, le librerie realiPreinstallati, le librerie reali sui nodi del kernel
serial (pyserial)Solo i percorsi UART del PiIl pyserial reale su una tty reale, /dev/serial0
adafruit_dht, Adafruit_DHTPreinstallatiPreinstallati
w1thermsensor, l’albero sysfs 1-WirePreinstallatoTramite requirements.txt; l’albero sysfs è presente
luma.oled, RPLCD, ST7789, Adafruit BlinkaPreinstallatiPreinstallati
gpiod e gli strumenti gpio*Nessun character device nel browserPreinstallati
cv2 (OpenCV)SìNessuna build per il guest
picamera2Sì, tramite la tua webcamNo; usa rpicam-jpeg e i suoi simili
requests, urllibTramite un proxy in uscita con una allowlistNessuna rete all’interno del guest
Qualsiasi altra cosa su PyPITramite requirements.txtTramite requirements.txt, quando PyPI ha una wheel musl aarch64

Cosa non fa nessuna delle due modalità, così non sprechi una sessione di prova per scoprirlo:

Due abitudini fanno risparmiare tempo. Chiama il file principale script.py, così entrambe le modalità eseguono lo stesso file. E metti i pacchetti di terze parti in un requirements.txt accanto ad esso — quando uno script importa un pacchetto mancante, la console di esecuzione offre la riga e un pulsante la scrive per te.

Quanto costa

Chiunque può cablare un circuito con Raspberry Pi senza un account. Eseguirlo è soggetto a restrizioni:

La barra degli strumenti come la vede un visitatore non autenticato, con il chip Free trial, sign in evidenziato

Le sessioni di prova sono identiche su entrambi i motori, quindi uno script che necessita solo della modalità base dovrebbe restare lì — si avvia in secondi invece che in un minuto, e il guest Linux è per ciò che solo Linux può fare.

Dove andare adesso

Due progetti, due motori. La stazione d’allarme Grove ha girato in modalità base su un Raspberry Pi 5, da una tela vuota a un circuito che reagisce in pochi minuti, con il codice gpiozero e Adafruit DHT che userebbe un tutorial su Raspberry Pi. Il setup dei sensori ha girato prima in modalità base su un Raspberry Pi 4, poi in modalità Linux, dove lo stesso script ha comunicato con l’ADS1115, l’SHT31 e l’OLED tramite /dev/i2c-1 del kernel, e un comando gpioset digitato al prompt ha acceso un LED sulla tela. La modalità base copre la maggior parte di ciò che chiede un tutorial su Raspberry Pi; la modalità Linux è lì per il terminale, i file e gli strumenti di sistema, al prezzo di un minuto di boot.


Condividi su:
David Montero

Scritto da

David Montero

Creator of Velxio, the open-source circuit and Arduino simulator.

GitHub velxio.dev

Articoli correlati


Articolo successivo
Castlevania: Symphony of the Night in esecuzione nativa sull'ESP32-S3