После общего знакомства с nooLite, начнем изучение вопросов неглупого освещения жилища от nooLite с модуля МТ1132. Этот модуль подключается к управляющему устройству через UART и принимает от него 12 байт. Если команда составлена правильно, на модуле загорается красный диод и команда транслируется на силовой блок, иначе ничего не происходит. (Производитель мог бы добавить мааааленький диодик на канал RX модуля, дабы неопытный пользователь понимал, что электрическая часть соединения исправно работает, а вот программистские навыки еще требуют совершенствования. Без диодика не всегда ясно, доходит ли сигнал до модуля в принципе, или нет. Хорошо, если под рукой есть осциллограф etc., а если — нет?)
Что же должен принять от управляющего устройства модуль? Ниже — картинка, где показана структура команды. Эта картинка несколько упрощена, но достаточна для работы с модулем, исключая случаи, когда он будет управлять трехцветной светодиодной лентой.
Сразу ухватить картинку удается не всегда, поэтому несколько пояснений.
Перечислим команды для ячейки 6:
0 — выключить нагрузку
1 — запустить плавное понижение яркости
2 — включить нагрузку
3 — запустить плавное повышение яркости
4 — включить или выключить нагрузку
5 — запустить плавное изменение яркости в обратном направлении
6 — установить заданную в «Байт данных 0» яркость
7 — вызвать записанный сценарий
8 — записать сценарий
9 — отвязка
10 — остановить регулировку
15 — привязка
Поскольку модуль может отправлять команды на 32 силовых блока, он обязательно должен получить номер канала (0-31). Это элемент [5].
На силовой блок в элементе [2] будет отправлена одна из возможных команд.
Если это команда 6 (установить яркость), то в элемент [3] нужно записать единицу, а в элемент [6] — значение яркости. Значение это ни в процентах, ни в привычных байтах, а просто, значение из ряда 35 — 155. Казалось бы, что мешало производителю привести эти значения к привычной амплитуде: 0 — 100, или 0 -255… Да, странно.
Но, оказывается, из этого можно извлечь некоторую пользу. Возможно, прозорливый производитель и надеялся на нашу сообразительность. Итак, заметим, что значение команд и значение яркости не пересекаются! Следовательно, программным путем мы можем оперировать только двумя данными: номером канала и командой/яркостью.
Поясню. Если команды в диапазоне 0 — 15, то значение ячеек [3] и [6] — ноль. А если мы отправим команду, например, 75, то автоматически ячейку [3] можно установить в единицу, а [2] — в 6. Позже мы напишем функцию, которая все это будет делать.
Элемент [10] представляет собой контрольную сумму. Все предыдущие элементы необходимо сложить, а потом взять лишь младший байт от сложения. В примере на сайте Ноотехники это делается так:
int checkSum = 0;
for(byte i = 0; i < 10; i++) {
checkSum+= buf[i];
}
buf[10] = lowByte(checkSum);
Но следует заметить, что в обычном С нет функции lowByte(); поэтому правильно будет использовать следующую конструкцию:
buf[10] = checkSum & 0xFF;
Теперь разберемся с командами, то есть содержанием элемента [2].
0 — выключить нагрузку.
1 — запустить плавное понижение яркости, от текущего до выключения.
2 — включить нагрузку полностью.
3 — запустить плавное повышение яркости до максимума.
4 — включить или выключить нагрузку. Посылая одну единственную эту команду мы то включаем то выключаем силовой блок, в зависимости от предыдущего состояния.
5 — запустить плавное изменение яркости в обратном направлении. Эта команда плавно включает или выключает силовой блок, меняет его текущее состояние.
6 — установить заданную яркость.
9 — запустить процедуру стирания адреса (отвязать модуль от силового блока).
15 — привязка к силовому блоку.
Теперь напишем функцию, которая принимала бы два аргумента, и посылала на силовой блок правильную команду. За основу был взят пример с сайта Ноотехники.
void sendCommand(uint8_t channel, uint8_t command) {
/*
Мы не будем проверять command на допустимость.
В данном случае command должно принимать значение
от 0 до 10, 15, 32 - 155.
Значение channel должно быть от 0 до 31.
Если по каким-то причинам Вы не уверены в том, что
эти аргументы могут не соответствовать требованиям,
следует проверить их и осуществить возврат из функции
до передачи команды MT1132.
*/
// Создаем массив из 12 элементов
uint8_t buf[12];
// Сначала заполняем массив понятными значениями
buf[0] = 85;
buf[1] = 80;
buf[4] = 0;
buf[5] = channel;
buf[7] = 0;
buf[8] = 0;
buf[9] = 0;
buf[11] = 170;
// Если команда от 15 и меньше - это любая команда кроме управления яркостью
// 6, отправлять не рекомендуется, но и в этом случае ничего страшного не произойдет
if (command < 16) {
buf[2] = command;
// В этом случае требуется обнуление элементов [3] и [6]
buf[3] = 0;
buf[6] = 0;
}
// Если команда от 32 до 155 - это управление яркостью
else {
// Значит настоящая команда - 6
buf[2] = 6;
// Элемент [3] требует установки в 1
buf[3] = 1;
// А в элемент [6] передаем значение яркости.
buf[6] = command;
}
// Вычисляем контрольную сумму
int checkSum = 0;
// Складываем первые 10 элементов
for(uint8_t i = 0; i < 10; i++) {
checkSum+= buf[i];
}
// Оставляем от сложения младший байт
buf[10] = checkSum & 0xFF;
// Отправляем команду в UART
for(uint8_t i=0;i<(12);i++)
{
mySerial.write(buf[i]);
}
}
Таким образом, вызывая из программы эту функцию с аргументами 3,15 — мы можем привязать силовой блок к модулю, а каждая посылка аргументов 3,3 будет плавно включать или выключать его. Если же мы вызовем функцию с аргументами 3, 45 — мы лишь слегка включим нагрузку.
О практической реализации — в следующей заметке. А пока — как это работает:
Устраивает? Читаем дальше.