[Из песочницы] Noolite MTRF-32 + Arduino + Domoticz
В данной статье я описываю подключение модуля Noolite MTRF-32 к своей системе управления умным домом на базе Domoticz.
Немного о самом доме
Дом у меня частный. В нем уже внедрены некоторые зачатки умного дома на основе Domoticz и беспроводные исполнительные устройства на MySensors.
На данный момент реализованы датчики открытия дверей, включение придомового освещения, датчики температуры и влажности дома и на улице, голосовое информирование о событиях и прогнозе погоды.
Дом деревянный, поэтому управлять освещением замыканием релюшек из китая не очень хотелось. Тянуть провода где попало тоже не вариант. После долгих раздумий управление светом сделал на силовых блоках и пультах noolite и оставалось как-то подружить это с Domoticz.
В этот момент на глаза попалась статья про модуль MTRF-32 от Noolite. Domoticz поддерживает отправку HTTP GET запросов. Перспектива использования модулей с обратной связью так же манила, поэтому модуль был заказан.
О том что нужно 7 раз отмерить прежде чем отрезать
Как оказалось купил я не совсем то что нужно. На момент покупки был доступен один модуль MTRF-32. Да и читая статью я не увидел информацию о разновидностях этих модулей. В общем мне нужен был USB вариант MTRF-32-USB.
32 означает возможность управления по 32-м каналам. На сегодняшний день на сайте noolite доступен модуль с 64 каналами, причем оба варианта как с USB так и без. Вопрос к читателям MTRF-32 как-то можно обновить до MTRF-64?
Что сделано, то сделано. Платка была отложена до того как кто-нибудь не выложит готовую библиотеку лучших времен.
Почему-то лучшие времена не настали. Хотя я думал что система популярная.
Первая попытка
Походив по сайту Noolite нашел ПО NooliteOne для работы с MTRF-64-USB. Оказалось что оно работает через com-порт и я понял что MTRF-64 отличается от MTRF-64-USB встроенным USB-COM адаптером. В комплекте с ПО были драйвера от чипа FTDI, а на моей плате была контактная подходящая контактная площадка.
Паять чип я не стал. Но сделал из китайского Arduino Nano с FTDI USB-COM адаптер и подключил к плате.
Не взлетело. По какой-то причине NooliteOne не находил мой адаптер. Я уже начал смотреть в сторону де компиляции, когда обнаружил библиотеку для модуля MT1132.
Вторая попытка
Я сравнил описание модулей и понял, что в части передачи данных они почти не отличаются. Реализованный в библиотеке для MT1132 функционал мне был достаточен (Обратная связь пока не нужна — нет подходящих силовых блоков).
Подправив код в библиотеке, я начал получать ответы от MTRF-32. Как ни странно все заработало с первого раза. И вот что в итоге получилось:
Исходный код
#ifndef ARDUNOO_H
#define ARDUNOO_H
#if defined (ARDUINO) && ARDUINO >= 100
#include «Arduino.h»
#else
#include «WProgram.h»
#endif
#include
class ArduNoo {
byte chnl;
SoftwareSerial ns;
public:
ArduNoo (byte rx, byte tx, byte ch=0);
void on (byte ch=-1);
void off (byte ch=-1);
void onoff (byte ch=-1);
void bind (byte ch=-1);
void unbind (byte ch=-1);
bool command (byte channel, byte command);
};
#endif
ArduNoo: ArduNoo (byte rx, byte tx, byte ch): ns (rx, tx){
chnl=ch;
ns.begin (9600);
}
void ArduNoo: off (byte ch){
command (ch, 0);
}
void ArduNoo: on (byte ch){
command (ch, 2);
}
void ArduNoo: onoff (byte ch){
command (ch, 4);
}
void ArduNoo: unbind (byte ch){
command (ch, 9);
}
void ArduNoo: bind (byte ch){
command (ch, 15);
}
bool ArduNoo: command (byte chnl, byte command){
static byte i, r, buf[17]={171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,172};
int sum = 0;
memset (buf+2,0,14); /* clear message body */
buf[4] = chnl;
buf[5] = command;
for (i = 0; i<15; ++i) {//10
sum+= buf[i];
}
buf[15] = lowByte (sum);//10
buf[16] = 172;//11
for (i=0; i<17; ++i){
ns.write (buf[i]);
}
//debug code
for (i=0; i<17;++i){
while (! ns.available ()) delay (10);
r=ns.read ();
Serial.print®;
}
Serial.println ();
return true;
}
#include
#define RXpin 10
#define TXpin 11
ArduNoo noo (RXpin, TXpin);
String readString, chString;
void setup () {
Serial.begin (9600);
}
void loop () {
readString = »;
chString = »;
while (Serial.available ()) {
delay (3); //delay to allow buffer to fill
if (Serial.available () > 0) {
char c = Serial.read (); //gets one byte from serial buffer
readString += c; //makes the string readString
}
}
if (readString.length () > 1 && readString.length () < 4) { //we expect 1 letter and 1 or 2 digits (ch = 0-31)
for (int i = 1; i < readString.length(); i++) {
if (isDigit (readString[i])) {
chString.concat (readString[i]);
}
}
//Serial.println (readString[0]);
int ch = chString.toInt ();
switch (readString[0]) {
case 'n': //on
noo.on (ch);
break;
case 'f': //off
noo.off (ch);
break;
case 'x': // toggle
noo.onoff (ch);
break;
case 'b': //bind
noo.bind (ch);
break;
case 'u': //unbind
noo.unbind (ch);
break;
case 'y': //on all channels
for (int i = 0; i < 32; i++) {
noo.on (i);
delay (100);
}
break;
case 'z': //off all channels
for (int i = 0; i < 32; i++) {
noo.off (i);
delay (100);
}
break;
}
}
}
Copyright © 2014 Zhumatiy Sergey
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the «Software»), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED «AS IS», WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Реализованы команды выключить, включить, переключить, включить все, выключить все.
Дело за малым, нужно отдавать в com порт команды. Поскольку из Domoticz на Windows это проблематично, решил написать консольное приложение которое будет транслировать команды из lua скрипта. Команды передаются в приложение в виде параметров запуска.
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
namespace noo
{
class Program
{
static void Main (string[] args)
{
if (args.Length == 2)
{
SerialPort COM = new SerialPort (args[0]);
COM.Open ();
COM.WriteLine (args[1]);
COM.Close ();
}
}
}
}
Пример команды:
noo.exe com5 n4 — включить свет на 4 канале, передается на плату Arduino на порту COM5. Возможные значения второго параметра запуска:
- nX — включить канал X
- fX — выключить канал X
- xX — переключить канал X
- bX — привязать силовой блок к каналу X
- uX — отвязать силовой блок от канала X
- yX — включить все каналы, X любое значение
- zX — выключить все каналы, X любое значение
local sensor1 = 'SWHallWay'
local sensor2 = 'SWHall'
local sensor3 = 'SWKitchen'
local sensor4 = 'SWBedroom'
local sensor5 = 'BTNLiteOff'
commandArray = {}
if (devicechanged[sensor1] == 'On') then
os.execute («c:\\PROGRA~1\\Domoticz\\scripts\\noo.exe com4 n3»)
end
if (devicechanged[sensor1] == 'Off') then
os.execute («c:\\PROGRA~1\\Domoticz\\scripts\\noo.exe com4 f3»)
end
if (devicechanged[sensor2] == 'On') then
os.execute («c:\\PROGRA~1\\Domoticz\\scripts\\noo.exe com4 n0»)
end
if (devicechanged[sensor2] == 'Off') then
os.execute («c:\\PROGRA~1\\Domoticz\\scripts\\noo.exe com4 f0»)
end
if (devicechanged[sensor3] == 'On') then
os.execute («c:\\PROGRA~1\\Domoticz\\scripts\\noo.exe com4 n1»)
end
if (devicechanged[sensor3] == 'Off') then
os.execute («c:\\PROGRA~1\\Domoticz\\scripts\\noo.exe com4 f1»)
end
if (devicechanged[sensor4] == 'On') then
os.execute («c:\\PROGRA~1\\Domoticz\\scripts\\noo.exe com4 n2»)
end
if (devicechanged[sensor4] == 'Off') then
os.execute («c:\\PROGRA~1\\Domoticz\\scripts\\noo.exe com4 f2»)
end
if (devicechanged[sensor5] == 'Off') then
os.execute («c:\\PROGRA~1\\Domoticz\\scripts\\noo.exe com4 z9»)
end
return commandArray
Короткое видео