Цифровой вольтметр 0-25В на микроконтроллере AVR ATmega32


В этой статье мы рассмотрим схему на микроконтроллере ATmega32A (семейство AVR), реализующую цифровой вольтметр с пределами измерений от 0 до 25В. Для этого мы задействуем 10-битный аналого-цифровой преобразователь (АЦП), имеющийся в данном микроконтроллере. Поскольку АЦП микроконтроллера ATmega32A не может на своем входе обрабатывать напряжение больше 5В, для увеличения диапазона рассматриваемого нами цифрового вольтметра мы применим делитель напряжения.

Цифровой вольтметр 0-25В на микроконтроллере AVR ATmega32: внешний вид

При проектировании схем с делителем напряжения следует принимать во внимание то, что входной ток на АЦП микроконтроллера AVR должен быть не менее 50 мкА. Поэтому следует правильно выбирать резисторы делителя напряжения чтобы минимизировать влияние нагрузки (loading effect) резистора на проходящий через делитель ток.

Схема делителя напряжения

Как показано на представленной схеме, мы будем использовать делитель напряжения на двух резисторах, поэтому при входном напряжении 25В мы на выходе этого делителя будем иметь 5В (при соответствующем подборе номиналов резисторов). Таким образом, для получения истинного значения измеряемого напряжения мы должны будем умножить измеренное (с выхода делителя) напряжение на 5.

Необходимые компоненты

Аппаратное обеспечение

  1. Микроконтроллер ATmega32 (купить на AliExpress).
  2. Программатор AVR-ISP (купить на AliExpress), USBASP (купить на AliExpress) или другой подобный.
  3. JHD_162ALCD (ЖК дисплей 16x2) (купить на AliExpress).
  4. Конденсатор 100 мкФ (купить на AliExpress).
  5. Конденсатор 100 нФ (5 шт.) (купить на AliExpress).
  6. Резистор 10 кОм (купить на AliExpress).
  7. Резистор 2,2 кОм (купить на AliExpress).
  8. Переменный резистор (потенциометр) 1 кОм (купить на AliExpress).
  9. Источник питания с напряжением 5 Вольт.

Программное обеспечение

  1. Atmel Studio версии 6.1 (или выше).
  2. Progisp или flash magic (необязательно).

Работа схемы

Схема устройства приведена на следующем рисунке.

Схема цифрового вольтметра на микроконтроллере AVR ATmega32

В представленной схеме PORTB микроконтроллера ATmega32 соединен с портом данным жидкокристаллического (ЖК) дисплея. При этом следует помнить о том, что необходимо деактивировать JTAG интерфейс микроконтроллера на порту PORTC при помощи изменения фьюзов (fuse bytes) если мы хотим использовать PORTC как обычный порт ввода/вывода. В ЖК дисплее (если мы не хотим использовать черный цвет) можно задействовать только 14 его контактов: 8 контактов для передачи данных (7-14 или D0-D7), 2 контакта для подачи питания (1&2 или VSS&VDD или gnd&+5v), 3-й контакт для управления контарстностью, 3 контакта для управления (RS&RW&E).

В представленной схеме мы использовали только 2 контакта управления ЖК дисплея для лучшего понимания работы схемы. Бит контраста и READ/WRITE используются нечасто, поэтому они могут быть замкнуты на землю. Это обеспечивает ЖК дисплею максимальную контрастность и переводит его в режим чтения. Теперь нам всего лишь нужно контролировать контакты ENABLE и RS чтобы передавать на ЖК дисплей символы и данные. Также на нашем сайте вы можете прочитать более подробную статью о подключении ЖК дисплея к микроконтроллеру AVR ATmega32.

В схеме необходимо сделать следующие соединения с ЖК дисплеем:
PIN1 или VSS - земля
PIN2 или VDD или VCC - +5v питание
PIN3 или VEE - земля (обеспечивает максимальный контраст ЖК дисплею)
PIN4 или RS (Register Selection) – контакт PD6 микроконтроллера
PIN5 или RW (Read/Write) - земля (переводит ЖК дисплей в режим чтения что упрощает взаимодействие с ним для начинающих)
PIN6 или E (Enable) - контакт PD5 микроконтроллера
PIN7 или D0 - контакт PB0 микроконтроллера
PIN8 или D1 - контакт PB1 микроконтроллера
PIN9 или D2 - контакт PB2 микроконтроллера
PIN10 или D3 - контакт PB3 микроконтроллера
PIN11 или D4 - контакт PB4 микроконтроллера
PIN12 или D5 - контакт PB5 микроконтроллера
PIN13 или D6 - контакт PB6 микроконтроллера
PIN14 или D7 - контакт PB7 микроконтроллера

В схеме мы использовали 8-битную связь (D0-D7) ЖК дисплея с микроконтроллером, хотя можно было ограничиться и 4-битной – но в этом случае код программы стал бы немного сложнее. Таким образом, мы использовали 10 контактов ЖК дисплея, 8 из которых будут использоваться для передачи данных и 2 для управления.

Напряжение на резисторе R2 (2,2 кОм) не будет полностью линейным – оно будет подвержено влиянию шума. Для борьбы с этим явлением в схеме параллельно резисторам делителя включены два конденсатора.

Переменный резистор 1 кОм служит для задания точности АЦП. В микроконтроллере ATMEGA32A мы можем подключить аналоговый выход к любому из восьми каналов PORTA – не важно к какому. В данной схеме мы использовали канал 0 (контакт 0) PORTA.

В микроконтроллере ATmega32A АЦП имеет разрешение (разрешающую способность) 10 бит, таким образом микроконтроллер способен реализовать чувствительность равную Vref/2^10, то есть если опорное напряжение (Vref) равно 5В мы получим цифровой инкремент на выходе 5/2^10 = 5мВ. Таким образом, на каждое приращение напряжения на 5 мВ мы будем получать один дополнительный инкремент цифрового выхода АЦП.

Для обеспечения работы схемы мы должны установить значения регистров АЦП следующим образом:

  1. Сначала мы должны активировать АЦП микроконтроллера.
  2. Максимальное входное напряжение для АЦП микроконтроллера составляет +5В (5*(12.2/2.2) =27.7В; поскольку R1 = 10 кОм and R2 = 2.2 кОм). Поэтому мы можем установить максимальное значение опорного напряжения АЦП равное 5В.
  3. АЦП микроконтроллера в нашей схеме будет начинать действовать при внешнем воздействии (не от действий пользователя), поэтому нам следует установить его в режим непрерывного преобразования (free running mode): в этом режиме запуск преобразований выполняется непрерывно через определенные интервалы времени.
  4. В любом АЦП частота преобразования аналогового значения в цифровое и точность цифрового выхода обратно пропорциональны. То есть для лучшей точности цифрового выхода мы должны выбрать меньшую частоту. Для этого мы должны установить коэффициент деления предделителя АЦП в максимальное значение (128). Поскольку мы используем внутреннюю частоту микроконтроллера 1 МГц, то значение частоты преобразования АЦП будет равно 1000000/128.

Четыре основных принципа работы с АЦП микроконтроллера мы рассмотрели, теперь нам нужно установить правильные значения в регистрах АЦП.

Регистр ADMUX АЦП микроконтроллера AVR ATmega32

Регистр ADCSRA АЦП микроконтроллера AVR ATmega32

RED (красный, ADEN): этот бит устанавливается чтобы задействовать функции АЦП в ATmega32A.

BLUE (синий, REFS1, REFS0): эти два бита используются для установки опорного напряжения (максимального входного напряжения, которое мы собираемся обрабатывать). Поскольку мы будем использовать опорное напряжение равное 5В, бит REFS0  необходимо выставить в соответствии с приведенной таблицей.

Установка битов REFS1, REFS0 в регистре ADMUX АЦП

LIGHT GREEN (светло зеленый, ADATE): этот бит должен быть установлен чтобы АЦП работал непрерывно (в режиме непрерывного преобразования).

PINK (розовый, MUX0-MUX4): эти 5 бит используются чтобы задать входной канал. Поскольку мы будем использовать ADC0 (PIN0) то, как следует из ниже приведенной таблицы, нам нет необходимости устанавливать все эти биты.

Установка битов MUX0-MUX4 в регистре ADMUX АЦП

BROWN (коричневый, ADPS0-ADPS2): эти три бита используются для установки коэффициент деления предделителя АЦП. Поскольку мы используем коэффициент деления предделителя 128, мы должны установить все эти три бита.

Биты для установки коэффициента деления предделителя АЦП

DARK GREEN (темно-зеленый, ADSC): этот бит необходимо установить для того чтобы АЦП начал осуществлять преобразование. Далее в программе мы можем его сбросить (в 0) если нам нужно будет остановить процесс аналого-цифрового преобразования.

Объяснение работы программы

Программа для рассматриваемой схемы представлена следующим фрагментом кода на языке С (Си). Комментарии к коду программы поясняют принцип работы отдельных команд.

Видео, демонстрирующее работу схемы

(2 голосов, оценка: 5,00 из 5)
Загрузка...
6 234 просмотров

Комментарии

Цифровой вольтметр 0-25В на микроконтроллере AVR ATmega32 — 19 комментариев

  1. Здравствуйте, опираясь на вашу статью пишу курсовую, можете подсказать почему вы выбрали именно AVR ATmega32, а не любой другой микропроцессор?

    • Добрый день, данный проект вольтметра можно реализовать практически на любом микроконтроллере AVR и, в принципе, возможности ATmega32 для данного проекта избыточны, просто данный микроконтроллер был в тот момент под рукой, поэтому и было принято решение сделать проект на нем

  2. Кстати, низкое сопротивление на первом входе с PT100, похоже, оказывает влияние на второй АЦП с потенциометром на втором входе.

    • Да, теоретически такое влияние возможно, маленьких сопротивлений в подобных схемах все таки стараются избегать

  3. Здравствуйте. Попытался включить в схему с делителем напряжений на рисунке выше вместо нижнего резистора на 2,2k термосопротивление PT100 с диапазоном примерно 80...265 Ом при измеряемой температуре -50...+450 градусов С. Вместо верхнего резистора поставил резистор на 270 Ом. В Протеусе работает, но вот на практике, показывает совсем не то. А главное, что если просто выводить показания ADC, то они хотя бы показываются на дисплее (не уверен, что они соответствуют напряжению с делителя), и, если нагревать это термосопротивление, то показания ADC растут на 100-150 единиц по мере нагрева. А вот если ADC использовать в формуле расчёта температуры ( в моём случае t=ADC/"число" и т. д.), то показания похожи на настоящую температуру, но при нагреве абсолютно не изменяются. Вопрос: не с слишком ли низким сопротивлением PT100 и второй резистор я выбрал? (Специально хотел схему измерения попроще, точность в пределах 1-5 градусов вполне устраивает, лишь бы показания не прыгали).

    • Добрый вечер, к сожалению что то конкретного по вашей проблеме не могу подсказать, с такими небольшими сопротивлениями для подобных целей не сталкивался. Во всех таких схемах, которые я видел, в большинстве случаев используются сопротивления порядка нескольких кОм. А вы не пробовали использовать терморезистор с большим сопротивлением? Например, можете посмотреть статью про измерение температуры с помощью терморезистора и Arduino, там применен терморезистор сопротивлением примерно 10 кОм.

      • И там у вас применён простой делитель? Я имею в виду, что с него напряжение подаётся сразу на вход АЦП микроконтроллера? Кстати, я от делителя всё-таки ушёл из-за малых сопротивлений, и применил ОУ LM358, посмотрю, напишу.

        • Да, это стандартный прием. На моем сайте целая куча проектов, в которых напряжение на вход АЦП микроконтроллера AVR или платы Ардуино подается сразу с делителя напряжения на резисторах. Но номиналы резисторов не менее 1 кОма. Может быть, ваша проблема связана как раз с малой величиной сопротивления этих резисторов, хотя я в этом не уверен

          • С ОУ работает лучше, но показания почему-то немного прыгают +/-2 градуса. До максимальных температур пока не грел, но t нагретого паяльника измеряет (проверял совместно с термопарой мультиметра).

            • Ну ОУ это дополнительное усложнение схемы, поэтому неудивительно что с помощью ОУ можно достичь более корректных результатов чем с помощью простейшего делителя напряжения

          • А установка однопроцентных резисторов в делителях с сохранением маленьких номиналов сопротивлений дало хорошие результаты: 2,5В равно 512 - теперь и с делителями всё прекрасно работает)

            • Ну я рад что у вас получилось. Спасибо что делитесь с другими посетителями нашего сайта секретами своего мастерства

  4. Здравствуйте. Подскажите, как использовать не один, а два входа для преобразования двух аналоговых сигналов, чтобы они выводились каждый на своей строке LCD1602 (оба сигнала напряжения). Может, стоит бит ADATE установить в "0"? У меня получается, что при переключении на второй вход к измеренному на нём напряжению прибавляется результат, измеренный на первом входе, и на дисплее просто набор цифр после того как он переполнится символами.

    • Да, у вас здесь просто "каша" получилась )) ADATE не стоит устанавливать в 0. Но я рад, что у вас все же получилось

      • Всё решилось, когда в программу ввёл проверку while(!(ADCSRA & (1<<ADIF))), до этого не получалось выводить оба измерения независимо друг от друга.

        • Ну вот, вы уже становитесь микроконтроллерщиком "высшего" уровня, поздравляю ))

            • Да, спасибо за внимательность, но картинку и видео поправить уже, к сожалению, не получится. Проект то разобран

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *