Подключаем датчики к Raspberry Pi без проводов и с Arduino

Подключение датчиков к Raspberry Pi по радиоканалу. В процессе создания умного дома, каждый рано или поздно сталкивается с размещением датчиков, показатели которых нужно выводить на экран, а то и обрабатывать для чего-то более умного.Большинство датчиков легче всего подключаются к Arduino, за счет наличия библиотек, безгеморройных PWM, ADC и прочих вкусностей.Но слишком умную логику на Arduino не построишь, и волей-неволей возникает необходимость использования чего-то более быстрого, универсального, и с простой индикацией\управлением. Например, почти ставший стандартом де-факто, Raspberry Pi.У него есть HDMI\AV выход. Есть флешка, сеть, память, USB и SSH. image Все что нам нужно.

Но напрямую датчики к Raspberry Pi подключить весьма непросто, в силу отсутствия большого количества библиотек, примеров, и просто потому что она не совсем к этому приспособлена. Да и держать эти датчики тогда придется рядом, а значит либо Малинке придется жить на балконе, либо датчику влажности воздуха у вас в шкафу.

Разумеется, тянуть два-три провода от датчиков к Малине — тоже не вариант, ибо тогда умный дом станет сложным домом.

Интересно? Для этих целей была придумана радиосвязь. В качестве самой дешевой, понятной и доступной радиосвязи, я выбрал радиомодуль-трансивер nrf24l01, и вот почему:1) Дальность. В пределах дома — до ста метров. То что нам подходит.2) Скорость передачи данных — до 2 Мбит. Хоть потоковое видео передавай.3) Возможности подключения точка-точка, точки-хаб, хаб-хаб, хаб-точка.4) Толерантны к 5В, хотя могут принимать и 3.3В. 5) Эти контроллеры имеют свою прошивку, которая позволяет им становиться независимым девайсом.6) Автоматически шлет идентификатор сигнала, избавляя нас от необходимости заморачиваться с индивидуальной настройкой каналов для каждого трансивера.7) Дуплекс. 8) Дешевизна. Кстати взял я их не дешево, решил не ждать три недели ради экономии 10 баксов.Вот так выглядит этот девайс. imageТопология связи очень проста, дешева и понятна. 1) Набор датчиков в какой-либо локации, подключается к Arduino. Таких локаций может быть несколько.2) Она (Arduino) играет роль предварительного буфера, который собирает данные с датчиков, и комбинирует их для последующей отправки.Ну и выполняет какую-то базовую логику, например включает на балконе свет по датчику движения (без участия центрального сервера). В общем согласно наши потребностям.3) Raspberry Pi через такой же самый модуль, принимает радиосигнал.В интернете очень много примеров связи Arduino-Raspberry Pi, используя эти трансиверы nrf24l01.Однако почему-то все эти примеры рассматривают Arduino как центральный узел (хаб), а Raspberry Pi как придаток (клиент). И мало что из примеров работоспособно с первого раза.

Методом проб и ошибок, мне удалось сделать обратное — один Raspberry Pi-блок, и несколько узлов с Ардуинами, которые настраиваются абсолютно одинаково, не нуждаются в выборе каналов, частот и прочего. Поменяли циферку в строке — получили новое устройство.

Несколько фоток из центра событий. Малиновый сервер. Не удобно подключаться по сети, WiFi рулит.image

Первый подопечный. Arduino Nano с датчиком движения.image

Второй подопечный. Arduino Mini и USB-TTL. Где-то там отстает проводок.image

Все вместе.image

Итак, не буду вдаваться в подробности установок IDE, библиотек, а выложу сразу работающий код для двух устройств.

Arduino-часть. #include #include // CE, CSN пины RF24 radio (9,10); // init counter unsigned long count = 0; int sensor1 = 2;

void setup (void) { // Инициализируем канал связи и не только. radio.begin (); radio.setPALevel (RF24_PA_MAX); radio.setChannel (0×4c); radio.openWritingPipe (0xF0F0F0F0E1LL); radio.enableDynamicPayloads (); radio.powerUp (); pinMode (sensor1, INPUT); pinMode (3, OUTPUT); } void loop (void) { char outBuffer[32]= »; int pin1 = digitalRead (sensor1); // Следующая строка изменяется по нашему желанию. Я шлю на сервер три значения: ID блока (ардуины), ID пина, и его значение. Больше ничего изменять не нужно. String out = «dev1: p1:»+pin1;

out.toCharArray (outBuffer, 32); radio.write (outBuffer, 32); delay (50); // Не знаю почему, но периодически трансивер зависает. Помогает повторная инициализация. radio.begin (); radio.setPALevel (RF24_PA_MAX); radio.setChannel (0×4c); radio.openWritingPipe (0xF0F0F0F0E1LL); radio.enableDynamicPayloads (); radio.powerUp (); delay (50);

// Следующий костыль включает свет по датчику движения на 10 секунд, не замораживая при этом основной цикл loop.

if (pin1=HIGH) { digitalWrite (3, HIGH); count=0; } count++; if (count>100) { digitalWrite (3, LOW); count=0; } }

На Малине нам понадобится библиотека, установить которую можно так:

git clone https://github.com/stanleyseow/RF24.git cd RF24 cd librf24-rpi/librf24 make sudo make install C++ код для Raspberry Pi. В инклуде нужно указать путь к файлу хидера. #include #include #include »…/RF24.h» #include using namespace std; // spi device, spi speed, ce gpio pin RF24 radio (»/dev/spidev0.0»,8000000,25); void setup (void) { // init radio for reading radio.begin (); radio.enableDynamicPayloads (); radio.setAutoAck (1); radio.setRetries (15,15); radio.setDataRate (RF24_1MBPS); radio.setPALevel (RF24_PA_MAX); radio.setChannel (76); radio.setCRCLength (RF24_CRC_16); radio.openReadingPipe (1,0xF0F0F0F0E1LL); radio.startListening (); } void loop (void) { char receivePayload[64]; while (radio.available ()) { uint8_t len = radio.getDynamicPayloadSize (); radio.read (receivePayload, len);

// Костыль для создания промежуточного файла. ofstream out (»/dev/nrf24»); out << receivePayload << "\n"; out.close (); delay(200); } } int main(int argc, char** argv) { cout << "Driver initialized, please check values of /dev/nrf24" << endl; setup(); while(1) loop(); return 0; } Скомпилировать на Малинке мы его можем командой

g++ -Wall -Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s -L…/librf24/ -lrf24 receiver.cpp -o rpi Не забываем, где мы положили librf24.И запустить ./rpi & Запустив это поделие в фоне, мы получим файл /dev/nrf24, который будет содержать строку, пришедшую к нам по радиоканалу.Его мы можем читать и парсить как нам заблагорассудится. Хоть read, хоть cat, хоть tail.Внимание: костыль с этим файлом был введен ТОЛЬКО для «удобства» совместной работы приложений на разных языках: bash, PHP. По феншую все делать только на С++.

На закуску, видео работы двух Arduino с одной Raspberry Pi. [embedded content]Ради интереса попробовал сформировать строку в JSON, это видно на видео. Неэффективно, если датчиков много. Лимит на 32 символа, а разбираться глубже не было времени. Просто поменять циферку 32 на 64 — не помогает.

Все элементы использую только для наглядности примера. Реальная реализация выглядит по-другому.

© Habrahabr.ru