|
проблема с АЦП, проблема с АЦП |
|
|
|
Mar 20 2008, 13:45
|
Группа: Участник
Сообщений: 12
Регистрация: 20-03-08
Пользователь №: 36 086

|
Помогите разобратся с АЦП. Пишу программу для считывания уровня напряжения с переменного резистора (от 0 до 5 В). Микроконтроллер: ATmega16 работает на частоте 16МГц. Вход A0. Разрядность АЦП: 10бит. Считывание одинарное (но вызывается регулярно) Программа работает, но при считывании уровня 0В выдает в ADCW не 0, а 15. При этом с верхним уровнем никаких проблем нет (1023). Код программы ниже. Написано в WinAVR последней версии (на нижних версиях результат тот же). Бьюсь неделю, не могу понять. Пробовал прошивать другой контроллер (8535) - результат тот же Код #include <stdio.h> #include <avr/io.h> #include <avr/pgmspace.h> #include <avr/interrupt.h> #define F_CPU 16000000UL #include <util/delay.h>
volatile unsigned int ADC_w = 0;
int segment_decoder(int num, int point) { int result = 0x3F; switch(num) { case 0: result = 0x3F; break; case 1: result = 0x06; break; case 2: result = 0x5B; break; case 3: result = 0x4F; break; case 4: result = 0x66; break; case 5: result = 0x6D; break; case 6: result = 0x7D; break; case 7: result = 0x07; break; case 8: result = 0x7F; break; case 9: result = 0x6F; break; default: result = 0x3F; break; }
if(point!=0) { result = (result | 0x80); }
return result; }
ISR(ADC_vect) { ADC_w = ADCW;//ADCL; }
int main(void) { _delay_ms(2);
DDRA = 0x00; DDRB = 0xFF; DDRC = 0xFF; DDRD = 0xFF;
PORTA= 0xFF; PORTB= 0x00; PORTC= 0x00; PORTD= 0x00;
SREG |= _BV(7);
ADCSRA |= (1<<ADPS0); ADCSRA |= (1<<ADPS1); ADCSRA |= (1<<ADPS2); ADMUX = 0x40; ADCSRA |= (1 << ADATE); ADCSRA |= (1<<ADIE); ADCSRA |= (1<<ADEN);
sei(); while(1) { ADCSRA |= (1<<ADSC); while(ADCSRA & 0x40) { PORTB = segment_decoder( (ADC_w/1000)%10, 0); PORTD = 2; _delay_us(10); PORTD = 0; PORTB = segment_decoder( (ADC_w/100)%10, 0); PORTD = 4; _delay_us(10); PORTD = 0; PORTB = segment_decoder( (ADC_w/10)%10, 1); PORTD = 8; _delay_us(10); PORTD = 0; PORTB = segment_decoder( ADC_w%10, 0); PORTD = 16; _delay_us(10); } };
return 0; }
Сообщение отредактировал azure - Mar 20 2008, 13:46
|
|
|
|
|
Mar 20 2008, 14:28
|
Группа: Участник
Сообщений: 12
Регистрация: 20-03-08
Пользователь №: 36 086

|
Я результат преобразования вывожу на семисегментные индикаторы, ручку переменоого резистора кручю - вижу колеблится или нет (внешних помех никаких нет, результат стоит стабильно). Общался я с человеком, который подобное писал на Асемблере для МК 8535 - говорит, что у него начинает с 0 до 1023. Свою программу я прогнал и в 8535 - у меня с 15 до 1023. Что интересно, при моделировании в VMLab - показывает от 0 до 1023. Вот и думаю что не так: или код, или программатор, или ?? Не могу никак добится результата
|
|
|
|
|
Mar 20 2008, 14:42
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(azure @ Mar 20 2008, 17:28)  Я результат преобразования вывожу на семисегментные индикаторы, ручку переменоого резистора кручю - вижу колеблится или нет (внешних помех никаких нет, результат стоит стабильно). Общался я с человеком, который подобное писал на Асемблере для МК 8535 - говорит, что у него начинает с 0 до 1023. Свою программу я прогнал и в 8535 - у меня с 15 до 1023. Что интересно, при моделировании в VMLab - показывает от 0 до 1023. Вот и думаю что не так: или код, или программатор, или ?? Не могу никак добится результата  А если закоротить вход на землю? Скорее всего просто нету нуля у этого резистора
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Mar 20 2008, 14:45
|
Группа: Участник
Сообщений: 12
Регистрация: 20-03-08
Пользователь №: 36 086

|
 я это уже пробовал, он там есть. Мерял тестером - 0.
|
|
|
|
|
Mar 20 2008, 15:14
|
Знающий
   
Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640

|
Цитата(MrYuran @ Mar 20 2008, 17:42)  А если закоротить вход на землю? Скорее всего просто нету нуля у этого резистора +1 Только нуля нет именно в момент измерения. Я с таким сталкивался, правда не на АВР. АЦП в момент измерения ток вытекающий начинает генерировать. А когда не мереет ничо из него не течёт. А переменный резистор с большим сопротивлением? Нет не в этом дело. У вас в программе ошибка. Ну остаток от деления на 1000 вы на индикатор вывели. А при выводе след. разряда надо из значения АЦП предыдущий * 1000 ( 100, 10) вычетесть, а уж потом остаток считать. Как же у вас вообще всё это работало? Там ведь начиная со следующего после 1го ненулевого разряда ошибка получалась! Попробуйте под отладчиком таким способом 222 (десятичное) вывести - 200 на индикаторе получите. Или я что-то там с вашей программой не понял?
|
|
|
|
|
Mar 20 2008, 15:23
|
Группа: Участник
Сообщений: 12
Регистрация: 20-03-08
Пользователь №: 36 086

|
8 бит мне мало, нудно мерять с точностью 0.1% при штучном ADC_w=0, ноль показывается, ща буду мерять напряжения Цитата(galjoen @ Mar 20 2008, 17:14)  Или я что-то там с вашей программой не понял? Что-то не понялм  Там такие опреации: (ADC_w/100)%10 ADC_w = 222 следует: ADC_w/100 = 22.2 делее %10 получаем то что после точки 2 ADC_w = 321 следует: ADC_w/100 = 32.1 делее %10 получаем то что после точки 1 Ранее использовал floor()
|
|
|
|
|
Mar 20 2008, 16:05
|
Группа: Участник
Сообщений: 12
Регистрация: 20-03-08
Пользователь №: 36 086

|
Внутренней землей я задавался - был 0 (меряло верно) - что странно  . Нашол я AVR120: Characterization and Calibration of the ADC on AVR, где рассказывается о возможных искажениях (ошибках) измерений. То-есть: АЦП меряет от 15 до 1023. Делаю смещени (математикой): получаю от 0 до 1008. Умножаю на коэффициент 1024/1009: получаю прямую от 0 до 1023. При практике: идеальное измерение значений подаваемых на вход. Подавалось на вход напряжение 5В, 2.5В. 0.25В и 0В - проверка мультиметром показало АЦП с этой корекцией меряет верно. Эксперементировал на 2 ATmega16 и одной 8535. Может это и не верное, но пока решение. Очень и искрене благодарен всем за отклик на помощь. СПС!
|
|
|
|
|
Mar 21 2008, 08:55
|
Группа: Участник
Сообщений: 12
Регистрация: 20-03-08
Пользователь №: 36 086

|
Цитата(Lexdaw @ Mar 21 2008, 09:05)  На Меге16 у меня работают сразу три АЦП без выключения ядра 10 бит и все нормально от 0 до 1023.Единственное что подается сигнал с ОУ. а код программы можете выложить? я сделал смещение, с ним все отлично работает (совпадает с измерениями мультиметра), но совесть мучает
|
|
|
|
|
Mar 21 2008, 12:10
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(azure @ Mar 20 2008, 13:45)  Помогите разобратся с АЦП. Пишу программу для считывания уровня напряжения с переменного резистора (от 0 до 5 В). Микроконтроллер: ATmega16 работает на частоте 16МГц. Вход A0. Разрядность АЦП: 10бит. Считывание одинарное (но вызывается регулярно). Программа работает, но при считывании уровня 0В выдает в ADCW не 0, а 15. При этом с верхним уровнем никаких проблем нет (1023) Похоже у вас плохое опорное напряжение. Попробуйте внутреннее 2,56В для начала или подключите к ноге AREF внешний опорник. Не забудьте только биты REFS1-0 поправить. Ну и несколько замечаний по коду, что сходу бросаются в глаза. 1) Запустили ацп в режиме free run, но в главном цикле вы всё время запускаете начало преобразования. Если вы хотите single conversion, то надо дождаться конца преобразования. 2) Есть стробы записи в регистры 1, 2, 3. А вот в регистр 4 строба записи нет, надо добавить. 3) В главном цикле используется переменная ADC_w, но она может быть испорчена в любой момент в прерывании. Примите меры. 4) Непонятна роль оператора while(ADCSRA & 0x40). Почему что-то делается, когда преобразование не закончено? 5) Зачем стоит оператор return 0 в конце программы? У вас там что, операционка стоит?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Mar 21 2008, 12:42
|
Местный
  
Группа: Свой
Сообщений: 426
Регистрация: 5-04-07
Из: Санкт-Петербург
Пользователь №: 26 782

|
Цитата(Lexdaw @ Mar 21 2008, 10:05)  Единственное что подается сигнал с ОУ. +1. Для себя после принял за правило: с переменника прямо на вход АЦП сигнал не подавать. На ОУ собрать повторитель да еще и подфильтровать немного.
|
|
|
|
|
Mar 21 2008, 17:03
|
Группа: Участник
Сообщений: 12
Регистрация: 20-03-08
Пользователь №: 36 086

|
Нашол я где была зарыта ошибка! Скажу что все перепробывал, что советовали (про MUX4...MUX0 для контроля точек 0B 1.22B) - на них тоже выдавало ошибки, причем на 1.22 - непостежимого характера  . Только операционик не пробовал лепить, он сути б не менял. И так ошибка была в коде (про непрерывный режим - тоже ошибка была, но в том коде была незаметна) и в самом начале: Код int main(void) { _delay_ms(2);
[b]DDRA = 0x00;[/b] DDRB = 0xFF; DDRC = 0xFF; DDRD = 0xFF;
[b]PORTA= 0xFF;[/b] PORTB= 0x00; PORTC= 0x00; PORTD= 0x00; Изначально порт А устанавливался как входно на считывание. И при считывании 0В выдавал уровень. При удалении выделенных строк - все заработало как надо, меряет от 0...1023  Всем сноваже СПС!
|
|
|
|
|
Mar 24 2008, 14:19
|
Участник

Группа: Участник
Сообщений: 44
Регистрация: 11-03-08
Пользователь №: 35 811

|
поделюсь тоже соображениями, нет защиты от дребезга, 50мс думаю не помешает, также очень интересно как подведена аналоговая линия, подтяжка к + или к земле, стоит ли защитный диод, насколько развязана плата по питанию....
|
|
|
|
|
Apr 9 2008, 12:29
|
Группа: Участник
Сообщений: 12
Регистрация: 20-03-08
Пользователь №: 36 086

|
Цитата(Kibi @ Mar 24 2008, 16:19)  поделюсь тоже соображениями, нет защиты от дребезга, 50мс думаю не помешает, также очень интересно как подведена аналоговая линия, подтяжка к + или к земле, стоит ли защитный диод, насколько развязана плата по питанию.... Дребезга тут нет, сигнал снимается с резистором в параллель которому конденсаторы. Аналоговая земля с цифровой объеденены. Питания тоже, только питание к АЦП шло от основного через даташитовскую LC цепочку. Для лучшей точности пробовал питать АЦП от другого источника с общей землей - полождительные результаты.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|