Lab works 5. Розробка пристрою для Alterozoom IoT на базі мікроконтролера Arduino
Мета роботи
Навчитися розробляти пристрої, сумісні з концепцією IoT від Alterozoom
Завдання роботи
1.Установка біблітекі для протоколу взаємодії з додатком Alterozoom.
2.Розробка скетчу.
3.Перевірка взаємодії з пристроєм через монітор послідовного порту.
Інструменти для виконанню роботи
1.Комп'ютер з підключенням до мережі Internet.
2.Плата Arduino з USB виходом (наприклад, Arduino Uno).
Теоретична частина
Для спрощення розробки пристроїв IoT і уніфікації їх підключення до платформи Alterozoom був розроблений простий текстовий протокол для взаємодії пристрою з комп'ютером через різні канали зв'язку, призначені для послідовної передачі інформації. Протокол призначений для організації взаємодії двох пристроїв (точка-точка) за допомогою обміну простими текстовими повідомленнями. Використання текстових повідомлень спрощує розробку і налагодження пристрою, так як дозволяє взаємодіяти з ним без спеціалізованого ПЗ з командного рядка або монітора послідовного порту. Опис протоколу можна знайти за посиланням: http://wl.unn.ru/ftp/public/IoT/Alterozoom/Alterozoom IoT protocol ptp.pdf
Так само була розроблена бібліотека для Arduino IDE, що реалізує даний протокол.
Виконання роботи
Установка бібліотеки для протоколу взаємодії з додатком Alterozoom
Завантажуємо архів з бібліотекою для Arduino IDE за посиланням: http://wl.unn.ru/ftp/public/IoT/Alterozoom/ARpc.zip Встановлюємо бібліотеку через менеджер бібліотек: вибираємо пункт меню "Скетч -> Управління бібліотеками -> Додати. ZIP бібліотеку "і знаходимо скачаний архів ARpc.zip.
Розробка скетчу
В рамках роботи буде створено скетч, що дозволяє блимати світлодіодом з інтерфейсу програми Alterozoom і передавальний раз на пів-секунди "вимірювання" (згенерований двовимірний сигнал (sin (t); cos (t))). Так само у пристрої буде ще один "датчик" - лічильник миганий світлодіодом.
Для взаємодії з комп'ютером через послідовний порт ми створимо об'єкт класу ARpc і визначимо для нього дві callback-функції - одна для обробки команд від ПК, друга для відправки повідомлень на комп'ютер. Дані функції будуть викликатися самою бібліотекою при необхідності. Для однозначної ідентифікації пристрою так само необхідно вказати ідентифікатор і ім'я пристрою. А для забезпечення можливість управління пристроєм необхідно розробити xml-опис панелі управління пристроєм.
Створюємо новий скетч і зберігаємо під ім'ям AlterozoomTest. Перевіряємо, що правильно вказана плата і порт. Підключаємо до скетчу бібліотеку ARpc (Скетч -> Підключити бібліотеку -> ARpc). На початку файлу повинен був з'явитися потрібний #include <ARpc.h>.
Генеруємо унікальний ідентифікатор в форматі UUID (наприклад, можна скористатися сервісом https://www.uuidgenerator.net/version4, при відкритті сторінки вгорі буде готовий UUID). Додаємо дві глобальних змінних для ідентифікатора і назви пристрою:
const char *deviceName="led_blink_test";//имя устройства
const char *deviceId="{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}";//идентификатор устройства
xxxxxxxxxxxx-xxxxxxxx-xxxxxxxxxxxx замінюємо на отриманий UUID, фігурні дужки повинні залишитися.
Так само визначаємо дополнітелной глобальні змінні
int ledPin=13;//пин светодиода
unsigned long blinksCount=0;//число миганий
Для того, щоб в подальшому для пристрою був доступний інтерфейс управління пристроєм, необхідно розробити xml-опис. Детально про це можна почитати в pdf-описі (посилання з теоретичної частини). Для нашого сценарію необхідна одна кнопка, передає на контролер команду "blink", яка описується в такий спосіб:
const char *interfaceStr="<controls><group title=\"Device controls\"><control sync=\"0\" title=\"Blink\" command=\"blink\"/></group></controls>";
Так само для отримання даних з пристрою необхідно підготувати опис датчиків. Для нашого пристрою воно виглядає ось так:
const char *sensorsDef="<sensors>"
"<sensor name=\"blinks_count\" type=\"single\"/>"//датчик blinks_count
"<sensor name=\"sin_x\" type=\"single\"><constraints dims=\"2\"/></sensor>"//датчик sin_x (двумерный)
"</sensors>";
Визначаємо функцію обробки команд, що передаються пристрою. Бібліотека буде викликати цю функцію, коли на пристрій будуть приходити команди, наприклад, введені нами в моніторі порту. Ця функція приймає команду, аргументи команди, кількість аргументів і покажчик на об'єкт класу ARpc, від якого прийшла команда:
void processCommand(const char *cmd,const char *args[],int argsCount,ARpc *parser)
{
if(strcmp(cmd,"blink")==0)//проверяем, что cmd == "blink"
{
//мигаем
digitalWrite(13,HIGH);
delay(200);
digitalWrite(13,LOW);
delay(200);
++blinksCount;
//генерируем "измерение"
parser->writeMeasurement("blinks_count",String(blinksCount).c_str());
//сообщаем библиотеке что команда обработана
parser->writeOk();
}
else parser->writeErr("Unknown cmd");//неизвестная команда
Тут ми обробляємо одну команду - "blink", при приході якої кліпаємо штатним світлодіодом на 13 порту і передаємо нове "вимір" лічильника миганий.
Визначаємо функцію для передачі повідомлень до ПК через послідовний порт:
void arpcWriteCallback(const char *str)
{
Serial.print(str);
}
Ця функція викликається, коли бібліотеці потрібно передати будь-які дані від пристрою. В даному випадку це дані, які ми побачимо в моніторі порту. Зверніть увагу, що не використовується println, так як ця функція додає зайвий новий рядок, який буде заважати нормальній обробці повідомлень.
Далі ми оголошуємо об'єкт класу ARpc і передаємо йому посилання на створені вище змінні і функції:
ARpc parser(300,&processCommand,&arpcWriteCallback,deviceId,deviceName);
Далі готується функція для генерації відліків sin і cos
int t=0;
void writeSinVal()
{
String sinVal;
sinVal+=String(sin(0.1*t));
sinVal+="|";
sinVal+=String(cos(0.1*t));
parser.writeMeasurement("sin_x",sinVal.c_str());
++t;
}
300 - розмір буфера для одного повідомлення. Неможливо передати на контролер повідомлення розміру більше зазначеного.
Розмір буфера потрібно підбирати, виходячи з доступного обсягу пам'яті. На мікроконтролерах з великим об'ємом пам'яті можна використовувати більший розмір буфера.
Проходімоо ініціальзацію Піна і послідовного порту в функції setup () і встановити опис датчиків і інтерфейсу управління:
void setup()
{
Serial.begin(9600);
pinMode(13,OUTPUT);
parser.setControlsInterface(interfaceStr);
parser.setSensorsDescription(sensorsDef);
}
І нарешті, в функції loop () необхідно перевіряти послідовний порт на наявність нових даних, передавати їх об'єкту parser, згенерувати новий відлік sin, після чого зробити затримку на пів-секунди, щоб відліки НЕ генерувалися занадто часто.
void loop()
{
while(Serial.available())
parser.putChar(Serial.read());
writeSinVal();
delay(500);
}
Завантажуємо отриманий скетч на мікроконтролер.
Перевірка взаємодії з пристроєм через монітор послідовного порту.
Відкриваємо монітор порту. У ньому повинні регулярно з'являтися повідомлення "meas" з новими значеннями sin і cos.
Перевіряємо, щоб внизу було вибрано "Новий рядок", а не "Немає кінця рядка".
Пишемо в поле введення "identify" і натискаємо Надіслати. У відповідь має з'явитися повідомлення deviceinfo.
У цьому повідомленні повинні бути ідентифікатор і ім'я пристрою, зазначені в скетчі.
Додаткове завдання: передати повідомлення на пристрій з командою миготіння светодиодом "blink", запросити з пристрою список датчиків і опис інтерфейсу управління.