AVR. Учебный курс. Использование аналогового компаратора
Автор DI HALT
Опубликовано 13 Сен 2008
Рубрики: AVR. Учебный курс
Метки: AVR, Аналог, АЦП, Компаратор, Микроконтроллер, Описание
Есть почти в каждой AVRке, такая полезная приблуда как аналоговый компаратор. Это уже почти стандартное устройство и встречается очень часто во множестве разных контроллеров. Даже в древнем, как говно мамонта, АТ89С2051 он уже есть. Штучка прикольная, позволяет сравнивать два аналоговых сигнала и выносить свой вердикт 0 первый больше второго, 1 второй больше первого.
Применить его можно, например, чтобы отслеживать уровень заряда аккумулятора по просадке напряжения. Схема простейшая - стабилитрон создает опорное напряжение, которое всегда одиннаково, а напряжение с резистивного делителя зависит от входного напряжения.
Например, на входе у нас 8 вольт. Со стабилитрона, рассчитанного на 3.3 вольта, выходит всегда одно и то же напряжение — 3.3 вольта. А с симметричного резистивного делителя выходит половина напряжения то есть 4 вольта. 4 это больше чем 3.3, (3.3 - 4 = -0.7 результат меньше нуля) с компаратора выходит 0
Теперь если просядет батарейка и напряжение снизится до 6 вольт, то с делителя будет уже 3 вольта, а с опорного как было 3.3 так и осталось. Зато теперь на компараторе ситуация в корне поменялась - 3 меньше чем 3.3 (3.3 - 3 = 0.3 результат больше нуля) , а значит на выходе у него будет 1
Вот так, например, можно легко и просто следить за питающим напряжением и выдавать сигнал тревоги если батарейка сядет.
Настройка компаратора в контроллере AVR ATMega16
Для других моделей AVR все очень и очень похоже, просто мне так удобней. Если будет затруднение спросишь в комментах.
Мега16 имеет на борту компаратор, со входами AIN0(прямой вход) и AIN1(инверсный вход) Чтобы компаратор заработал его выводы нужно подключить на вход (DDR=0) и отключить подтяжку до единицы (PORT=0).
Регистр конфигураций компаратора ACSR
Биты:
- ACD включение компаратора 0 включен, 1 выключен. По дефолту там ноль, а значит при старте компаратор включен.
- ACBG - подключение к прямому входу компаратора внутреннего источника опорного напряжения (ИОН) на 1.22+(-)0.05V. Если 0 то ИОН не подключен.
- ACO - бит результата. Собственно, это и есть выход компаратора.
- ACI - флаг прерывания. Я думаю, что ты уже привык к тому, что в AVR есть прерывание на каждый чих. Компаратор не исключение. Устанавливается по событию, сбрасывается после ухода на обработчик либо программно, как всегда, записью в него 1.
- ACIE - где есть прерывание там должен быть и бит разрешения. Это он и есть. Установив в 1 мы разрешаем прерывания от компаратора. По дефолту, естественно, нуль.
- ACIC - подключение компаратора к схеме захвата таймера1. При попадании сигнала на схему захвата текущее значение с таймера тут же тырится в специальный регистр захвата, а таймер продолжает считать дальше. А в привязке к компаратору это удобно когда нужно измерять длительности сигналов.
- Биты ACIS1:ACIS0 определяет условие возникновения прерывания от компаратора:
- 00 - любое изменение на входе.
- 01 - зарезервировано для следующих поколений
- 10 - переход с 1 на 0
- 11 - переход с 0 на 1
Вот за что люблю АТМеги так это за фарш! Даже свой собственный источник опорного напряжения есть. Так что из схемы со стабилитроном можно смело выкинуть все, что касается стабилитрона :) Оставив только делитель, ну и подобрав плечи резисторного делителя так, чтобы получить напругу на выходе чуть выше чем 1.22V.
Мало того, если в контроллере есть АЦП, то на вывод AIN1 можно подключить ЛЮБОЙ вход АЦП. Нереально круто! Для того, чтобы это сделать нужно:
- В регистре SFIOR (регистр специальных функций) выставить бит ACME (вроде бы так ракеты назывались в мультике про койота и страуса ;) )
- Выключить АЦП, сбросив бит ADEN в регистре настроек АЦП (ADCSRA)
- В регистре ADMUX в разрядах MUX2:MUX1:MUX0 указать номер входа АЦП.
Пример:
В качестве примера я возьму своего робота. Сварганив ему систему контроля за питанием. Напряжение с аккумулятора проходит через делитель 1.5:10 в результате на 12 вольтах у нас на выходе будет (1.5/(1.5+10))*12=1.56 и только при просадке напруги до 9.5 вольт на выходе делителя будет ниже 1.22 вольта. Заюзаю пока неиспользованный вход PC5 (это вход ADC5)
Заправлю его через АЦП в компаратор, а в качестве опорного напряжения возьму встроенный ION который посажу на AIN0 изнутри. При просадке напряжения буду зажигать контрольную лампу.
Что нам нужно:
Для начала подключить ИОН - бит ACBG
Далее, бит прерывания - в обработчике прерываний я включу лампочку
Ну и выставить условие по которому будет прерывание с 0 на 1. Дело в том, что на плюс-вход компаратора идет 1.22 с ИОН, а на минус-вход пойдет 1.5 с делителя. В результате 1.22-1.5<0, следовательно на выходе 0. Ну, а как только ситуация поменяется будет 1.
1 2 3 4 5 6 7 8 9 10 11 | ; Инициализирую компаратор LDI R16,(1<<ACBG)|(1<<ACIE)|(1<<ACIS1)|(1<<ACIS0) OUT ACSR,R16 ; Забрасываем в регистр IN R16,SFIOR ; Достаем SFIOR ORI R16,(1<<ACME) ; Выставялем в нем бит ACME OUT SFIOR,R16 ; АЦП у меня по дефолту вырублен, поэтому пока не напрягаюсь с его отключением LDI R16,5 ; подаю напругу на 5й вход АЦП OUT ADMUX,R16 |
Ну и собственно все, осталось только добавить в программу переход по вектору
1 2 3 4 5 6 | .ORG ACIaddr ; Analog Comparator RJMP Battary_LOW ;И добавить где нибудь в программе обработчик прерывания Battary_LOW: LIGHT_ON ; Вызов макроса зажжения огня. RETI ; Выход из прерывания. |
Или вот, второй пример. Попроще.
На компаратор подается два напряжения. Одно опорное, со стабилизатора 3.3 вольта демоплаты Pinboard. Второе с потенциометра, то которое мы сравниваем. Подаются напрямую на выводы компаратора AIN0 и AIN1
Когда напряжение с потенциометра выше чем 3.3 вольта с стабилизатора, то в компараторе у нас на выходе 0 (бит ACO=0). И наоборот. Также настроено прерывание так, чтобы при попадании в него происходила инверсия бита PD4 - на нем висит светодиод LED1
Код
Обработчик прерывания:
1 2 3 4 5 6 7 8 9 | COMP_OK: PUSHF ; Сохранили флаги PUSH R17 ; Сохранили R17 INVB PORTD,4,R17,R16 ; Инвертировали бит PD4 POP R17 ; Достали все из стека POPF ; И флаги тоже RETI ; Вышли |
Инициализация периферии:
1 2 3 4 5 6 7 8 9 10 11 | ; Internal Hardware Init ======================================= ;Comparator Init OUTI ACSR,1<<ACIE|1<<ACIS1|1<<ACIS0 ; Разрешаем прерывание ; Ловим 0-1 переход. ; Ports Init SBI DDRD,4 SBI DDRD,7 SEI ; End Internal Hardware Init =================================== |
Главная программа:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ; Main ========================================================= Main: IN R16,ACSR ; Взяли состояние компаратора ANDI R16,1<<ACO ; Оставили только бит состояния BST R16,ACO ; Скопировали его в Т BLD R16,7 ; Выгрузили в 7й разряд R16 IN R17,PORTD ; Взяли значение из PORTD ANDI R17,0b01111111 ; Подавили значение 7го разряда OR R17,R16 ; Наложили на него значение ACO OUT PORTD,R17 ; Вернули значение в порт. RJMP Main |
Светодиод LED3 показывает состояние бита ACO, а LED1 фиксирует заходы в обработчик прерывания компаратора. При этом наблюдается мерзкий эффект — когда сравниваемые напряжения на входах компаратора очень близки, то возникает дребезг. Т.е. мельчайшие помехи уже начинают играть роль и перевешивают чашу весов компаратора то в одну то в другую сторону. Возникает жуткий дребезг. Этот дребезг надо подавлять программно. Скажем игнорировать изменения сигнала если он чаще чем раз в несколько миллисекунд.
На видео дребезг очень хорошо видно на экране осциллографа.
Комментарии
51 комментариев на «AVR. Учебный курс. Использование аналогового компаратора»
Оставьте свой отзыв
Вы должны войти, чтобы оставлять комментарии.





1.22В опорного напряжения есть постоянное для всех типов мег? конкретно интересно для 8535 )
Да, вроде бы для всех
то есть на “плюс” сравнителя не надо ничего подключать (в электрическом смысле) в этом случае?
Да. Все уж подключено внутри.
А я как раз думал как отслеживать разряд батарейки…
Что-то я читаю даташит на мегу8 и не пойму…
“ATmega8 features an internal bandgap reference. This reference is used for Brown-out Detection,
and it can be used as an input to the Analog Comparator or the ADC. The 2.56V reference
to the ADC is generated from the internal bandgap reference.”
Так там 2.56В или 1.22 внутреннее опорное напряжение?
А, разобрался. Сорри за тупизм.
“Теперь если просядет батарейка и напряжение снизится до 6 вольт, то с делителя будет уже 3 вольта, а с опорного как было 4 так и осталось.”
“Со стабилитрона, рассчитанного на 3.3 вольта, выходит всегда одно и то же напряжение — 3.3 вольта.”
Опечатка?
Угу. Вертел его в руках вот и написал 3.3 :)
Так как же правильно-то?
И че за фигня - С 4 больше чем 3.3, (3.3 - 4 = -1.3 это меньше нуля) с компаратора выходит 0. Вроде 3.3-4 = -0.7 !!
-0.7 ага. Что один хрен то же самое, чтои -1.3 - меньше нуля, с компаратора ноль.
при одинаковом то напряжении чего ожидать?
Одинакового напряжения не существует :) Всегда одно будет больше другого, хотя бы изза теплового дрейфа. Если уж совсем равно, то компаратор колбасит нипадецки из одного в другое состояние.
Что-то я не понял. На http://www.gaw.ru/html.cgi/txt/doc/micros/avr/arh128/9.htm написано “Аналоговый компаратор сравнивает уровни напряжений на неинвертирующем входе AIN0 и инвертирующем входе AIN1. Если напряжение на неинвертирующем входе AIN0 превышает напряжение на инвертирующем входе AIN1, то выход аналогового компаратора ACO принимает единичное состояние.” Тут же все наоборот. Где же правда?
Пофиксил. В статье была злостная опечатка.
Где-то читал, что при использовании встроенного АЦП выводы порта АЦП нельзя использовать на вывод, иначе это приведет к погрешности измерения, так вот вопрос: нельзя или не желательно? И к использованию входов АЦП как входов компаратора это тоже относится? т.е. если я сконфигурировал один вход АЦП как вход компаратора, могу ли я остальные выводы порта использовать на вывод?
В смысле как входов компаратора? В режиме диф входа чтоль?
Можно использовать их на выход, но при изменение уровня будет скакать напряжение на порту, что крайне негативно скажется на точности работы АЦП блока.
В качестве входа компаратора: “Мало того, если в контроллере есть АЦП, то на вывод AIN1 можно подключить ЛЮБОЙ вход АЦП. Нереально круто!” - т.е. через мультиплексор АЦП один вход порта на компаратор, а остальным на вывод работать никто не запрещает? Спасибо за ответ.
Не запрещает. Можете использовать переход с АЦП на компаратор, а остальные выводы использовать как угодно. Разумеется в этом случае АЦП и компаратор не могут использоваться одновременно.
Здравствуйте,
а какое максимальное напряжение можно подавать на аналоговый компаратор микроконтроллера?
Не выше питания
Вроде можно хоть 1000в, хоть переменного напряжения, но через резистор R=U/I=1000В/1ма(?)=1000 килоом. Диоды отправят этот +1 ма тока в источник питания, там его должны скушать другие нагрузки. Вытекающий -1 ма берется с “земли” не важно.
Я так понимаю там диоды, положительное напряжение отправляют в питание, отрицательное в “землю”. При небольших токах напрежения не превысят указанные в описании. Вопрос только в мощности тех диодов. Можно прикольнуться теоретически подать питание +5в на reset, 0 на вход какой-нибудь, мало кто поймет как оно работает от такого “паразитного” питания :)
Напряжение батарейки можно проще мерить.
Включаем АЦП. Опору переключаем на лапку AVcc, а номер канала измерения ставим = 14 (0×0E) (для меги48, уточняйте в даташите). В итоге вход АЦП подключается к внутренней опоре.
Получаем работу от противного: мерием точный сигнал относительно плавающей опоры.
Пусть батарейка заряжена до 2,2 вольт, опора в м48 == 1,1В. Значит АЦП вернёт 127 (256/2). При напряжении 3,3 вольта вернёт 85 (256/3).
Без единой внешней детали получаем ЗНАЧЕНИЕ напряжения батареи, да ещё и достаточно точно.
Способ работает (впрочем, это документированая фича АВР), реализовал в железе пару раз.
Это все конечно замечательно, но АЦП есть дааалеко не во всех АВР, а вот компаратор встроен по моему поголовно везде.
Напряжение на батареи питания можно мерить RC цепочкой. Разряжаем конденсатор (транзистором или ножкой контроллера включенной на выход с 0 на выходе), ногу переключаем на вход. Конденсатор начинает заряжаться через резстор от источника питания, 0.1в, 0.2в ю… 1.0в, 1.1в, тут бац сработал компаратор! время заряда конденсатора пропорционально напряжению. От +2в конденсатор будет заряжаться в 100 раз дольше чем от +200. Кондер можно поставить от 10 пикофарад, 10 000 пикофарад или 10 микрофарад (лучше керамический), чем дольше заряжается тем точнее формально измерение. 5 тиков дадут точность 1/5, 5 млн. тиков 1/5 млн, 20 бит точности, реально конечно будут шумы компаратора, дрейф нуля, плавание емкости конденсатора и сопротивлений левых. Но сам принцип помоему верен. И контроллер может не только грубо сравнивать напряжение в норме или нет, но и взять его с точностю до микровольт, используя только компаратор :)
Если условия еще более суровые, компаратора нету, можно использовать любой вход как компаратор, только напряжение сравнения там не такое точное 2в вроде. Переключились в ноль, кондер разрядили, переключились в Z ждем на входе еденицу и считаем тики. 100 тиков - 1В, 1000 тиков - 10В и тому подобное.
Бысрые сигналы так мерить понятно что нельзя, а напряжения питания как-раз. И нога остается свободной частично, светодиод можно повесить например, на выход +5В светодиод горит, конденсатор не мешается, а резистор от внешнего напряжения только добавит яркости :)Для разных ATtiny может быть актуально )))
Извини, но что то в описании компаратора, в даташите, фигурирует опорное напряжение 2,56 В.
Cluster пишет что разобрался - у меня как то неполучаается.
2.56 это ИОН для АЦП
Согласен, но ссилка в даташите на эту величину идет как для АЦП так и для компаратора. А вот упоминания про 1.22 нигде ненашол. Я даже пробовал тупо искать значение 1.2 :(
Ладна, покопаюсь нормально в доке, может пропустил чего типа “но если через … тагды все ОК”
Спасибо за ответ !!!
В даташите на Мега8535 идет отсыл на страницу 41, где описан Internal Voltage Reference и указано, что есть
Bndgap reference voltage min1.15 typ1.23 max1.35V И используется он для схемы BOD, но при желании его можно замкнуть и на компаратор
Как я понял, это напряжение от встроенного ИОН на 2.56 деленое пополам резисторами.
Парни подскажите не могу понять.
Использую Attiny 2313, могу ли я ногу AIN0 использовать как вход/выход, подключив к компаратору внутренний ИОН, напряжение проверять инверсным входом AIN1, при срабатывании компаратора ждать прерывания:
outi ACSR,(3<<ACIS0)|(1<<ACIE)|(1<<ACBG)?
То есть, можно ли работать с компаратором только по ноге AIN1?
Может вопрос поставлен некорректно, попробую еще раз.
Для моей программы компаратор не главное устройство, но желательное (дополнительные функции), но использовать оба входа нет возможности (не хватает лап для главного).
Так вот, можно ли использовать внутренний ИОН, ногу AIN1 использовать как измерительный вход компаратора, при этом на ногу AIN0 повесить светодиод и периодически им помигивать?!.
;)
Честно говоря не знаю. Почитай даташит там должно быть написано, ну или эксперимнет поставь.
С английским не знаком, пришлось почитать с помощью товарища. Ничего нет, написано, что либо используется внешний ИОН, либо внутренний. Ставил эксперимент в AVRStudio и Proteuse, не пошло (хотя, это может быть глюк Proteusa). Железяку пока не купил. :(
Всем привет.
Я новичок в области микроконтроллеров и меня тут возник такой вопрос, насколько я понял из даташита (atmega32), если в регистре SFIOR прописать 011, включить ADEN и ADATE (заодно и ADIE),то при прерывании на сравнение в счетчике0 в бит ADSC будет записываться 1 и АЦП начнет свою работу (и так каждый раз при прерывании счетчика0), для того чтоб все это дело проверить и не писать зря код, я запустил АВР студию и ручками проставил все значение и стал жать F11, но так и не увидел 1 в бите ADSC, так в чем же все таки проблема, может я чето не понял из даташита? да и при наведении курсора в аврСтудии на бит ADATE вылазет сообщение в котором много чего написано про таймер-счетчик2(что тоже не совсем понятно так-как в даташите указано 8 источников если бит ADATE установлен).
Помогите кто может…
Мега8 ?
32
Знаю что у меги8 такой глюк в студии был с АЦП. Т.е. не работал фриран. В железе же было все ок.
Хотелось узнать подробней о схеме захвата. Попробывал реализовать - не срабатывает. Что я делал: включил компаратор, подключил к схеме захвата таймера1 битом ACIC, прерывания от компаратора выключил, прерывания по захвату в таймере - включил. Запускаю в студии. Пробую сначала в один момент вручную поставить флаг прерывания компаратора (самого-то прерывания, естественно не будет, в железе флаг-то появится и предполагаю, что произйдет работа схемы захвата). Ничего не меняется.
Потом пробую флаг захвата таймера1 Input Capture Flag 1 вручную установить. Возникает прерывание. Но наблюдаю за изменением в регистраз ICR1H и ICR1L - ничего в них не менятся, как были нули так и остались. А по идеи там должно появить состояние региров TCNT1H и TCNT1L. Что я ещё забыл?
Код залил сюда http://slil.ru/28285895
DI HALT, кстати, я там переменную в ОЗУ объявил, можешь глянуть правильно или нет, и правильно ли я с ней работаю в прерывании. Компилятор вроде ошибок не нашёл.
Здравствуйте. Прошу помощи по следующему вопросу:
1) Собрал на mega8 вольтметр, который через com порт передает значение АЦП на компьютер и там строит график. Работает нормально если измеряет напряжение на полностью развязанном от сети источнике напряжения (батарейка).
2) Подключил к схеме ЛАТР-выпрямитель-конденсатор-делитель 100/1 (на выходе 1 в) . Контроллеру тут же настала …она.
3) Причина - согласно осцилограмме COM порт подводит к нулю контроллера реальную землю и соответственно на АЦП размах в 380 вольт. От лабораторного блока питания размах поменьше но все же гораздо выше 5 в.
4) Вопрос в следующем - какие существуют способы решения.
1. Заземление компьютера (или включение в правильную евророзетку). Без заземления на корпусе компа ~120В и ток в толи мА
2. Опторазвязка схемы, запитка схемы от неимпульсного БП, там теже фильтры из конденсаторов, лучше от батарейки или трансформатора (есть еще специальные трансы с малой емкостью между обмотками)
такая проблема:
сконфигурировал порты, настроил ACSR (выставил условие прерывания, разрешил прерывания, запустил компаратор, опорное внешнее). в аврстудио ковырял, ковырял - не срабатывает прерывание… если самому поставить флаг, то все отлично, а вот при изменении результата флаг почему-то не ставиться…
подскажите пожалуйста, где может быть косяк? поставил платформу тиньки15, перед этим обновил среду до 4,17. может дело в студии?
Ув, Di, второй день мучаюсь с компаратором в Меге32. Вроде бы работает, но крайне неустойчиво как-то. AIN0 подключен к внутреннему ИОН, на AIN1 - 2в. Суть проблемы - при включении питания компаратор часто срабатывает. Причем и при быстром выключении-включении ИП и в случае, если выключаю ИП и даю возможность емкостям разрядится. Как это привести в порядок? И еще вопрос, надо ли запрещать прерывания до (или на время) инициализации компаратора? И в какой последовательности правильно инициализировать начинку МК??
Во первых включить BOD во вторых можно потупить с пол секунды прежде чем кидаться инициализировать периферию.
я только начал разбиратся с контроллерами…и есть такая задача сравнить освещение двух фотодиодов и если один освещен больше то начать вращать двигатель через Н-мост в одну сторону а если второй до в другую сторону….как посоветуете это сделать??? я думаю проще всего через компаратор…но в програмировании темболее на асме только начал разбираться…прошу накидать примерный текст программы (кому не впадло) с коментариями.
Большое спасибо!!!
Поищи на сайте статью про фотодатчики. Тебе не нужен тут компаратор, для отлова фотодиодов хватит и выводов МК, ты с них снимать будешь сразу 0 или 1 в зависимости от того освещен у тебя фотодиод или нет.
Есть такая задумка: имеется базовое напяжение, которое подается на один из входов компаратора, на второй вход подается напряжение с заряженного конденсатора, то есть он начинает разряжаться при подключении к этому входу. Как будет вести себя компаратор? Будет ли он отслеживать разницу напряжений при разряде конденсатора или время разряда слишком мало? И каким образом можно сделать так, чтобы компаратор отследил разницу только между базовым напряжением и самым максимальным напряжением при разряде конденсатора, при условии что во время разряда конденсатор к питанию не подключен.
Компаратор не показывате величину разницы, он показывает что одно больше другого. Успеет он и кондер обслужить. Другой вопрос успеет ли контроллер обработать это время?
А чтобы ловить напряжение между чем то и чем то надо либо:
-два компаратора
-АЦП
-Быстро менять опорное напряжение при прохождении контрольных точек.
Никак не могу понять, что даст если быстро менять опорное напряжение? Ведь с конденсатора идет разряд напряжения, а если еще менять опорное, то будет что-то непонятное… И как можно поймать напряжение с помощью двух компараторов? DI HALT, будь добр - разъясни картину. Заранее благодарен.
Сначала обьясни толком что ты хочешь получить?
Идея такая: Имеется переменный резистор, сопротивление которого непрерывно меняется. Нужно сравнить два напряжения, снимаемых с этого переменного резистора с разницей во времени t (пусть для примера t=1 секунда). Подробнее: В данный момент времени t1 напряжение на резисторе U1, через некоторый промежуток времени (пусть для примера 1 секунда) на переменном резисторе будет напряжение U2. Нужно сравнить два этих напряжения U1 и U2. Но поскольку они различны во времени, то я хочу использовать для запоминания напряжения U1 конденсатор, а напряжение U2 будет как опорное. Таким образом, одно напряжение (U1)подается для сравнения с конденсатора, а второе непосредственно с переменного резистора. Но проблема в том, что напряжение с конденсатора непостоянное, т.к он будет разряжаться и мне нужно поймать самое максимальное напряжение на кондере. То есть, мне нужно сравнивать максимальное напряжение на конденсаторе(U1) и напряжение с переменного резистора (U2). Отсюда вопрос как это можно сделать? Возможно ли это сделать с помощью компаратора или есть другие варианты?
С компаратором ты затрахаешься. Потому что тебе придется именно что запоминать опорное напряжение, а у кондера есть утечки и прочие гадости. Изврат придумать можно, но надо будет делать ключи котыре придется коммутировать, чтобы отрезать кондер от U2 и законсервировать его до следующего измерения. В топку эти извраты, лучше заюзай АЦП. Там будет все просто - первое напряжение замерил, запомнил. Второе напряжение замерил - запомнил. Сравнил.
Либо сделай АЦП из аналогового компаратора, как я уже писал в статье:
http://easyelectronics.ru/avr-uchebnyj-kurs-delaem-acp-iz-analogovogo-komparatora.html