Підключаємо датчики до 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 <SPI.h>
#include <RF24.h>

// 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(0x4c);
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(0x4c);
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 < cstdlib>
#include < iostream>
#include "../RF24.h"
#include < fstream> 
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.



Заради цікавості спробував сформувати рядок в JSON, це видно на відео. Неефективно, якщо датчиків багато. Ліміт на 32 символу, а розбиратися глибше не було часу. Просто поміняти циферку 32 на 64 — не допомагає.

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

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.