Работа с кнопками. В помощь новичку.
- Войдите на сайт для отправки комментариев
ВСЕМ НЕОФИТАМ, ЖАЖДУЩИМ ЗАДАТЬ ВОПРОС!
ДАННАЯ ТЕМА НЕ ПРЕДНАЗНАЧЕНА ДЛЯ ОБУЧЕНИЯ ВАС ОСНОВАМ ЯЗЫКА И ПРИЕМАМ СОВОКУПЛЕНИЯ ДВУХ И БОЛЕЕ СКЕТЧЕЙ. В ТЕМЕ РАССМАТРИВАЮТСЯ СПОСОБЫ ПОДКЛЮЧЕНИЯ КНОПОК, ПОДАВЛЕНИЕ ДРЕБЕЗГА, ФИКСАЦИЯ СОБЫТИЙ.
ВСЕ ВЫХОДЯЩЕЕ ЗА ОЗНАЧЕННЫЕ РАМКИ К РАБОТЕ С КНОПКАМИ НЕ ОТНОСИТСЯ И ОБСУЖДАЕТСЯ ВО ВНОВЬ СОЗДАННЫХ ИЛИ ПОДХОДЯЩИХ ТЕМАХ.
ОТВЕТЫ НА ОСНОВНЫЕ ВОПРОСЫ, ПО КНОПКАМ, МОЖНО НАЙТИ НА ПЕРВЫХ ПЯТИ СТРАНИЦАХ ТЕМЫ, УЧИТЕСЬ ЧИТАТЬ.
Ардуино и кнопка.
Кнопка – простейшее электромеханическое устройство.
Кнопки бывают двух видов.
1.Кнопки (переключатели) с фиксированным положением.
2.Так называемые тактовые кнопки (которые возвращаются в исходное положение).
С первыми все ясно, а вот как работать со вторыми ?
В этой статье я расскажу, как правильно подключить кнопку к МК и как работать с ней программно. Так же расскажу, как подключить несколько кнопок к одному пину МК.
Обычно, самый первый раз, кнопку пытаются подключить вот так.
Это НЕ ПРАВИЛЬНОЕ подключение.
Дело в том, что пин МК (в режиме входа) должен иметь заранее известное состояние (1или 0).
В «подвешенном» состоянии будет собирать внешние наводки (статические, электрические и электромагнитные излучения).
Чтобы привести пин в заранее известное состояние и используют подтягивающие резисторы.
Они бывают двух видов, верхние и нижние подтяжки.
Верхние (pull-up) подключаются к плюсу питания и нижние (pull-down) к минусу.
В ардуино есть встроенные подтягивающие резисторы (pull-up) которые можно включить программно, но я не советую их использовать.
ПРАВИЛЬНОЕ подключение кнопки.
В данном случае, когда кнопка отключена, пин будет подключен к земле через резистор, сопротивление которого заведомо меньше внутреннего сопротивления пина.
Поэтому наводка, попавшая на пин, стечет в землю. Если же подключен полезный сигнал (+5в) то он будет стекать в пин (незначительная часть сигнала стечет в землю через подтяжку).
В итоге, при нажатой кнопке, у нас будет стабильный сигнал (+5в), а при отпущенной кнопке будет стабильный ноль.
Рассмотрим несколько простых программных примеров.
void setup() { pinMode(13, OUTPUT); } void loop() { digitalWrite(13,analogRead(14)); //состояние входа равно состоянию выхода }
Это самый простой пример. Немного усложним его
void setup() { pinMode(13, OUTPUT); } void loop() { if(digitalRead(14)==HIGH)//если кнопка нажата ... { digitalWrite(13,HIGH);//включаем светодиод } else//если не нажата... { digitalWrite(13,LOW);//выключаем } }
Этот пример можно инвертировать. Когда кнопка не жата светодиод горит, когда нажата – нет.
Идем дальше.
void setup() { pinMode(13, OUTPUT); } void loop() { if(digitalRead(14)==HIGH)//если кнопка нажата ... { digitalWrite(13,!digitalRead(13));//инвертируем состояние пина delay(500);//небольшая защита от "дребезга" контактов кнопки } }
Если удерживать кнопку, то получим мерцание светодиода с частотой заданной функией delay.
А если нам нужно включить что то по удержанию кнопки?
Для этого введем переменную val.
int val=0; void setup() { pinMode(13, OUTPUT); } void loop() { if(digitalRead(14)==HIGH)//если кнопка нажата ... { val++;// прибавляем к переменной 1 при каждой смене цикла. delay(500);//небольшая защита от "дребезга" контактов кнопки } else { val=0; } if(val>=5) { digitalWrite(13,!digitalRead(13));//инвертируем состояние пина val=0; } }
Здесь я использовал простейший «самодельный» таймер.
Рассмотрим пример с более сложным таймером.
long previousMillis = 0; int val=0; void setup() { pinMode(13, OUTPUT); } void loop() { if(digitalRead(14)==HIGH)//если кнопка нажата ... { if (millis() -previousMillis >500) { previousMillis = millis(); val++; } } else { val=0; } if(val>=5) { digitalWrite(13,!digitalRead(13));//инвертируем состояние пина val=0; } }
Основной плюс этого таймера это то, что он не использует паразитную функцию delay и, соответственно, не тормозит программу.
Очень не советую использовать функцию pulseIn для данных целей (да и вообще не советую).
Потому что эта функция использует все программные таймеры ардуино.
С функцией pulseIn НЕ будут работать
Tone()
Millis()
analogWrite()
Так же не будут работать сервоприводы.
Теперь рассмотрим вариант, когда нам нужно сделать лишь одно действие по одному нажатию кнопки (предыдущие программы циклично повторяли действие при удержании)
Для этого введем новую переменную flag (названия переменных могут быть какими угодно).
int flag=0; void setup() { pinMode(13, OUTPUT); } void loop() { if(digitalRead(14)==HIGH&&flag==0)//если кнопка нажата // и перемення flag равна 0 , то ... { digitalWrite(13,!digitalRead(13)); flag=1; //это нужно для того что бы с каждым нажатием кнопки //происходило только одно действие // плюс защита от "дребезга" 100% } if(digitalRead(14)==LOW&&flag==1)//если кнопка НЕ нажата //и переменная flag равна - 1 ,то ... { flag=0;//обнуляем переменную flag } }
Алгоритм такой. Нажали кнопку – загорелся светодиод, удерживаем кнопку – ничего не происходит (светодиод горит). Отпустили кнопку – светодиод горит.
Для того чтобы погасить светодиод нужно повторно нажать кнопку.
Т.е. нажали – горит, отпустили, нажали – не горит.
Можно инвертировать действие вот так
int flag=0; void setup() { pinMode(13, OUTPUT); } void loop() { if(digitalRead(14)==HIGH&&flag==0)//если кнопка нажата // и перемення flag равна 0 , то ... { flag=1; //это нужно для того что бы с каждым нажатием кнопки //происходило только одно действие // плюс защита от "дребезга" 100% } if(digitalRead(14)==LOW&&flag==1)//если кнопка НЕ нажата //и переменная flag равна - 1 ,то ... { digitalWrite(13,!digitalRead(13)); flag=0;//обнуляем переменную flag } }
Нажали – ничего, отпустили – горит. Повторно нажали, отпустили – не горит.
Теперь сделаем небольшое меню.
Меню будет содержать четыре режима (можно сколько угодно, но для примера хватит и четырех).
Меню будет управлять двумя светодиодами.
Введем еще одну переменную – regim.
int regim=1; int flag=0; void setup() { pinMode(10,OUTPUT); pinMode(9,OUTPUT); } void loop() { if(digitalRead(14)==HIGH&&flag==0)//если кнопка нажата // и перемення flag равна 0 , то ... { regim++; flag=1; //это нужно для того что бы с каждым нажатием кнопки //происходило только одно действие // плюс защита от "дребезга" 100% if(regim>4)//ограничим количество режимов { regim=1;//так как мы используем только одну кнопку, // то переключать режимы будем циклично } } if(digitalRead(14)==LOW&&flag==1)//если кнопка НЕ нажата //и переменная flag равна - 1 ,то ... { flag=0;//обнуляем переменную "knopka" } if(regim==1)//первый режим { digitalWrite(9,LOW);//выключаем все светодиоды digitalWrite(10,LOW); //здесь может быть любое ваше действие } if(regim==2)//второй режим { digitalWrite(10,HIGH);//включае красный светодиод digitalWrite(9,LOW); //здесь может быть любое ваше действие } if(regim==3)//третий режим { digitalWrite(9,HIGH);//включае зеленый светодиод digitalWrite(10,LOW); //здесь может быть любое ваше действие } if(regim==4)//четвертый режим { digitalWrite(9,HIGH);//включаем светодиоды одновременно digitalWrite(10,HIGH); //здесь может быть любое ваше действие } }
Внутреннй подтягивающий резистор.
В микроконтроллерах ATmega168 и ATmega328 есть внутренние подтяжки. Они имеют номинал 20Ком и включаются программно. Нужно иметь в виду что внутренняя подтяжка "Прижимает" пин только к +5в.
В связи с этим нужно инвертировать логику.
Ранее мы рассматривали примеры в которых одна нога кнопки подключена к +5,вторая к пину а пин к GND (через внешнюю подтяжку) . С внутренней подтяжкой все наоборот.
Одна нога кнопки подключается к GND, другая к пину (никаких внешних резисторов не нужно).
В этом случае 1 на цифровом входе означает отсутствие сигнала а 0 - присутствие.
Вот простой пример включения внутренней подтяжки.
Делитель напряжения и ЦАП.
Резистивный делитель напряжения представляет собой два резистора, включенных последовательно друг другу и параллельно источнику питания.
Вот так.
Данный делитель рассчитывается по формуле
Пример расчета
Примем Uвх = 5в , R1 = 1К, R2 = 1К.
5*1/(1+1)=2.5в
Резисторы делителя называют плечами. Верхнее плечо – Uвх, нижнее - GND.
Т.е. R1 – верхнее плечо, R2 – нижнее плечо.
Если номиналы обоих резисторов равны напряжение будет поделено пополам.
Важно знать, что общее сопротивление делителя должно быть значительно меньше сопротивления нагрузки подключенной к нему (примерно в 100 раз).
НО общее сопротивление делителя не должно быть и слишком низким. В этом случае мы получим нагрев делителя и расход тока в пустую.
Не опускайте общее сопротивление ниже 4.7К.
Вобщем, идеальный диапазон сопротивлений от 4.7К до 50К
Теперь рассмотрим ЦАП на основе делителя напряжения.
ЦАП - Цифро-аналоговый преобразователь.
Устройство преобразует цифровой сигнал в аналоговый.
Подключение двух кнопок к одному пину.
На этой схеме изображен простой двух канальный резистивный ЦАП.
Рассмотрим некоторые важные моменты.
Резистор R3 является подтягивающим и его номинал не стоит опускать ниже 4.7К.
В то же время R3 является нижним плечом делителя напряжения.
Когда кнопки не нажаты на пине АЦП – лог 0.
Нажатая кнопка К1 образует делитель напряжения с номиналами плеч R1=4.7K, R2=10K.
Считаем по формуле.
5*10/(4.7+10) = 3.4в
Когда нажата кнопка К2 номиналы делителя будут R1=3 , R2=10K.
5*10/(3+10) = 3.8в.
Но что произойдет, если обе кнопки будут нажаты одновременно?
В этом случае верхнее плечо делителя будет состоять из двух резисторов R1 и R2 включенных параллельно.
Общий номинал параллельно включенных резисторов считаем по формуле
Rобщ = (4.7*3)/(4.7+3) = 1.83K
Считаем выходное напряжение делителя
5*10/(1.83+10) = 4.22в.
Напишем простую программу.
Количество каналов ЦАПа может быть сколь угодно большим (и соответственно количество кнопок).
Нужно точно рассчитывать номиналы резисторов. И уделять особенное внимание соотношениям номиналов между собой.
Ну, вот и все (или почти все) о кнопках.
Данная статья была ранее опубликована мной на http://forumdvrobot.ru/forum/3-21-1
P.S. Просьба к админам, прикрепите статью куда нибудь , что бы вниз не ушла.
Внутренняя подтяжка тянет только вверх. Внешней можно прижать и к земле.
К тому же статья расчитана на новичков которым нужен наглядный пример. Внешняя подтяжка и есть тот наглядный пример, который можно потрогать, измерить, изменить номинал и т.д.
Данная статья и примеры программ не являются "Истиной в последней инстанции". Это мой личный опыт и мой личный путь "Проб и ошибок".
И что что она "тянет" только "вверх" - это никак не отражается на качестве работы кнопки. То что нужно потрогать - это да, для обучения/понимания тоже да, но не советовать ими пользоваться это на мой взгляд не верно, не нужно вводить в заблуждение "новичков", что внутренняя подтяжка - это плохо. Это очень удобная и нужная вещь, просто описание работы кнопок с внутренней подтяжкой выходит за рамки этой статьи.
UPD: И да, кстати, не замечал раньше этого комментария: // плюс защита от "дребезга" 100% - уберите, не дурите людям голову, нет там никакой защиты от дребезга.
Одно из решений "аналоговой клавиатуры", которое можно подредактировать и под вашу схему:
данный код написан под эту схему
как видите количество кнопок задается параметром NUM_KEYS,
а "диапазоны" акуратненько "лежат" в массиве adc_key_val[].
maksim, в приведенной вами схеме не совсем понятно что будет происходить при одновременно нажатых кнопках.
Убирать скобки очень плохо, формула 5*1/1+1=2.5 убивает, а
5*1/(1+1)=2.5 понимается совсем по другому.
>>Убирать скобки очень плохо, формула 5*1/1+1=2.5 убивает, а
5*1/(1+1)=2.5 понимается совсем по другому.<<
Спасибо что указали ошибку. Исправил.
Народ, привет!
С точки зрения новичка прошу рассмотреть пример подключения кнопки с внутренней подтяжкой.
А так же указать как включать внутреннюю подтяжку.
а про это где можно подробнее почитать? Если я правильно понимаю, то это 3,4в на первой кнопке? Как вообще этот диапазон вычисляется или есть какие-то табличные значения?
>>То есть если нажать S4, то S3 и S2 будут игнорироваться. Схема, кстати, взята с коммерческого шилда.<<
Примерно так я и думал. Это не есть хорошо. Достаточно немного изменить включение резисторов и кнопки можно будет отслеживать и две и три и все сразу.
>>а про это где можно подробнее почитать? Если я правильно понимаю, то это 3,4в на первой кнопке? Как вообще этот диапазон вычисляется или есть какие-то табличные значения?<<
Да это 3.4в . Если вы имеете в виду диапазон АЦП, то это от 0 до 1023 . Что соответствует напряжению от 0 до 5в. Например значение 512 это 2.5в.
А вот вам конкретый множитель - 0.0048828125. Если умножить значение пина АЦП на этоу цифру то получите точное напряжение в вольтах.
Народ, привет!
С точки зрения новичка прошу рассмотреть пример подключения кнопки с внутренней подтяжкой.
А так же указать как включать внутреннюю подтяжку.
Эх... если бы не "специфичность темы" - послал-бы вас в документацию. В любом случае привыкайте искать ответ вначале там. Все равно на все темы такие ветки написать не возможно. Идете в раздел "Программирование" (шапка сайта) и в "базовые и полезные знания необходимые для успешного программирования под платформу Arduino" читаем Цифровые выводы, где есть глава "Подтягивающие (нагрузочные) резисторы". Так же, можно увидеть "как их включать" в описании фунции digitalWrite() (а прочитать описание всех базовых функций - тоже нужно).
Ладно. Считайте это не "посылом в документацию", а рассказом "где это искать, если нужно".
Включение - простейшие. Такое же как вообще без потяжки, только не к питанию, а к земле
Включаем подтяжку, банальным digitalWrite(D2,HIGH) - на порте включенном на ВХОД (надеюсь вы уже прочитали про это в документации).
Работат с подтянутой вверх кнопкой, отличается только одним. Теперь не нажатая кнопка это HIGH, а нажатая LOW. То есть значения "инвертировались".
Вот как выглядит в коде зажигание диода по такой кнопке
В реальности ни разу не видел что-бы кто-нибудь так делал, но для "параноиков" приведу "грамотную схему включения".
Вне зависимости от того внешняя подтяжка или внутреняя, к питанию или земле - между кнопкой и пином дуины должен стоять резистор малого номинала (100 ом).
Для чего он нужен? При нормальной работе - ни для чего. Но что произойдет если мы случайно включим порт на ВЫХОД, дадим в него HIGH и нажмем кнопку? У нас на пине образуется 5V, через кнопку они замкнутся на землю и мы полчим короткое замыкание - большой ток через пин. Этим мы имеем шансы спалить пин или даже весь контроллер.
А случайно включить на выход мы можем по всякому. И в коде ошибится (особенно если будет осваивать прямую запись в порт, без digitalWrite()), так и банально просто - схема у нас собрана одна, а мы залили какой-то другой скетч, у которого это "выход" (или наоборот сегодня собрали новую схему, а в контроллере старый скетч "со вчера", про который мы забыли)
Если же там стоит резистор, то, по закону Ома, он пропустит через себя (а значит и через пин) ток, не более чем 5v/100ом=0.05A=50mA. Что тоже чуток многовато для пина, но "не на долго" - уже не будет "смертельным".
Но еще раз. Это просто "предупреждение". Это знать нужно, но обычно считают (и я тоже :), что "уж я-то не ошибусь" поэтому "незачем усложнять схему лишним резистором" ;)
>>Вне зависимости от того внешняя подтяжка или внутреняя, к питанию или земле - между кнопкой и пином дуины должен стоять резистор малого номинала (100 ом).<<
С внешней подтяжкой к земле такого не случиться. Включение защитного резистора целесообразно , но стоит так же учитывать некоторое падение напряжения на нем.
>>Вне зависимости от того внешняя подтяжка или внутреняя, к питанию или земле - между кнопкой и пином дуины должен стоять резистор малого номинала (100 ом).<<
С внешней подтяжкой к земле такого не случиться.
Это почему? Если "подтяжка к земле", значит "кнопка к 5v". Включаем порт на выход, даем в него LOW и зажимаем кнопку (даже "давать" - не обязательно, он там уже будет по дефолту. достаточно включить на выход. так что тут "еще нужней"). Что произойдет если в подтяжке достаточно большой номинал стоит? К пину подведен 5v, а сам пин, внутри, подключился к земле. Рискнете на свое дуине проверить? ;)
Вообщем подобные резистор всегда "может спасти". Даже не только в кнопках. Моторы, светики и т.п. Во всех ситуациях когда мы не уверены какой там ток пойдет. Есть опасение "большого тока" - можно вкорячить защитный (токоограничивающий) резистор.
Включение защитного резистора целесообразно , но стоит так же учитывать некоторое падение напряжения на нем.
Если мы говорим про цифровые пины - не стоит "учитывать". Там довольно большой зазор "что считать логической единицей". К примеру если у нас подтягивающий 20кОм (внутренний такой номинал имеет), то защитный на 100 Ом даст нам падение всего в 0.02V, то есть в итоге на пин прийдется 4.98V Учитывая что логической единицей считается "все что выше 3v" (не помню точно, но что-то около этой цифры), то подобное падение точно можно не учитывать.
Вспоминать про него прийдется только если мы таким же макаром, начнем подключатся к аналоговым портам и работать с помощью analogRead, там уже это будет "небольшим искажением".
Если кому-нибудь захочется разобратся с кнопками/портами "досконально", могу порекомендовать статью AVR. Учебный курс. Устройство и работа портов ввода-вывода . Там немного, конечно, сложновато для новичка. Статья не "ардуинистая", а просто AVR-микроконтроллер описан (но, ардуина построена именно на нем), но понять "как порт устроен" и "зачем нужен подтягивающий, как он работает" - можно.
Хотя, при желании, все что там описано страшными словами "PIN, PORT, DDR это регистры конфигурации порта." можно использовать и при программировани ардуины. Вместо digitalRead/digitalWrite/pinMode . Но это уже "продвинутый уровень". Почитать про это можно тут: Прямое управления выходами через регистры микроконтроллера Atmega
Вообщем "дополнительная литература" :)
long previousMillis = 0;
Основной плюс этого таймера это то, что он не использует паразитную функцию delay и, соответственно, не тормозит программу.
Прошу прощения, но не содержится ли в этом коде ошибка? Я попробовал этот код в симуляторе но никаких действий не происходит, цикл крутится но на пине 13 "светодиод" не загорается, переменная val имеет значение 0, previuosMillis так же значение 0, внезависимости от нажатия кнопки. Да забыл уточнить цифровой вход кнопки я установил не 14 а 9.
С уважением.
Александр.
Прошу прощения, но не содержится ли в этом коде ошибка? Я попробовал этот код в симуляторе но никаких действий не происходит, цикл крутится но на пине 13 "светодиод" не загорается, переменная val имеет значение 0, previuosMillis так же значение 0, внезависимости от нажатия кнопки. Да забыл уточнить цифровой вход кнопки я установил не 14 а 9.
Очень похоже что вы руками перенабирали этот пример и допустили ошибку (иначе как понять что у вас "millis() -previousMillis >500" превратилось в "millis() *previousMillis >500" ).
Прочитайте, внимательней ветку Вставка программного кода в тему/комментарий Там описанно и как правильно "забирать к себе код" с форума.
Leshak да я действительно забивал код от руки с экрана телевизора, и в этом месте символ не оч четабилен, вот я и пробовал подставлять другой знак но всеравно у меня цикл крутится в "холостую".
В данный момент он имеет такой вид:
P.S.
nestandart очень приятно встретить земляка, я с Ленинска-Кузнецкого. Сори за флуд.
Я бы, еще, посоветовал поменить "long previousMillis = 0" на "unsigned long previousMillis = 0". Не существенно (проблема проявится только при непрерывной работе дуины более 24-рех дней), но "так правильней будет".
Leshak да я действительно забивал код от руки с экрана телевизора, и в этом месте символ не оч четабилен, вот я и пробовал подставлять другой знак но всеравно у меня цикл крутится в "холостую".
А в чем это проявляется? Вы учитываете что для того что-бы он "что-то сделал" (переключил светик) нужно пять-раз нажать кнопку, с интервалом нажатий не быстрее чем пол-секунды? Хотя.... возможно я не понял что тут netstanart хотел показать сделать. Пусть он лучше сам ответит. Лично бы я попробовал бы выкинуть ветку else { val=0; } (кстати, ее вы тоже "набрали не туда", так что "осваивать по телевизору" - было явно плохой идеей).
А ишо, возможно, стоило вынести в отдельную ветку разбирательство именно с вашим примером. Оставить ее более чистой в качестве "учебного материала". Без разбирательств "ошибок набора".
Так же, если вы в симуляторе это гоняете. У вас может быть неправильно выставленна тактовая частота/фьюзы для камня. И все millis() будут врать (камень работает очень медленно, и "пол секунды" превратся в минуты).
>>nestandart очень приятно встретить земляка, я с Ленинска-Кузнецкого. Сори за флуд.<<
Никогда бы не подумал что в этом богом забытом краю есть еще люди увлекающиеся электроникой.
triada13, вот зачем вы набиваете программу вручную ? Если навести курсор на код , то в правом верхнем углу появляется набор значков, нажимаете значек "КОД" и копируете.
Вот сейчас , не поленился, спаял схему , залил ВАШ последний код - действительно не работает. НЕ МОЖЕТ БЫТЬ! Ведь во время написания статьи я несколько раз тестил все программы на реальном железе. Потом залил свою первоначальную программу.
Работает!
А теперь вопрос к вам triada13 ,найдете свою ошибку с трех раз ?
Странно что компилятор вообще "Съел" вашу программу.
>>Вы учитываете что для того что-бы он "что-то сделал" (переключил светик) нужно пять-раз нажать кнопку, с интервалом нажатий не быстрее чем пол-секунды? Хотя.... возможно я не понял что тут netstanart хотел показать сделать.<<
Это задержка действия. Нажимаем на кнопку и держим. Действие происходит после пяти секунд удержания кнопки.
>>Нажимаем кнопку....., 2-10 светодиодов включаются по порядку с задержкой например 1 секунда, ну и выключаются в обратном порядке .<<
На днях поработаю с вашей просьбой.
Вот сейчас , не поленился, спаял схему , залил ВАШ последний код - действительно не работает. НЕ МОЖЕТ БЫТЬ! Ведь во время написания статьи я несколько раз тестил все программы на реальном железе. Потом залил свою первоначальную программу.
Работает!
Чудеса да и только. Я не понимаю КАК оно может работать? Если оно постоянно val в ноль сбрасывает, сразу при отпускании кнопки? val у нас поднятся больше единицы - не может в принципе. А значит и достичь 5-ть что-бы переключить светик.
Ну может "чего-то не вижу". Залил, таки не работает :( Выкинул ветку else - заработало.
Вот мой код. В нем я сделал такие поправки:
1. Поправил тип previousMillis (не существенно, но что-бы "было аккуратно/правильно").
2. Выкинул ветку else (вот это главное изменение)
3. Включил подтяжку вверх, и поменял HIGH, на LOW (вообщем у меня кнопка подключена от пина к земле)
4. Поменял номер пина на A0 (ну просто у меня уже там кнопка стоит, лень было переподключать)
5. Вывожу в Serial, при нажатии кнопки текущие значение val (что-бы видеть что там происходит).
2nestandart: попробуйте свой код запустить не то что у вас локально в файле, а скопируйте с форума, неужели работает? речь идет про "Рассмотрим пример с более сложным таймером"
>>Я не понимаю КАК оно может работать? Если оно постоянно val в ноль сбрасывает, сразу при отпускании кнопки?<<
Так и должно быть. Пока мы держим кнопку val считает до пяти. Досчитал - включил светодиод. Не успел досчитать (отпустили кнопку раньше) - сбрасывается в ноль.
Действительно , else можно и убрать .
>>Ну может "чего-то не вижу". Залил, таки не работает<<
Вы какую прогу залили ? Из поста №27 или №1 ?
>>Nestandart про богом забытый можно сказать и о Кемерове, все зависит от того с чем сравнивать. ))<<
Я говорил о Кем.области в целом.
>>попробуйте свой код запустить не то что у вас локально в файле, а скопируйте с форума, неужели работает? <<
Если вы залили прогу из первого поста , то скорее всего вы просто не правильно юзаете девайс. Удерживайте кнопку пять секунд и светодиод переключится.
Чудеса да и только. Я не понимаю КАК оно может работать?
Любая программа работает, если ничего не трогать и не нажимать! МК же работает! :)
nestandart, не принимайте на свой счет, шучу просто.
>>Я не понимаю КАК оно может работать? Если оно постоянно val в ноль сбрасывает, сразу при отпускании кнопки?<<
Так и должно быть. Пока мы держим кнопку val считает до пяти. Досчитал - включил светодиод. Не успел досчитать (отпустили кнопку раньше) - сбрасывается в ноль.
Ага. Значит я, все-таки, не правильно понял что вы хотели сделать. Мне показалось что вы пытались поймать "пять нажатий".
Как-то слегка нетрадиционно (хотя на вкус и цвет) вы подошли к вопросу "удержания кнопки". Обычно просто засекают "время нажатия" и "время отпускания". Если разница между ними больше "то что нам нужно" - что-то делаем.
Nestandart щас ради интереса попробовал скопировать и вставить после этого изменил только пин кнопки. не работает, либо я не так симулирую нажатие кнопки.
Подскажите каков алгоритм нажатий кнопки? длительность нажатия, и длительность паузы между нажатиями?
Вот код:
С заказчиками такое сплошь и рядом. Скинешь готовую программу, отлаженую на железе. Он зальет на свое идентичное железо.
Сначала нормально, через полдня начинается. "Что то глючит" "Сначала работало а потом нет". Начинаются качели.
"Что делали" "Как подключали" и т.д. Ответ один - "ничего не делал , не знаю". Начинаем железо , буквально , по дорожкам прозванивать. Все нормально. Потом просишь его скинуть ТУ программу , которую ОН ШЬЕТ. И начинается "Найди десять отличий" от оригинала. Находишь. Спрашиваешь "Зачем в программу лез" ? Обычно сознаются извиняются. Но бывают и такие что "Не видел , не знаю" и точка.
>>каков алгоритм нажатий кнопки? длительность нажатия, и длительность паузы между нажатиями?<<
Нажимаем, держим пять секунд - загорается. Отпускаем (на любой промежуток времени) - горит. Опять нажимаем , держим - гаснет. И т.д.
Я не работаю с симуляторами так что не знаю. Но разве он может эмулировать удержание кнопки ?
Как-то слегка нетрадиционно (хотя на вкус и цвет) вы подошли к вопросу "удержания кнопки". Обычно просто засекают "время нажатия" и "время отпускания". Если разница между ними больше "то что нам нужно" - что-то делаем.
Что-бы небыть голословным, вот мой вариант "переключаем светик при удержании 5-ть секунд":
А в вашем варианте - не ясно зачем этот счетчик val++ вооще нужен. Ну просто увеличить интервал от 0.5 до 5-ти секунд и прямо там внутри - менять состояние пина.
Кстати , triada13 если бы вы раньше сказали что вы с Ленинска. Вам не пришлось бы заказывать дуину и т.д. черт знает откуда.
Вот вам ценная информация.
Слышали про компанию freeduino ? Если нет то они выпускают платы клоны ардуино , плюс торгуют некоторыми сопутствующими товарами.
Так вот это Кемеровская компания. Вот вам сайт http://www.freeduino.ru/arduino/index.html. Там в контактах телефон. Звоните и договариваетесь о компонентах , месте/времени встречи и т.д. Я думаю что съездить в Кемерово явно быстрей и лучше чем ждать несколько недель.
>>Может что то симулятор чудит? Хотя вы намекнули про ошибку, значит иду курить код.<<
Но код в вашем посте №41 правильный. Вы скопировали его с первого поста ?
Просто найдите разницу между кодом из поста №27 и кодом из поста №1.
Nestandart проблематично смотаться с Челябы до Кемерово, всетаки 1500 км. Да с 41 поста, но и он не пашет тоже.
Leshak в вашем коде помоему ошибка, во всяком случае дуиновский редактор ругается.
Походу не видит симулятор нажатия кнопки, надо завязывать с симулятором, и всетаки дождаться дуинку.
leshak, ваша программа работает , но показывать ее новичку не стоит.
IMHO стоит. Иначе потом дикие проблемы с пониманием отлавливания "фронта сигнала" и "спада". А нужно это - чуть ли не везде (да и "понять" без этого как ваша програма работает - тоже сложновато, "магия" получается).
Ну разве что использование pressTime одновременно и для "хранения времени" и "в качестве флага" - немного переборщил. Возможно отдельный флаг bool timerStarted=false; для этого стоило выделить в явном виде.
Можно в вещи типа if(pressTime) писать более явно if(pressTime>0).... но ведь это "обычная практика кода". Или
писать
Но ведь, много примеров написанно именно так. Нужно же когда приучать к тому что в реальном инете встретится :)
Я и так удержался от того как-бы я писал в "боевом коде" :
Кстати у вас исключена цикличность инвертации светодиода.
Вообще не понял. Особенно что такое "циличность инвертации светодиода".
Да и не понял, зачем вы делаете этот счетчик, увиличивающийся "раз в секунда", а потом проверяете что он достиг 5-ти? Не проще ли один раз "раз в пять секунд" и без счетчика?
>>Да и не понял, зачем вы делаете этот счетчик, увиличивающийся "раз в секунда", а потом проверяете что он достиг 5-ти?<<
Так понятнее.
>>Вообще не понял. Особенно что такое "циличность инвертации светодиода".<<
В моей первой программе , при удержании кнопки, светодиод циклично инвертится раз в 2.5 секунды. В последней прграмме я это убрал.
>>Да и не понял, зачем вы делаете этот счетчик, увиличивающийся "раз в секунда", а потом проверяете что он достиг 5-ти?<<
Так понятнее.
Но видимо не мне. Хотя, будем смотреть правде в глаза - мне стать на место "новичка" уже довольно трудно. Возможно вы правы.
>>Вообще не понял. Особенно что такое "циличность инвертации светодиода".<<
В моей первой программе , при удержании кнопки, светодиод циклично инвертится раз в 2.5 секунды. В последней прграмме я это убрал.
Ага. Ясно. Но у меня это тоже не сложно сделать. При инвертации диода делать не pressTime=0;, а pressTime=millis(); и все :) Проверил. Работает. Просто я такое поведение посчитал "нежелательным" и "задавил его" :) Но если ТЗ говорит "надо", то "нет проблемм" ;)
Вынужден признать что я гораздо тупее чем я думал. С автомобилями у меня гораздо лучше получается.
А вас "автомобилям" тоже учило сразу 3 челвека (помните про 7-мь нянек ;), удаленно, через форум, в темных очках ночью (это я на ваш телевизор намекаю) , да еще при отсутсвии самого автомобиля? :)
Так шо "по началу" - оно всегда трудно.
Нет меня не учили а посылали когда я спрашивал, иди мол читай Эльзу и не отвлекай от зарабатывания денюжги. Так что первые пять лет доходил своим умом и с помощью тех. руководства по ремонту автомобилей семейства VAG ELSA.
А насчет трудностей, ведь без них не интересно.
Нет меня не учили а посылали когда я спрашивал, иди мол читай Эльзу и не отвлекай от зарабатывания денюжги. Так что первые пять лет доходил своим умом и с помощью тех. руководства по ремонту автомобилей семейства VAG ELSA.
Вот. Меня тоже так учили "вот в той книге все есть" (даже без намека в какой главе). Только потому и знаю что-то ;)
>>Просто я такое поведение посчитал "нежелательным" и "задавил его" <<
Оно и есть не желательное. Просто у меня избавление от него (при помощи флага) описано в примерах ниже а должно было быть в этом. Пропустил.
По просьбе пользователя NE_XT.
>>А можно пример привести, задержки включения - выключения светодиода. Нажимаем кнопку....., 2-10 светодиодов включаются по порядку с задержкой например 1 секунда, ну и выключаются в обратном порядке .<<
Набросал программу последовательного включения/выключения ряда светодиодов. Я использовал три светодиода , но можно и больше (просто лень было паять).
При нажатии кнопки последовательно включаются светодиоды 1 , 2 , 3 с задержкой 150мс.
При повторном нажатии светодиоды , так же последовательно , выключаютя.
При удержании кнопки ничего не происходит.
leshak, будьте добры почистите тему. Диалоги с triada13 можно удалить полностью. Остальное на ваше усмотрение.
Можно и без дополнительных функций. Внутри loop.
Можно и без delay , но сейчас я этого делать не буду.
leshak, а как бы вы написали прграмму из поста №65 ?
Мне интересна оптимизация кода ( не силен я в ней).
Это просто оптимизация вашего кода
maksim, компилятор жутко матюгается на вашу программу.