«Вот бы можно было удаленно включить кондишн…» — подумал я.
Итак, у меня имеется сплит-система Panasonic CS-XE9DKE. Идея управлять кондиционером сводилась к созданию «своего» ИК-пульта. Назовем его «ИК-контроллер». А уж управлять самим контроллером — это задача десятая. И это зависит от конкретного места применения. Мне, например, было бы удобнее управлять с домашнего сервера через WizFi200(только вот достать его за приемлемые деньги проблематично). Моим родителям — с помощью отправки SMS(на SIM900) на номер контроллера. Возможны и другие варианты. Но это не главное, о чем я хотел рассказать.
Реверс-инжиниринг
Так как же родной пульт передает команду? Имея в наличии ИК-приемник TSOP17XX я начал анализировать поток данных от пульта. Выяснилось, что пульт шлет 2 посылки с небольшой паузой. Первая — заголовок, вторая — команда. Заголовок был всегда одинаковый.
Ознакомившись с существующими системами кодирования ИК-сигналов(RC5, RC6, NEC, JVC и другие) стало ясно, что здесь применяется что-то другое, хотя принцип схож.
Сингал выглядит следующим образом:
(активный уровень — низкий)
(значения бит для примера, время в мкс приблизительно)
В начале идет пилотный сигнал, за ним примерно вдвое короче второй пилотный(пауза), за ним стартовый бит длительностью примерно в 8 раз короче чем первый пилотный. Далее начинается битовый поток. Один бит кодируется длительностью паузы(высокий уровень). Если пауза одинарная — это НОЛЬ, если пауза тройная — это ЕДИНИЦА.
Всего при одном нажатии кнопки пульт шлет 2 таких посылки. Первая — заголовок, вторая — команда. Пауза между посылками около 10 мс.
Таким образом заголовок содержит 64 бита, или 8 байт. Сначала идут младшие биты.
Поток данных заголовка выглядит следующим образом:
0100000000000100000001110010000000000000000000000000000001100000
Или в байтах(HEX): 02 20 E0 40 00 00 00 06
Следует заметить, что последний байт является контрольной суммой всех предыдущих.
Теперь немного отвлечемся на сам пульт. Пульт имеет следующие кнопки:
- ON/OFF(включение/выключение)
- ± (настройка температуры)
- O2 (генератор кислорода)
- ion (ионизатор)
- quiet (тихий режим)
- mode ( auto, heat, cool, dry, fan)
- fan speed
- swing <>(горизонтальное направление)
- swing ^v (вертикальное направление)
Также есть кнопки для установки текущего времени, таймеров включения и выключения(раздельно, самостоятельно).
3 кнопки, которые отличаются от других, это:
- ion
- quiet
- O2
Смысл в том, что эти кнопки не посылают все настройки, а включают/выключают конкретный режим. Т.е. Эти 3 режима можно включать/выключать в любом состоянии кондиционера.
Теперь вернемся к протоколу передачи. Любой команде предшествует заголовок.
Байты заголовка: 02 20 E0 40 00 00 00 06
Далее идет вторая посылка с командой.
Команды трех особых кнопок:
ion: 02 20 E0 04 80 48 33 01
oxyg: 02 20 E0 04 80 50 33 09
quiet: 02 20 E0 04 80 81 33 3A
Отмечу, что, как и в заголовке, последний байт — контрольная сумма.
А вот все остальные кнопки посылают пакет со всеми настройками сразу. И формат этого пакета следующий:
Поток бит:
0100000000000100000001110010000000000000PNF1mmm00ccccc0000000001vvvvFFFF
hhhh0000nnnnnnnnnnn0fffffffffff0000010000000000010000000ttttttttttt00000ssssssss
Расшифровка полей по порядку следования:
P — 1, если нажата кнопка ON/OFF. При нажатии других кнопок здесь 0.
N — 1, если установлен таймер включения
F — 1, если установлен таймер выключения
mmm — режим(Mode). Auto — 0, heat — 4, cool — 3, dry — 2, fan — 6
ccccc — температура. От 16 до 30
vvvv — вертикальное направление. Auto — 15, 1 — под потолок, … 5 — в пол.
FFFF — скорость вентилятора. Auto — 10, F1 — 3, F2 — 4, F3 — 5, F4 — 6, F5 — 7
hhhh — горизонтальное направление. Auto — 13, | | — 6, / / — 9, / | — 10, | \ — 11, \ \ — 12
nnnnnnnnnnn — время включения. Номер минуты в сутках. (например 16:00 = 960)
fffffffffff — время выключения. Номер минуты в сутках.
ttttttttttt — текущее время.
ssssssss — контрольная сумма посылки.
Если таймер включения не установлен, то время включения д.б. 1536 = 0x600 = 0b11000000000. С временем таймера выключения аналогично. По крайней мере так шлет родной пульт.
Разделим поток бит на байты и развернем биты:
00000010 02 00100000 20 11100000 E0 00000100 04 00000000 00 0mmm1FNP Mode<<4 + 8 + FlagOFF<<2 + FlagON<<1 + Power 00ccccc0 Temperature<<1 10000000 80 FFFFvvvv Fan<<4 + Vert 0000hhhh Horiz nnnnnnnn OnTime%0xFF ffff0nnn OnTime>>8 + OffTime%0x0F 0fffffff OffTime>>4 00010000 10 00000000 00 00000001 01 tttttttt Time%0xFF 00000ttt Time>>8 ssssssss Sum
Итого команда 19 байт.
Контроллер
Для тестирования я собрал схему(позаимствовал здесь) на макетке для беспаечного монтажа. Компоненты:
- atmega8
- ИК-диод
- транзистор кт361
- резистор 470 на базу транзистора
- резистор 220 ограничивает ток диода
- резистор 10к на RESET
Отличие моей схемы от схемы по ссылке — светодиод подключен к PB1, а база транзистора к PB3.
При отпускании кнопки на порту PD7 запускается таймер 1 в режиме CTC с выводом сигнала на PB1/OC1A, а так же таймер 2 с выводом на PB3/OC2 для несущей частоты, на которой и модулируется основной сигнал. Таймеры работают с предделителем 8.
Прошивка
#include <avr/io.h> #include <avr/interrupt.h> #define F_CPU 8000000 #define LED_CARIER DDB3 #define LED_SIGNAL DDB1 #define BASE 480 #define PAUSE 10000 #define START_1 BASE*8 #define START_2 BASE*4 #define DELIM 520 #define PULSE1 BASE*3 #define PULSE0 BASE unsigned char state = 0; unsigned char byteIndex = 0; unsigned char frameIndex = 0; unsigned char bit = 0; unsigned char phase = 0; unsigned char packetLen = 0; unsigned char process = 0; char header[] = {0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06}; char cmd_ion[] = {0x02, 0x20, 0xE0, 0x04, 0x80, 0x48, 0x33, 0x01}; char cmd_oxygen[] = {0x02, 0x20, 0xE0, 0x04, 0x80, 0x50, 0x33, 0x09}; char cmd_quiet[] = {0x02, 0x20, 0xE0, 0x04, 0x80, 0x81, 0x33, 0x3A}; char* data; char* cmd; unsigned char cmdLen; void stop(); ISR(SIG_OUTPUT_COMPARE1A) { switch (state) { case 0: OCR1AH = START_2 / 256; OCR1AL = START_2 % 256; state = 1; break; case 1: OCR1AH = DELIM / 256; OCR1AL = DELIM % 256; state = 2; byteIndex = 0; frameIndex++; if (frameIndex == 1) { data = header; packetLen = 8; } else { data = cmd; packetLen = cmdLen; } bit = 0; phase = 0; break; case 2: if (byteIndex < packetLen) { if (phase == 0) { if (data[byteIndex]&(1 << bit)) { OCR1AH = PULSE1 / 256; OCR1AL = PULSE1 % 256; } else { OCR1AH = PULSE0 / 256; OCR1AL = PULSE0 % 256; } } else { OCR1AH = DELIM / 256; OCR1AL = DELIM % 256; bit++; if (bit == 8) { bit = 0; byteIndex++; } } phase = 1 - phase; } else { OCR1AH = PAUSE / 256; OCR1AL = PAUSE % 256; if (frameIndex == 2) { stop(); } else { state = 3; } } break; case 3: OCR1AH = START_1 / 256; OCR1AL = START_1 % 256; state = 0; break; } } void start() { state = 0; byteIndex = 0; frameIndex = 0; packetLen = sizeof (header); TCNT1H = 0; TCNT1L = 0; OCR1AH = START_1 / 256; OCR1AL = START_1 % 256; TCCR1A = (1 << COM1A0); TCCR1B = (1 << WGM12) | (1 << CS11); TCNT2 = 0; OCR2 = 13; TCCR2 = (1 << WGM21) | (1 << COM20) | (1 << CS21); TIMSK = (1 << OCIE1A); sei(); } void stop() { cli(); TCCR2 = (1 << WGM21) | (1 << COM20); TCCR1A = (1 << FOC1A); TCCR1B = (1 << WGM12) | (0 << CS12) | (0 << CS11) | (0 << CS10); TIMSK = 0; PORTB = (1 << LED_SIGNAL) | (1 << LED_CARIER); process = 0; } int main(void) { process = 0; PORTB = (1 << LED_SIGNAL) | (1 << LED_CARIER); DDRB = (1 << LED_SIGNAL) | (1 << LED_CARIER); PORTD = (1 << 7); // PD7 input, pull up DDRD = 0; while (1) { int but = (PIND & (1 << PD7)); if (process == 0 && but == 0) { process = 1; } else if (process == 1 && but != 0) { process = 2; cmd = cmd_oxygen; cmdLen = 8; start(); } } }
Вывод
Текущая тестовая реализация пока умеет слать заголовок и фиксированную команду. Но вот тут у меня возник вопрос — а какая должна быть у этого контроллера глубина реализации? Ведь можно контроллеру сказать «включи охлаждение на 23 градуса», а можно просто сказать «передай команду» и передать весь поток бит с уже сформированной командой. А ведь можно еще и тайминги указать. Тогда можно управлять через один контроллер-излучатель различными устройствами. Надеюсь в комментариях вы мне поможете принять решение.
Планируется также подключение пары датчиков температуры для контроля температуры помещения и выходного потока воздуха из кондиционера. Это удобно для обратной связи(например оповещение по смс с текущими параметрами климата) и контроля(а включился ли кондиционер?).
ссылка на оригинал статьи http://habrahabr.ru/post/189142/
Добавить комментарий