Леший в мире Ардуины

Первоначально эта статья задумывалась как продолжение Еще одни часы на Ардуине. Часть 2. Выводим время на экран . Но потом решил что будет лучше "освоится с кнопками отдельно", а потом эти наработки — применим к построению часов.
Поэтому, в этой статье я буду использовать вывод в Serial, а не на экран. Что-бы те у кого нет такого LCD KeyPad Shiled могли повторить у себя мои эксперименты с помощью обычных кнопок и резисторов.

Если вы будете собирать cамостоятельно не обязательно брать "в точности такие же номиналы резисторов", мы все равно будет учится "калибровать скетч" под те резисторы которые удалось найти 🙂

Железная составляющая

Согласно документации на шилд кнопки этого шилда подключены к пину A0.
Когда мы нажимаем кнопку у нас образуется делитель напряжения . Его верхнее плечо равно 2K, а нижние — зависит от того какую кнопку мы нажали. C помощью A0 пина мы замеряем какое напряжение образовалось на этом делителе и так узнаем "какая кнопка была нажата".

Давайте посмотрим что происходит когда мы нажимаем кнопку LEFT. Ток пройдет через резистор R2 (верхние плечо делителя) и пойдет через резисторы R3,R4,R5 , через кнопку, в землю. Как мы знаем (надеюсь) последовательное соединение резисторов можно мысленно заменить одним резистором с номиналом равным их сумме. Складываем R+R4+R5=0.33K+0.62K+1K=1.95K . Это у нас получился номинал нижнего плеча делителя при нажатой кнопке LEFT. Верхнее плечо мы уже знаем — 2K. Далее с помощью закона ома, калькулятора или онлайн сервиса вычисляем что делить 2K/1.95K должен дать нам на выходе 2.47V (при пяти-вольтовом питании) . Это напряжение мы прочитаем с помощью analogRead(A0).
Но analogRead() возвращает нам значение не в вольтах, а в неких абстрактных "попугаях". Из документации мы знаем что " Напряжение поданное на аналоговый вход, обычно от 0 до 5 вольт будет преобразовано в значение от 0 до 1023, это 1024 шага с разрешением 0.0049 Вольт." Значит при нажатии кнопки LEFT analogRead() вернет нам число 2.47V/0.0049V

=504
По этой цифре мы и можем понять что нажата кнопка LEFT.

Вообщем-то, если мы поняли суть делителя. То мы можем немного "схитрить" и сразу высчитывать значение "в попугаях", не занимаясь конвертацией в "вольты". Главное соотношение номинала верхнего и нижнего плеча. Напряжение на делителе вычисляется Uвых.=Uпит. * Rнижнего /(Rверхние+Rнижнее) . В "попугаях" у нас Uпит.=1024.
Подставляем: 1024*1.95/(2+1.95)

=505 (цифра вышла на "один попугай больше" за счет округления, нам это не существенно).

Для закрепления давайте еще посчитаем что выйдет если нажать DOWN. Нижнее плечо, в этом случае, у нас образуется резисторам R4 и R4 , Rнижние=330 Ом + 620 Ом= 0.33K+0.62K=0.95K
Подставляем Uвых=1024*0.95/(2+0.95)

= 330
Значит, при нажатии кнопки DOWN, analogRead(A0) нам будет возвращать цифру 330
Вернее "около этой цифры". Так как реальные, в отличии от идеальных, резисторы имеют погрешность. От процентов до десятков процентов.

А можно как-то не заниматься этими расчетами?

Что в "переводе" означает такие значения для кнопок

  • ничего не нажато — 1023
  • RIGHT — 0
  • UP — 98
  • DOWN — 253
  • LEFT — 405
  • SELECT — 635

Так а как же читать кнопки?

Только теперь мы можем понять "почему она именно такая". Что значат эти цифры. И перепроверить производителя если он ошибся. Скажем для кнопки DOWN. Судя по коду кнопка будет опознаваться если analogRead(A0) вернул число в диапазоне от 250 до 450 (точнее 451)
Смотрим "намерянные цифры". У меня DOWN возвращает 253. Что "попадает в диапазон". Кнопка распознается правильно. Хотя и опасно близко к границе диапазона. Может начать "глючить" (температура поменялась и т.п.)
Смотрим кнопку "SELECT’. По коду должна быть в диапазоне 650-850. А у меня — 635. Значит эта функция с моим шилдом будет работать не верно. Вместо SELECT распознает кнопку LEFT.
Но. ниже в комментариях мы видим еще цифры. Для старой версии шилда. Там другие диапазоны. Там SELECT должен лежать в интервале 555-790 — мне подходит 🙂
DOWN — должен лежать в 195-380 , а у меня 253. Тоже все верно.
LEFT/UP/RIGHT — тоже все совпадает.
Вывод — у меня версия шилда 1.0 Мне нужно закоментировать (или выкинуть) версию кода для V1.1 и использовать "For V1.0"
К сожалению нигде на шилде я не смог найти указания его версии. Так что пришлось выяснять "кто он" вот таким способом.

И все это было только ради того что-бы выяснить какая версия шилда?

Обратите внимание, что для btnNONE — у нас нет пина. Так как мы "сменили парадигму". Ушли от "код клавиши", к идее "цифровых пинов". А для обычных пинов — нет пина "никакой" 🙂

Следующие что мы поменяем в "идеологии". Мы будем проверять не "попадается ли значение analogRead()" в какой-то диапазон. А возьмем "ожидаемое значение" (которое получили с помощью измерительного скетча выше) и будем сравнивать analogRead с ним. Если он "отличаемся" не больше чем, скажем на 50 — cчитаем что кнопка нажата. Если больше — считаем не нажатой.

Но что-бы написать эту функцию нам нужно для каждой кнопки задать "ожидаемые значение analogRead()". Сделаем это с помощью массива структур

Ну а теперь, мы можем написать свою версию digitalReadA(). Которая может читать и обычные цифровые пины, так и "псевдо".

Вот и все.
Теперь мы можем взять любой стандартный пример, скажем
http://www.arduino.cc/en/Tutorial/Switch — включение, выключение светодиода по нажатию обычной кнопки и вся его "переделка" сведется к замене двух строчек :
В качестве inPin мы укажем не D2, а PIN_SELECT и вызов функции digitalRead(inPin) заменим на вызов нашего "расширенного аналога" digitalReadA(inPin)

Правда мне пришлось сделать еще одно косметическое изменения. Я поменял номер пина на котором мигаем диодом с 13-того (встроенный в ардуину диод), на 10-тый. outPin = 10 сделал.
Сути это не меняет. Просто с нахлобученным шилдом — не видно встроенного светика. Он оказывается "под ним". Поэтому пришлось мигать 10-тым пином. На нем висит подсветка дисплея.
Так что если вы владелец шилда — у вас будет включатся выключатся подсветка при нажатии кнопки SELECT. Если шилда у вас нет и вы сами собирали/подключали кнопки — оставьте outPin=13 как в оригинальном туториале и смотрите на встроенный светодиод.


Источник: alxarduino.blogspot.com