выполнить команды с Ик пульта
- Войдите на сайт для отправки комментариев
Всем привет.
Суть в следующем: с помощью библиотеки IRremote.h
(взято отсюда http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html)
ардуина принимает и распознаёт сигналы пульта. То есть напрмер кнопка "вкл" расшифровыется - 41BEF00F, а кнопка "ок" - 41BEE01F.
Полученные значения свободно выводяся в ком порт.
Вопрос такой, как сделать, чтобы при получении конкретных команд включались светодиоды на пинах ардуино? Я так понимаю, что раз команды распознаются, то их можно сравнить с заранее указанными значениями и если они совпадают, то включать светодиод. С помощью каких функций это возможно сделать?
вот собственно код:
#include <IRremote.h> int RECV_PIN = 11; int RELAY_PIN = 4; int pin5 =5; IRrecv irrecv(RECV_PIN); decode_results results; // Dumps out the decode_results structure. // Call this after IRrecv::decode() // void * to work around compiler issue //void dump(void *v) { // decode_results *results = (decode_results *)v void dump(decode_results *results) { int count = results->rawlen; Serial.print(results->value, HEX); Serial.println(""); } void setup() { delay (1000); pinMode(RELAY_PIN, OUTPUT); pinMode(5, OUTPUT); pinMode(13, OUTPUT); Serial.begin(9600); irrecv.enableIRIn(); // Start the receiver } int on = 0; unsigned long last = millis(); void loop() { if (irrecv.decode(&results)) { // If it's been at least 1/4 second since the last // IR received, toggle the relay if (millis() - last > 250) { on = !on; digitalWrite(RELAY_PIN, on ? HIGH : LOW); digitalWrite(13, on ? HIGH : LOW); dump(&results); } last = millis(); irrecv.resume(); // Receive the next value } }
В этой программе ардуино включает и выключает светодиод просто по любой команде с пульта. А полученый код отправляет в ком порт.
UPDATE от модератора: я поправил фоматирование. Вы можете сами пользоваться кнопочкой вставки кода, также красивше.
Ни разу не работал с IR, взможно там и есть какие-то функции для этого, но думаю можно сделать как-то так:
HOCKU, не получается обратится к "value". Ошибка "value" is not declarated in this scoupe. пробовал и results.value., всё равно не срабатывает. Нужно по другому как то.
А в какую собственно переменную записывается значение, получаемое с IR сенсора?
Вот эту переменную и надо подставить вместо value в конструкции switch-case.
Вот так нужно написать: if (results->value == 0x41BEF00F) { }. Работает.
Ну отлично. а если results->value подставить в switch вместо value?
switch(results->value)
Вероятно так тоже заработает)
Просто конструкция switch-case более удобна в том случае, когда нужно перебирать много значений одной переменной.
Для начала хотелось бы сказать,что библиотека IRremote на arduino-1.0 не заработала. Скетч не хотел компилиться и выдавал кучу ошибок. Скачав прошлую версию arduino-0023 скетч без проблем скомпилился.
Лично у меня способ с if (results.value == 0x41BEF00F) { } не заработал. Я так понимаю что код с пульта это 41BEF00F. У меня заработало когда я в Serial.println глянул значение НЕ в HEX, и уже потом его ввел в конструкцию if. Примерно вот так:
думал только у меня проблема с библиотекой для IR.
есть ли возможность использовать ее с arduino-1.0 ?
Оказывается возможность есть! Одно из изменений в ардуино-1.0 это переименование WProgram.h в Arduino.h . Соответственно чтобы работала ардуино нужно все упоминания в библиотеке об WProgram.h нужно заменить на Arduino.h. Проделав это, у меня скетч скомпилировался. Переделанная библиотека:
www3.zippyshare.com/v/24546193/file.html
Diemon
Большое спасибо !
Все заработало !
Немного поигрался с приемом сигнала с пульта и возник вопрос.
Почему вместо кода который распознается надо писать 0x и код , что означает 0x ?
Почему вместо кода который распознается надо писать 0x и код , что означает 0x ?
Префикс 0x означает, что далее следует шестнадцатиричный код.
Префикс 0 означает, что далее следует восьмиричный код.
Префикс B означает, что далее следует двоичный код.
www.arduino.ru/Reference/IntegerConstants
как все просто, когда знаешь где смотреть.
Спасибо !
а получилось ли у когото использовать конструкцию switch case? Типа такого:
У меня такой код не захотел работать. Хотя такой работает без проблем:
В каждую ветвь case после уже имеющихся инструкций поместите оператор break; - вдруг поможет?
я использую конструкцию с IF проблема в том что если нажать и держать кнопку пульт сначала передаст индивидуальный код кнопки а потом начинает слать код что кнопка нажата, этот код ля все один, как сделать что бы при удерживании кнопки например горел светодиод а при отпускании гас?
Когда делал код, столкнулся с той же проблемой. Пульт передает периодически один и тот же сигнал(нажата кнопка). Тоесть сигнал-пауза-сигнал-пауза и так далее. Поидее нужен какойто таймер, чтобы если через определенный промежуток времени после последнего сигнала не следует следующий, то нужно выключать двигатель/светодиод.
У меня сделано так, коряво но кое как работает. Как сделать по другому - не знаю
То есть через delay (300); ардуино выключает двигатели а потом снова включает по сигналу пульта. Так как выключение-включение происходит быстро, то это почти не заметно изза инерционности самих двигателей. Задержка подбиралась методом тыка.
хм... спасибо попробую потестирую с delay
а еще вот у меня пульт другой он немного не так работает, сначала шлет код кнопки а за ним идет общий код если кнопку удерживать тоесть смотри в Serialпример
111111000 - нажали один раз
111111111 - если удерживать
111111111
111111111
есть мысли какие?
Вся соль в том, что пульт шлет сигналы с некоторым промежутком. И ардуине непонятно, то ли пауза между сигналами то ли кнопка отжата и сигнала больше не будет. Через delay конечно коряво и неправильно)
В университете, когда изучали intel 8051 нам рассказывали что применяют спец таймер. Задается время таймера, и он циклически работает. А из программы микроконтроллера этот таймер сбрасывается в начало.
Например: задержка между сигналами с пульта 0.2 сек. Таймер настраивается на время >0.2с, пусть будет 0.3с. Так вот, когда пришел сигнал с пульта, то таймер опять сбрасывается в начало и начинает считать от 0.3 до 0. Если через 0.2с сигнал опять пришел, то таймер опять сбрасывается и т.д. То есть если идут сигналы с пульта, то таймер никогда не доходит до 0. А вот если сигнал не пришел через 0.2 секунды, то таймер доходит до нуля, и должен, в вашем случае выключить светодиод.
Но как это сделать на ардуине - пока не знаю, про таймеры честно говоря не читал, пока времени не хватает. Другой способ решения проблемы пока себе не представляю.
вообшем нашел пример http://www.youtube.com/watch?v=_1om5E--8FM&feature=endscreen&NR=1 тут у человека работает все как надо)
скетч вроде тот что он использовал(как написано на форуме)
я пока что не могу заставить его работать(
...
а еще вот у меня пульт другой он немного не так работает, сначала шлет код кнопки а за ним идет общий код
...
есть мысли какие?
Не совсем понятно какие мысли вас интересуют.
Ну да.. разные пульты работают по разному (особенно разных производителей). По разному кодируют сигналы, по разному сообщают о "удерживании кнопки". Я встречал три основных подхода:
Или вас интересовало "как обрабатывать" такую ситуацию? (когда шлется код повторения)
я столкнулся с двумя типами который сначала шлет код кнопки а потом код повторения, и с пультом который поочереди шлет два разных кода.
у меня не получается оброботать ни один из вариантов и я хотел бы получить помощи)))
на видео у человека пульт второго типа( я знаю, потому что у меня такойже) так вот он смог обработать такой сигнал на форуме есть пример кода, но я немогу его заставить работать. можете помоч мне?
но я немогу его заставить работать. можете помоч мне?
Не знаю. Но попытаться можно. По крайней мере указать на те ошибки которые мне видны (но не факт что нет других).
Для начала, я думаю сделать две вещи: "плюнуть на код который вы нашли на форуме" (он может работать только при удачной фазе луны) и танцевать от кода данного Diemon. С ним тоже не "все здорово", но пошагово его можно привести в чувство. И второе: где только можно - отказаться от delay (не буду сейчас расписывать почему, но он очень часто является "самонаступаемыми граблями").
Слона нужно "есть по кусочку". Для начала, мне видится две задачи которые нужно решить:
Согласны идти по этим шагам? (а я, пока, подниму машину с Arduino IDE, давно не брал в руки шашку, да попробую накидать пару примеров).
у меня получился изначально такойж код как у Diemon. так что можно и от него плясать.
как раз над этим я и ломаю голову.
давайте, буду вам благодарен)
Попробуйте вот такой скетч
Ожидаемое поведение: после нажатия кнопки, диод должен еще гореть "какое-то время". "Время" подкручиваем в строке 21.
Если даже на больших цифрах видимой на глаз задержки нет - пробуем в конце loop вставить маленький delay. В диагностических целях. Потом уберем его. Прийдется чуть сложней логику сделать, но нужно вначале попробовать "что попроще".
Если "ожидаемое поведение" наблюдается - сообщите, будем дальше копать.
P.S. На всякий случай. Когда вы наводите мышку на код в посте, то в его верхнем правом углу появляется контекстное меню. Второй иконкой, можно скопировать в клип-боард, готовый код для вставки в ArduinoIDE, без номеров строк и необходимости перенабирать руками.
Ладно, поехали дальше.
Обрабатываем "повторение".
Кстати код 111111111 - это не пульт шлет. О повторении он сообщает несколько сложней. Это уже сама библиотека IRremote.h так сообщает о том что "распознала повторение".
У нее есть дефайнах есть REPEAT 0xffffffff. Лучше использовать его.
Троеточия означают "ничего не поменялось". Все так же как в предыдущем скетче
Кстати код 111111111 - это не пульт шлет.
я знаю, это я просто как пример привел
Кстати код 111111111 - это не пульт шлет.
я знаю, это я просто как пример привел
Ну я же не телепат. Лучше перебдеть... :) Тем более что и другие ветку читать могут. Вы знаете, а другие могут не знать. Тут люди очень разного уровня.
Так что со скетчами, как себя ведут?
вообще первый скетч работает, нажимаем кнопку светодиод вспыхивает и тухнит,
второй, может быть я не правельно их совместил, не работает вот проверте меня
вообще первый скетч работает, нажимаем кнопку светодиод вспыхивает и тухнит,
Ключевой вопрос "как тухнет", есть видимая задержка? Или "сразу как отпустили"?
второй, может быть я не правельно их совместил, не работает вот проверте меня
На глаз вроде все верно. А в чем именно проявляется "не работает"?
Попробуйте вставить "Serial.print("results:");Serial.println(results->value, HEX);" перед ""int keyCode=results.value"
и
"Serial.print("keycode:");Serial.println(keyCode, HEX);" перед "if(keyCode == 0x40BF00FF)"
И киньте сюда что видно при этом в сериал мониторе (ну и в setup не забудте инициализацию serial порта добавить)
<< Ключевой вопрос "как тухнет", есть видимая задержка? Или "сразу как отпустили"?>>
нажали кнопку он загорелся на некоторое время , может быть на 1 сек., и тухнет, кнопку при этом не отпускали. теперь отпускаем - нажимаем и сново вспыхивает и тухнит
сейчас попробую
Посмотрев свежим взглядом, вижу что можно чуток упростить код (но, по идее это ни на что не должно влиять).
Строчку
заменить на
А строчки
выкинуть. На одну проверку меньше будет.
Update: строчки "что выкинуть" неправильно дал. Теперь правильно.
<< Ключевой вопрос "как тухнет", есть видимая задержка? Или "сразу как отпустили"?>>
нажали кнопку он загорелся на некоторое время , может быть на 1 сек., и тухнет, кнопку при этом не отпускали. теперь отпускаем - нажимаем и сново вспыхивает и тухнит
Ну по описанию "то что доктор прописал" :) А вто втором скетче есть это "на 1 сек и тухнет"? Или вообще не зажигается?
Значит трабла где-то в обработке повторений. Может быть все таки код повторения не равен REPEAT (возможно если пульт работает не по NEC протоколу). А пульт вы взяли именно тот который "код повторения" дает, не тот который "чередует коды"? Если в serial выведете коды, то по идее, мы должны увидеть ответы на эти вопросы :)
вообщем на Serial.println(results->value, HEX); прога ругаться начала я сделал так Serial.println(results.value, HEX); сработало, есть разница?
вот результат: нажали на первую клавишу и подержали ее
results:40BF00FF
keycode:FF
results:FFFFFFFF
keycode:FF
results:FFFFFFFF
keycode:FF
results:FFFFFFFF
keycode:FF
на другую нажал и тоже подержал:
results:40BF807F
keycode:FFFF807F
results:FFFFFFFF
keycode:FFFF807F
results:FFFFFFFF
keycode:FFFF807F
что дальше делать?
Ну по описанию "то что доктор прописал" :) А вто втором скетче есть это "на 1 сек и тухнет"? Или вообще не зажигается?
нет. во втором скетче ни чего не происходит.
Сделайте переменным lastPressedKey и keyCode тип "unsigned long" вместо int. Похоже я не угадал c int и в него код клавиши не помещается. Годы C# подвели. Там бы такую ошибку компилятор просто не пропустил, сразу бы послал подальше :)
То есть должно быть
ну и опять "что в serial воводится" покажите, после этой замены.
теперь светодио загорается и начинает быстро моргать, сть какойнибудь способ чтоб убрать эти моргания или сделать их незаметными? просто мне нужно управлять двигателями и двигатель дергается при таком раскладе...вообщем ничего хорошего)
вот что Serial выдает
нажал и подржал кнопку:
results:40BF00FF
keycode:40BF00FF
results:FFFFFFFF
keycode:40BF00FF
results:FFFFFFFF
keycode:40BF00FF
results:FFFFFFFF
keycode:40BF00FF
results:FFFFFFFF
keycode:40BF00FF
и вторую кнопку:
results:40BF807F
keycode:40BF807F
results:FFFFFFFF
keycode:40BF807F
results:FFFFFFFF
keycode:40BF807F
вот что Serial выдает
Ну похоже, теперь в логике потоврений все нормально. Можно закомментить эти serial (но пока не выкидывайте может еще пригодятся)
теперь светодио загорается и начинает быстро моргать, сть какойнибудь способ чтоб убрать эти моргания или сделать их незаметными?
Конечно. Для этого нужно понять "почему они есть". Думаю потому, что он успевает потухнуть раньше чем успевает прийти-обработаться код повторения. Боротся с этим можно несколькими способами:
Но в любом случае, механизм через ledCounter=5000; это временное решение. Только что-бы "проверить подход". Он слишком зависит от того за какое время выполняются другие части кода. Его все время нужно будет "подкручивать". Поэтому нужно будет перейти на использование внутренних часов (счас накидаю как это делается).
ммм я вроде убрал "моргание" ledCounter=7500; вроде бы не видно как мигает светодиод.
куда теперь вписывать дополнительные фукции для того чтоб работать с другими кнопками?
"лобовой вариант" это завести еще несколько ledCounter2,ledCounter3, ledCounter4 и т.п.
для каждой нопки увеличивать свой счетчик, и для каждого повторить весь if после комментария ""// а теперь обрабатываем "зарегистрированные факты""
ну и каждый будет включать свой диод.
Но это получится, мягко говоря "попахивающий-код". Который потом поддерживать и менять будет затруднительно.
Чуток подождите, покажу как это сделать более аккуратно с помощью массивов.
Вообщем поехали :)
Раз у нас "моторы", то дальше я термин LED использовать не буду. Буду просто назвыать PIN, включить PIN и т.п. Пины я условно обозвал ВПЕРЕД, НАЗАД, ВЛЕВО, ВПРАВО
Буду по кусочкам давать, пока не дойду до конца, скетч компилироваться не будет.
вместо
вставляем
Перед setup()
задаем две новые функции. Первая будет включать пин и взводить счетчик, вторая выключать пин и уменьшать счетчик
Теперь внутри setup выствляем для наших пинов режим.
Вместо
Пришем
Дальше переходим логике "какая клавиша нажата". Переходим от if к кошерному, в данном случае, switch и не напрямую включаем наши пины, а через функцию turnONPin
вместо
пишем
Ну и осталось, уменьшать счетчики и выключать, когда пришло "время" пины.
Вместо
пишем
Все. Теперь мы, по идее, сделали так, что на при нажатии каждой клавиши у нас включается соответсвующий пин (все-го их четыре).
Пробуйте.
ругается на void turnONPin(int)
и вот что выдает
IRrecvDemo.cpp: In function 'void loop()':
IRrecvDemo.pde:-1: error: too few arguments to function 'void turnONPin(int)'
IRrecvDemo.pde:-1: error: at this point in file
IRrecvDemo.pde:-1: error: too few arguments to function 'void turnONPin(int)'
IRrecvDemo.pde:-1: error: at this point in file
IRrecvDemo.pde:-1: error: too few arguments to function 'void turnONPin(int)'
IRrecvDemo.pde:-1: error: at this point in file
IRrecvDemo.pde:-1: error: too few arguments to function 'void turnONPin(int)'
IRrecvDemo.pde:-1: error: at this point in file
IRrecvDemo.pde:-1: error: too few arguments to function 'void turnONPin(int)'
IRrecvDemo.pde:-1: error: at this point in file
IRrecvDemo.pde:-1: error: too few arguments to function 'void turnONPin(int)'
IRrecvDemo.pde:-1: error: at this point in file
IRrecvDemo.pde:-1: error: too few arguments to function 'void turnONPin(int)'
IRrecvDemo.pde:-1: error: at this point in file
IRrecvDemo.pde:-1: error: too few arguments to function 'void turnONPin(int)'
IRrecvDemo.pde:-1: error: at this point in file
Немного забегаю вперед. Надеюсь что все заработает. Но уж "что-бы закончить".
Предлагаю еще уйти от магических 7500. Сделать скетч более устойчивым к временным измененим.
Для этого вместо счетчиков будем использовать фунцию arduino.ru/Reference/Millis
Итак вместо массива счетчиков
объявим массив в котором будем хранить время "когда нужно выключить пин", для каждого пина время храним отдельно
Заодно объявили и константу, что-бы потом в коде не искать "где подкрутить задержку.
Теперь в функции turnONPin вместо
пишем
Ну и напоследок, выкидываем все из функции turnOffPinIfRequired, теперь она будет проще (не нужно счетчик уменьшать, время само тикает), и вставляем
Вот теперь вроде "все хорошо". Теперь если где-то в loop будет "времяемкие задержки", они не будут "автоматически" умножатся на "магическое число". В крайнем случае, если эта задержка будет больше OFF_DELAY, то пин будет гаснуть чуть позже чем "ему положено" (потому-то и нежелательно в реальных скетчах использовать delay, лучше везде вычислять время, потом сверятся с ним и делать действие только если время пришло.
ругается на void turnONPin(int)
Показыавйте скетч целиком, который у вас получился. Может где-то лишнюю ; воткнули или } потеряли.
я заменил название пинов , т.к до этого работал так и мне немного удобнее, думаю это ведь не важно..
вот что получилось, я проверил все но не нашел лишних или не доставленых "}"