Главная » Статьи » Проекты |
Аналогово-Цифровой Преобразователь служит для преобразования аналогового сигнала на входе в цифровую форму, понятную для МК. Практически во всех современных микроконтроллерах от AVR имеется 10 битный АЦП, позволяющий оцифровывать аналоговый сигнал с дискретностью 1024 значений. Этого достаточно чтобы, например, делать замеры напряжений (в разумных пределах), снимать показания с различных датчиков, таких как фотодиод и термопара, делать анализаторы спектра и многое другое. Примерная работа преобразования приведена на рисунке ниже; через равные промежутки времени (ось X) происходит считывание значения напряжения на входе АЦП (ось Y). Так как АЦП имеет ограниченную разрешающую способность, появляется дискретность (дробление) значений. Величина по оХ называется частотой дискретизации, чем больше частота тем точнее может быть полученная информация о сигнале. АЦП в мк AVR может работать на частотах дискретизации от 50 до 200 кГц В Bascom-AVR конфигурирование АЦП сводится к одной строчке: Config Adc = SINGLE , Prescaler = 128 , Reference = Avcc здесь Adc - режим считывания значения: Single - единичное считывание, также может быть Free (режим постоянной работы преобразователя) Prescaler = 128 - выбираем частоту дискретизации путем деления частоты кварца на определенное число (также может быть 2,4,8,16,32,64 или Auto). Если выбрать Auto, то компилятор сам выберет подходящую частоту работы АЦП Reference – выбор источника опорного напряжения. Aref – внешний источник, Avcc – напряжение питания схемы, Internal – внутренний ИОН на 2,56 в. Преобразование аналога в цифру в Bascom-AVR происходит следующим образом, для примера считаем значение напряжения на первом канале АЦП и выведем результат преобразования на ЖКИ: Start ADC ' запускаем преобразование M = GetADC(1) ' приравниваем переменную М результату преобразования Stop ADC ' останавливаем работу АЦП LCD M ' выводим значение на ЖКИ Считывание может быть произведено с любого пина АЦП микроконтроллера, от 0 до 7 (например для ATMEGA32). Для этого в строке GetADC(x) заместо х ставим интересующий нас канал. И все! В дополнение решил собрать вольтметр на ATMega8. Во-первых стало интересно как точно все это работает в железе, и во-вторых вольтметр пригодится в регулируемом блоке питания который хочу собрать. Итак, первым делом нужно определиться с диапазоном измеряемых значений. Я выбрал пределом измерения 30 Вольт, от этого зависит коэффициент на который нужно будет умножать результат преобразования, а также расчет резисторного делителя напряжения на входе АЦП. В качестве источника опорного напряжения выбран внутренний ИОН на 2,56 В. Поэтому резисторный делитель рассчитан таким образом, чтобы при максимально измеряемом напряжении 30 В на вход АЦП заходило не более 2,56 В. Схема вольтметра приведена ниже: Подстроечник RV1 - многооборотный, для точной настройки делителя. В схеме использованы семисегментные индикаторы с общим анодом, но без точки. Точку пришлось добавлять путем высверливания отверстия и вставки в него светодиода. Точку я сделал горящей постоянно, а сегменты управляются динамически. Индикация организована в главном цикле программы. Для считывания показаний АЦП задействован Timer1, который переполняется примерно 2 раза в секунду. При переполнении вызывается подпрограмма, в которой происходит считывание данных с АЦП и их преобразование. Так как переполнение таймера происходит каждые 0,5 сек, то показания вольтметра будут обновляться 2 раза в секунду. Это сделано для того чтобы четвертая цифра отображающая сотые доли не скакала слишком быстро, размазывая показания (так как АЦП имеет свойство иногда менять показания при неизменном напряжении на входе). $regfile = "m8def.dat" $crystal = 8000000 ' * * * переменные * * * Dim W As Integer ' переменная для хранения значения АЦП Dim N1 As Integer Dim N2 As Integer Dim N3 As Integer Dim N4 As Integer Dim M1 As Integer Dim M2 As Integer Dim M3 As Integer Dim M4 As Integer Dim C1 As Integer Dim C2 As Integer Dim C3 As Integer Dim C4 As Integer ' * * * настройка портов * * * Ddrb = &B11111111 Ddrd = &B11111111 ' * * * конфигурируем таймер1 и прерывание по его переполнению * * * Config Timer1 = Timer , Prescale = 64 On Timer1 Acp: ' * * * конфигурация АЦП * * * Config Adc = Single , Prescaler = Auto , Reference = Internal ' * * * разрешаем прерывания * * * Enable Interrupts Enable Timer1 ' * * * основная программа * * * Do Portb = &B11101111 Select Case N1 Case 0 : Portd = &B11111111 Case 1 : Portd = &B11111001 Case 2 : Portd = &B10100100 Case 3 : Portd = &B10110000 Case 4 : Portd = &B10011001 Case 5 : Portd = &B10010010 Case 6 : Portd = &B10000010 Case 7 : Portd = &B11111000 Case 8 : Portd = &B10000000 Case 9 : Portd = &B10010000 End Select Waitms 5 Portb = &B11110111 Select Case N2 Case 0 : Portd = &B11000000 Case 1 : Portd = &B11111001 Case 2 : Portd = &B10100100 Case 3 : Portd = &B10110000 Case 4 : Portd = &B10011001 Case 5 : Portd = &B10010010 Case 6 : Portd = &B10000010 Case 7 : Portd = &B11111000 Case 8 : Portd = &B10000000 Case 9 : Portd = &B10010000 End Select Waitms 5 Portb = &B11111011 Select Case N3 Case 0 : Portd = &B11000000 Case 1 : Portd = &B11111001 Case 2 : Portd = &B10100100 Case 3 : Portd = &B10110000 Case 4 : Portd = &B10011001 Case 5 : Portd = &B10010010 Case 6 : Portd = &B10000010 Case 7 : Portd = &B11111000 Case 8 : Portd = &B10000000 Case 9 : Portd = &B10010000 End Select Waitms 5 Portb = &B11111101 Select Case N4 Case 0 : Portd = &B11000000 Case 1 : Portd = &B11111001 Case 2 : Portd = &B10100100 Case 3 : Portd = &B10110000 Case 4 : Portd = &B10011001 Case 5 : Portd = &B10010010 Case 6 : Portd = &B10000010 Case 7 : Portd = &B11111000 Case 8 : Portd = &B10000000 Case 9 : Portd = &B10010000 End Select Waitms 5 Loop ' * * * подпрограмма считывания показания с АЦП * * * Acp: Start Adc ' считываем показания АЦП W = Getadc(1) ' <---- число которое получили с первого канала АЦП M1 = W * 3 ' переводим значение АЦП в вольты. Так как запятая у меня ' фиксированная, то для удобства работать будем с целыми числами 3069/1023=3; ' где 3069 максимальное значение напряжения отображаемое вольтметром, ' или 30.69 В M2 = M1 M3 = M1 M4 = M1 M1 = M1 / 1000 ' обработка тысяч N1 = Abs(M1) M2 = M2 Mod 1000 ' обработка сотен M2 = M2 / 100 N2 = Abs(M2) M3 = M3 Mod 100 ' обработка десяток M3 = M3 / 10 N3 = Abs(M3) M4 = M4 Mod 10 ' обработка единиц N4 = Abs(M4) Return End Заснял небольшое видео, показывающее работу вольтметра. Разрешение измерения вольтметра получилась 0,03 В (большего из 10 битного АЦП на таком диапазоне не выжать), точность не менее 0,05 В. Что весьма не плохо, учитывая что использовался внутренний ИОН и не использовались ВЧ-фильтры на входе преобразователя. Для блока питания самое то. ЗЫ. Если говорить о точности измерения, то в качестве эталонного измерителя напряжения выступал мой Mastech MAS838, поэтому все относительно =) Скачать файлы к проекту | |
Просмотров: 72661 | Комментарии: 32
| Теги: |
Всего комментариев: 32 | 1 2 » | |||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||
1-30 31-32 | ||||||||||||||||||||||||||||
Проекты [46] |
Как подключить [32] |
Инструменты [3] |
Полезная информация [18] |
Объявления [3] |