Volver

Raspberry Pi 4 y 5 en el navegador: modo básico y modo Linux, paso a paso

Una Raspberry Pi en Velxio es una placa sobre el lienzo que ejecuta un script de Python contra el circuito que cableas a su alrededor. No hay nada que compilar. Escribes el script, pulsas Run y uno de los dos motores lo ejecuta:

Este artículo construye dos proyectos, uno por modo, y muestra cada clic por el camino. El primero es una estación de alarma hecha con módulos Grove sobre una Raspberry Pi 5: un sensor de movimiento, un interruptor de vibración y un DHT11 en el lado de entrada, un zumbador, dos LEDs y un relé con un ventilador en el lado de salida. El segundo es un montaje de sensores sobre una Raspberry Pi 4 con tres dispositivos I2C. Ambos scripts usan las librerías que vienen con Raspberry Pi OS, así que funcionan sin cambios en una placa real.

Antes de empezar, dos cosas sobre el acceso. Cualquiera puede colocar una Raspberry Pi en el lienzo y cablear un circuito a su alrededor. Ejecutarla requiere una cuenta con sesión iniciada: cada cuenta gratuita recibe tres sesiones de prueba de 15 minutos en la familia Raspberry Pi, en cualquiera de los dos modos, y cualquier plan de pago elimina el límite. Los detalles están en la sección Qué cuesta cerca del final.

Dos formas de ejecutar el mismo script

Modo básicoModo Linux
Dónde se ejecuta el scriptUn intérprete de Python en la pestaña de tu navegadorUn invitado Alpine Linux bajo QEMU en los servidores de Velxio
Tiempo de arranqueUnos segundosAlrededor de un minuto
GPIORPi.GPIO, gpiozero, Adafruit BlinkaLo mismo, más /dev/gpiochip0 y las herramientas de libgpiod
I2C, SPI, UART, 1-WireLos smbus2, spidev, pyserial y w1thermsensor reales sobre archivos de dispositivo emuladosLas mismas librerías sobre los nodos de dispositivo reales del kernel
Un shell y un sistema de archivosNoSí, en el Serial Monitor
Paquetes de tercerosDesde un requirements.txtDesde un requirements.txt, resueltos sin conexión antes de que arranque el invitado
Ideal paraCasi todoHerramientas de shell, subprocesos, archivos y cualquier cosa que un tutorial haga desde una terminal

El motor se elige por ti. Un script que pide algo que solo Linux puede hacer, como subprocess, se envía al modo Linux y un chip en la barra de herramientas te dice por qué. También puedes forzar el modo Linux tú mismo, que es lo que hace el segundo proyecto.

Proyecto 1: una central de alarma Grove sobre una Raspberry Pi 5

Los módulos Grove son la forma más rápida de conectar sensores a una Pi: todos los módulos tienen el mismo conector de cuatro pines y, en Velxio, cada uno se conecta a la regleta con tres cables, SIG, VCC y GND. Esta central vigila una sala con un sensor de movimiento PIR y un interruptor de vibración, lee el aire con un DHT11 y responde a través de un zumbador, un LED verde para “todo en calma”, un LED azul para “alarma” y un relé que pone en marcha un ventilador cuando la sala se calienta.

Paso 1: iniciar un proyecto sobre la Raspberry Pi 5

Abre velxio.dev/editor. El diálogo Start a new project se abre solo. Desplázate hasta la sección Raspberry Pi y haz clic en la tarjeta Raspberry Pi 5. La tarjeta Raspberry Pi 4B funciona igual: las dos placas comparten la regleta de 40 pines y las mismas librerías, así que todo lo que sigue se aplica a ambas.

El diálogo Start a new project con la sección Raspberry Pi; la tarjeta Raspberry Pi 5 está resaltada

Paso 2: añadir los componentes

Haz clic en el botón azul Add en el extremo derecho de la barra de herramientas. Se abre el catálogo de componentes.

La barra de herramientas con el botón Add resaltado

Escribe un nombre en el campo de búsqueda y haz clic en la tarjeta para colocar el componente en el lienzo. Los módulos Grove aparecen todos con sus nombres de Seeed, así que “Grove PIR” o “Grove relay” los encuentra. Añade estos ocho componentes, uno a uno:

  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

El diálogo Add Component con Grove PIR escrito en el campo de búsqueda y la tarjeta del sensor de movimiento PIR resaltada

Los componentes se pueden arrastrar a cualquier parte del lienzo. Dejar la Pi abajo y los módulos encima de su regleta mantiene los cables cortos.

Paso 3: cablearlo

Para dibujar un cable, haz clic en un pin y luego en el pin del otro extremo. Los nombres de los pines aparecen al pasar el ratón por encima de un componente. Todos los módulos Grove llevan los mismos tres cables: SIG a un GPIO, VCC a 3V3, GND a GND. El relé es la excepción en cuanto a la alimentación, su bobina necesita 5 V.

MóduloSIGVCCGND
Sensor de movimiento PIRGPIO173V3GND
Sensor de vibración (SW-420)GPIO273V3GND
DHT11GPIO43V3GND
ZumbadorGPIO243V3GND
LED verdeGPIO53V3GND
LED azulGPIO63V3GND
ReléGPIO235VGND

El ventilador no tiene cable de señal propio. Va sobre los contactos conmutados del relé, como una carga en un banco de pruebas: la alimentación entra por COM y sale por NO solo mientras la bobina está excitada.

DesdeHasta
Raspberry Pi 5VRelé COM
Relé NOVentilador +
Ventilador -Raspberry Pi GND

La central cableada: la Raspberry Pi 5 abajo, el PIR, el sensor de vibración, el DHT11 y el zumbador en fila encima de su regleta, los dos LED y el relé con su ventilador debajo de ellos, con etiquetas en cada módulo

Paso 4: el script

El explorador de archivos de la izquierda ya contiene un archivo llamado script.py con un breve script de parpadeo. Conserva ese nombre. El modo básico ejecuta el primer archivo .py que encuentra, pero el modo Linux ejecuta script.py en concreto, así que un proyecto cuyo archivo principal conserve ese nombre funciona en ambos.

El editor de código con script.py seleccionado en el explorador de archivos

Sustituye su contenido por este 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)

Hay tres cosas en él que merece la pena mirar, porque son iguales que en el hardware real:

Paso 5: ejecutarlo

En la barra de herramientas, haz clic en el triángulo verde para ejecutar el proyecto. El Monitor Serie se abre en la parte inferior e informa de lo que está haciendo el motor: carga el entorno de ejecución de Python, instala la librería GPIO e imprime una línea como [Velxio] ready in 6068 ms seguida del nombre del script que está ejecutando. A partir de ahí, cada print() del script aparece ahí.

La barra de herramientas con el botón Run resaltado

El script imprime Station armed y luego una línea de temperatura y humedad cada dos segundos. El DHT11 del lienzo empieza en 31 C, así que el relé se cierra de inmediato y el ventilador arranca: el motor muestra una flecha de dirección y su velocidad en rpm, y el propio indicador del relé se enciende. Ahora interactúa con los sensores:

La central en funcionamiento en modo básico: el ventilador gira detrás del relé, el LED azul está encendido tras un clic en la cúpula del PIR, y el Monitor Serie muestra las lecturas y la línea ALARM

El cuadrado rojo junto al botón Run detiene el script. Eso es el modo básico en su totalidad: el script se ejecuta en tu pestaña, los pines llegan directamente al lienzo y todo el ciclo desde Run hasta un circuito que reacciona tarda segundos.

Proyecto 2: un montaje de sensores I2C sobre una Raspberry Pi 4, y después el modo Linux

El segundo proyecto coloca tres dispositivos I2C en el bus del conector y usa el smbus2 real para hablar con ellos: un convertidor analógico-digital Grove ADS1115 con dos potenciómetros, un sensor de temperatura y humedad Grove SHT31 y un OLED SSD1306. Un botón y un LED en GPIO simple lo completan. El mismo circuito funciona en una Raspberry Pi 5 sin cambiar un cable ni una línea: el conector es el mismo.

El ADS1115 está ahí por un motivo que sorprende a mucha gente: una Raspberry Pi no tiene entrada analógica. Un potenciómetro conectado directamente a un GPIO solo lee alto o bajo, tanto en la placa real como en Velxio, así que los mandos pasan por el ADC.

El circuito

Inicia un proyecto nuevo sobre la tarjeta Raspberry Pi 4B y añade estas piezas desde el catálogo:

Después conéctalos. Los tres dispositivos I2C comparten GPIO2 (SDA) y GPIO3 (SCL):

Desde (Raspberry Pi 4)Hacia
GPIO2 (SDA)SDA del ADS1115, del SHT31 y del OLED
GPIO3 (SCL)SCL del ADS1115, del SHT31 y del OLED
3V3VCC del ADS1115, del SHT31, del OLED y de ambos potenciómetros
GNDGND del ADS1115, del SHT31, del OLED y de ambos potenciómetros
GPIO27Ánodo del LED; cátodo del LED a 220 Ω, y después a GND
GPIO22Pushbutton; el otro lado del botón a GND
DesdeHacia
Potenciómetro 1 SIGADS1115 A0
Potenciómetro 2 SIGADS1115 A1

El montaje de sensores cableado: la Raspberry Pi 4 abajo, el ADS1115 con dos potenciómetros, el OLED y el SHT31 encima, y el LED y el botón a la derecha, con llamadas sobre los pines I2C y sobre cada dispositivo

El script

Guarda esto como script.py. Primero pregunta a cada una de las tres direcciones si alguien responde, y después entra en bucle: dos canales del ADC, temperatura y humedad, el estado del botón en el LED y las lecturas en el OLED a través de 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)

Hay tres detalles que merece la pena mirar. El ADS1115 se configura campo a campo, tal como su hoja de datos organiza el registro de configuración, de modo que cada constante se puede comprobar contra la tabla 8 de ese documento. El SHT31 se lee con i2c_rdwr porque su comando de medición son dos bytes sin dirección de registro, algo que las llamadas SMBus normales no pueden expresar. Y luma.oled es la misma librería de pantalla que los tutoriales de Raspberry Pi instalan con pip; aquí viene preinstalada, igual que smbus2 y gpiozero.

Ejecútalo primero en modo básico

Pulsa Run. La sonda encuentra los tres chips, el bucle imprime las lecturas y el OLED las muestra. Gira un potenciómetro y la tensión de A0 o A1 lo sigue; haz clic en el SHT31 y puedes fijar la temperatura y la humedad que reporta; mantén pulsado el botón y el LED se enciende.

El montaje de sensores ejecutándose en modo básico: el OLED muestra las dos tensiones, la temperatura y la humedad y el estado del botón, y el Monitor Serie muestra los tres dispositivos encontrados y las lecturas

Todo lo visto hasta ahora se ejecutó en el navegador. Los siguientes pasos ejecutan ese mismo proyecto en una máquina Linux.

Cambia al modo Linux

  1. Si el Monitor Serie no está abierto, haz clic en Serial en la barra de herramientas.
  2. En la barra de título del Monitor Serie, a la derecha, haz clic en Linux terminal.

La barra de título del Monitor Serie con el botón Linux terminal resaltado

  1. Aparece un diálogo llamado Advanced Linux mode que explica lo que va a pasar: el proyecto se reinicia, el arranque tarda alrededor de un minuto y todo va más lento que en el navegador. Haz clic en Start Linux mode.

El diálogo Advanced Linux mode con el botón Start Linux mode resaltado

El invitado arranca en el Monitor Serie, que se ha convertido en una terminal real. Mientras arranca, el chip que hay junto al selector de placa en la barra de herramientas muestra Linux, y su tooltip dice que el modo Linux está activado para este proyecto.

La barra de herramientas con el chip del motor mostrando Linux resaltado

Cuando aparece el prompt, Velxio copia script.py en el directorio home del invitado y lo inicia. En un servidor tranquilo el prompt aparece al cabo de unos 20 segundos y las primeras lecturas alrededor de un minuto después de que hicieras clic en el botón. La salida es la misma que antes, y el OLED lo controla la misma llamada a luma.oled, ahora desde dentro del invitado a través de /dev/i2c-1 del kernel.

El montaje de sensores en modo Linux: la terminal muestra los tres dispositivos encontrados y las lecturas, y el OLED muestra los mismos valores

Usa el shell

Para esto sirve el modo Linux. Haz clic dentro de la terminal, pulsa Ctrl+C para detener el script y estarás en un prompt de root en un sistema Alpine Linux. Unas cuantas líneas para probar:

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

La segunda línea lista los buses del conector como nodos de dispositivo: /dev/i2c-0, /dev/i2c-1, /dev/spidev0.0, /dev/spidev0.1 y /dev/gpiochip0. Responden a las mismas llamadas al sistema que en una Raspberry Pi, así que una librería que los abra por su cuenta, un programa en C o tu propio código con ioctl hablan con las piezas del lienzo.

La tercera línea es la forma moderna de controlar un pin desde el shell, con las herramientas libgpiod que incluye Raspberry Pi OS Bookworm. En el momento en que pulsas Enter, el LED de GPIO27 se enciende en el lienzo. El invitado tiene libgpiod versión 1, así que el chip es un argumento posicional, como se escribe arriba, y la sintaxis de la versión 2 con --chip no se entiende.

El shell de Linux después de interrumpir el script: el comando gpioset está resaltado y el LED del lienzo está encendido

Para ejecutar el script de nuevo a mano, escribe python3 script.py. Para volver al motor del navegador, haz clic en Exit Linux terminal en la misma barra de título. La elección no se guarda con el proyecto: vuelve a abrirlo mañana y Run volverá al modo básico.

La barra de título del Monitor Serie en modo Linux con el botón Exit Linux terminal resaltado

Qué funciona en cada modo

La tabla de abajo es la versión corta de la página de Raspberry Pi en la documentación, que se midió pieza por pieza contra el producto en vivo.

MóduloModo básicoModo Linux
RPi.GPIO, gpiozeroPreinstaladoPreinstalado
smbus2, spidevPreinstalado, las librerías realesPreinstalado, las librerías reales sobre los nodos del kernel
serial (pyserial)Solo las rutas UART de la PiEl pyserial real sobre una tty real, /dev/serial0
adafruit_dht, Adafruit_DHTPreinstaladoPreinstalado
w1thermsensor, el árbol sysfs de 1-WirePreinstaladoA través de requirements.txt; el árbol sysfs está ahí
luma.oled, RPLCD, ST7789, Adafruit BlinkaPreinstaladoPreinstalado
gpiod y las herramientas gpio*No hay dispositivo de caracteres en el navegadorPreinstalado
cv2 (OpenCV)SíNo hay build para el huésped
picamera2Sí, a través de tu webcamNo; usa rpicam-jpeg y sus hermanos
requests, urllibA través de un proxy de salida con una lista de permitidosSin red dentro del huésped
Cualquier otra cosa en PyPIA través de requirements.txtA través de requirements.txt, cuando PyPI tiene una wheel musl aarch64

Lo que ningún modo hace, para que no gastes una sesión de prueba descubriéndolo:

Dos hábitos ahorran tiempo. Nombra el archivo principal script.py, para que ambos modos ejecuten el mismo archivo. Y pon los paquetes de terceros en un requirements.txt junto a él: cuando un script importa un paquete que falta, la consola de ejecución ofrece la línea y un botón la escribe por ti.

Cuánto cuesta

Cualquiera puede cablear un circuito de Raspberry Pi sin una cuenta. Ejecutarlo está restringido:

La barra de herramientas tal como la ve un visitante sin sesión iniciada, con el chip de prueba gratuita e iniciar sesión resaltado

Las sesiones de prueba son iguales en ambos motores, así que un script que solo necesita el modo básico debería quedarse ahí: arranca en segundos en lugar de un minuto, y el huésped Linux es para lo que solo Linux puede hacer.

A dónde ir después

Resumen

Dos proyectos, dos motores. La estación de alarma Grove se ejecutó en modo básico sobre una Raspberry Pi 5, desde un lienzo vacío hasta un circuito que reacciona en unos minutos, con el código de gpiozero y Adafruit DHT que usaría un tutorial de Raspberry Pi. El montaje de sensores se ejecutó primero en modo básico sobre una Raspberry Pi 4, y luego en modo Linux, donde el mismo script habló con el ADS1115, el SHT31 y el OLED a través de /dev/i2c-1 del kernel, y un comando gpioset escrito en el prompt encendió un LED en el lienzo. El modo básico cubre la mayor parte de lo que pide un tutorial de Raspberry Pi; el modo Linux está ahí para la terminal, los archivos y las herramientas del sistema, al precio de un minuto de arranque.


Compartir en:
David Montero

Escrito por

David Montero

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

GitHub velxio.dev

Artículos relacionados


Artículo siguiente
Castlevania: Symphony of the Night ejecutándose de forma nativa en el ESP32-S3