А мы продолжаем возиться с тестовым стендом, попутно изучая особенности программирования микроконтроллера AVR.
На этот раз рассмотрим работу с ним со стороны "устройств ввода информации", в качестве которых будут использоваться обычные кнопки.
Нефиксируемые, срабатывающие на замыкание.
Как и прошлые статьи, данная статья для всех, кто изучает микроконтроллеры и учится их программировать. Для всех, кому это интересно. Каких-либо открытий и инноваций здесь нет, за исключением собственного полученного практического опыта.
1. Начнём с простой схемотехники
Обычно при подключении к микроконтроллеру одной или нескольких нефиксируемых кнопок пользуются вот такими схемами:
Если картинки данной статьи на вашем устройстве отображаются не очень отчётливо, можно попробовать открывать их отдельно, в соседней вкладке браузера. Или увеличить, просто щёлкнув по картинке мышью.
Резисторы подтяжки нужны, чтобы неподключенный вход микроконтроллера не висел в воздухе, принимая на себя импульсные помехи и срабатывая от них.
Это простой и надежный способ подключения, но когда в конструкции используется несколько таких кнопок, то с каждой дополнительной кнопкой недостатки постепенно начинают перевешивать его достоинства.
А именно:
- Каждая из подключенных кнопок занимает одну линию порта микроконтроллера. Целый отдельный вывод. И если на роскошном ATmega328P это не выглядит слишком большой расточительностью, то на крохах вроде ATtiny10, ATtiny13 или ATtiny45 может оказаться просто критичным для существования самой схемы.
- Для каждой из подключенных кнопок необходимо разводить на плате отдельные печатные проводники или подключать кнопки отдельными проводами. Сказывается отрицательно на стремлении к миниатюризации конструкции.
- К каждой кнопке по умолчанию прилагается свой отдельный резистор подтяжки. Для снижения эффекта "дребезга контактов" может прилагаться и отдельный конденсатор. А если задействовать срабатывание от нажатий кнопки по прерываниям, как вот здесь или здесь, то может потребоваться и по дополнительному разделительному диоду.
Многие (но не все) вышеперечисленные недостатки удастся обойти, если подключать кнопки по схеме делителя напряжения. Аппаратная сложность подключения при этом сопоставима с обычным способом подключения.
А из главных преимуществ ‒ возможность подключения практически любого (разумного) количества кнопок на одну линию порта микроконтроллера.
Подобные схемы, когда несколько кнопок подключены к одному входу и различаются только по коммутируемому сопротивлению, иногда можно видеть в конструкциях китайских разработчиков. Например вот в этом MP3-проигрывателе, только здесь используются разные сопротивления, что не совсем удобно.
При использовании делителя с одинаковыми резисторами есть и недостаток. Это некорректная обработка при одновременном нажатии сразу нескольких кнопок. И нам придётся это учитывать, выбирая соответствующую схему и область применения.
А наша схема делителя напряжения может выглядеть примерно так:
2. Добавим немного расчётов
Перед сборкой понадобится рассчитать или хотя бы примерно прикинуть параметры делителя.
Например:
- Мне необходимо использовать и распознавать нажатия от 8-ми кнопок. Соответственно делитель должен выдавать восемь уровней напряжения. То есть содержать минимум восемь последовательно соединенных резисторов, по одному на каждую кнопку.
- Ток, протекающий через делитель, с одной стороны не должен быть слишком велик, ради экономии энергии источника питания, с другой, должен быть достаточным для определения срабатывания отдельной кнопки микроконтроллером. Я остановился на значении в 3-5 мА (это меньше, чем у индикаторного светодиода), но вполне возможны и другие варианты.
- Сам делитель будет запитываться от источника питания с напряжением в 5 вольт.
Дальше закон Ома.
5 V / 0.003 А = 1667 Ом ‒ Это сопротивление всего делителя.
По 208 Ом на каждый из входящих в него резисторов.
У меня под рукой были резисторы на 180 Ом. При их использовании ток, протекающий через делитель, должен быть около 3.5 мА. Тоже вполне подойдёт.
Соответственно при последовательном нажатии кнопок (от одной до восьми) на выходе делителя напряжения теоретически получим 0.63, 1.26, 1.89, 2.52, 3.15, 3.78, 4.41 и 5.04 вольт.
3. Поясним общий принцип действия
Для распознавания нажатых кнопок задействуем аналого-цифровой преобразователь ‒ АЦП. Такой, и даже не один, есть практически в любом микроконтроллере AVR. Например в ATmega328P АЦП восьмиканальный для микроконтроллера в TQFP-корпусе и шестиканальный для микроконтроллера в DIP-корпусе. Нам будет достаточно использовать всего один канал. Каждый канал 10-ти разрядный, то есть измеряемое напряжение на входе канала может быть представлено в 1024 отсчётах: минимум ‒ 0, максимум ‒ 1023.
Во многих источниках при работе с АЦП советуют не учитывать показания двух младших разрядов в результатах измерений, так как в них мало полезной информации и много информационного шума, в основном наводок и импульсных помех на входе АЦП, пойманных в процессе измерения. Учтём этот полезный совет на будущее, на тот случай, когда будем делать высокоточный цифровой вольтметр. В данном же практикуме он не потребуется. Нам даже не потребуется переводить отсчёты измерения в вольты, преобразуя числа с плавающей запятой, экономя тем самым вычислительный ресурс микроконтроллера. Почему? Читаем дальше.
Из дополнительных преимуществ ‒ АЦП в микроконтроллере может работать с использованием системы прерываний. Что позволяет задействовать перевод микроконтроллера в спящий режим и снизить его энергопотребление. А на практике оказывается, что программировать распознавание кнопок с помощью АЦП даже проще, чем вести обработку нажатий обычных отдельных кнопок.
Для отображения результатов измерений будем использовать четырёхразрядный 7-ми сегментный индикатор, а также 10-ти сегментную светодиодную шкалу.
Тестовый стенд с ними ‒ "цифровой кирпичик номер 3" ‒ подробно рассматривался в прошлой статье.
Вот и пришла пора выводить на них что-то более осмысленное, чем циклический перебор значений заложенного в прошивку знакогенератора.
4. Представим окончательную схему
Сама же итоговая схема электрическая принципиальная для реализации описанной функциональности будет выглядеть так:
5. И реализуем её на практике
Как можно заметить большая часть схемы это микроконтроллер с модулем отображения информации, собранные в виде тестового стенда из предыдущей статьи.
Нужно добавить к ним делитель напряжения, из резисторов и кнопок. Сделать это можно, например, используя дополнительную беспаечную макетную плату и обычные тактовые кнопки. Мне же показалось удобнее расположить кнопки PBS-10B, срабатывающие на замыкание, на отдельной планке, вырезанной из листового полистирола толщиной 2 мм.
Также понадобятся разноцветные многожильные и одножильные провода, термоусадка для изоляции и однорядный 5-ти контактный разъём для подключения.
Соединил кнопки между собой с помощью выводных резисторов, словно с помощью проводов. Сами резисторы предварительно поместил в трубочки термоусадки.
Вторые контакты кнопок соединил одножильным медным проводом в эмалевой изоляции. Немного лишнего по длине его оставил намеренно с целью поймать побольше паразитных наводок. Лучше прояснить эти моменты на этапе тестового стенда, чем потом бороться с ними в реальной конструкции.
После монтажа кнопок и их соединения делитель выглядит так.
Три монтажных провода делителя (плюс напряжения питания, корпус и информационный выход) вывел на однорядный разъём для подключения к тестовому стенду.
Информационный выход делителя напряжения подключим к входу 23 микроконтроллера (канал ADC0 АЦП), а выводы плюса напряжения питания и корпуса подключаются к шине питания на тестовом стенде.
После подключения делителя напряжения с кнопками наш тестовый стенд будет выглядеть так.
6. Приступим к программированию
Вот и дошло дело до программирования микроконтроллера.
Основу программы составляют процедуры отображения информации с помощью сегментных индикаторов и светодиодной шкалы, рассмотренные в прошлой статье.
Нужно лишь вместо циклической пересылки очередных символов знакогенератора передавать этим процедурам значения от АЦП, полученные в результате очередного измерения.
Так же, как и для предыдущей статьи, при подготовке данного раздела использовались материалы с замечательного сайта AVR Project.ru ‒ Проекты на микроконтроллерах AVR.
В частности тщательно изучались следующие статьи:
Эта информация оказалась очень полезной для понимания работы АЦП микроконтроллера и особенностей его программирования.
А ещё полезным оказалось заглянуть в стандартную документацию Bascom-AVR, при необходимости помогая себе онлайн-переводчиком. Ну и техническое описание к микроконтроллеру тоже не будет лишним.
На основании прочитанного приступим к программированию аналого-цифрового преобразователя в среде Bascom-AVR.
В начале программы производится его конфигурация, задаются параметры работы. Делается это с помощью всего одной строки:
Config Adc = Single, Prescaler = Auto, Reference = Avcc
Здесь указаны следующие параметры:
- Adc = Single ‒ работа преобразователя в режиме однократного считывания. Если вместо параметра Single поставить Free АЦП будет работать в непрерывном режиме измерений
- Prescaler = Auto ‒ делитель частоты тактового генератора микроконтроллера для АЦП. От него зависит с какой частотой будет работать АЦП. В данном случае компилятор выбирает значение автоматически. Также можно установить значение вручную (2, 4, 8, 16, 32, 64).
- Reference = Avcc ‒ выбор источника опорного напряжения. Aref ‒ внешний источник, подключаемый к входу Aref, Avcc ‒ напряжение питания схемы, Internal ‒ внутренний источник опорного напряжения на 2.56 в.
Далее с помощью команды
Start Adc
запускаем функционал АЦП в работу.
Если вдруг нам понадобится сообщить микроконтроллеру об остановке процесса измерений АЦП даём команду
Stop ADC
В процессе работы программы будем периодически опрашивать АЦП, получая с него значения измерений. Делается это с помощью команды
W = Getadc(0)
,которая сохраняет измеренные значения в заданной нами числовой переменной. В качестве параметра указан опрашиваемый номер канала АЦП. Для ATmega328P-PU могут использоваться значения от 0 до 5, соответствующие выводам микроконтроллера ADC0-ADC5.
Напомню, что данные сохраняются не в вольтах, а в отсчётах разрядности АЦП, от 0 до 1023, где 0 соответствует минимальному значению напряжения ‒ уровню земли (на входе АЦП стоит резистор подтяжки к общему проводу), а 1023 соответствует максимальному опорному ‒ у нас это напряжение питания +5 вольт.
Для начала будем просто выдавать показания АЦП на индикаторы. Посмотрим, как эти значения будут меняться при той или иной нажатой кнопке.
В дальнейшем используем калибровочные данные, полученные с помощью этой программы для распознавания нажатой кнопки.
Исходный текст калибровочной программы с подробными комментариями можно скачать отсюда.
Прошивка в виде откомпилированного .hex-файла находится здесь.
Вот участок кода с основным циклом обработки.
А результаты работы калибровочной программы выглядят так.
При нажатии на кнопки на индикаторах отображаются измеренные АЦП значения.
Показания не стабильны, при одних и тех же нажатых кнопках и нескольких измерениях можно заметить, что значения "пляшут" или "плавают", меняются на несколько единиц (относительно некоторых базовых величин).
Замеренные значения я свёл в таблицу. В дальнейшем использую их в коде распознавания нажатых кнопок.
Видно, что при нескольких одновременно нажатых кнопках значения, измеренные АЦП, отличаются от показаний при обычных, однократных нажатиях.
Это можно использовать для определения самого факта одновременного нажатия кнопок.
Далее преобразуем нашу программу таким образом, чтобы при нажатии на ту или иную кнопку вместо значения отсчётов АЦП отображался номер нажатой кнопки. Вместо использования нескольких условных операторов IF-ELSE нам поможет конструкция CASE.
А если в ней указывать не точные значения отсчетов каждой нажатой кнопки, а диапазон возможных значений (допуск вправо и влево), то можно не так сильно волноваться, что кнопка не определяется из-за нестабильного питания или импульсных помех с наводками на входе АЦП.
Основной цикл программы теперь выглядит так.
В данном варианте программы также задействованы сегменты светодиодной шкалы. При ненажатых кнопках светятся сегменты 9-10, при нажатых кнопках ‒ сегменты от 1 до 8, по номеру нажатой кнопки.
Исходный текст варианта программы с определением нажатой кнопки находится здесь.
Прошивку в виде откомпилированного .hex-файла можно скачать отсюда.
Изменим немного блок распознавания, сузив диапазон возможных значений (отклонение вправо и влево) каждой из нажимаемых кнопок.
В этом случае можно определять и отбрасывать часть (но, к сожалению, не все) ошибочных комбинаций при одновременно нажатых кнопках.
Также, чем больше сужаем диапазон, тем больше вероятность ошибочного определения уже и для правильного нажатия кнопки.
Некий компромиссный вариант можно, наверное, подобрать на практике, исходя из текущих потребностей. Но я попробовал использовать программу с таким вариантом распознавания нажатой кнопки, и в результате был вынужден от него отказаться.
Да, сам факт одновременного нажатия нескольких кнопок он определяет.
При этом возросшее число ошибочных определений данное преимущество сводит на нет.
В следующем, третьем варианте программы задействованы прерывания и спящий режим микроконтроллера.
При работе программы командой Idle микроконтроллер переводится в сон, отключая большую часть функциональных модулей и снижая своё энергопотребление. Прерывания по входам АЦП при этом разрешены.
При изменении состояния на входе ADC0 микроконтроллера
- Возникает программное прерывание
- В подпрограмме его обработки IntADC устанавливается флаг ADCFlag
- Микроконтроллер просыпается, начинает выполнение основной программы, проверяет состояние флага и при его установленном значении производит замер на входе АЦП.
- После чего измеренное значение выводится на индикаторы, а микроконтроллер опять засыпает.
Здесь также сделана попытка использования режима ADСNOISE.
В этом режиме "создаются более благоприятные условия для аналого-цифрового преобразования с повышенной разрешающей способностью за счет снижения влияния шумов на результат измерения. При использовании режима ADСNOISE прекращается тактирование процессора, памяти программ, а также системы ввода/вывода, но продолжают работу АЦП и внешние прерывания".
В данный режим отдельные модели микроконтроллеров могут быть переведены командой
Config Powermode = ADCNOISE
Также в коде для снижения энергопотребления переводится в режим Shutdown и микросхема-контроллер сегментных индикаторов MAX7219.
Участок основного цикла программы здесь выглядит так.
А это код обработчика прерывания.
Исходный текст третьего варианта программы (с прерыванием и спящим режимом) с подробными комментариями находится здесь.
Прошивку в виде откомпилированного .hex-файла можно скачать отсюда.
По внешним результатам работы третий вариант программы (с использованием прерываний) практически не отличается от второго.
7. Про энергопотребление
Была надежда, что при использовании данного варианта прошивки удастся резко снизить энергопотребление микроконтроллера и всей схемы.
Надежда, к сожалению, не оправдалась.
Для всех трёх вариантов программы ток потребления микроконтроллера составлял примерно 1.8 мА при ненажатых кнопках и около 2.0 мА при их нажатии.
Вся схема потребляет от 20 до 28 мА.
Вполне вероятно я чего-то (или многого и важного) ещё не учёл или где-то (быть может во многом) ошибся. Если у вас возникнут идеи или советы по данному поводу ‒ большая просьба поделиться ими в комментариях.
8. Про прошивку и FUSE-биты
Все три варианта прошивки занимают в памяти микроконтроллера меньше 4 kB, а это значит, что для компиляции вполне подойдет демонстрационная и бесплатная версия среды Bascom-AVR.
Какой бы вариант прошивки вы не использовали, откомпилировать программу в Bascom-AVR и залить её в микроконтроллер можно с помощью способа, подробно описанного вот в этой статье.
Возможно при этом вам пригодится картинка с настройками FUSE-бит из CodeVisionAVR.
Или можете использовать любой другой, удобный для вас способ.
9. Окончательный результат ‒ это всего лишь начало новой конструкции
Ниже представлено видео работы тестового стенда, оно не очень хорошего качества, но разобрать, что к чему, можно.
Да, это совсем не готовая конструкция, а всего лишь отработка одной из её частей, "цифровой кирпичик номер 4".
При желании вы вполне можете применить её в каком-то из своих устройств, например в кодовом замке, цифровом пианино, проводном пульте управления, схеме освещения умного дома или в любом другом.
Пока ещё рано говорить о том, где собираюсь применить её я. Тем более, что остались не совсем ещё решённые вопросы и ещё есть куда стремиться.
Но, надеюсь, когда-нибудь удастся и этот кусочек использовать и, если до этого дойдёт, обязательно об этом дополнительно напишу.
06 сентября 2020 года.
С уважением, Ваш @mp42b.
<-- Предыдущая статья | Содержание 2019-2020 | Следующая статья -->
#простые вещи #Bascom-avr #кнопки и ацп #mp42b #микроконтроллеры_mp42b