Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: АЦП в ATMega8: 8 бит или 10 бит?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Sminder
При использовании АЦП в микроконтроллере ATMega8 была замечена одна интересная особенность. По официальным справочным данным в корпусе DIP микроконтроллер имеет два канала АЦП с разрешением 8 бит (ADC4 и ADC5) и четыре канала с разрешением 10 бит (ADC0...ADC3). Использовался канал ADC5. При считываении данных из регистра ADC в выбранном канале значение менялось от 0 до 1023(!!!), что эквивалентно разрешению 10 бит. Возник вопрос: как это обьяснить?
SasaVitebsk
Цитата(Sminder @ Mar 18 2007, 20:35) *
При использовании АЦП в микроконтроллере ATMega8 была замечена одна интересная особенность. По официальным справочным данным в корпусе DIP микроконтроллер имеет два канала АЦП с разрешением 8 бит (ADC4 и ADC5) и четыре канала с разрешением 10 бит (ADC0...ADC3). Использовался канал ADC5. При считываении данных из регистра ADC в выбранном канале значение менялось от 0 до 1023(!!!), что эквивалентно разрешению 10 бит. Возник вопрос: как это обьяснить?


Вы не совсем точно перевели даташит. Разрешение всех каналов составляет 10 бит. Но в DIP корпусе точность не гарантируется более 8 бит.
Сергей Борщ
Цитата(Sminder @ Mar 18 2007, 18:35) *
При считываении данных из регистра ADC в выбранном канале значение менялось от 0 до 1023(!!!), что эквивалентно разрешению 10 бит. Возник вопрос: как это обьяснить?
Очень просто - младшим двум битам верить нельзя. Т.е. их достоверность Атмел не гарантирует, в них скорее всего шум.
singlskv
Цитата(Sminder @ Mar 18 2007, 19:35) *
При использовании АЦП в микроконтроллере ATMega8 была замечена одна интересная особенность. По официальным справочным данным в корпусе DIP микроконтроллер имеет два канала АЦП с разрешением 8 бит (ADC4 и ADC5) и четыре канала с разрешением 10 бит (ADC0...ADC3). Использовался канал ADC5. При считываении данных из регистра ADC в выбранном канале значение менялось от 0 до 1023(!!!), что эквивалентно разрешению 10 бит. Возник вопрос: как это обьяснить?


Чтобы считывать только 8бит из ADC установите бит ADLAR в ADMUX
и читайте только регистр ADCH, получите 8бит и время на считывание
сэкономите
=GM=
Цитата(Sminder @ Mar 18 2007, 16:35) *
При использовании АЦП в микроконтроллере ATMega8 была замечена одна интересная особенность. По официальным справочным данным в корпусе DIP микроконтроллер имеет два канала АЦП с разрешением 8 бит (ADC4 и ADC5) и четыре канала с разрешением 10 бит (ADC0...ADC3). Использовался канал ADC5. При считываении данных из регистра ADC в выбранном канале значение менялось от 0 до 1023(!!!), что эквивалентно разрешению 10 бит. Возник вопрос: как это обьяснить?

Такое было в описаниях до версии М включительно, однако, начиная с версии N, все каналы имеют одинаковую разрядность и одинаковую абсолютную точность НЕЗАВИСИМО от типа корпуса. 1.75 lsb при 200 кГц клока и 3 lsb при 1000 кГц клока ацп. Работают люди(:-).

Объяснений можно дать много, но скорее всего у вас канал висел в воздухе, и вы оцифровывали наводку.
Sminder
Цитата(=GM= @ Mar 18 2007, 21:21) *
Объяснений можно дать много, но скорее всего у вас канал висел в воздухе, и вы оцифровывали наводку.

Я, наверное, не совсем понятно обрисовал ситуацию, но вывод в воздухе конечно же не висел - на него подавалось калиброванное напряжение, что и контролировалось с помощью АЦП.
Цитата
Очень просто - младшим двум битам верить нельзя. Т.е. их достоверность Атмел не гарантирует, в них скорее всего шум.

Вероятно, так оно и есть, измерения особой точностью не блещут, но я правда не ставил режим шумопонижения и фильтры в цепях опорного напряжения.
Цитата
Вы не совсем точно перевели даташит. Разрешение всех каналов составляет 10 бит. Но в DIP корпусе точность не гарантируется более 8 бит

Я являюсь обладателем справочника А.В. Евстифеева "Микроконтроллеры AVR семейств Tiny и Mega фирмы Atmel", где в принципе и написано, цитирую: "... Кроме того, во всех моделях ATMega8x два канала (ADC4 и ADC5) являются 8-разрядными." Даташит на английском я тоже имею, но и в нем ничего путевого не нашел.
arttab
Верить надо даташитам на ту версию мк на которую хотите узнать. Книги фиксируют актуальность на момент редакции. Вы же не ищите современные элементы по старым справочникам.

Цитата(=GM= @ Mar 19 2007, 01:21) *
Такое было в описаниях до версии М включительно, однако, начиная с версии N, все каналы имеют одинаковую разрядность и одинаковую абсолютную точность НЕЗАВИСИМО от типа корпуса. 1.75 lsb при 200 кГц клока и 3 lsb при 1000 кГц клока ацп. Работают люди(:-).
Sminder
Извиняюсь, я был неправ. Действительно, просмотрев версию мануала ревизии Р (раньше была Н), я убедился, что все каналы АЦП 10-разрядные.
=GM=
Цитата(Sminder @ Mar 20 2007, 19:22) *
Извиняюсь, я был неправ. Действительно, просмотрев версию мануала ревизии Р (раньше была Н), я убедился, что все каналы АЦП 10-разрядные.

Да уже версия Q есть, октябрь 2006, полгода прошло, что ж вы всё старые качаете(:-).
arttab
а если документ с историей изменений? что то не попадался мне такой.
=GM=
Цитата(arttab @ Mar 21 2007, 07:31) *
а есть ли документ с историей изменений? что то не попадался мне такой.

Конечно, раздел называется Datasheet Revision History. Стр. 297 упоминавшейся версии Q.
umup
Цитата
во всех моделях ATMega8x два канала (ADC4 и ADC5) являются 8-разрядными


там наверно имеется ввиду не буквальная 8-разрядность, а точность измерения по этим каналам (измерение проходит в нормальном 10-битном режиме, но младшие 2 разряда должны прыгать), возможно связано это с совмещением этих выводов с TWI. Хотя я не заметил существенной разницы между этими и другими каналами АЦП, наверно в более новых кристаллах переразвели аналоговую часть.
defunct
Цитата(Sminder @ Mar 19 2007, 22:28) *
канала (ADC4 и ADC5) являются 8-разрядными." Даташит на английском я тоже имею, но и в нем ничего путевого не нашел.

Если под "путевым" имеется в виду та чушь из справочника А.В. Евстифеева, то вы ее там не найдете потому что в даташите ее нет...

В даташите есть достоверная инфа про конкретный чип, его просто надо читать, а не картинки рассматривать...
kv_addr
Цитата(defunct @ Apr 23 2007, 13:51) *
Если под "путевым" имеется в виду та чушь из справочника А.В. Евстифеева, то вы ее там не найдете потому что в даташите ее нет...

В даташите есть достоверная инфа про конкретный чип, его просто надо читать, а не картинки рассматривать...

Та ну, не стоит так набрасываться, и на Евстифеева в том числе. Было такое дело, 6+2 или 4+2 каналов, два из которых позиционировались как 8-битной точности. Именно в дейташите. Правда, древнем. wink.gif Могу ревизию указать, поскольку и антиквариат храню wink.gif Rev. 2486I–AVR–12/02.

А что Евсифеев, он тоже ведь мог оным дейташитом пользоваться, просто на момент написания книги более новых не существовало.

Мало того, в старом дейташите есть упоминание об одном хитром бите регистра SFIOR. Это - Bit 4 – ADHSM: ADC High Speed Mode. Вот что о нем написано: Writing this bit to one enables the ADC High Speed mode. This mode enables higher conversion rate at the expense of higher power consumption. В более поздних ревизиях дейташитов это упоминание было изъято. Хотя бит, как ни странно, работает. wink.gif

Вот такие пироги.
defunct
Цитата(kv_addr @ Apr 23 2007, 14:59) *
Вот такие пироги.

Извиняюсь погорячился.. Понедельник - день тяжелый ;>
А ДШ свежий желательно иметь всегда, особливо когда возникают спорные вопросы.
kv_addr
Цитата(defunct @ Apr 23 2007, 16:04) *
Извиняюсь погорячился.. Понедельник - день тяжелый ;>

В понедельник бывает. wink.gif
Цитата(defunct @ Apr 23 2007, 16:04) *
А ДШ свежий желательно иметь всегда, особливо когда возникают спорные вопросы.

Тут - без каких-либо возражений.
NVade
немного не по теме, но сталкивался с ситуацией с тексасовскими ЦАПами. Как это принято имеется семейство с одинаковой цоколевкой и разрядностью 8/10/12 в зависимости от типа (и цены в геометрической прогрессии естественно). Брали 10 -разрядный, а оказалось что у него все 12 разрядов работают. Для себя объяснил что так делается по маркетинговым соображениям.
Может и здесь Atmel пытался покончить с архаичным dip'ом. Явно кристаллы одинаковые идут в разные корпуса. В том, что разрядность может в 4 раза пострадать из-за большей длины от кристалла до пина сильно сомневаюсь.
arttab
В старых ревизиях было 8 бит. Потом в новой ревизии стало 10 bit ADC. Ограничение по корпусам не видел, т.е. на всех корпуса 10 bit. Или я что то проглядел.
Anjey_N
Я новичок, поэтому наверное сейчас задам глупый вопрос!
Пишу прогу для вольтметра, использую Мегу16 со встроенным АЦП. Делаю 128 выборок, суммирую и затем делю на 128. Получаю результат. Мне сказали, что теперь нужно применить вычисление скользящего среднего. А как это сделать, я не знаю! Может, кто-нибудь подскажет или даст ссылку на это чудо! help.gif
Сергей Борщ
Цитата(Anjey_N @ Apr 24 2007, 18:50) *
Мне сказали, что теперь нужно применить вычисление скользящего среднего. А как это сделать, я не знаю!
Поиск по форуму по словосочетанию "скользящее среднее" дает несколько результатов, уже не говоря о том, сколько результатов на такое же словосочетание дает google.
arttab
я делал простое усреднение так:
Xi = (Xi + Xi+1) / 2
Xi+1 результат нового измерения
только частоты выборок должна быть больше скорости изменения сигнала иначе фигня получиться.
в общем вмде можно так записать:
Xi = (k/n)*Xi + (p/n)*Xi+1
от коэффициентов будет зависеть скорость приближения к устоявшемуся значению.
IgorKossak
Цитата(Anjey_N @ Apr 24 2007, 19:50) *
Я новичок, поэтому наверное сейчас задам глупый вопрос!
Пишу прогу для вольтметра, использую Мегу16 со встроенным АЦП. Делаю 128 выборок, суммирую и затем делю на 128. Получаю результат. Мне сказали, что теперь нужно применить вычисление скользящего среднего. А как это сделать, я не знаю! Может, кто-нибудь подскажет или даст ссылку на это чудо! help.gif

Делаете кольцевой массив на количество выборок и переменную для суммы.
С каждой новой выборкой вычитаете из суммы самое старое значение из массива, пишете на его место значение выборки, прибавляете к сумме значение выборки и делите сумму на количество элементов в массиве (константа).
Как проинициализировать массив решайте сами.
defunct
Цитата(Anjey_N @ Apr 24 2007, 18:50) *
Мне сказали, что теперь нужно применить вычисление скользящего среднего. А как это сделать, я не знаю!


Пример скользящего усреднения по 16-ти точкам (без использования массивов)

Код
int UpdateAverage( int CurrVal )
{
    static int Sum = 0;
    int tmp = (Sum + (16 >> 1)) >> 4; // среднее = (Sum + n/2) / n, где n = 16
    Sum += CurrVal - tmp;
    return tmp;
}



<Усредненное значение АЦП> = UpdateAverage( <Текущее значение АЦП> );
Snaky
Цитата(defunct @ Apr 26 2007, 03:52) *
Пример скользящего усреднения по 16-ти точкам (без использования массивов)

Код
int UpdateAverage( int CurrVal )
{
    static int Sum = 0;
    int tmp = (Sum + (16 >> 1)) >> 4; // среднее = (Sum + n/2) / n, где n = 16
    Sum += CurrVal - tmp;
    return tmp;
}



<Усредненное значение АЦП> = UpdateAverage( <Текущее значение АЦП> );

нерабочий примерчик-то. вызвал 16 раз функцию с аргументом CurrVal = 10, в результате получил 6. через 20 итераций получил 7. blink.gif
и вообще странный какой-то алгоритм - возвращать результат целочисленного деления (накопленной суммы + константа) на константу.

PS я всегда пользуюсь методом с кольцевым массивом, как описал IgorKossak
defunct
Цитата(Snaky @ Apr 26 2007, 05:56) *
нерабочий примерчик-то. вызвал 16 раз функцию с аргументом CurrVal = 10, в результате получил 6. через 20 итераций получил 7. blink.gif

Пример рабочий. Вы дальше повызывайте.
Хотите чтоб быстрее получался рез-тат усредняйте по 8-ми или по 4-м точкам.

Цитата
и вообще странный какой-то алгоритм - возвращать результат целочисленного деления (накопленной суммы + константа)

Почитайте какую-нить книжку по усреднению прежде чем выступать.
Константа эта для устранения абсолютной погрешности в 0.5LSB при накоплении суммы.

Цитата
PS я всегда пользуюсь методом с кольцевым массивом

У вас видать памяти в МК всегда много..
Lepeksiy
В общем виде фильтрация выглядит примерно так (для чайников):

Код
// Размер массива - должен быть степенью двойки!!
#define ARRAY_SIZE 16

// Функция берет текущее значение и возвращает отфильтрованное
int GetMovingAverage(int current_value)
{
    static int filter_array[ARRAY_SIZE];
    static unsigned int index = 0;
    static int sum = 0;

    // Вычитаем удаляемое значение из суммы и прибавляем текущее
    sum += current_value - filter_array[index];
    // Вставляем текущее значение в массив
    filter_array[index] = current_value;
    // Изменяем индекс. Не забывать, что ARRAY_SIZE должен быть степенью двойки!!
    index = (index + 1) & (ARRAY_SIZE - 1);
    // Возвращаем отфильтрованное значение.
    return sum / ARRAY_SIZE;
}

Реальные типы переменных должны быть согласованы с размерностью данных. Данные считаются недостоверными, пока функция не будет вызвана ARRAY_SIZE раз.
VladimirYU
Можно испоьзовать алгоритм апериодического звена. Строится он по принципу интегратора ( сумматора накопителя) охваченного отрицательной обратной связью. Это позволяет уйти от скользящего массива, правда требуется сумматор (интегратор) двойной длины по сравнению с длиной результатов измерений и переменная для хранения предыдущего фильтрованного результата.
Lepeksiy
VladimirYU
А как это выражается формулами?
Anjey_N
Цитата(Lepeksiy @ Apr 26 2007, 13:08) *
В общем виде фильтрация выглядит примерно так (для чайников):

Код
// Размер массива - должен быть степенью двойки!!
#define ARRAY_SIZE 16

// Функция берет текущее значение и возвращает отфильтрованное
int GetMovingAverage(int current_value)
{
    static int filter_array[ARRAY_SIZE];
    static unsigned int index = 0;
    static int sum = 0;

    // Вычитаем удаляемое значение из суммы и прибавляем текущее
    sum += current_value - filter_array[index];
    // Вставляем текущее значение в массив
    filter_array[index] = current_value;
    // Изменяем индекс. Не забывать, что ARRAY_SIZE должен быть степенью двойки!!
    index = (index + 1) & (ARRAY_SIZE - 1);
    // Возвращаем отфильтрованное значение.
    return sum / ARRAY_SIZE;
}

Реальные типы переменных должны быть согласованы с размерностью данных. Данные считаются недостоверными, пока функция не будет вызвана ARRAY_SIZE раз.



Спасибо, буду разбираться и учиться! w00t.gif
ReAl
Цитата(defunct @ Apr 26 2007, 12:07) *
Пример рабочий. Вы дальше повызывайте.
Хотите чтоб быстрее получался рез-тат усредняйте по 8-ми или по 4-м точкам.

Фильтр неплохой, сам пользуюсь :-)
Но это, IMHO, не скользящее среднее.
Реакция скользящего среднего на единичный скачок - прямая линия с выходом на уровень, т.е. если у нас было "много" нулей и вдруг пошло 32, то на 16-ом значении (при скользящем усреднении окном в 16 отсчётов) на выходе уже будет 32.
А этот "экспоненциальный" фильтр имеет поведение как у RC-цепочки.
defunct
Snaky

Ради интереса попробуйте вот это (по 4м точкам):

Код
int UpdateAverage( int CurrVal )
{
    static int Sum = 0;
    int tmp = (Sum + 2) >> 2;
    Sum += CurrVal - tmp;
    return tmp;
}


за 12 итераций будет вам 10. ;>
А алгоритм прост до ужаса, упрощенно:

среднее = Sum / кол-во выборок по который усредняем.
Sum = Sum + Текущее значение - среднее.

Цитата(ReAl @ Apr 26 2007, 22:17) *
Но это, IMHO, не скользящее среднее.
...
А этот "экспоненциальный" фильтр имеет поведение как у RC-цепочки.

Согласен
Snaky
Цитата(defunct @ Apr 26 2007, 16:07) *
Пример рабочий. Вы дальше повызывайте.
Хотите чтоб быстрее получался рез-тат усредняйте по 8-ми или по 4-м точкам.
Почитайте какую-нить книжку по усреднению прежде чем выступать.
Константа эта для устранения абсолютной погрешности в 0.5LSB при накоплении суммы.
У вас видать памяти в МК всегда много..

Тогда называйте вещи своими именами сразу. А то человек спросил про скользящее среднее, а вы ему совсем другое под этим названием подсовываете. Метод скользящего среднего - это то,что описал IgorKossak и Lepeksiy. Иначе захочется кому-нибудь сэкономить на памяти под массив, и будет потом долго удивляться, что результат поменялся.

PS Да, памяти у меня в МК всегда много - не жалуюсь.
defunct
Цитата(Snaky @ Apr 27 2007, 04:30) *
Тогда называйте вещи своими именами сразу. А то человек спросил про скользящее среднее, а вы ему совсем другое под этим названием подсовываете.

Свои имена не всегда упомнишь.
Я не подсовываю, а делюсь примером, мог бы ведь и не делиться. Он сам решит подходит ему пример или нет.
ReAl
Цитата(Snaky @ Apr 27 2007, 04:30) *
Иначе захочется кому-нибудь сэкономить на памяти под массив, и будет потом долго удивляться, что результат поменялся.
Да, реакция на выбросы у них отличается.
Кстати, а в чём вообще смысл скользящего среднего? Фильтрует он не лучше, чем "экспоненциальный", памяти жрёт. Раз уж есть массив - так сделать бы фильтр с "более нормальным" откликом, чем прямоугольник. Да, счёту больше, ну так а жалко счёту - вон он, экспоненциальный, заодно и памяти меньше :-)
Anjey_N
Спасибо всем! Благодаря вашим советам мне удалось запустить АЦП.
Только врёт он немножко.

Эталон --- АЦП
96 мВ --- 89 мВ
207 мВ --- 201 мВ
500 мВ --- 496 мВ
1 В --- 1 В
1.49 мВ --- 1.492 мВ
2 В --- 2.011 В
2.52 В --- 2.532 В

Как это исправить, подскажите! help.gif
Сергей Борщ
Цитата(Anjey_N @ Apr 27 2007, 21:05) *
Как это исправить, подскажите! help.gif
Если эталон - китайский мультиметр, то сменить мультиметр. Если же эталон заслуживает доверия, то давайте думать. Это не похоже на погрешность источника опорного напряжения, ибо отклонения имеют разный знак на концах шкалы. Какое у вас выходное сопротивление источника сигнала? И что вы используете в качестве опорного напряжения? Если внешняя опора, то какое выходное сопротивление ее источника?
singlskv
Цитата(ReAl @ Apr 27 2007, 19:49) *
Да, реакция на выбросы у них отличается.
Кстати, а в чём вообще смысл скользящего среднего? Фильтрует он не лучше, чем "экспоненциальный", памяти жрёт. Раз уж есть массив - так сделать бы фильтр с "более нормальным" откликом, чем прямоугольник. Да, счёту больше, ну так а жалко счёту - вон он, экспоненциальный, заодно и памяти меньше :-)

Разница между скользящим средним и "экспоненциальным" заключается в том что
"экспоненциальный" дает сдвиг фазы сигнала до 1/2 частоты сигнала
То есть если сигнал "постоянный" то разницы нет никакой, а вот если
изменяющийся, то тогда в каждом конкретном случае нужно рассчитывать
в какой момент времени данные уже устаканились и устраивает ли нас такой сдвиг фазы
Snaky
Цитата(ReAl @ Apr 27 2007, 21:49) *
Да, реакция на выбросы у них отличается.
Кстати, а в чём вообще смысл скользящего среднего? Фильтрует он не лучше, чем "экспоненциальный", памяти жрёт. Раз уж есть массив - так сделать бы фильтр с "более нормальным" откликом, чем прямоугольник. Да, счёту больше, ну так а жалко счёту - вон он, экспоненциальный, заодно и памяти меньше :-)

Оба фильтра по сути цифровая реализация ФНЧ. Просто фильтр скользящего среднего с массивом - это КИХ фильтр, экспоненциальный - БИХ. В моих задачах нужна конечная по времени реакция на отклик - я иду на затраты памяти.
Олссон/Пиани интерпретируют экспоненциальный фильтр как авторегрессионный фильтр скользящего среднего первого порядка (признаю, тут можно согласиться с defunct). Подробнее - см. аттач (имхо лучше не объяснишь).

PS Что значит "с более нормальным откликом" - я не понял smile.gif
VladimirYU
Цитата(Lepeksiy @ Apr 26 2007, 18:21) *
VladimirYU
А как это выражается формулами?


Все очень просто, привожу не код, а алгоритм:

Исходно имеем

Summator - переменная двойной длины,
Current - результат текущих измерений (данные с прибора, АЦП ...)
Previos - предыдущий фильтрованный результат

Далее

error = Current - Previos
Summator = Summator +error
Previos = Summator>>N

N определяет степень фильтрации ( количество результатов по которым идет усреднение).
Ньюансы кода, как понимаете, зависят от формы предсавления результатов (разрядность, тип и т.д.)

А математика за этим следующая

1/(TS+1) представить можно как интегратор 1/TS охваченный единичной отрицательной
обратной связью.

W(S) = Wпр(S)/(Wпр(S)*Wос(S) + 1)
yod
Вот такой вот рабочий код приведен в документе
slaa037.pdf - апликэшн репорт от тексаса

Код
*****************************************************************************
* Anti–bias results
* answer = input + (0.875 * lasty) – lastx;
* lasty = answer;
* lastx = input;
*****************************************************************************
Anjey_N
Цитата(Сергей Борщ @ Apr 28 2007, 00:50) *
Если эталон - китайский мультиметр, то сменить мультиметр. Если же эталон заслуживает доверия, то давайте думать. Это не похоже на погрешность источника опорного напряжения, ибо отклонения имеют разный знак на концах шкалы. Какое у вас выходное сопротивление источника сигнала? И что вы используете в качестве опорного напряжения? Если внешняя опора, то какое выходное сопротивление ее источника?



1) Мультимер UNI-T M890F, купленный 4 года назад за 20 баксов. На него я ещё не разу не жаловался!
2) В качестве источника входного сигнала я ис пользую такую сему
3) ИОН внутренний с конденсатором на ножке AREF, равен 2.66 В


Может я чего намутил в программе,посмотрите, пожалуйста, код
Сергей Борщ
Цитата(Anjey_N @ Apr 29 2007, 09:13) *
На него я ещё не разу не жаловался!
Это не значит что он показывает правильно.
Цитата(Anjey_N @ Apr 29 2007, 09:13) *
2) В качестве источника входного сигнала я ис пользую такую сему
Выходное сопротивление вашей цепи близко к предельному:
Цитата
The ADC is optimized for analog signals with an output impedance of approximately 10k or less. If such a source is used, the sampling time will be negligible.
Попробуйте увеличить время выборки (sampling time) снизив тактовую частоту АЦП или возьмите потенциометр на 10К
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.