Разборка с кондиционером

Естественно одна из функций умного дома — управление климатом, и кондиционерами в частности. У меня однотипные древние кондиционеры под маркой Zephir, гуглить которую бесполезно, и разумеется никаких smart функций там нет и быть не может, соответственно единственный вариант делать эмуляцию пульта.

Чтобы считать, что же там передает пульт, зацепил к Arduino датчик KY-022, поставил библиотеку irremote и залив банальный пример, получил довольно приличный объем данных, передаваемый от пульта к кондиционеру.

Encoding : SANYO
Code : FFFFFFFF (0 bits)
Timing[97]:
+ 650, -3350 + 650, -3350 + 650, -3350 + 650, -3350
+ 650, -1400 + 600, -3350 + 650, -3350 + 650, -3300
+ 650, -1400 + 600, -1400 + 650, -1400 + 600, -1400
+ 600, -3350 + 650, -1400 + 600, -1400 + 650, -1500
+ 600, -1350 + 650, -3350 + 650, -3350 + 650, -1400
+ 600, -1400 + 600, -1450 + 600, -3350 + 650, -1350
+ 600, -3400 + 600, -1400 + 650, -1400 + 600, -3350
+ 650, -3350 + 650, -3350 + 650, -1400 + 600, -3350
+ 600, -1400 + 650, -3350 + 650, -1400 + 600, -3350
+ 650, -1400 + 600, -3400 + 600, -1400 + 600, -1350
+ 650, -3350 + 650, -1350 + 650, -3350 + 650, -1400
+ 600, -3400 + 600, -1400 + 600, -3400 + 600, -3300
+ 600

Этот результат дал понять, что в реальности Zephir это как минимум по части электроники SANYO, и что даже если затея провалится, на алиэкспресс легко можно будет заказать пульты ZH/LW-03, так как из четырех один сломался и один потерялся.

Второй очевидный момент, который предполагался и ранее, так как настроенный в одной комнате на 25 градусов пульт, кнопкой ВКЛ передавал настройки температуры, заключается в том, что пульт передает не команды в режиме «ВКЛ-ВЫКЛ», «увеличить-уменьшить температуру», а весь пакет настроек, то есть режим работы «обогрев-охлаждение-осушка-автомат», скорость вентиляторов, температуру и т.д. одним пакетом.

Поковыряв исходник и найдя там константу под названием USECPERTICK, наводящую на мысль о том, что цифры в результате это микросекунды (для информации в 1 секунде 1000000 микросекунд).

Очевидно, что китайский пульт, читаемый землячкой ардуиной через датчик, который тоже им земляк, имеет определенную погрешность, и по факту из всего ряда цифр есть +600(650), а так же -1400 и -3400 с погрешностью до 100 микросекунд.

Появилась мысль, что всё, что + это фиксированные разделители данных, а минуса, то есть когда инфракрасный светодиод не горит — это собственно данные, где по логике 3400 это единица, а 1400 это ноль.

Чтобы упростить процесс расшифровки протокола общения пульта и кондиционера, модифицировал, а точнее кастрировал скрипт, чтобы он не выдавал лишней информации, типа производителя, не выдавал разделители, которые для анализа данных не нужны, а информативные затухания ИК представлял в виде нулей и единиц, в итоге получилось следующее:


[97] = {111101110000100001100010100111010101010010101011}; - включение
[97] = {111101110000100001110010100011010101010010101011}; - выключение

То есть, очевидно 20 и 28 биты отвечают за включение и выключение, а поскольку «хвост» не изменился, значит контрольная сумма похоже не использует, хотя не факт, что контрольная сумма не в 28 или 20 бите, иначе зачем менять два бита для состояния ON-OFF. Сразу скажу, заметка эта пишется по ходу экспериментов.

Вторая, очевидная штука — это установленная температура, которая на пульте выставляется от 18 до 30 градусов, и нажав пульт, опуская с 30 до 18 получилась вот такая картинка, сильно сомневаюсь, и даже надеюсь, что температуры на каждый режим отдельно протоколе общения пульта и кондея нет, но увидим. Результат от 30 до 18 выглядит следующим образом:

[97] = {111101110000100001100100100110110101010010101011}; - 30С
[97] = {111101110000100001101100100100110101010010101011};
[97] = {111101110000100001100010100111010101010010101011};
[97] = {111101110000100001101010100101010101010010101011};
[97] = {111101110000100001100110100110010101010010101011};
[97] = {111101110000100001101110100100010101010010101011};
[97] = {111101110000100001100001100111100101010010101011};
[97] = {111101110000100001101001100101100101010010101011};
[97] = {111101110000100001100101100110100101010010101011};
[97] = {111101110000100001101101100100100101010010101011};
[97] = {111101110000100001100011100111000101010010101011};
[97] = {111101110000100001101011100101000101010010101011};
[97] = {111101110000100001100111100110000101010010101011}; - 18С

Очевидно, что с 21 по 24 бит и 29 по 31 идет управление температурой, но так же очевидно, что если бы это была оригинальная бинарная система, то через строчку менялся бы последний бит, а меняется первый, что наталкивает на мысль что мы имеет дело с инверсией бинарной системы, которая логична, так как пульт пишет в стэк, а стэк это топка тарелок, где первая сложенная, вытирается последней.

С битами 21-24 инвертируя первую строку как 0010 получаем в десятичном значение 2, а инвертируя 0111 получаем 14 в DEC. Соответственно температура задается как 32-<требуемая температура> в инвертированном бинарном варианте.

С битами 29-32, похоже опять инверсия, 18 градусов записано как 0001 (то есть 1), 30 градусов как 1101 = 13, тут опять пазл сошелся, формула температуры получилась как <требуемая температура>-17, преобразованная в бинарную систему и инвертированная.

Проверяем теорию с режимами и температурами, меняя режимы «охлаждение, нагрев и осушка», при температуре 30 градусов, получаем следующие записи:


[97] = {111101110000100001100100100110110101010010101011};
[97] = {111101110000100011000100001110110101010010101011};
[97] = {111101110000100010100100010110110101010010101011};

Синим отмечена температура 30С, которая не зависит от режима, режимы же меняются 17-19 битах и в 25-27, и с ними всё просто, записать, что в 011-100 в этих диапазонах — это охлаждение, 110-001 — это обогрев, а 101-010 это осушка.

Остается разобраться еще с несколькими кнопками, а именно econom, уровень мощности вентилятора и hi power, которая походу антипод эконому.

Тестируем Air Flow:


[97] = {111101110000100001100100100110110101010010101011}; - автомат
[97] = {111111110000000001100100100110110101010010101011}; - пол силы
[97] = {111011110001000001100100100110110101010010101011}; - по максимуму

Тут на 4-5 и 12-13 битах очевидно прослеживается инверсия значений, хотя она же, кстати, если чуть выше взглянуть прослеживалась и на режимах, просто там она была не так заметна, походу вместо контрольной суммы используется задвоение инвертированных бинарных данных, и она же кстати применяется для контроля корректности температуры, так что зря я формулы выводил.

Экономичный режим.


[97] = {111101110000100001100100100110110101010010101011}; - обычный режим
[97] = {111100100000110101100100100110110101010010101011}; - экономичный режим

Тут даже комментировать по сути нечего, 6-8 бит, инвертированный на 14-16ых, в варианте 111-000 дает норму, 010-101 дает экономию, а на практике заставляет тупить кондей и заставляет потеть кожаного ублюдка. Кто не вкурил юмор про кожаного ублюдка, смотрите видео:

Смотрим управление скоростью вентиляторов, честно говоря я до конца не вкурил чем Air Flow отличается от Fan Speed, но кнопки разные и кондей ведет себя реально иначе.


[97] = {111101110000100001100100100110110101010010101011}; - автомат
[97] = {111100110000110001100100100110110101010010101011}; - вентиляторы на полную
[97] = {111101010000101001100100100110110101010010101011}; - средний уровень
[97] = {111100010000111001100100100110110101010010101011}; - низкий уровень мощности

Функции явно связаны с экономией, потому пересекаются биты экономичного режима, походу 8 бит отвечает за экономию, но есть еще прикол, что при экономичном режиме уровень вентиляторов не меняется. Параметр FanSpeed не укладывается лично у меня ни в какую логику, и пришлось в лоб записать, что 11-100 это автомат, 01-110 это полная, 10-101 средний, а 00-111 низкий уровень вентокрылов. Логика скорее всего есть, но вычислять её для 4 режимов вентилятора лично мне банально лень, проще в лоб записать их.

Остался HiPower.

[97] = {111101110000100001100100100110110101010010101011}; - обычный режим
[97] = {111101100000100101100100100110110101010010101011}; - HiPower

Куча лишних данных, я полагаю отдана для работы таймера, с которым разбираться нет не времени, ни сил, ни интереса в данном случае, вычислив бинарный ряд, подключить ИК светодиод и скомпилировав по вышеизложенному любую команду кондиционеру, думаю не проблема.

Код для этой штуки писать не буду, меня тут уже на форуме профильном опускали, что дескать я «лох в стрингах», не в смысле чтобы пидером обозвали, а в смысле, что типа String в С++ использовал. Но на том же профильном форуме, уж простите, ничего кроме как «записать данные кнопки пульта» с вопросом «почему не могу воспроизвести?», без попытки разобраться как формируется код пульта, я лично не нагуглил.

Updated 12.08

Классический пример дампа у библиотеки IRRemote оказывает слишком умный, настолько, что вместо нормального дампа выдает слегка обработанные данные, вырезая инициализацию и финализацию пакета, сволочь. В общем как вариант использовать скрипт irdumper.ino которые дает чистый дамп.

В моем конкретном случае оказалось, что инициализация начинается с {6820, 7820… и завершается …7620, 660}; разделитель всё таки 660 микросекунд, ноль 1440, единица 3500, после этих изменений Arduino начала управлять кондиционером как надо, единственное, что походу слабоват сигнал, пульт работает намного лучше, но с этим еще разберемся, плюс в итоговой версии она будет стационарно закреплена недалеко от кондея, так что не критично, теперь в целях экономии есть мысль переделать всё это дело с Arduino на ESP8266, которые пучками продаются по 150 рублей на али и дружат с WiFi.

Update 12.08

Всё срослось и кондишен неплохо так управляется, заморозив меня на тестах, еще походу надо в боевом режиме лезть с паяльником внутрь кондея и выпаивать нахрен пишалку, потому что никакой обратной связи с кондеем на предмет принял ли он команду — нет, принимает видимо из-за расположения ИК-диода через раз и при этом, каждый раз приняв сигнал, мерзко подает сигнал на бипер, что не делает дом комфортнее, а скорее бесит. Ну да это не плоблема, вырезать не впаять… Кому интересно как в итоге ZH-LW-03 управляется ардуиной, выкладываю ClimaZHLW03.ino, но прошу не пинать на тему кода.