- PVSM.RU - https://www.pvsm.ru -
Это вторая статья из цикла о интеграции модулей Laurent (Лоран) компании KernelChip [1] в системы домашней автоматизации и в этой части речь пойдёт об интеграции этих модулей с экосистемой Ардуино. В первой части [2] цикла речь шла об интеграции с популярной системой домашней автоматизации MajorDoMo, а в третьей части вы узнаете как управлять этими модулями из скетчей на языке программирования Processing, прямо с рабочего стола вашего компьютера.
Куда же без Ардуино? Не буду здесь долго расписывать достоинства этой платформы, её популярность говорит сама за себя, поэтому давайте сразу приступим к техническим деталям реализации взаимодействия Ардуино и модулей Лоран. И по пути не забудем систему Arduino Mega Server [3], как очень интересное производное от экосистемы Arduino.
Для управления модулями по сети подойдёт, например, распространённая плата Arduino Uno или не менее популярная плата Arduino Mega в комплекте с платой сетевого интерфейса Ethernet Shield, собранной на основе чипа W5100. Все примеры в этой статье даются для такого сочетания и были протестированы на практике. Всё работает надёжно и без каких-либо проблем.
Ethernet Shield на основе чипа W5100
То есть вам остаётся только взять скетч и залить его на свою плату Uno или Mega, предварительно немного изменив его под свои задачи.
В первой части цикла я уже рассказывал о принципах управления модулями Laurent по сети, для тех, кто не читал первую часть, кратко повторю здесь теорию.
Обмен информацией с модулями осуществляется по сети и для начала работы с ними нужно установить TCP/IP соединение на 2424 порту. Как только соединение установлено, можно посылать текстовые команды (т. н. КЕ команды) которые и управляют модулем. На сайте компании KernelChip [1] есть подробная документация и, в том числе, доступное описание КЕ команд.
Теперь давайте попробуем перевести это теоретическое «техзадание» на простой язык скетчей Ардуино.
Я здесь не буду объяснять, как установить и настроить среду программирования Ардуино, предполагается, что вы уже это сделали и умеете писать простейшие скетчи. Итак, для начала нам нужно подключить необходимые библиотеки SPI.h и Ethernet.h для управления шиной и собственно Ethernet модулем.
#include <SPI.h>
#include <Ethernet.h>
Затем нужно задать сетевые настройки для Ethernet модуля и модуля Laurent, которым мы будем управлять. Обратите внимание, что MAC адреса и IP адреса должны быть уникальны, а LAURENT_PORT должен иметь значение 2424 и никакое другое.
byte SELF_MAC[] = {0x00, 0x2A, 0xF5, 0x12, 0x67, 0xEE};
byte SELF_IP[] = {192, 168, 2, 20};
byte LAURENT_IP[] = {192, 168, 2, 19};
int LAURENT_PORT = 2424;
Нам ещё понадобится буфер для хранения сетевых команд, он выбран размером 200 байт с некоторым запасом, если у вас есть проблемы с нехваткой оперативной памяти, то вы можете его сократить, например, до 100 байт или даже меньше.
char buf[200];
И последний штрих, это Ethernet клиент для модуля Laurent. Теперь все операции с модулем мы будем проводить с использованием объекта lclient.
EthernetClient lclient;
Всё, теперь давайте рассмотрим функцию, посылающую команды модулю Laurent.
void sendLaurentRequest() {
if (lclient.connect(LAURENT_IP, LAURENT_PORT)) {
Serial.print("Command: ");
Serial.println(buf);
lclient.println(buf);
delay(100);
Serial.print("Answer: ");
while(lclient.available() != 0) {
char c = lclient.read();
Serial.print(c);
}
delay(500);
lclient.stop();
} else {
Serial.println("Error sending command");
}
}
Если установлено соединение с модулем Laurent на 2424 порту, то содержимое буфера посылается модулю и дублируется в Serial для визуального контроля. Затем ожидается 100 миллисекунд и принимается ответ модуля. После этого опять пауза и связь с модулем разрывается. Если соединения с модулем по какой-либо причине установить не удалось, то выводится сообщение об ошибке.
Теперь разберём инициализацию. Инициализация Ethernet производится простой функцией
void ethernetInit() {
Ethernet.begin(SELF_MAC, SELF_IP);
}
А инициализация модуля Laurent производится функцией laurentInit(), работу которой мы сейчас подробно разберём. Она довольно большая и вам нужно хорошенько в ней разобраться потому, что именно на основе кода этой функции вы сможете строить свои собственные запросы к модулям Laurent.
void laurentInit() {
Serial.println("Start modul Laurent Init...");
Serial.print("Connect to Laurent... ");
if (lclient.connect(LAURENT_IP, LAURENT_PORT)) {
Serial.println("OK");
lclient.stop();
// Send test command
Serial.println("Selftest...");
sprintf(buf, "$KE");
sendLaurentRequest();
// Send password (default: "Laurent")
Serial.println("Set password...");
sprintf(buf, "$KE,PSW,SET,Laurent");
sendLaurentRequest();
} else {
Serial.println("failed");
}
delay(500);
// останавливаем выдачу DATA
sprintf(buf, "$KE,DAT,OFF");
sendLaurentRequest();
delay(100);
// выключаем реле
sprintf(buf, "$KE,REL,2,0");
sendLaurentRequest();
Serial.println("Modul Laurent Init done");
}
Вначале выводится сообщение об инициализации и производится попытка соединиться с модулем Laurent. Если это не удаётся, то выводится сообщение об ошибке, а если соединиться с модулем происходит успешно, то посылается команда на самодиагностику, на которую исправный модуль должен ответить «#OK».
Далее посылается команда на ввод пароля (в данном случае это пароль по умолчанию). И ожидается 500 миллисекунд.
Далее вводятся две дополнительные команды — одна из них останавливает выдачу данных модулем (если она идёт), а вторая выключает реле №2, которое мы используем в своих экспериментах. Другими словами, эти команды приводят модуль в некое начальное состояние.
Вот распечатка процесса инициализации на которой видны все команды и все ответы модуля:
Start modul Laurent Init...
Connect to Laurent... OK
Selftest...
Command: $KE
Answer: #OK
Set password...
Command: $KE,PSW,SET,Laurent
Answer: #PSW,SET,OK
Command: $KE,DAT,OFF
Answer: #DAT,OK
Command: $KE,REL,2,0
Answer: #REL,OK
Modul Laurent Init done
Теперь код стандартной функции setup(). Инициализируются все подсистемы, в том числе последовательный порт на стандартной скорости обмена 9600.
void setup() {
Serial.begin(9600);
ethernetInit();
laurentInit();
}
Итак, мы инициализировали модуль и можем управлять им так, как нам нужно: посылать команды, читать ответы, строить логику управления с учётом выдаваемых модулем Laurent данных.
Рассмотрим, для примера, простейшую задачу — зажигать и гасить через равные промежутки времени свет лампы, подключённой ко второму реле модуля Laurent.
void loop() {
// включаем реле
sprintf(buf, "$KE,REL,2,1");
sendLaurentRequest();
delay(3000);
// выключаем реле
sprintf(buf, "$KE,REL,2,0");
sendLaurentRequest();
delay(3000);
}
Функция loop() это бесконечный цикл и лампа, повинуясь нашим командам, будет беспрерывно зажигаться и гаснуть через каждые 3 секунды. Это, естественно, просто пример, на самом деле логика работы может быть любой и тут всё зависит от ваших потребностей. И конечно, посылать можно не только команды на включение или отключение нагрузок, но и любые другие, поддерживаемые модулем. С полным перечнем команд и их описанием вы можете ознакомиться в документации к модулям Laurent.
Вы можете взять этот скетч и интегрировать его в собственные проекты, таким образом добавив в них поддержку управления модулями Лоран. Или наоборот, взять за основу этот скетч и постепенно наращивать его функциональность. Предела для совершенства нет. Вот полный текст скетча.
byte SELF_MAC[] = {0x00, 0x2A, 0xF5, 0x12, 0x67, 0xEE};
byte SELF_IP[] = {192, 168, 2, 20};
byte LAURENT_IP[] = {192, 168, 2, 19};
int LAURENT_PORT = 2424;
char buf[200];
EthernetClient lclient;
void ethernetInit() {
Ethernet.begin(SELF_MAC, SELF_IP);
}
void laurentInit() {
Serial.println(«Start modul Laurent Init...»);
Serial.print(«Connect to Laurent… „);
if (lclient.connect(LAURENT_IP, LAURENT_PORT)) {
Serial.println(“OK»);
lclient.stop();
// Send test command
Serial.println(«Selftest...»);
sprintf(buf, "$KE");
sendLaurentRequest();
// Send password (default: «Laurent»)
Serial.println(«Set password...»);
sprintf(buf, "$KE,PSW,SET,Laurent");
sendLaurentRequest();
} else {
Serial.println(«failed»);
}
delay(500);
// останавливаем выдачу DATA
sprintf(buf, "$KE,DAT,OFF");
sendLaurentRequest();
delay(100);
// выключаем реле
sprintf(buf, "$KE,REL,2,0");
sendLaurentRequest();
Serial.println(«Modul Laurent Init done»);
} // laurentInit
void sendLaurentRequest() {
if (lclient.connect(LAURENT_IP, LAURENT_PORT)) {
Serial.print(«Command: „);
Serial.println(buf);
lclient.println(buf);
delay(100);
Serial.print(“Answer: „);
while(lclient.available() != 0) {
char c = lclient.read();
Serial.print©;
}
delay(500);
lclient.stop();
} else {
Serial.println(“Error sending command»);
}
} // sendLaurentRequest
void setup() {
Serial.begin(9600);
ethernetInit();
laurentInit();
}
void loop() {
// включаем реле
sprintf(buf, "$KE,REL,2,1");
sendLaurentRequest();
delay(3000);
// выключаем реле
sprintf(buf, "$KE,REL,2,0");
sendLaurentRequest();
delay(3000);
}
Arduino Mega Server [4] (AMS) это мощная система для Arduino Mega (теперь уже и для Arduino DUE и, вскоре, для других 32-битных платформ M0 (Zero) и Genuino 101), которая содержит код «на все случаи жизни» и плюс ещё встроенный сервер и удобный веб-интерфейс. AMS поддерживает модули Laurent прямо «из коробки» и вам ничего не нужно добавлять, кроме пользовательской логики.
AMS имеет модульную структуру и включение и отключение модулей производится простым комментированием строки в скетче, например,
#define LAURENT_FEATURE
или
//#define LAURENT_FEATURE
Если строка закомментирована, то модуль не компилируется и не участвует в работе, что видно на индикаторах модулей в шапке сайта. Или наоборот, откомпилированный и работающий модуль индицируется синим цветом. В данном случае модуль управления «Лоранами» LRT не работает.
Индикаторы работы модулей
Теперь давайте добавим возможность не просто показывать ответы модуля, но и работать с ними, например, анализировать их или выводить на веб-странички Arduino Mega Server. Для этого нам понадобится новая строковая переменная и константа, которая определяет длину строки, которую мы отводим под ответы модулей Laurent. В тестовом примере она равна 25 символам, но вы можете её увеличить, если ответы не будут умещаться в это значение. Нужно только помнить, что оперативная память микроконтроллера это ценный ресурс и её нужно экономить. Добавляем такие строки в стандартный модуль laurent.ino из поставки AMS:
byte MAX_LEN_LREQUEST = 25;
String lrequest = String(MAX_LEN_LREQUEST);
Нам также нужно изменить код функции, которая осуществляет запросы (добавленные изменения выделены стрелками).
void sendLaurentRequest() {
if (lclient.connect(LAURENT_IP, LAURENT_PORT)) {
Serialprint("Command: ");
Serial.println(buf);
lclient.println(buf);
delay(100);
Serialprint("Answer: ");
// -------------------->
lrequest = "";
// -------------------->
while(lclient.available() != 0) {
char c = lclient.read();
Serial.print(c);
// -------------------->
if (lrequest.length() < MAX_LEN_LREQUEST) {
lrequest += (c);
}
// -------------------->
}
delay(500);
lclient.stop();
} else {
Serialprint("Error sending commandn");
}
}
Таким образом, мы научились получать ответы Лоранов в переменную lrequest и теперь можем делать с ней всё, что посчитаем нужным. Дальше я покажу, как вывести результаты запросов прямо в dash-панель в шапке сайта AMS.
Небольшое примечание. В этом примере используется функция Serialprint вместо стандартной Serial.print потому, что она более экономно расходует оперативную память. И её легко можно переделать в стандартную, просто поставив точку между двумя словами.
И последний пример. Давайте выведем ответы модулей Лоран в шапку сайта Arduino Mega Server. Для этого нам нужно добавить запрос в главный цикл loop() скетча AMS. Открываем файл arduino_mega_server.ino и перед функцией cyclosInSecWork() вводим такой код:
#ifdef LAURENT_FEATURE
if (cycle30s) {
sprintf(buf, "$KE");
sendLaurentRequest();
}
#endif
Этот код будет каждые тридцать секунд запрашивать состояние здоровья модуля Laurent. Естественно, это только пример, на этом месте может быть любой запрос и любой код. Таким образом, в переменной lrequest мы имеем ответ о состоянии модуля и можем теперь вывести его в шапку сайта. Для этого открываем модуль server_ajax.ino и в самом конце, в коде функции responseDash(EthernetClient cl), перед строкой cl.println(""); добавляем такой код:
#ifdef LAURENT_FEATURE
sendTagString("laurent", "", lrequest, cl);
#endif
Этот код, собственно, и посылает ответы модуля на веб-страничку. Осталось сделать две вещи: первая — добавить код на языке JavaScript, который будет «ловить» наши данные и вторая — код HTML на самой страничке AMS, где и будут выводиться ответы модуля.
Итак, открываем файл scripts.js и в функции getDashData() перед закрывающей скобкой } //if (this.responseXML != null) вводим код, который будет принимать наши посылки.
// Laurent
try {
var laurent = this.responseXML.getElementsByTagName('laurent')[0].childNodes[0].nodeValue;
} catch (err) {
laurent = "-";
}
document.getElementById("laurent").innerHTML = laurent;
Осталось только немного поправить файл dash.htm из стандартной поставки AMS и добавить в него код, который будет выводить информацию на экран. Сразу после строки, содержащей class=«online-device» вводим нашу новую строку с кодом:
<p>Laurent: <span class="value" id="laurent">...</span></p>
Вот и всё. Мы вывели ответы модуля Laurent в шапку сайта Arduino Mega Server. И вот результат наших стараний. Состояние модуля наглядно видно в панели AMS и оно обновляется каждые 30 секунд, так что, если с модулем что-то случится, то вы узнаете об этом максимум через 30 секунд.
Как видите, в управлении модулями Лоран при помощи Ардуино и Arduino Mega Server нет ничего сложного и если у вас уже есть такие модули или вы планируете добавить их в свою систему Умного дома, то эта статья поможет вам сделать это легко и просто.
А в следующей статье из цикла вы узнаете как управлять «Лоранами» прямо с экрана своего компьютера и как сделать процесс обучения детей программированию интерактивным и более интересным.
Автор: smart_alex
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/diy/104606
Ссылки в тексте:
[1] KernelChip: http://www.kernelchip.ru/
[2] первой части: http://geektimes.ru/post/262892/
[3] Arduino Mega Server: http://geektimes.ru/post/259248/
[4] Arduino Mega Server: http://geektimes.ru/post/264360/
[5] Источник: http://geektimes.ru/post/266454/
Нажмите здесь для печати.