Voltar

Raspberry Pi 4 e 5 no navegador: modo básico e modo Linux, passo a passo

Um Raspberry Pi no Velxio é uma placa na tela que executa um script Python contra o circuito que você monta ao redor dela. Não há nada para compilar. Você escreve o script, pressiona Run, e um de dois motores o executa:

Este artigo monta dois projetos, um por modo, e mostra cada clique ao longo do caminho. O primeiro é uma estação de alarme feita de módulos Grove em um Raspberry Pi 5: um sensor de movimento, um interruptor de vibração e um DHT11 no lado da entrada, um buzzer, dois LEDs e um relé com um ventilador no lado da saída. O segundo é um conjunto de sensores em um Raspberry Pi 4 com três dispositivos I2C. Ambos os scripts usam as bibliotecas que vêm com o Raspberry Pi OS, então eles rodam sem alterações em uma placa real.

Antes de começar, duas coisas sobre o acesso. Qualquer pessoa pode colocar um Raspberry Pi na tela e montar um circuito ao redor dele. Executá-lo exige uma conta conectada: toda conta gratuita recebe três sessões de teste de 15 minutos na família Raspberry Pi, em qualquer um dos modos, e qualquer plano pago remove o limite. Os detalhes estão na seção Quanto custa perto do final.

Duas maneiras de executar o mesmo script

Modo básicoModo Linux
Onde o script é executadoUm interpretador Python na aba do seu navegadorUm convidado Alpine Linux sob QEMU nos servidores do Velxio
Tempo de inicializaçãoPoucos segundosCerca de um minuto
GPIORPi.GPIO, gpiozero, Adafruit BlinkaOs mesmos, mais /dev/gpiochip0 e as ferramentas libgpiod
I2C, SPI, UART, 1-WireOs smbus2, spidev, pyserial e w1thermsensor reais sobre arquivos de dispositivo emuladosAs mesmas bibliotecas sobre os nós de dispositivo reais do kernel
Um shell e um sistema de arquivosNãoSim, no Serial Monitor
Pacotes de terceirosDe um requirements.txtDe um requirements.txt, resolvidos offline antes do convidado inicializar
Melhor paraQuase tudoFerramentas de shell, subprocessos, arquivos e qualquer coisa que um tutorial faça a partir de um terminal

O motor é escolhido para você. Um script que pede algo que só o Linux pode fazer, como subprocess, é enviado para o modo Linux e um chip na barra de ferramentas informa o motivo. Você também pode forçar o modo Linux por conta própria, que é o que o segundo projeto faz.

Projeto 1: uma estação de alarme Grove em um Raspberry Pi 5

Os módulos Grove são a forma mais rápida de colocar sensores em um Pi: todo módulo tem o mesmo conector de quatro pinos e, no Velxio, cada um se conecta ao header com três fios, SIG, VCC e GND. Esta estação vigia uma sala com um sensor de movimento PIR e um sensor de vibração, lê o ar com um DHT11 e responde por meio de um buzzer, um LED verde para “tudo tranquilo”, um LED azul para “alarme” e um relé que aciona um ventilador quando a sala esquenta.

Passo 1: inicie um projeto no Raspberry Pi 5

Abra velxio.dev/editor. A caixa de diálogo Iniciar um novo projeto abre sozinha. Role até a seção Raspberry Pi e clique no cartão Raspberry Pi 5. O cartão do Raspberry Pi 4B funciona da mesma forma: as duas placas compartilham o header de 40 pinos e as mesmas bibliotecas, então tudo abaixo se aplica a ambas.

A caixa de diálogo Iniciar um novo projeto com a seção Raspberry Pi; o cartão Raspberry Pi 5 está destacado

Passo 2: adicione as peças

Clique no botão azul Adicionar na extremidade direita da barra de ferramentas. Ele abre o catálogo de peças.

A barra de ferramentas com o botão Adicionar destacado

Digite um nome no campo de busca e clique no cartão para soltar a peça na tela. Os módulos Grove estão todos listados com seus nomes Seeed, então “Grove PIR” ou “Grove relay” os encontra. Adicione estas oito peças, uma de cada vez:

  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

A caixa de diálogo Adicionar Componente com Grove PIR digitado no campo de busca e o cartão do sensor de movimento PIR destacado

As peças podem ser arrastadas para qualquer lugar da tela. Deixar o Pi na parte de baixo e os módulos acima do seu header mantém os fios curtos.

Passo 3: faça a fiação

Para desenhar um fio, clique em um pino e depois clique no pino na outra extremidade. Os nomes dos pinos aparecem quando você passa o mouse sobre uma peça. Todo módulo Grove usa os mesmos três fios: SIG para um GPIO, VCC para 3V3, GND para GND. O relé é a exceção no lado da alimentação, sua bobina quer 5 V.

MóduloSIGVCCGND
Sensor de movimento PIRGPIO173V3GND
Sensor de vibração (SW-420)GPIO273V3GND
DHT11GPIO43V3GND
BuzzerGPIO243V3GND
LED verdeGPIO53V3GND
LED azulGPIO63V3GND
ReléGPIO235VGND

O ventilador não tem fio de sinal próprio. Ele fica nos contatos comutados do relé, como uma carga em uma bancada: a alimentação entra no COM e sai pelo NO apenas enquanto a bobina está energizada.

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

A estação com fiação: o Raspberry Pi 5 na parte de baixo, o PIR, o sensor de vibração, o DHT11 e o buzzer em uma fileira acima do seu header, os dois LEDs e o relé com seu ventilador abaixo deles, com legendas em cada módulo

Passo 4: o script

O explorador de arquivos à esquerda já contém um arquivo chamado script.py com um script curto de piscar. Mantenha esse nome. O modo básico executa o primeiro arquivo .py que encontra, mas o modo Linux executa especificamente o script.py, então um projeto cujo arquivo principal mantém esse nome funciona em ambos.

O editor de código com script.py selecionado no explorador de arquivos

Substitua seu conteúdo 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)

Três coisas nele merecem uma olhada, porque são iguais no hardware real:

Passo 5: execute

Na barra de ferramentas, clique no triângulo verde para executar o projeto. O Monitor Serial abre na parte de baixo e informa o que o motor está fazendo: ele carrega o runtime Python, instala a biblioteca de GPIO e imprime uma linha como [Velxio] ready in 6068 ms seguida pelo nome do script que está executando. A partir daí, todo print() no script aparece ali.

A barra de ferramentas com o botão Executar destacado

O script imprime Station armed e depois uma linha de temperatura e umidade a cada dois segundos. O DHT11 na tela começa em 31 C, então o relé fecha imediatamente e o ventilador gira: o motor mostra uma seta de direção e sua velocidade em rpm, e o próprio indicador do relé acende. Agora interaja com os sensores:

A estação em execução no modo básico: o ventilador gira atrás do relé, o LED azul está aceso após um clique na cúpula do PIR, e o Monitor Serial mostra as leituras e a linha ALARM

O quadrado vermelho ao lado do botão Executar para o script. Isso é o modo básico por completo: o script roda na sua aba, os pinos alcançam a tela diretamente, e todo o ciclo de Executar até um circuito reagindo leva segundos.

Projeto 2: uma bancada de sensores I2C em um Raspberry Pi 4, depois o modo Linux

O segundo projeto coloca três dispositivos I2C no barramento do header e usa o smbus2 de verdade para conversar com eles: um conversor analógico-digital Grove ADS1115 com dois potenciômetros, um sensor de temperatura e umidade Grove SHT31 e um OLED SSD1306. Um botão e um LED em GPIO comum completam o conjunto. O mesmo circuito funciona em um Raspberry Pi 5 sem trocar um fio ou uma linha: o header é o mesmo.

O ADS1115 está ali por um motivo que pega muita gente: um Raspberry Pi não tem entrada analógica. Um potenciômetro ligado direto a um GPIO só lê alto ou baixo, tanto na placa real quanto no Velxio, então os botões passam pelo ADC.

O circuito

Inicie um novo projeto no cartão Raspberry Pi 4B e adicione estas peças do catálogo:

Depois faça a fiação. Os três dispositivos I2C compartilham GPIO2 (SDA) e GPIO3 (SCL):

De (Raspberry Pi 4)Para
GPIO2 (SDA)SDA do ADS1115, do SHT31 e do OLED
GPIO3 (SCL)SCL do ADS1115, do SHT31 e do OLED
3V3VCC do ADS1115, do SHT31, do OLED e de ambos os potenciômetros
GNDGND do ADS1115, do SHT31, do OLED e de ambos os potenciômetros
GPIO27Ânodo do LED; cátodo do LED para 220 Ω, depois GND
GPIO22Pushbutton; o outro lado do botão para GND
DePara
Potenciômetro 1 SIGADS1115 A0
Potenciômetro 2 SIGADS1115 A1

A bancada de sensores montada: o Raspberry Pi 4 na parte de baixo, o ADS1115 com dois potenciômetros, o OLED e o SHT31 acima dele, e o LED e o botão à direita, com chamadas nos pinos I2C e em cada dispositivo

O script

Salve isto como script.py. Ele primeiro pergunta a cada um dos três endereços se alguém responde, depois entra em loop: dois canais do ADC, temperatura e umidade, o estado do botão no LED e as leituras no OLED através do 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)

Três detalhes merecem atenção. O ADS1115 é configurado campo a campo, do jeito que o datasheet dele organiza o registrador de configuração, então cada constante pode ser conferida na tabela 8 daquele documento. O SHT31 é lido com i2c_rdwr porque o comando de medição dele tem dois bytes sem endereço de registrador, o que chamadas SMBus comuns não conseguem expressar. E o luma.oled é a mesma biblioteca de display que os tutoriais de Raspberry Pi instalam com pip; aqui ela já vem pré-instalada, assim como smbus2 e gpiozero.

Execute primeiro no modo básico

Pressione Run. A sondagem encontra os três chips, o loop imprime as leituras e o OLED as mostra. Gire um potenciômetro e a tensão de A0 ou A1 acompanha; clique no SHT31 e você pode definir a temperatura e a umidade que ele reporta; segure o pushbutton e o LED acende.

A bancada de sensores rodando no modo básico: o OLED mostra as duas tensões, a temperatura e a umidade e o estado do botão, e o Serial Monitor mostra os três dispositivos encontrados e as leituras

Tudo até aqui rodou no navegador. Os próximos passos rodam exatamente o mesmo projeto em uma máquina Linux.

Mude para o modo Linux

  1. Se o Serial Monitor não estiver aberto, clique em Serial na barra de ferramentas.
  2. Na barra de título do Serial Monitor, à direita, clique em Linux terminal.

A barra de título do Serial Monitor com o botão Linux terminal destacado

  1. Uma caixa de diálogo chamada Advanced Linux mode explica o que está prestes a acontecer: o projeto reinicia, a inicialização leva cerca de um minuto e tudo roda mais devagar do que no navegador. Clique em Start Linux mode.

A caixa de diálogo Advanced Linux mode com o botão Start Linux mode destacado

O guest inicializa no Serial Monitor, que virou um terminal de verdade. Enquanto ele inicializa, o chip ao lado do seletor de placa na barra de ferramentas mostra Linux, e sua dica de ferramenta diz que o modo Linux está ativado para este projeto.

A barra de ferramentas com o chip de engine mostrando Linux destacado

Quando o prompt aparece, o Velxio copia o script.py para o diretório home do guest e o inicia. Em um servidor tranquilo o prompt aparece depois de cerca de 20 segundos e as primeiras leituras cerca de um minuto depois de você clicar no botão. A saída é a mesma de antes, e o OLED é controlado pela mesma chamada luma.oled, agora de dentro do guest através do /dev/i2c-1 do kernel.

A bancada de sensores no modo Linux: o terminal mostra os três dispositivos encontrados e as leituras, e o OLED mostra os mesmos valores

Use o shell

É para isso que serve o modo Linux. Clique dentro do terminal, pressione Ctrl+C para parar o script, e você está em um prompt de root em um sistema Alpine Linux. Algumas linhas para experimentar:

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

A segunda linha lista os barramentos do header como nós de dispositivo: /dev/i2c-0, /dev/i2c-1, /dev/spidev0.0, /dev/spidev0.1 e /dev/gpiochip0. Eles respondem às mesmas chamadas de sistema que em um Raspberry Pi, então uma biblioteca que os abre por conta própria, um programa em C ou seu próprio código ioctl conversa com as peças na tela.

A terceira linha é a forma moderna de acionar um pino pelo shell, com as ferramentas libgpiod que o Raspberry Pi OS Bookworm traz. No momento em que você pressiona Enter, o LED no GPIO27 acende na tela. O guest tem a versão 1 do libgpiod, então o chip é um argumento posicional, como escrito acima, e a grafia da versão 2 com --chip não é reconhecida.

O shell Linux depois que o script foi interrompido: o comando gpioset está destacado e o LED na tela está aceso

Para rodar o script de novo manualmente, digite python3 script.py. Para voltar ao engine do navegador, clique em Exit Linux terminal na mesma barra de título. A escolha não é salva com o projeto: reabra amanhã e o Run volta ao modo básico.

A barra de título do Serial Monitor no modo Linux com o botão Exit Linux terminal destacado

O que funciona em cada modo

A tabela abaixo é a versão resumida da página do Raspberry Pi na documentação, que foi medida peça por peça contra o produto ao vivo.

MóduloModo básicoModo Linux
RPi.GPIO, gpiozeroPré-instaladoPré-instalado
smbus2, spidevPré-instalado, as bibliotecas reaisPré-instalado, as bibliotecas reais sobre os nós do kernel
serial (pyserial)Apenas os caminhos UART do PiO pyserial real em um tty real, /dev/serial0
adafruit_dht, Adafruit_DHTPré-instaladoPré-instalado
w1thermsensor, a árvore sysfs do 1-WirePré-instaladoAtravés do requirements.txt; a árvore sysfs está lá
luma.oled, RPLCD, ST7789, Adafruit BlinkaPré-instaladoPré-instalado
gpiod e as ferramentas gpio*Nenhum character device no navegadorPré-instalado
cv2 (OpenCV)SimSem build para o guest
picamera2Sim, através da sua webcamNão; use rpicam-jpeg e seus similares
requests, urllibAtravés de um proxy de saída com uma allowlistSem rede dentro do guest
Qualquer outra coisa no PyPIAtravés do requirements.txtAtravés do requirements.txt, quando o PyPI tem uma wheel musl aarch64

O que nenhum dos modos faz, para você não gastar uma sessão de teste descobrindo:

Dois hábitos economizam tempo. Nomeie o arquivo principal como script.py, para que ambos os modos executem o mesmo arquivo. E coloque pacotes de terceiros em um requirements.txt ao lado dele: quando um script importa um pacote que está faltando, o console de execução oferece a linha e um botão a escreve para você.

Quanto custa

Qualquer pessoa pode montar um circuito de Raspberry Pi sem uma conta. Executá-lo é restrito:

A barra de ferramentas como um visitante desconectado a vê, com o chip de teste gratuito e entrar destacado

As sessões de teste são iguais em ambos os motores, então um script que só precisa do modo básico deve ficar nele: ele inicia em segundos em vez de um minuto, e o guest Linux é para o que só o Linux consegue fazer.

Para onde ir em seguida

Resumo

Dois projetos, dois motores. A estação de alarme Grove rodou no modo básico em um Raspberry Pi 5, de uma tela vazia a um circuito reagindo em poucos minutos, com o código gpiozero e Adafruit DHT que um tutorial de Raspberry Pi usaria. A bancada de sensores rodou primeiro no modo básico em um Raspberry Pi 4, depois no modo Linux, onde o mesmo script conversou com o ADS1115, o SHT31 e o OLED através do /dev/i2c-1 do kernel, e um comando gpioset digitado no prompt acendeu um LED na tela. O modo básico cobre a maior parte do que um tutorial de Raspberry Pi pede; o modo Linux está lá para o terminal, os arquivos e as ferramentas de sistema, ao preço de um minuto de boot.


Compartilhar em:
David Montero

Escrito por

David Montero

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

GitHub velxio.dev

Artigos relacionados


Próximo artigo
Castlevania: Symphony of the Night rodando nativamente no ESP32-S3