Содержание
Урок 1. Первый проект
Урок 2. Управление кнопками
Урок 3. Подключение LCD
Урок 4. Использование ШИМ
Урок 5. Таймеры
Урок 6.1. Статическая индикация
Урок 6.2. Динамическая индикация
Урок 7.1. Генерация звука
Урок 7.2. Генерация звука. Продолжение
Урок 8.1. Передача данных через UART
Урок 8.2. Передача данных через UART. Продолжение»
Урок 9. Передача данных через SPI
Урок 10. Изучение АЦП. Простой вольтметр
Урок 11. Получение синуса при помощи ШИМ
Урок 12. Измерение температуры
Урок 13. Внешние прерывания.
Урок 14. Использование отладчика
Урок 15.1. Управление инкрементальным энкодером
Урок 15.2. Управление громкостью, при помощи энкодера
Урок 16. Управление RGB светодиодом
Урок 17. Использование ИК
Урок 18.1. Знакомство с графическим дисплеем
Урок 18.2 Вывод изображения на графический дисплей
Урок 18.3 Вывод русскоязычного текста
Урок 19. Формирование сигнала, при помощи ЦАП (R2R)
Урок 20. Опрос матричной клавиатуры
Урок 21. Сторожевой таймер
Урок 22.1 Воспроизведение wav. Введение.
Урок 22.2 Воспроизведение wav. Продолжение.
Урок 23.1 Работа с внешней памятью
Урок 23.2 Работа с файловой системой Fat

adc_logАЦП — Аналого-цифровой преобразователь. Из названия можно догадаться, что на вход подается аналоговый сигнал, который преобразуется в число.

Первое о чем нужно сказать — АЦП микроконтроллера умеет измерять только напряжение. Чтобы произвести измерение других физических величин, их нужно вначале преобразовать в напряжение. Сигнал всегда измеряется относительно точки называемой опорное напряжение, эта же точка является максимумом который можно измерить. В качестве источника опорного напряжения (ИОН), рекомендуется выбирать высокостабильный источник напряжения, иначе все измерения будут плясать вместе с опорным.

Одной из важнейших характеристик является разрешающая способность, которая влияет на точность измерения. Весь диапазон измерения разбивается на части. Минимум ноль, максимум напряжение ИОН. Для 8 битного АЦП это 2^8=256 значений, для 10 битного 2^10=1024 значения. Таким образом, чем выше разрядность тем точнее можно измерять сигнал.

Допустим вы измеряете сигнал от 0 до 10В. Микроконтроллер используем Atmega8, с 10 битным АЦП. Это значит что диапазон 10В будет разделен на 1024 значений.  10В/1024=0,0097В — с таким шагом мы сможем измерять напряжение. Но учтите, что микроконтроллер будет считать, величину 0.0097, 0.0098, 0.0099… одинаковыми.

Тем не менее шаг в 0,01 это достаточно неплохо. Однако, есть несколько рекомендаций, без которых эта точность не будет соблюдена, например для измерения с точностью 10бит, частота на которой работает АЦП должна быть 50-200 кГц. Первое преобразование занимает 25 циклов и 13 циклов далее. Таким образом, при частоте 200кГц мы сможем максимум выжать
200 000/13 = 15 384 измерений.

В качестве источника опорного напряжения можно использовать внутренний источник и внешний. Напряжение внутреннего источника (2,3-2,7В) не рекомендуется использовать, по причине низкой стабильности. Внешний источник подключается к ножке AVCC или Aref, в зависимости от настроек программы.

При использовании АЦП ножка AVCC должна быть подключена. Напряжение AVCC не должно отличаться от напряжения питания микроконтроллера более чем на 0,3В. Как было сказано, максимальное измеряемое напряжение равно опорному напряжению(Vref), находится оно в диапазоне 2В-AVCC. Таким образом, микроконтроллер не может измерить более 5В.

Чтобы расширить диапазон измерения, нужно измерять сигнал через делитель напряжения. Например, максимальное измеряемое напряжение 10В, опорное напряжение 5В. Чтобы расширить диапазон измерения, нужно уменьшить измеряемый сигнал в 2 раза.

Формула для расчета делителя выглядит так:

Uвых =  UвхR2/(R1 + R2)

Подставим наши значения в формулу:

5 = 10*R2/(R1+R2)

(R1+R2)=2*R2

R1=R2

т.е. можно взять любые два одинаковых резистора и подключить их по схеме
adc6

Следовательно, когда мы измеряем напряжение через делитель, нужно полученное значение АЦП умножить на коэффициент=Uвых/Uвх.

Полная формула вычисления измеряемого напряжения будет выглядеть так:
U=(опорное напряжение*значение АЦП*коэффициент делителя)/число разрядов АЦП

Пример: опорное 5В, измеренное значение АЦП = 512, коэффициент делителя =2, АЦП 10разрядный.

(5*512*2)/1024=5В — реальное измеренное значение напряжения.

Некоторые программисты пишут программу так, чтобы микроконтроллер автоматически вычислял коэффициент делителя, для этого выходной сигнал измеряют образцовым прибором и заносят это значение в программу. Микроконтроллер сам соотносит истинное напряжение каждому значению АЦП, сам процесс однократный и носит название калибровки.

Перейдем к программной реализации. Создаем проект с указанными параметрами. Также подключим дисплей на порт D для отображения информации.

adc3

Измерение будет производиться в автоматическом режиме, обработка кода в прерывании, опорное напряжение подключаем к ножке AVCC. По сути нам нужно только обрабатывать получаемые данные. Измеренные данные хранятся в переменной adc_data[0]. Если нужно опрашивать несколько каналов, то выбираем какие каналы сканировать, а данные будут для ножки 0 в adc_data[0], для ножки 1 в adc_data[1] и т.д.

В основном цикле добавим строки:

result=((5.00*adc_data[0])/1024.00); //пересчитываем значение АЦП в вольты
sprintf(lcd_buffer,»U=%.2fV»,result);   //помещаем во временную переменную результат
lcd_puts(lcd_buffer);                          //выводим на экран

Небольшое замечание, чтобы использовать числа с плавающей точкой, нужно в настройках проекта изменить (s)printf Features: int, width на float, width, precision. Если этого не сделать десятые и сотые мы не увидим.
adc_feature

Таким образом, мы всего лишь перевели значение АЦП в вольты и вывели на дисплей. Результат в протеусе выглядит так:
adc1

Резистором можно менять напряжение, измеряемое напряжение выведено на дисплей. При сборке на реальном железе к ножке Aref нужно подключить конденсатор на 0,1мкФ. Урок получился немного сложным, но думаю он вам понравится.

Файл протеуса и прошивка:

Update:
Измерение тока:
adc_current

258 комментариев: Урок 10. АЦП в AVR микроконтроллерах. Простой вольтметр на AVR.

  • с помощью регистра здвига 74hc595 эта проблема решается просто


  • result=((5*adc_data[0])/1024); //пересчитываем значение АЦП в вольты
    sprintf(lcd_buffer,»U=%d»,result); //помещаем во временную переменную результат
    lcd_puts(lcd_buffer); //выводим на экран

  • гн Админ да result=((5*adc_data[0])/1024) эта формула работает но result=((78*adc_data[0])/1024) показывает что ты не те цифры???

  • Значит делитель неправильно посчитан. Можно взять вольтметр, померить на входе и выходе, пересчитать результат.

  • стоп я это все пока проверяют на протеусе!!! здесь программная загвоска почему под цыфру 64 все ок 65 глюк

  • sprintf(lcd_buffer,»U=%i»,result); кобинация работаеть от 0 до 63

  • Создайте тему на форуме и прикрепляйте туда проект, так это гадание на кофейной гуще

  • ок

  • Доброе время суток.
    А как сменить порт у АЦП? В данном коде ADC0, а мне необходимо мерить два напряжение и на ADC0 и на ADC1.
    Спасибо.

  • АЦП на борту один, к разным входам он подключается через мультиплексор, в генераторе кода есть галочка автоматически сканировать порты и выбираете какие. Результат будет в adc_data[0] и adc_data[1]

  • добрый день
    умне вапрос а как я зделию
    схема контроля заряда аккумулятора АЦП мне направление дайте пожалуйста

  • Направление — нужно измерять dU/dt

  • Доброе время суток. возможна объявить один бить переменною если да как это выглядит???

  • например как «bit a=0;»

  • здравствуйте
    КАК можна получит цифровой индикатором

    result=((15.0*adc_data[0])/1024.00);
    float и switch не получилса

  • не вкурил вопрос

  • здравствуйте

    result=((15.0*adc_data[0])/1024.00);
    как можна подключит цифравой индикатор замена на lcd

  • КАК можна разбиваю float в switch

    x = result*10;
    x = x/10;
    nom2 = x/10;
    nom = nom2;
    switch(nom)
    {
    case 0:{PORTD=0x3F; break;} // 0. ÎÁØÈÉ ÊÀÊÒÎÄÍÈ
    case 1:{PORTD=0x06; break;} // 1.
    case 2:{PORTD=0x5B; break;} // 2
    case 3:{PORTD=0x4F; break;} // 3.
    case 4:{PORTD=0x66; break;} // 4.
    case 5:{PORTD=0x6D; break;} // 5 .
    case 6:{PORTD=0x7D; break;} // 6.
    case 7:{PORTD=0x07; break;} // 7.
    case 8:{PORTD=0x7F; break;} // 8.
    case 9:{PORTD=0x6F; break;} // 9
    }

  • num1 = result/10; //десятки
    num2 = result%10; //единицы
    num3 = ((float)result — (char)result)*10; //дробная часть, будет с небольшой погрешностью

  • !!! В МК ATmega8 номер вывода подключенного к входу АЦП задается с помощью регистра ADMUX — регистр мультиплексора АЦП.

    Менюха Automatically Scan Inputs, со значениями 0 0, выбирает нулевую ногу ADC0

    Тоесть строка

    #define FIRST_ADC_INPUT 0
    #define LAST_ADC_INPUT 0
    ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index; определяет под АЦП ножку «0» тоесть ADC0

    Можно выбрать от 0 до 5.

    Пятый выход будет вот такой

    #define FIRST_ADC_INPUT 5
    #define LAST_ADC_INPUT 5
    ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index;

    Можно не ставить галочку Automatically Scan Inputs — тогда будет сконфигурирован выход ADC0

    Я так понял это хитрая тема, позволяет подключать до 5 входов под АЦП (задавая диапазон от 0 до 5), поочередно сканирует значения на ножках…

  • A можно и так :
    sprintf(lcd_buffer,»U = %i.%u V «,result/1000,result%1000 );
    Внаглую поставить запятую после первого разряда и не думать о флоатинг поинт … 😛

  • Делаем вольтметр на 8 атмеге, есть у нас некоторые проблемы с внутренним опорным напряждением, скажите возможно ли что при инициализации внутреннего источника опорного напряжения, на ножку AREF выводится уровень не 2,56 а 2,61 и если это возможно, то от какого значения брать поправочные коэффициенты: 2,56 как заявлено в даташите или 2,61 как показывает наш мультиметр?

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

  • ПОЗДРАВЛЯЮ ВСЕХ
    помагите разобратся с ацп у меня работает все норм только проблема в том что входное напряжениеот 0— 2,2 вольта. допустим вход 1,1в на идикации нужно чтоб высвечивалось 150 , соответс 2,2 _ 300
    АДЦ 300/1023=0,29
    read_adc(5);
    for(i=0;i<50;i++)ind_davlenie(ADCW * 0.29);
    но все не то помагите пожалуста

  • Погрешность может быть, правильно поставить внешний стабилизированный источник опорного.

  • АЦП на борту один

  • Админ, у тебя в примере строчка
    register static unsigned char input_index=0;

    Что за register? С ним не компилировался хекс, а без него вроде полет нормальный.

  • Этот код сгенерен мастером CAVR. Из стандарта СИ, данный спецификатор указывает компилятору хранить значение переменной не в памяти, а в регистре процессора, т.е. указываем компилятору что будем часто пользоваться этой переменной. Я думаю здесь этот спецификатор роли не играет

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

  • АЦП снимает правильно показания, при желании можно и датчик холла подцепить

  • что означяет старший байт и младший байт подробнее кто обяснит?

  • Если у вас число состоит из двух байт (16 битное), например число 61 695 в двоичной записи
    0b 1111 0000 1111 1111. Чтение битов справа налево, таким образом первые восемь бит 1111 1111 будут образовывать младший байт, а 0000 1111 будут образовывать старший байт. Еще проще рассматривать такие вещи в шестнадцатеричной, число 61 695 = 0хF0FF, тогда младший байт 0xFF старший 0xF0

  • Доброго времени суток
    Админ спасибо за сайт+++++
    Есть вопрос
    Написал благодаря вашему сайту несколько проэктов для тренировки,но во всех использовал атмега8
    Теперь решил попробовать аттини13
    но как насторить АЦП в аттини13,открываю проэкт-совсем не так как у атмега8(в даташите немогу разобрать)
    Просьба,можете описать пару строчек о настройке пункта ADC
    Спасибо.

  • Полная формула вычисления измеряемого напряжения будет выглядеть так:
    U=(опорное напряжение*значение АЦП*коэффициент делителя)/число разрядов АЦП

    Пример: опорное 5В, измеренное значение АЦП = 512, коэффициент делителя =2, АЦП 10разрядный.

    (5*512*2)/1024=5В — реальное измеренное значение напряжения.
    ===================================
    Скажите пожалуйста а как получить обратное значение?? Допустим имеем мы 5 вольт на входе АЦП (после делителя)и по какой формуле рассчитать какое значение должен АЦП контроллера показывать при входном напряжении 5 вольт??

    Задача такая у меня. Я считываю значение напряжение из файла допустим это напряжение 12.5 в. потом я контроллером мерию напряжение на входе и когда они совпадают с считанным 12.5 делаю что мне надо. Хочу реализовать так. Считываю из файла напряжение 12.5 преобразую его в значение АЦП которое соответствует напряжению 12.5 и сравниваю это значение с там которое сейчас в АЦП и когда они совпадают делаю что мне надо. Но как преобразовать 12.5 в и узнать какое значение должно быть в АЦП при таком напряжении на входе??

  • Померяйте тестером напряжение на входе делителя и на выходе. Поделите напряжение входа на выход, получите коэффициент.

  • Так мне не нужно узнавать коэффициент делителя он автоматически рассчитывается и показывается в калькуляторе. из этой статьи имеем что

    ===================
    Полная формула вычисления измеряемого напряжения будет выглядеть так:
    U=(опорное напряжение*значение АЦП*коэффициент делителя)/число разрядов АЦП
    Пример: опорное 5В, измеренное значение АЦП = 512, коэффициент делителя =2, АЦП 10разрядный.
    (5*512*2)/1024=5В — реальное измеренное значение напряжения.
    ===================================

    мне нужно обратное зделать преобразование!!! Допустим на вход делителя подаётся напряжение 12.5 в. (коэффициент делителя мы знаем)так по какой формуле можно рассчитать какой код внутри АЦП контроллера будет при таком входном напряжении???

  • Подставляете в эту формулу известные значения, переносите неизвестное. Математика 5 класс.

  • и как в этой формуле что надо перенести куда? расскажите если знаете.

    ===================
    Полная формула вычисления измеряемого напряжения будет выглядеть так:
    U=(опорное напряжение*значение АЦП*коэффициент делителя)/число разрядов АЦП
    Пример: опорное 5В, измеренное значение АЦП = 512, коэффициент делителя =2, АЦП 10разрядный.
    (5*512*2)/1024=5В — реальное измеренное значение напряжения.
    ===================================

    мы знаем:
    опорное напряжение = 5в
    коэффициент деление = 2
    число разрядов АЦП = 1024

    надо найти значение АЦП, как??? Я пробовал переносить не работает

  • U=(опорное напряжение*значение АЦП*коэффициент делителя)/число разрядов АЦП
    12.5 = (5 * x * 2)/1024
    x = (12.5*1024)/10

  • Ураа вот как надо на радиокоте помогли

    А вывести из формулы одну из переменных в школе еще не научили? :facepalm:
    U = (Vr * X * d) / 2 ^ n, где U — напряжение на входе, Vr — опорное, X — код, d — делитель, n — разрядность
    выносим X:
    X = U * 2 ^ n / (Vr * d)

    Например делитель у вас 2, на вход попадает — 12.5, тогда:

    X = 12.5 * 1024 / (5 * 2) = 5120

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

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

Последние комментарии
  • Загрузка...
Счетчик
Яндекс.Метрика