Как стать автором
Обновить

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

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

image

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


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

Железо


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

image
Ethernet Shield на основе чипа W5100

То есть вам остаётся только взять скетч и залить его на свою плату Uno или Mega, предварительно немного изменив его под свои задачи.

Управляем модулями из скетчей


В первой части цикла я уже рассказывал о принципах управления модулями Laurent по сети, для тех, кто не читал первую часть, кратко повторю здесь теорию.

Обмен информацией с модулями осуществляется по сети и для начала работы с ними нужно установить TCP/IP соединение на 2424 порту. Как только соединение установлено, можно посылать текстовые команды (т. н. КЕ команды) которые и управляют модулем. На сайте компании KernelChip есть подробная документация и, в том числе, доступное описание КЕ команд.

Теперь давайте попробуем перевести это теоретическое «техзадание» на простой язык скетчей Ардуино.

Скетч


Я здесь не буду объяснять, как установить и настроить среду программирования Ардуино, предполагается, что вы уже это сделали и умеете писать простейшие скетчи. Итак, для начала нам нужно подключить необходимые библиотеки 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 (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 command\n");
    }
}

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

А в следующей статье из цикла вы узнаете как управлять «Лоранами» прямо с экрана своего компьютера и как сделать процесс обучения детей программированию интерактивным и более интересным.

Дополнение. Открыт канал на Youtube и вот промо ролик Arduino Mega Server, который демонстрирует работу с реальной системой.
Теги:
Хабы:
+8
Комментарии 0
Комментарии Комментировать

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн