Блок дистанционный сервисный многофункциональный БДС-М

в 20:41, , рубрики: arduino, DIY, diy или сделай сам, умный дом, метки: , , ,

На этой радостной ноте я завершаю рассказ о текущей конфигурации «Удобного дома». Последняя часть системы в моих секретных планах всегда проходила под шифром «медиаконтроллер». И, что закономерно, предназначалась для управления ТВ, медиаплеером и кондиционером со смартфона или вообще любого компьютера с интернетом и браузером. Функционал, как всегда, дополнялся и развивался на ходу — у меня, кажется, просто какая-то пагубная страсть к импровизациям.

Поэтому из простого ретранслятора ИК-команд медиаконтроллер превратился в не совсем простой. Сначала я добавил туда датчик атмосферного давления, чтобы завершить картину метеоданных. А потом — ретранслятор радиосигналов от беспроводных датчиков, что несколько упростило жизнь и использование некоторых функций центрального контроллера. Если точнее, то получилось практически безотказное управление кормушкой для котов.

Чтобы не было недопонимания: особой цели или необходимости в этом контроллере я не видел. Просто было интересно его сделать и заодно занять длинные зимние вечера чем-нибудь, кроме как задумчиво смотреть в окно, пить кофе и размышлять о вечном, обязательно под теплым клетчатым пледом.

Одно из текущих практических применений (от которого пришлось отказаться) — одновременное включение одной кнопкой беспроводной клавиатуры ТВ и запуск файлового менеджера на подключенном к телевизору Android-брелке, чтобы чего-нибудь посмотреть. Второе применение, о котором я думаю, но которое, скорее всего, тоже будет отправлено в топку — автоматическое управление кондиционером в зависимости от температуры в комнате.

Наверное, лучше обо всем по порядку.

. и антенками так в стороны: зырк-зырк
image

Назначение и функции

Медиаконтроллер предназначен для работы совместно с центральным контроллером.

При ограничении функциональности возможна автономная работа совместно с радиопультом дистанционного управления, который способен выдавать команды по совместимому протоколу с фиксированным кодом для каждой кнопки (как правило — пульты от простых радиорозеток, радиореле, выключателей света).

Реализованные функции (Ц — с центральным контроллером; А — возможно в автономном режиме):

1) Управление ТВ LG (Ц, А)
2) Управление медиаплеером G-mini HDR900D (Ц, А)
3) Управление кондиционером LG CS12AQ (Ц, А)
4) Ретрансляция команд радиопультов и сигналов беспроводных датчиков центральному контроллеру (Ц)
5) Измерение и передача центральному контроллеру значений атмосферного давления и температуры в помещении (Ц)

История вопроса

Базовая идея медиаконтроллера состояла в следующем. Он принимает радиокоманды от центрального контроллера и передает соответствующую команду, но уже через ИК-диод. Разумеется, при этом медиаконтроллер должен располагаться в относительной близости от управляемых устройств, а прямая видимость между ИК-диодом и ИК-приемником управляемой аппаратуры — просто обязательное условие.

ИК-команды для устройств я получил примитивным способом: собрал небольшой стенд из ИК-приемника и Arduino с библиотекой IRremote. Особенность библиотеки в том, что она распознает массу протоколов и во многих случаях уверенно «читает» коды управления ИК-пультов. В этом она сильно похожа на RC-Switch: один раз получаем коды, и потом используем их в любых своих устройствах.

На случай, если код не распознан, есть «сырая» последовательность длительностей импульсов, которую IRremote выдает вместе с управляющим кодом. Минус, правда, в том, что этот вариант гораздо более расточителен с точки зрения ресурсов контроллера. Но если надо здесь и сейчас — альтернативы, в общем, нет.

Применение нашли оба способа. Так уж вышло, что с ТВ и медиаплеером проблем не возникло, а кондиционер закапризничал. Чтение рассказов соратников открыло страшную правду: в кодовом слове команды кондиционера содержится абсолютно вся информация об устанавливаемом режиме работы.

Укрощение кондиционера

Среднестатистический кондиционер — существо довольно глупое и послушное. Ничего не помнит, ничего не знает, и делает только то, что ему говорит мировая закулиса пульт ДУ.

Понять, что это вариант, когда нужно использовать «сырой» код довольно просто. К примеру, если неограниченное количество раз нажимать одну и ту же кнопку пульта ДУ от телевизора, то команда каждый раз будет одной и той же. И эту команду можно использовать где угодно.

Но если нажимать, предположим, кнопку увеличения температуры на пульте кондиционера, то команда в пределах диапазона температуры будет каждый раз разная. Все потому, что в кодовом слове передается устанавливаемая температура, а не признак ее изменения. Также в кодовом слове передаются: режим работы (холод/тепло/вентилятор), скорость вентилятора, положение жалюзи и т.п. Понятно, что если использовать «декодированный» результат из IRremote, ничем хорошим это не закончится, потому что он не имеет ничего общего с реальностью.

Еще одна проблема в том, что особенности и функции кондиционеров постоянно меняются — от поколения к поколению, от модели к модели. Поэтому даже если бы кому-то в голову пришло написать свою библиотеку для какого-нибудь бренда, то в лучшем случае функциональность (а в худшем — работоспособность) ограничивалась бы функциями модели, которую взяли за основу.

Вот пример: у человека кондиционер без автоматического управления вертикальными жалюзи. И откуда ему знать (если он не видел оригинального протокола), что в кодовом слове какая-то пара байт отвечает именно за управление вертикальными жалюзи? Если хотите мое мнение — ниоткуда. Ведь даже если в кодовом слове есть резерв на новые команды, невозможно понять, что именно они делают — может, ионизацию включают. А может — сушку воздуха. Такая, понимаешь, загогулина.

Тем не менее, герои существуют. Товарищ вот написал свою библиотеку для кондиционеров LG.

Ну а я, после небольших размышлений о том, надо ли как-то вычислять логику построения команд кондиционера, пришел к выводу, что острой необходимости нет. Дело в том, что мы пользуемся довольно ограниченным набором функций: как правило, одна и та же температура нагрева и одна и та же температура охлаждения. Поэтому я решил не тратить время на реализацию всего и вся, а просто последовательно установил в пульте и прочитал команды актуальных режимов: включение, выключение, обогрев и охлаждение.

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

Атмосферный сюрприз

С датчиком BMP085 связана интересная история. Во-первых, о существовании двух версий с напряжением 3В и 5В я узнал только после того, как не только заказал, но и получил свой экземпляр. Причем на плате, что характерно, не пишут какое именно напряжение нужно данному датчику. Пришлось посмотреть на фото разных датчиков и, в конечном итоге, рискнуть.

Во-вторых, при заказе я был абсолютно уверен, что покупаю датчик атмосферного давления. Ведь везде BMP085 преподносится именно таким образом. Поэтому очень удивился, когда уже после получения почитал спецификации датчика, и увидел там «Temperature measurement included». А потом и детали — "-40 to +85°C operational range, +-2°C temperature accuracy".

По всему выходило, что измерять можно одновременно и давление, и температуру. Причем точность меня вполне устраивала, тем более, что это такой приятный бонус.

Сразу скажу — я не сравнивал показания с неким стандартным термометром, поэтому не могу сказать, насколько и в какую сторону ошибается (если вообще ошибается) датчик.

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

Ретранслятор

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

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

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

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

Понимаю, что звучит это сомнительно. Да и реализация тоже как-то не очень. Но на практике мы забыли о проблемах с радиокнопкой. Теперь срабатывает всегда и безо всяких там нелепых размахиваний руками.

Ну а на волне успеха я заодно добавил и ретрансляцию сигналов беспроводных датчиков (протечки и задымления) — просто на всякий случай. Мне не сложно, а если это поможет — почему нет?

Принцип работы

Вообще, медиаконтроллер предназначен для работы вместе с центральным контроллером. Автономная работа — довольно экзотическое применение, которое требует многокнопочного радиопульта ДУ и ограничивает функциональность.

Поэтому я расскажу именно о взаимодействии с центральным контроллером.

Ретрансляция ИК-команд

Для любой команды управления по ИК должно быть выполнено несколько условий:

1) Должна быть составлена таблица соответствий сетевых (веб), управляющих радио- и ИК-команд
2) В центральном контроллере должны быть описаны сетевые (веб) команды и управляющие радиокоманды
3) В медиаконтроллере должны быть описаны управляющие радиокоманды и соответствующие им ИК-команды

Управление происходит по схеме:

1) Пользователь набирает (нажимает кнопку на смартфоне) сетевую (веб) команду в браузере
2) Центральный контроллер обрабатывает сетевую (веб) команду и выдает соответствующую радиокоманду
3) Медиаконтроллер принимает радиокоманду и выдает на ИК-диод соответствующую ИК-команду

Сетевые (веб) команды представляют собой обычные HTTP POST-запросы (в примитивном виде — адрес в строке браузера). Например:

192.168.22.185/?TVON

Здесь «192.168.22.185/» — адрес контроллера, а «TVON» — команда. Соответственно, команды придумываем сами, основываясь на фантазии и здравом смысле.

Радиокоманды следуют из протокола RC-Switch, который позволяет передавать 24-битные цифровые коды, то есть числа от 0 до 16777216. Т.е. можно выбирать любые, при условии, что они не дублируют коды, которые вы уже можете использовать или которые «летают» поблизости (у соседей, например).

Узнать, что творится рядом можно двумя путями: во-первых, по неадекватному поведению своей техники, а, во-вторых, если собрать простенький приемный стенд из Arduino, ASK/OOK-приемника на выбранной частоте (315 или 433 МГц) и библиотеки RC-Switch (пример ReceiveDemo_Simple).

ИК-команды своей техники можно узнать с помощью библиотеки IRremote.

Подтверждение приема и выполнения радиокоманды медиаконтроллером не предусмотрено.

Передача атмосферного давления и температуры в помещении

Для передачи этих показателей я использую ту же библиотеку RC-Switch и ту же технику, что в метеодатчике. То есть, контроллер периодически (раз в полчаса) измеряет значения и передает их в центральный контроллер по радиоканалу в виде числового кода.

Отличие от метеодатчика только в том, что здесь я поленился и выделил на каждый показатель по отдельной группе.

В результате давление передается кодом вида 1210XXXX, где XXXX — целая часть от значения давления (мне не очень интересны сотые доли) в mPa. Пересчет в mmHg выполняет центральный контроллер, не спрашивайте почему. Я не знаю.

Температура передается кодом вида 1310YXXX, где XXX — умноженное на 10 значение температуры (так передаются десятые доли), а Y — знак температуры (0 — положительная, 1 — отрицательная). Тоже не спрашивайте, зачем нужен знак для комнатной температуры.

Оба значения передаются друг за другом с небольшим интервалом.

Подтверждение приема команд центральным контроллером не предусмотрено.

Ретранслятор радиокоманд

Эта сервисная функция реализуется элементарно с помощью RC-Switch. Достаточно лишь определить ретранслируемые коды и занести их список в медиаконтроллер. Это могут быть коды радиорозеток или выключателей, до которых «не дотягивается» центральный контроллер. Или датчики, которые центральный контроллер «не слышит».

Таким образом, если медиаконтроллер распознает ретранслируемый код (нажата кнопка, сработал датчик, передана команда), то он просто повторяет его заданное количество раз.

Особенность только в том, что в моей реализации сигналы «непостоянных» датчиков, то есть, например, пультов ДУ, ретранслируются немедленно, а сигналы датчиков, которые, сигналят постоянно (например, протечка или дым) ретранслируются циклически и с некоторой задержкой.

Логика в этом следующая. Считается, что центральный контроллер (ЦК) всегда слышит мультимедийный контроллер (МК), что обеспечивается их взаимным расположением. Одновременно ретрансляция сигнала периферии через МК гарантированно завершается позднее, чем завершается передача сигнала инициатором.

Поэтому, с одной стороны, ЦК гарантированно получит ретранслируемый сигнал, даже если не слышит инициатора, а с другой — получит команду и в случае, если до него одновременно достают и инициатор, и МК.

Остается только специфика постоянно сигналящих датчиков. Как я говорил, датчик протечки может кричать все время, пока находится в воде, и пока не сядут батарейки. Замолкнет он только когда условия вернутся к нормальным. Поэтому МК, во-первых, начинает ретрансляцию его сигнала после 5-секундной паузы (это на случай, если ЦК сам слышит датчик) и, во-вторых, повторяет этот цикл все время, пока сигналит инициатор. Т.е. МК как бы «подпевает».

Подтверждение приема команд центральным контроллером не предусмотрено.

Железо

Понимаю, что надоел, но напоминаю — набор для текущей конфигурации, ссылки для примера. Итак:

1) Arduino Pro Mini (ATmega328p, 16 МГц, 5В)
2) Комплект приемника и передатчика 433 МГц ASK/OOK
3) ИК-светодиоды IR513B-40 (940 нм) (2 шт) или аналогичные
4) Токоограничительный резистор для светодиодов (в идеале — 68 Ом)
4) Датчик BMP085 (версия 5В)
5) Провод для размещения светодиодов, питания, коммутации, разъемы и макетные провода по вкусу
6) Корпус
7) Источник питания

Вам также понадобится фотоприемник для чтения сигналов ИК-пультов, если захотите сделать управление всякой AV-техникой. Я для этой цели использовал TSOP4836 (приемник-демодулятор с наиболее распространенной частотой модуляции 36 КГц). Особенность этой фиговины в том, что если не прикрыть чем-нибудь тыльную сторону, то цепляет огромное количество помех. Имейте в виду, или покупайте сразу что-нибудь экранированное.

Схема сборки здесь из скетча не совсем очевидна, потому что три из четырех компонентов подключаются к пинам «по умолчанию» — это светодиоды, приемник и датчик BMP085. Зато пин передатчика, в принципе, можете выбирать сами — только не забудьте потом в коде поправить.

1) Приемник

DATA — к цифровому пину 2
VCC — к питанию +5В
GND — на землю

2) Передатчик

DATA — к цифровому пину 6
VCC — к питанию +5В
GND — на землю

3) BMP085
Согласно инструкции Adafruit:

SCL — к аналоговому пину 5
SDA — к аналоговому пину 4
VCC — к питанию +5В (только для версии 5В, иначе — 3.3В)
GND — на землю

4) ИК-диоды

Оба соединены последовательно. Только у одного провод покороче — он на ТВ смотрит, а у другого — подлиннее — ему нужно в кондиционер попасть.

Простите, я все время путаю анод и катод. В общем, одной стороной — к земле (катод?), а другой (анод?), через токоограничительный резистор (у меня стоит пара 180 Ом, т.е. 90 Ом) на цифровой пин 3 (это заложено по умолчанию в библиотеке, но не будет работать на Mega, для которой потребуется модификация кода библиотеки — имейте в виду).

Сопротивление у меня, если честно, неправильное. Но других под руками не было, а ставить три в параллель было страшно, поскольку расчетный ток мог оказаться выше способностей Arduino, а я не хотел проверять.

Посчитать токоограничительное сопротивление сами и на свое количество диодов можете в удобном калькуляторе.

Все это счастье я запихнул (буквально) в небольшую коробочку. Ах да, не забудьте антенны для приемника и передатчика, если их нет. Если совсем ничего под руками нет — можно отрезок провода в четверть волны (173 мм или 164 мм).

Сначала и датчик BMP085 был внутри, но потом я сообразил, что он там может дополнительно нагреваться, да и вообще — и вынес его наружу. Не очень эстетично, зато температура должна измеряться немного точнее.

. разъемы: питания и для подключения светодиодов. Для последних — обычный моно 2.5-мм джек
image

Софт

Скетч требует следующие нестандартные библиотеки:

1) RC-Swtich для обмена данными и ретрансляции сигналов.
2) IRremote для управления AV-техникой с ИК-пультами.
3) Adafruit_BMP085 для получения данных от датчика BMP085.
4) SimpleTimer для отсчета временных интервалов.

Для работы вам потребуется:

1) Внести коды своих радиокоманд для ретрансляции.
2) Внести ИК-коды управляемых устройств.
3) Внести коды радиокоманд, по которым мультимедийный контроллер будет выдавать ИК-команды.
4) Настроить по вкусу секцию команд мультимедийного контроллера в коде центрального контроллера (для управления через интернет).

Предполагается, что коды радиокоманд для ретрансляции вы уже знаете (это ваши беспроводные датчики, пульты и т.п.). Если не знаете — воспользуйтесь Arduino, приемником и библиотекой RC-Switch с примером ReceiveDemo_Simple.

Узнать ИК-коды управляемых устройств можно либо из табличек, которые во множестве гуляют в интернете, либо прочтя их с пультов. Для второго случая вам понадобится подключить фотоприемник к Arduino и воспользоваться библиотекой IRremote. Если спешите, запомните главное:

1) Если при нажатии одной и той же кнопки получаете разные значения — значит, что-то пошло не так, или у вас пульт от кондиционера. В этом случае имеет смысл или поискать соответствующую библиотеку управления. Или, если ее нет — просто использовать «сырые» коды, как это сделал я в секции переменных, упаковав все в PROGMEM.

Помните, что в «сырых» кодах первое значение, явно выпадающее и ряда, следует отбросить вручную.

2) Если при нажатии одной и той же кнопки получаете один и тот же код — его можно смело использовать. Только не забудьте, что у IRremote тоже есть свой формат передачи, и кроме кода команды еще нужно указать и в какой системе команд осуществляется передача. У меня — NEC.

А вот сам код.

// 28.10.2013 - добавлено управление светом в ванной и гардеробе
// 29.11.2013 - удалено управление светом в ванной и гардеробе

#include <Wire.h> 
#include <Adafruit_BMP085.h>
#include <RCSwitch.h> //   http://code.google.com/p/rc-switch/
#include <SimpleTimer.h> // 
#include <IRremote.h>

unsigned long myData;
long aL;

boolean water1=false; // признаки сработавших датчиков для паузы между повторами
boolean water2=false;
boolean water3=false;
boolean smoke1=false;
boolean smoke2=false;
boolean smoke3=false;

#define txPin 6 // пин передатчика
SimpleTimer checkWeather; // объект таймера
RCSwitch meteoSwitch = RCSwitch(); объект RC-Switch
IRsend irsend; // объект IRRemote

// команды кондиционера в PROGMEM

const prog_uint16_t acON[59] PROGMEM ={9450, 4350, 650, 1600, 600, 500, 550, 550, 550, 500, 600, 1600, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 550, 1650, 600, 500, 600, 1600, 550, 1650, 600, 500, 550, 550, 600, 500, 550, 550, 600, 1600, 600, 450, 600, 1600, 600, 1600, 600};
const prog_uint16_t acOFF[59] PROGMEM ={9550, 4300, 600, 1600, 650, 450, 650, 450, 600, 500, 650, 1550, 600, 500, 600, 500, 600, 500, 600, 1600, 600, 1600, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 500, 600, 600, 500, 600, 500, 600, 450, 650, 450, 600, 1600, 650, 450, 600, 1600, 650, 450, 600, 500, 600, 500, 650, 1550, 600};
const prog_uint16_t acCool[59] PROGMEM ={9500, 4350, 600, 1650, 600, 500, 600, 500, 600, 500, 600, 1550, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 550, 1650, 600, 500, 600, 1600, 600, 1600, 600, 500, 600, 1600, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 1600, 600, 1550, 600, 1600, 600, 1600, 600};
const prog_uint16_t acHeat[59] PROGMEM ={9500, 4350, 600, 1600, 650, 450, 650, 450, 650, 450, 600, 1600, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 500, 600, 1600, 600, 500, 600, 1550, 650, 1550, 600, 1600, 650, 1550, 650, 450, 650, 1550, 600, 500, 600, 500, 600, 500, 650, 450, 650, 1550, 600, 500, 600, 500, 600, 500, 600};

// указатели на команды кондиционера
PROGMEM const prog_uint16_t *IRRemotePointer[] = {
acON,
acOFF,
acCool,
acHeat};


Adafruit_BMP085 bmp; // объект BMP085

void setup() { 
  pinMode(13, OUTPUT); // мигалка
  bmp.begin();
   
 meteoSwitch.enableTransmit(txPin); // 
 meteoSwitch.enableReceive(0);  // приемник на пине 2
 checkWeather.setInterval(1800000, getClimate); // отправляем погоду каждые полчаса
 

 
 delay(2000); // приходим в себя на старте
  
  }           
  
void txSwitch(long cmd) { // просто повтор отправки команд RC-Switch, в библиотеке даже команда для этого есть
  meteoSwitch.disableReceive(); // выключение приемника, чтобы не мешался
    for (byte txC=0; txC<1; txC++) {
  meteoSwitch.send(cmd, 24);
  meteoSwitch.enableReceive(0);
    }
}
  


void repeatAlarm() { // повторение сигнала "постоянных" датчиков и сброс признаков после
 
  txSwitch(aL);
  water1=false;
  water2=false;
  water3=false;
  smoke1=false;
  smoke2=false;
  smoke3=false;
  
}

void enableRx() {
  
  meteoSwitch.enableReceive(0); // включение приемника
}

void loop ()
{ 
checkWeather.run();

if (meteoSwitch.available()) {  // получаем команды по радио и решаем, что делать
    int value = meteoSwitch.getReceivedValue();
    if (value != 0) {
  
  switch (meteoSwitch.getReceivedValue()) {
        
      
      case 1418288: // Water leak KITCHEN - сработал датчик протечки, повторяем сигнал через 5 секунд (дальше по датчикам аналогично)
      if (water1 == false) {
          aL=1418288;
          checkWeather.setTimeout(5000, repeatAlarm);
          water1 = true;
      }
      break;
    
	case 3470133: // Water leak WASHER
      if (water2 == false) {
          aL=3470133;
          checkWeather.setTimeout(5000, repeatAlarm);
          water2 = true;
      }
      break;

      case 3592421: // Water leak MAIN
      if (water3 == false) {
          aL=3592421;
          checkWeather.setTimeout(5000, repeatAlarm);
        water3 = true;}
      break;

      case 1084887: // Smoke KITCHEN
      if (smoke1 == false) {
          aL=1084887;
          checkWeather.setTimeout(5000, repeatAlarm);
          smoke1=true;
      }
      break;

      case 2184536: // Smoke HALL
      if (smoke2 == false) {
          aL=2184536;
          checkWeather.setTimeout(5000, repeatAlarm);
          smoke2 = true;
      }
      break;

      case 12602757: // Smoke ROOM
      if (smoke3 == false) {
          aL=12602757;
          checkWeather.setTimeout(5000, repeatAlarm);
        smoke3 = true;}
      break;
      
      case 15741424: // Повтор команды на активацию кормушки
        txSwitch(15741424);
      break;
      
      case 46151: // Повтор команды на поворот кормушки
        txSwitch(46151);
      break;

      case 46150: // Повтор команды на останов кормушки
        txSwitch(46150);
      break;      

	  // БЛОК ИК-КОМАНД
	  
// tv-on
    case 88100: irsend.sendNEC(0x20DF10EF,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break; // передаем и светим лампочкой
// tv-back
    case 88116: irsend.sendNEC(0x20DF14EB,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // tv-volup
    case 88132: irsend.sendNEC(0x20DF40BF,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // tv-voldown
    case 88164: irsend.sendNEC(0x20DFC03F,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // tv-chup
    case 88128: irsend.sendNEC(0x20DF00FF,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // tv-chdown
    case 88256: irsend.sendNEC(0x20DF807F,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // tv-mute
    case 88512: irsend.sendNEC(0x20DF906F,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // tv-menu
    case 89100: irsend.sendNEC(0x20DFC23D,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // tv-ok
    case 89108: irsend.sendNEC(0x20DF22DD,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // tv-up
    case 89116: irsend.sendNEC(0x20DF02FD,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // tv-down
    case 89132: irsend.sendNEC(0x20DF827D,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // tv-left
    case 89164: irsend.sendNEC(0x20DFE01F,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // tv-right
    case 89128: irsend.sendNEC(0x20DF609F,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // tv-av
    case 89256: irsend.sendNEC(0x20DFD02F,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-on
    case 89512: irsend.sendNEC(0xF9EA15,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-off
    case 87108: irsend.sendNEC(0xF9EA15,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-play
    case 87116: irsend.sendNEC(0xF90AF5,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-back
    case 87132: irsend.sendNEC(0xF9F20D,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-volup
    case 87164: irsend.sendNEC(0xF9E817,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-voldown
    case 87128: irsend.sendNEC(0xF92AD5,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-ff
    case 87256: irsend.sendNEC(0xF9C03F,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-rew
    case 87512: irsend.sendNEC(0xF9E01F,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-menu
    case 92108: irsend.sendNEC(0xF96897,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-set
    case 92116: irsend.sendNEC(0xF958A7,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-up
    case 92132: irsend.sendNEC(0xF9C23D,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-down
    case 92164: irsend.sendNEC(0xF950AF,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-left
    case 92128: irsend.sendNEC(0xF9609F,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-right
    case 92256: irsend.sendNEC(0xF9708F,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // media-ok
    case 92512: irsend.sendNEC(0xF940BF,32); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW);  break;
  // ac-cool
    case 95108: IRTransmit(2, 59); delay(150); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW); break;
  // ac-heat
    case 95116: IRTransmit(3, 59); delay(150); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW); break;
  // ac-on
    case 95132: IRTransmit(0, 59); delay(150); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW); break;
  // ac-off
    case 95164: IRTransmit(1, 59); delay(150); digitalWrite(13, HIGH); delay(40); digitalWrite(13, LOW); break;  

    }      

   } 
      meteoSwitch.resetAvailable();
  }

}

// БЛОК МЕТЕОДАННЫХ

void getClimate() { 

int Pressure = bmp.readPressure()/100;
int Temperature = bmp.readTemperature()*10;
  
  myData = 12100000+Pressure;
  meteoSwitch.send(myData, 24); // передаем давление
  
  if (Temperature > 0) {
  myData = 13100000+Temperature;
  meteoSwitch.send(myData, 24); // передаем положительную температуру
  } else {
  myData = 13101000+abs(Temperature);
  meteoSwitch.send(myData, 24); // передаем отрицательную температуру
  }

}

// БЛОК ПЕРЕДАЧИ "СЫРЫХ" ИК-КОМАНД 

void IRTransmit(byte cmd, byte cmdlen) { // 

prog_uint16_t *currentIRRemotePointer = (prog_uint16_t *)pgm_read_word(&IRRemotePointer[cmd]); // указатель на нужный массив в PROGMEM
unsigned int IRRawCodes[cmdlen]; // локальный массив для импульсов кода управления

for (byte i = 0; i < cmdlen; i = i + 1) {  // заполняем массив импульсами
  IRRawCodes[i] = pgm_read_word(&currentIRRemotePointer[i]); // 
  }
irsend.sendRaw(IRRawCodes, cmdlen, 38); // скармливаем массив импульсов IRRemote
delay(150);

}


Ну и последнее. Если где-то ошибся — говорите, будем разбираться. А в остальном, я верю, что вы знаете, умеете и можете лучше.

ps. и кто жаловался на скучные аббревиатуры в названии?

Автор: spc

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js