обработка нажатия кнопки при включении питания arduino
- Войдите на сайт для отправки комментариев
Пнд, 03/09/2012 - 10:18
Здравствуйте.
Комплектация следующая: arduino nano, кнопка и Led (подключено все по стандартным схемам с примеров ардуинных).
Задача следующая (упращенная): если при включении ардуины кнопка была нажата - Led мигает с одной частотатой, если при включении ардуинки кнопка не нажата - Led мигает с совершенно другой частотой.
Но получается так что даже если при включении кнопка нажата, то ардуина обрабатывает ее как "кнопка не нажата".
код:
const int buttonPin = 2; // the number of the pushbutton pin int buttonState; // the current reading from the input pin int lastButtonState = LOW; // the previous reading from the input pin int ledPin = 9; // LED connected to digital pin 9 long lastDebounceTime = 0; // the last time the output pin was toggled long debounceDelay = 50; // the debounce time; increase if the output flickers int dCount; int fadeValue = 255; void setup() { pinMode(buttonPin, INPUT); // nothing happens in setup } void loop() { if (debounce() == 1) //если нажата {leds(1) ; leds(1); leds(1); leds(1); } else {leds(5); //если не нажата leds(5); leds(5); leds(5); } } int debounce() { // read the state of the switch into a local variable: int reading = digitalRead(buttonPin); // check to see if you just pressed the button // (i.e. the input went from LOW to HIGH), and you've waited // long enough since the last press to ignore any noise: // If the switch changed, due to noise or pressing: if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer // than the debounce delay, so take it as the actual current state: buttonState = reading; } // set the LED using the state of the button: digitalWrite(ledPin, buttonState); // save the reading. Next time through the loop, // it'll be the lastButtonState: lastButtonState = reading; return buttonState; } void leds(int d) { pinMode(ledPin, OUTPUT); digitalWrite(ledPin, LOW); delay(d*50); digitalWrite(ledPin, HIGH); delay(d*50); digitalWrite(ledPin, LOW); delay(d*50); digitalWrite(ledPin, HIGH); delay(d*50); }
Подскажите как можно решить эту проблему?
С уважением,
zz-vop
Вам нужно функцию debounce() переместить из loop (17 строка) в setup, предварительно объявив глобальную переменную.
объявляете переменную:
в setup() присваиваем этой переменной состояние кнопки:
в loop() меняем 17 строку вот так:
Или при объявлении переменной сразу присвоить состояние кнопки:
Сделал, но результат такой же.
Для эксперимента я объявил boolean button = 1, потом включил с нажатой кнопкой (по идее должно было сработать), но цикл пошел по "кнопка не нажата".
Спасибо. я вообще избавился от функции debounce(), а напрямую digitalRead(buttonPin) использовал и все как надо стало.
1. debounce, в вашем случае, не имеет смысла так как вы обильно вызываете delay() внутри loop. Смысл проверять прошло ли 50 миллисекунд с прошлого нажатия если саму проверку мы делаем не чаще чем в 200 msec? Конечно прошло. Само использование delay() уже является одним из способов debounce. Два основных подхода "програмнного антидребезга возможны" - или опрашивать кнопку не слишком часто, или опрашивать "часто как только возможно", но следить за тем сколько времени прошло с прошлого нажатия.
2. При включении debounce тем более не имеет смысла. Про какой lastButtonState может идти речь если мы только включились?
Вообщем debouce у нас тут "дважды не нужен". Нужно тупой digitalRead в setup()
Далее. Зачем эти портянки-повторения вызвовов leds(...)? Любую портянку можно заменить на цикл. for(...). Но если вспомнить что loop() это уже цикл, то и этого не нужно. Достаточно, в loop(), один раз вызывать leds с нужным параметром.
И input можно не включать кнопку. По умолчанию они все на Input. Хотя чистой ошибкой это не является. Для того что-бы легче было читать код можно и явно это указать. Так что это скорее "вопрос стиля", чем "правильно/не правильно".
Далле ledPin на выход достаточно включить один раз, в setup(). И сами пины лучше объявлять через #define, а не константы
Итого: в setup посмотрели на кнопку и решили с какой частотой мигать будем, в loop - мигаем. все.
Ну и естественно не забывает что кнопку нужно подключать в соотвесвии со скетчик. Данный скетч подразумевает что кнопка подключена от пина к питанию, а сам пин подтянут, внешним(!) резистором, к земле.
Спасибо. я вообще избавился от функции debounce(), а напрямую digitalRead(buttonPin) использовал и все как надо стало.
Не успел :) У вас вышло короче чем у меня?
а это что-то для меня новенькое.... можно поподробнее?
я так понял аналогично:
а это что для меня новенькое.... можно поподробнее?
сокращенный синтаксис для if. Грубо говоря можно напискать такую гипотетическую функцию
И вызывать ее
так понятно что происходит? Ну а так как написать такую функцию не просто. Из-за того что трудно объяснить компилятору что такое ЛЮБОЙ_ТИП, и не хочется делать писать такую для кажого типа вроде ifffInt, ifffByte и т.п., а нужда в этом - довольно часта, то эту функцию встроили в компилятор. Добавили "синтансический сахар". Ну и придумали, что-бы отличать от обычных функций особый сопрособ вызова.
УСЛОВИЕ?ЗНАЧЕНИЕ1:ЗНАЧЕНИЕ2
Эта конструкция вернет ЗНАЧЕНИ1 если условие истинно и ЗНАЧЕНИЕ2 если нет.
я так понял аналогично:
В данном случае - да. Но все -таки это ближе к "функции" чем к простому if. А если нам нужно два разных условия проверить? Ище и домножить, например, на разные значения по состоянию второй кнопки
Тогда как? Перебирать 4-ре варинта? Четыре if-а делать? Или два. Но прийдется водить дополнительную переменную.
P.S. Но компилятор, в любом случае, естествнно развернет это в обычные if-ы. Это просто "что-бы код легче читался".
Ладно. Перепишим так что-бы не смущать сокращенным if-ом. Но и полный if-elese я не хочу использовать. Установим значением переменной под дефолту, и будем метья его сли нопка нажата
P.S. Хотя, конечно, в споровождении такой код намного хуже. Значения "разбросанны по скетчу". При изменениях нужно два места найти и поменять их "синхронно".
[...]
Из-за того что трудно объяснить компилятору что такое ЛЮБОЙ_ТИП, и не хочется делать писать такую для кажого типа
[...]
Ну, если начальник отдела подношений не берет, то ведь есть же еще и референты ;)
Пишем определение
и готово. Можно использовать любые типы (естественно, удовлетворяющие синтаксису). Препроцессор сделает все за нас:
Спасибо. Много нового узнал.
Пишем определение
Ну я же сказал "трудно", а не "не возможно". Я же давал на примере функции, а не деректив препроцессора (так еще их объяснять нужно). Можно еще и через шаблоны сделать.
К тому же через #define у вас получилось только "присваивать переменной".
И лабуду типа
вашим дейфаном уже не напишешь. Он может только "присвоить в зависимости от условия", но не "вернуть значение".
Сейчас проверить не начем, а так заработает?
Можно еще и через шаблоны сделать.
Только через шаблоны (что-бы действительно получить функцию) нужно будет ее определение выносить в отдельный .h файл. Из-за глюков IDE который в скетче не понимает такой синтаксис C++.
Так что, лучше оставить эту функцию как "гипотетическую", просто для объяснения идеи сокращенного синтаксиса.
Кстати так же самая проблема с использованием enum или struct в качестве параметров функций. "Прямо в скетче" - не работает, а вот если вынести их определение в отдельный файл - нет проблем. И в скетче будет работать.
Сейчас проверить не начем, а так заработает?
Нет. Открывающих круглых скобок 6-ть штук, закрывающих -5ть. Не скомпилится. Где-то накосячили.
Но "как идея" - сработает. Раз "это функция", то ничто не мешает использовать саму себя в качестве аргументов.
Я же сказал "как идея" - сработает. Проверять конкретно эту строчку. Дописывать сейчас "все окружающие" (определение пинов), сидеть "жакать кнопки, ребуть плату, отписываться о результатах" - у мня нет времени.
Если хотите - напишите скетч целиком. Вместо digitalRead(buttonPin) используйтеся какие-нибудь bool переменные. Устанавливайте их. Результат - выводите в Serial.
Если проблема только "нет под руками на чем проверить" - запущу и отпощу его вывод. Но сам "рабочий скетч", который можно просто copy-past и запустил - пишите сами.
Я просто поправил.
Код:
Вывод:
Не стал создавать новую тему.
Вот код:
Я не исправлял функцию лед() она тут просто чтоб визуализировать процесс.
Как по моему мнению должен был бы исполняться код, представленный выше: при включеннии питания кнопка нажата и переменная Dsett = 0; -> переходим в условие и начинаем отсчитывать сколько горел LED. Отпускаем кнопку светодиод гаснет на время "сколько горел LED" потом загарается на такое же время. Дальше светодиод судорожно мигает и переменная Dsett становится равной 1. Потом когда я нажимаю кнопку начинается уменьшение частоты ШИМ (наглядно показывается на светодиоде). когда отпускаю - светодиод просто горит с "нужным" ШИМ.
Но на самом деле ШИМ нифига не настраивается. все зацикливается на
Я уже испробовал и "else if" чет вообще никак. У меня ощущение, что на условие (debounce() == 1 && Dsett == 1) вообще наплевать ардуинке/компилятору. Где я накосячил? может я не понимаю логику работы else/if/else if... (я осознаю говнокодовость выше написанного).
Отдельно без наворотов ШИМ без проблем настраивается вот так вот простым удержанием кнопки и по "отпусканию" кнопки ШИМ такой как надо...
Заранее спасибо.
Сейчас нет времени вглядывать в код, что-бы точно указать строчку, но общие направление поиска должно быть таким:
1. Как я уже писал механизм debounce() и использование delay() - не совместимые вещи. Если "оно работает", то значит debounce вам совсем не нужен. И вы используете его не понимая принципа его работы. Если, все-таки, хотите debounce, что-бы было все "по взрослому" - смотрите в разделе програмирование пример "Мигаем диодом без delay()".
2. Такое впечатление, что вы забываете, что loop() это цикл. Эта функция вызывается раз-за разом бесконечно. Вам нужно смотреть ЧТО у вас происходит ПОСЛЕ того как вы включили шим. Всего на 100 милисекунд. Далее, скорее всего, loop заканчивается и начинается сначала, там попадает в какой-то вариант где вы опять вызываете leds(). Который, естественно отменяет действие шим, и останавливает скетч кучей своих delay(). В результате шим у вас имеет шанс проявить себя всего 100 милисекунд.
Поставте там delay() ощутимей, что-бы точно увидеть что "вы туда попадаете" или Serial.print сделайте. Можете вообще натыкать Serial.print-тов во все ветки и посмотрите куда ваша логика бегает в реальности, а не "как вы думаете".
Спасибо. натыкаю Serial.print'ов. посмотрю куда он там бегает. Вы правы. я все время забываю, что void loop() это бесконечный цикл.
я все время забываю, что void loop() это бесконечный цикл.
Можете написать так:
С точки зрение логики это будет идентично. Расплатитесь несколькими байтами памяти, зато будет "перед глазами" и точно не забудете :)
так и сделал)
так и сделал. нашел все косяки. во всем виновата невнимательность и спешка. все переписал красиво. заработало
спасибо