[Перевод] Мониторинг качества воздуха с использованием Raspberry Pi 4, датчика Sensirion SPS30 и Microsoft Azure

В материале, перевод которого мы публикуем сегодня, речь пойдёт о том, как подключить датчик качества воздуха Sensirion Particulate Matter Sensor SPS30 к Raspberry Pi 4, и о том, как, пользуясь возможностями Microsoft Azure, представить сведения о качестве воздуха в удобном для восприятия виде.

pejmmejj-gqniil1-9vkqwq15p0.png

Аппаратные средства и программное обеспечение


  • Датчик качества воздуха Sensirion Particulate Matter Sensor SPS30.
  • Одноплатный компьютер Raspberry Pi 4 Model B.
  • Макетная плата.
  • Соединительные провода.
  • Дистрибутив Linux, собранный с помощью Yocto Project.
  • Программы на Rust и Python.
  • Облачная платформа Microsoft Azure.


Сборка ОС


Для того чтобы использовать в этом проекте Raspberry Pi 4 нужно для начала собрать минимальный дистрибутив Linux с помощью Yocto Project.

Клонируем Yocto-слой BSP для Raspberry Pi отсюда и переключимся на коммит 497a90a. Кроме того, воспользуемся коммитом 35364c0ce отсюда и коммитом ca701cb92d отсюда. Соберём образ и скопируем его на SD-карту, пользуясь инструкциями из репозитория. Проверим работоспособность образа.

Модифицируем образ, добавив в файл rpi-build/conf/local.conf следующее:

  1. IMAGE_ROOTFS_EXTRA_SPACE = «8388608» — для выделения дополнительного пространства;
  2. ENABLE_I2C = «1» и KERNEL_MODULE_AUTOLOAD_rpi += «i2c-dev i2c-bcm2708» — для включения I2C;
  3. CORE_IMAGE_EXTRA_INSTALL += «bash nano tar zip openssh curl ca-certificates ntp tzdata packagegroup-core-buildessential python3 python3-pip i2c-tools git startup-script rustup» — для добавления дополнительных пакетов.


Продолжим модификацию образа, добавим путь к слою meta-mylayer в список BBLAYERS, который находится в файле rpi-build/conf/bblayers.conf. Используем следующие рецепты:

  1. ntp — для получения точного времени.
  2. rustup — для копирования скрипта установки Rust в rootfs.
  3. startup-script — для копирования и инициализации скрипта, который организует подключение к WiFi-сети и запускает сервис ntp.
  4. tzdata — для установки часового пояса. Этот файл нужно модифицировать в соответствии с используемым часовым поясом.
  5. wpa_supplicant — для настройки WiFi-сети. В этот файл нужно внести данные беспроводной сети, к которой будет подключаться устройство.


Повторно соберём образ и скопируем его на SD-карту.

Подключение датчика к Raspberry Pi


Для подключения датчика к Raspberry Pi воспользуемся макетной платой и двумя резисторами на 10 кОм. Соберём всё в соответствии со схемой, приведённой на с. 16 технического описания датчика.

7b553b3f371a476ee7f36544d0c01a40.jpg


Подключение датчика SPS30 к Raspberry Pi

В ходе работы нам пригодится схема выводов GPIO Raspberry Pi 4.

67e4eed09a0f1115f07f0d1563003a26.jpg


Схема выводов GPIO Raspberry Pi 4

Вот как датчик подключается к Raspberry Pi:

  1. Пин VDD (1) SPS30 подключаем к пину 4 (5V power) Raspberry Pi.
  2. Пин SDA (2) SPS30 подключаем к пину 3 (GPIO 2 (SDA)) Raspberry Pi.
  3. Пин SCL (3) SPS30 подключаем к пину 5 (GPIO 3 (SCL)) Raspberry Pi.
  4. Пин SEL (4) SPS30 подключаем к пину 6 (Ground) Raspberry Pi.
  5. Пин GND (5) SPS30 подключаем к пину 6 (Ground) Raspberry Pi.


Проверим соединение, выполнив на Raspberry Pi команду i2cdetect -y 1 и узнав, обнаружено ли устройство с адресом 0x69.

Чтение данных


Установим на Raspberry Pi Rust, воспользовавшись скриптом rustup.

Загрузим драйвер для датчика:

git clone https://github.com/david-gherghita/sps30-i2c-rs.git


Проверим правильность работы системы следующей командой:

cargo run --example linux


Отправка данных в облако


Создадим учётную запись на сайте Microsoft Azure.

На вкладке Azure Services создадим новую группу ресурсов (Resource Group).

293b54ff0be01e893441bf3b78a7d35e.jpg


Создание новой группы ресурсов

Создадим в группе ресурсов новый IoT-хаб (IoT Hub) и перейдём на его страницу.

В разделе Explorers щёлкнем по IoT Devices и добавим новое устройство. Тут нужно обратить внимание на поле Primary Connection String, так как именно эта строка будет использоваться для подключения платы к облаку.

5e323ff49c0b5b336d029853c07a52f0.jpg


Настройка нового устройства

Скомпилируем и запустим программу на Rust (её можно найти в разделе «Код»), используя cargo, и настроим зависимости проекта:

linux-embedded-hal = "0.3.0"
sps30-i2c = "0.1.0"


Заполним строку соединения (Primary Connection String), проверим путь к Rust-программе и запустим Python-программу (её тоже можно найти в разделе «Код»).

Если всё сделано правильно — можно будет увидеть, как в IoT-хаб поступают данные.

457438410b878ce0f1fcfd0fc131e3f3.jpg


Данные поступают в IoT-хаб

Теперь вернёмся в Microsoft Azure, создадим задание Stream Analytics и добавим новый поток входных данных из IoT-хаба, проверив, чтобы в качестве Event serialization format был выбран JSON.

На вкладке Input Preview должны появиться новые данные.

0c05a664b6a1d03c9809a51000b60987.jpg


Данные, полученные с Raspberry Pi

Для того чтобы просматривать эти данные в более удобном виде, в форме графиков, нужно добавить к заданию Stream Analytics выход типа Power Bi. В качестве Authentication Mode нужно указать User Token. Это нужно для того чтобы у нас была бы возможность использовать собственное рабочее пространство в роли рабочего пространства Power Bi.

Далее, модифицируем функцию выполнения запроса, приведя её к виду, показанному ниже. Это нужно для отправки данных в Power Bi.

SELECT
    "mass_pm1.0",
    "mass_pm2.5",
    "mass_pm4.0",
    "mass_pm10",
    "number_pm0.5",
    "number_pm1.0",
    "number_pm2.5",
    "number_pm4.0",
    "number_pm10",
    "typical_size",
    CAST ("sensor_time" AS datetime) "sensor_time"
INTO
    "AQS-PowerBI"
FROM
    IoT


Для того чтобы наконец воспользоваться данными в Power Bi, нужно перейти на соответствующую страницу, войти в своё рабочее пространство и, пользуясь простым графическим интерфейсом, создать отчёт на основе набора данных, полученного от задания Stream Analytics.

1b321fe2898f5a5c60b74232195c669d.jpg


Визуализация данных

Схема подключения компонентов


b29454e150695ef9c52534dc80eff0e8.jpg


Подключение компонентов

Код


Вот код Rust-программы, вызываемой Python-скриптом для вывода сведений, полученных с датчика.

use linux_embedded_hal::{Delay, I2cdev};
use sps30_i2c::Sps30;

fn main() {
    let dev = I2cdev::new("/dev/i2c-1").unwrap();
    let delay = Delay;
    let mut sensor = Sps30::new_sps30(dev, delay);

    let result = sensor.read_measured_values().unwrap();

    println!("{}", result.mass_pm1_0);
    println!("{}", result.mass_pm2_5);
    println!("{}", result.mass_pm4_0);
    println!("{}", result.mass_pm10);

    println!("{}", result.number_pm0_5);
    println!("{}", result.number_pm1_0);
    println!("{}", result.number_pm2_5);
    println!("{}", result.number_pm4_0);
    println!("{}", result.number_pm10);

    println!("{}", result.typical_size);
}


Вот Python-скрипт, который вызывает программу, написанную на Rust, получает сведения с датчика и отправляет их в Microsoft Azure.

#!/usr/bin/python3.8

import os
import asyncio
from azure.iot.device.aio import IoTHubDeviceClient
from azure.iot.device import Message
import time
import subprocess

async def main():
  # Подключение устройства к IoT-хабу
  conn_str = "TODO"
  device_client = IoTHubDeviceClient.create_from_connection_string(conn_str)
  await device_client.connect()

  while True:
    # Чтение показателей датчика
    cmd = ['sensor-read/target/release/sensor-read']
    process = subprocess.Popen(cmd, stdout=subprocess.PIPE)

    results = []
    for line in process.stdout:
      results.append(float(line))

    # Отправка сообщения
    msg = Message('{\
      "mass_pm1.0": %f,\
      "mass_pm2.5": %f,\
      "mass_pm4.0": %f,\
      "mass_pm10": %f,\
      "number_pm0.5": %f,\
      "number_pm1.0": %f,\
      "number_pm2.5": %f,\
      "number_pm4.0": %f,\
      "number_pm10": %f,\
      "typical_size": %f,\
    }' % tuple(results))
    await device_client.send_message(msg)

    time.sleep(15)

if __name__ == "__main__":
  asyncio.run(main())


Планируете собрать систему для мониторинга качества воздуха, похожую на ту, о которой шла речь в этой статье?

oug5kh6sjydt9llengsiebnp40w.png

3piw1j3wd_cgmzq9sefgferaumu.png

© Habrahabr.ru