- PVSM.RU - https://www.pvsm.ru -

Модули Laurent и Умный дом (часть 2). Arduino и AMS

Это вторая статья из цикла о интеграции модулей Laurent (Лоран) компании KernelChip [1] в системы домашней автоматизации и в этой части речь пойдёт об интеграции этих модулей с экосистемой Ардуино. В первой части [2] цикла речь шла об интеграции с популярной системой домашней автоматизации MajorDoMo, а в третьей части вы узнаете как управлять этими модулями из скетчей на языке программирования Processing, прямо с рабочего стола вашего компьютера.

image

Ардуино наше всё

Куда же без Ардуино? Не буду здесь долго расписывать достоинства этой платформы, её популярность говорит сама за себя, поэтому давайте сразу приступим к техническим деталям реализации взаимодействия Ардуино и модулей Лоран. И по пути не забудем систему Arduino Mega Server [3], как очень интересное производное от экосистемы Arduino.

Железо

Для управления модулями по сети подойдёт, например, распространённая плата Arduino Uno или не менее популярная плата Arduino Mega в комплекте с платой сетевого интерфейса Ethernet Shield, собранной на основе чипа W5100. Все примеры в этой статье даются для такого сочетания и были протестированы на практике. Всё работает надёжно и без каких-либо проблем.

image
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.

Вы можете взять этот скетч и интегрировать его в собственные проекты, таким образом добавив в них поддержку управления модулями Лоран. Или наоборот, взять за основу этот скетч и постепенно наращивать его функциональность. Предела для совершенства нет. Вот полный текст скетча.

Полный код скетча

#include <SPI.h>
#include <Ethernet.h>

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

image

Arduino Mega Server [4] (AMS) это мощная система для Arduino Mega (теперь уже и для Arduino DUE и, вскоре, для других 32-битных платформ M0 (Zero) и Genuino 101), которая содержит код «на все случаи жизни» и плюс ещё встроенный сервер и удобный веб-интерфейс. AMS поддерживает модули Laurent прямо «из коробки» и вам ничего не нужно добавлять, кроме пользовательской логики.

AMS имеет модульную структуру и включение и отключение модулей производится простым комментированием строки в скетче, например,

#define LAURENT_FEATURE

или

//#define LAURENT_FEATURE

Если строка закомментирована, то модуль не компилируется и не участвует в работе, что видно на индикаторах модулей в шапке сайта. Или наоборот, откомпилированный и работающий модуль индицируется синим цветом. В данном случае модуль управления «Лоранами» LRT не работает.

image
Индикаторы работы модулей

Работа с ответами модуля Laurent

Теперь давайте добавим возможность не просто показывать ответы модуля, но и работать с ними, например, анализировать их или выводить на веб-странички 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 секунд.

image

Заключение

Как видите, в управлении модулями Лоран при помощи Ардуино и 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/