Назад

Raspberry Pi 4 и 5 в браузере: базовый режим и режим Linux, шаг за шагом

Raspberry Pi в Velxio — это плата на холсте, которая выполняет скрипт Python для схемы, собранной вокруг неё. Компилировать ничего не нужно. Вы пишете скрипт, нажимаете Run, и один из двух движков его выполняет:

Эта статья собирает два проекта, по одному на режим, и показывает каждый шаг. Первый — охранная станция из модулей Grove на Raspberry Pi 5: датчик движения, датчик вибрации и DHT11 на входе, зуммер, два светодиода и реле с вентилятором на выходе. Второй — стенд с датчиками на Raspberry Pi 4 с тремя устройствами I2C. Оба скрипта используют библиотеки, входящие в состав Raspberry Pi OS, поэтому они работают без изменений и на настоящей плате.

Прежде чем начать, два слова о доступе. Любой может разместить Raspberry Pi на холсте и собрать схему вокруг него. Для запуска нужен аккаунт: каждый бесплатный аккаунт получает три пробные сессии по 15 минут на семействе Raspberry Pi в любом режиме, а любой платный план снимает ограничение. Подробности — в разделе Сколько это стоит ближе к концу.

Два способа запустить один и тот же скрипт

Базовый режимРежим Linux
Где выполняется скриптИнтерпретатор Python во вкладке браузераГость Alpine Linux под QEMU на серверах Velxio
Время запускаНесколько секундОколо минуты
GPIORPi.GPIO, gpiozero, Adafruit BlinkaТо же самое, плюс /dev/gpiochip0 и утилиты libgpiod
I2C, SPI, UART, 1-WireНастоящие smbus2, spidev, pyserial и w1thermsensor через эмулированные файлы устройствТе же библиотеки через реальные узлы устройств ядра
Оболочка и файловая системаНетДа, в Serial Monitor
Сторонние пакетыИз requirements.txtИз requirements.txt, разрешаются офлайн до загрузки гостя
Лучше всего подходит дляПрактически всегоИнструментов оболочки, подпроцессов, файлов и всего, что руководство делает из терминала

Движок выбирается за вас. Скрипт, который запрашивает то, что умеет только Linux, например subprocess, отправляется в режим Linux, а значок на панели инструментов сообщает вам почему. Вы также можете принудительно включить режим Linux сами — именно так поступает второй проект.

Проект 1: охранная станция на Grove для Raspberry Pi 5

Модули Grove — самый быстрый способ подключить датчики к Pi: у каждого модуля одинаковый четырёхконтактный разъём, и в Velxio каждый из них подключается к гребёнке тремя проводами — SIG, VCC и GND. Эта станция следит за комнатой с помощью PIR-датчика движения и датчика вибрации, измеряет воздух с помощью DHT11 и отвечает через зуммер, зелёный светодиод для «всё спокойно», синий светодиод для «тревога» и реле, которое запускает вентилятор, когда в комнате становится тепло.

Шаг 1: создайте проект на Raspberry Pi 5

Откройте velxio.dev/editor. Диалоговое окно Start a new project открывается само. Прокрутите до раздела Raspberry Pi и нажмите на карточку Raspberry Pi 5. Карточка Raspberry Pi 4B работает так же: обе платы используют одну и ту же 40-контактную гребёнку и одни и те же библиотеки, поэтому всё нижеприведённое применимо к обеим.

Диалоговое окно Start a new project с разделом Raspberry Pi; карточка Raspberry Pi 5 выделена

Шаг 2: добавьте компоненты

Нажмите синюю кнопку Add в правом конце панели инструментов. Откроется каталог компонентов.

Панель инструментов с выделенной кнопкой Add

Введите название в поле поиска и нажмите на карточку, чтобы перетащить компонент на холст. Все модули Grove перечислены под своими именами Seeed, поэтому «Grove PIR» или «Grove relay» их находят. Добавьте эти восемь компонентов по одному:

  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

Диалоговое окно Add Component с введённым в поле поиска Grove PIR и выделенной карточкой PIR-датчика движения

Компоненты можно перетаскивать в любое место холста. Если оставить Pi внизу, а модули над его гребёнкой, провода останутся короткими.

Шаг 3: подключите

Чтобы нарисовать провод, нажмите на контакт, затем нажмите на контакт на другом конце. Названия контактов появляются при наведении на компонент. Каждый модуль Grove подключается одинаково тремя проводами: SIG к GPIO, VCC к 3V3, GND к GND. Реле — исключение по питанию: его катушке нужно 5 В.

МодульSIGVCCGND
PIR-датчик движенияGPIO173V3GND
Датчик вибрации (SW-420)GPIO273V3GND
DHT11GPIO43V3GND
ЗуммерGPIO243V3GND
Зелёный светодиодGPIO53V3GND
Синий светодиодGPIO63V3GND
РелеGPIO235VGND

У вентилятора нет собственного сигнального провода. Он подключён к переключаемым контактам реле, как нагрузка на стенде: питание идёт на COM и выходит из NO только пока катушка под напряжением.

ОтК
Raspberry Pi 5VРеле COM
Реле NOВентилятор +
Вентилятор -Raspberry Pi GND

Собранная станция: Raspberry Pi 5 внизу, PIR, датчик вибрации, DHT11 и зуммер в ряд над его гребёнкой, два светодиода и реле с вентилятором под ними, с подписями на каждом модуле

Шаг 4: скрипт

В проводнике файлов слева уже есть файл script.py с коротким скриптом мигания. Оставьте это имя. Базовый режим запускает первый найденный файл .py, но режим Linux запускает именно script.py, поэтому проект, чей главный файл сохраняет это имя, работает в обоих режимах.

Редактор кода с выбранным script.py в проводнике файлов

Замените его содержимое этим скриптом:

"""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)

На три вещи в нём стоит обратить внимание, потому что на реальном железе всё так же:

Шаг 5: запустите

На панели инструментов нажмите зелёный треугольник, чтобы запустить проект. Внизу открывается Serial Monitor и сообщает, что делает движок: он загружает среду выполнения Python, устанавливает библиотеку GPIO и печатает строку вроде [Velxio] ready in 6068 ms, а затем имя запускаемого скрипта. С этого момента каждый print() в скрипте попадает туда.

Панель инструментов с выделенной кнопкой Run

Скрипт печатает Station armed, затем строку с температурой и влажностью каждые две секунды. DHT11 на холсте начинает с 31 C, поэтому реле сразу замыкается и вентилятор раскручивается: у мотора появляется стрелка направления и скорость в об/мин, а на самом реле загорается индикатор. Теперь взаимодействуйте с датчиками:

Станция, работающая в базовом режиме: вентилятор вращается за реле, синий светодиод горит после нажатия на купол PIR, а Serial Monitor показывает показания и строку ALARM

Красный квадрат рядом с кнопкой Run останавливает скрипт. Это и есть базовый режим целиком: скрипт выполняется в вашей вкладке, контакты напрямую достигают холста, и весь цикл от Run до реагирующей схемы занимает секунды.

Проект 2: стенд с I2C-датчиками на Raspberry Pi 4, затем режим Linux

Второй проект размещает три I2C-устройства на шине разъёма и использует настоящую smbus2 для связи с ними: аналого-цифровой преобразователь Grove ADS1115 с двумя потенциометрами, датчик температуры и влажности Grove SHT31 и OLED-дисплей SSD1306. Кнопка и светодиод на обычных GPIO завершают картину. Та же схема работает на Raspberry Pi 5 без изменения ни одного провода или строки: разъём тот же.

ADS1115 здесь по причине, которая ловит многих: у Raspberry Pi нет аналогового входа. Потенциометр, подключённый напрямую к GPIO, всегда читается только как высокий или низкий уровень — и на реальной плате, и в Velxio, — поэтому ручки идут через АЦП.

Схема

Создайте новый проект на карточке Raspberry Pi 4B и добавьте эти детали из каталога:

Затем соедините их. Все три I2C-устройства используют общие GPIO2 (SDA) и GPIO3 (SCL):

От (Raspberry Pi 4)К
GPIO2 (SDA)SDA ADS1115, SHT31 и OLED
GPIO3 (SCL)SCL ADS1115, SHT31 и OLED
3V3VCC ADS1115, SHT31, OLED и обоих потенциометров
GNDGND ADS1115, SHT31, OLED и обоих потенциометров
GPIO27Анод светодиода; катод светодиода к 220 Ω, затем к GND
GPIO22Кнопка; другая сторона кнопки к GND
ОтК
Потенциометр 1 SIGADS1115 A0
Потенциометр 2 SIGADS1115 A1

Собранный стенд с датчиками: Raspberry Pi 4 внизу, ADS1115 с двумя потенциометрами, OLED и SHT31 над ним, а светодиод и кнопка справа, с выносками на пинах I2C и на каждом устройстве

Скрипт

Сохраните это как script.py. Сначала он спрашивает каждый из трёх адресов, отвечает ли кто-нибудь, затем зацикливается: два канала АЦП, температура и влажность, состояние кнопки на светодиоде и показания на OLED через 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)

Три детали заслуживают внимания. ADS1115 настраивается поле за полем, так, как его даташит раскладывает регистр конфигурации, поэтому каждую константу можно сверить с таблицей 8 этого документа. SHT31 читается через i2c_rdwr, потому что его команда измерения — это два байта без адреса регистра, что обычные вызовы SMBus выразить не могут. А luma.oled — та же библиотека дисплея, которую туториалы по Raspberry Pi устанавливают через pip; здесь она предустановлена, как smbus2 и gpiozero.

Сначала запустите в базовом режиме

Нажмите Run. Проверка находит три чипа, цикл печатает показания, и OLED их отображает. Поверните потенциометр — и напряжение A0 или A1 последует за ним; кликните по SHT31 — и вы сможете задать температуру и влажность, которые он сообщает; удерживайте кнопку — и светодиод загорится.

Стенд с датчиками, работающий в базовом режиме: OLED показывает два напряжения, температуру и влажность и состояние кнопки, а Serial Monitor показывает три найденных устройства и показания

Всё до сих пор выполнялось в браузере. Следующие шаги запускают тот же самый проект на машине с Linux.

Переключение в режим Linux

  1. Если Serial Monitor не открыт, нажмите Serial на панели инструментов.
  2. В строке заголовка Serial Monitor справа нажмите Linux terminal.

Строка заголовка Serial Monitor с выделенной кнопкой Linux terminal

  1. Диалоговое окно Advanced Linux mode объясняет, что сейчас произойдёт: проект перезапустится, загрузка займёт около минуты, и всё будет работать медленнее, чем в браузере. Нажмите Start Linux mode.

Диалоговое окно Advanced Linux mode с выделенной кнопкой Start Linux mode

Гостевая система загружается в Serial Monitor, который стал настоящим терминалом. Пока она загружается, чип рядом с селектором платы на панели инструментов показывает Linux, а его подсказка сообщает, что режим Linux включён для этого проекта.

Панель инструментов с выделенным чипом движка, показывающим Linux

Когда появляется приглашение, Velxio копирует script.py в домашний каталог гостевой системы и запускает его. На тихом сервере приглашение появляется примерно через 20 секунд, а первые показания — примерно через минуту после нажатия кнопки. Вывод тот же, что и раньше, и OLED управляется тем же вызовом luma.oled, теперь изнутри гостевой системы через /dev/i2c-1 ядра.

Стенд с датчиками в режиме Linux: терминал показывает три найденных устройства и показания, а OLED показывает те же значения

Используйте оболочку

Вот для чего нужен режим Linux. Кликните внутри терминала, нажмите Ctrl+C, чтобы остановить скрипт, и вы окажетесь в приглашении root в системе Alpine Linux. Несколько строк, которые стоит попробовать:

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

Вторая строка перечисляет шины разъёма как узлы устройств: /dev/i2c-0, /dev/i2c-1, /dev/spidev0.0, /dev/spidev0.1 и /dev/gpiochip0. Они отвечают на те же системные вызовы, что и на Raspberry Pi, поэтому библиотека, которая открывает их сама, программа на C или ваш собственный код с ioctl общаются с деталями на холсте.

Третья строка — современный способ управлять пином из оболочки, с помощью инструментов libgpiod, которые поставляет Raspberry Pi OS Bookworm. В момент нажатия Enter светодиод на GPIO27 загорается на холсте. В гостевой системе установлена libgpiod версии 1, поэтому чип — это позиционный аргумент, как написано выше, а написание версии 2 с --chip не понимается.

Оболочка Linux после прерывания скрипта: команда gpioset выделена, а светодиод на холсте горит

Чтобы снова запустить скрипт вручную, введите python3 script.py. Чтобы вернуться к браузерному движку, нажмите Exit Linux terminal в той же строке заголовка. Выбор не сохраняется вместе с проектом: откройте его завтра — и Run снова вернётся в базовый режим.

Строка заголовка Serial Monitor в режиме Linux с выделенной кнопкой Exit Linux terminal

Что работает в каждом режиме

Таблица ниже — краткая версия страницы Raspberry Pi в документации, которая была измерена по частям на живом продукте.

МодульБазовый режимРежим Linux
RPi.GPIO, gpiozeroПредустановленыПредустановлены
smbus2, spidevПредустановлены, настоящие библиотекиПредустановлены, настоящие библиотеки поверх узлов ядра
serial (pyserial)Только пути UART на PiНастоящий pyserial на настоящем tty, /dev/serial0
adafruit_dht, Adafruit_DHTПредустановленыПредустановлены
w1thermsensor, дерево sysfs для 1-WireПредустановленыЧерез requirements.txt; дерево sysfs на месте
luma.oled, RPLCD, ST7789, Adafruit BlinkaПредустановленыПредустановлены
gpiod и инструменты gpio*Нет символьного устройства в браузереПредустановлены
cv2 (OpenCV)ДаНет сборки для гостевой системы
picamera2Да, через вашу веб-камеруНет; используйте rpicam-jpeg и его аналоги
requests, urllibЧерез прокси-сервер выхода со списком разрешённых адресовНет сети внутри гостевой системы
Всё остальное на PyPIЧерез requirements.txtЧерез requirements.txt, когда на PyPI есть wheel для musl aarch64

Чего не делает ни один режим, чтобы вы не тратили пробную сессию на выяснение:

Две привычки экономят время. Назовите главный файл script.py, чтобы оба режима запускали один и тот же файл. И положите сторонние пакеты в requirements.txt рядом с ним: когда скрипт импортирует отсутствующий пакет, консоль запуска предлагает строку, а кнопка записывает её за вас.

Сколько это стоит

Любой может собрать схему с Raspberry Pi без учётной записи. Запуск же ограничен:

Панель инструментов, как её видит посетитель без входа в систему, с выделенным чипом Free trial, sign in

Пробные сессии одинаковы на обоих движках, поэтому скрипт, которому нужен только базовый режим, должен оставаться там: он запускается за секунды вместо минуты, а гостевая система Linux — для того, что может только Linux.

Куда двигаться дальше

Итог

Два проекта, два движка. Сигнальная станция Grove работала в базовом режиме на Raspberry Pi 5, от пустого холста до реагирующей схемы за несколько минут, с кодом gpiozero и Adafruit DHT, который использовал бы любой обучающий материал по Raspberry Pi. Стенд с датчиками сначала работал в базовом режиме на Raspberry Pi 4, затем в режиме Linux, где тот же скрипт общался с ADS1115, SHT31 и OLED через /dev/i2c-1 ядра, а команда gpioset, набранная в командной строке, зажгла светодиод на холсте. Базовый режим покрывает большую часть того, что требует обучающий материал по Raspberry Pi; режим Linux существует для терминала, файлов и системных инструментов, ценой минуты загрузки.


Поделиться:
David Montero

Автор

David Montero

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

GitHub velxio.dev

Похожие статьи


Следующая статья
Castlevania: Symphony of the Night, работающая нативно на ESP32-S3