azure 0 20 марта, 2008 Опубликовано 20 марта, 2008 (изменено) · Жалоба Помогите разобратся с АЦП. Пишу программу для считывания уровня напряжения с переменного резистора (от 0 до 5 В). Микроконтроллер: ATmega16 работает на частоте 16МГц. Вход A0. Разрядность АЦП: 10бит. Считывание одинарное (но вызывается регулярно) Программа работает, но при считывании уровня 0В выдает в ADCW не 0, а 15. При этом с верхним уровнем никаких проблем нет (1023). Код программы ниже. Написано в WinAVR последней версии (на нижних версиях результат тот же). Бьюсь неделю, не могу понять. Пробовал прошивать другой контроллер (8535) - результат тот же :07: #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; } Изменено 20 марта, 2008 пользователем azure Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба там 0 может и не быть, потому как шумы, эффекты квантования и т.п., а вы уверены, что это не ошибка в отображении значения? для проверки можно поставить светодиод на какой нибудь вывод порта и зажигать его если значение АЦП будет равно константе (15 в вашем случае). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
azure 0 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба Я результат преобразования вывожу на семисегментные индикаторы, ручку переменоого резистора кручю - вижу колеблится или нет (внешних помех никаких нет, результат стоит стабильно). Общался я с человеком, который подобное писал на Асемблере для МК 8535 - говорит, что у него начинает с 0 до 1023. Свою программу я прогнал и в 8535 - у меня с 15 до 1023. Что интересно, при моделировании в VMLab - показывает от 0 до 1023. Вот и думаю что не так: или код, или программатор, или ?? Не могу никак добится результата :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 27 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба Я результат преобразования вывожу на семисегментные индикаторы, ручку переменоого резистора кручю - вижу колеблится или нет (внешних помех никаких нет, результат стоит стабильно). Общался я с человеком, который подобное писал на Асемблере для МК 8535 - говорит, что у него начинает с 0 до 1023. Свою программу я прогнал и в 8535 - у меня с 15 до 1023. Что интересно, при моделировании в VMLab - показывает от 0 до 1023. Вот и думаю что не так: или код, или программатор, или ?? Не могу никак добится результата :( А если закоротить вход на землю? Скорее всего просто нету нуля у этого резистора Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
azure 0 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба :) я это уже пробовал, он там есть. Мерял тестером - 0. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
konstan 0 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба Я при работе с АЦП использую только 8 старших бита, так как если посмотреть в даташит, то оговаривается, что ошибка может быть в младших 2 битах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 27 20 марта, 2008 Опубликовано 20 марта, 2008 (изменено) · Жалоба А если так попробовать - ADC_w=0; и пустить разок Если покажет 0, то надо померить напряжение между входом и аналоговой землёй, только нормальным цифровым вольтметром Блин, это ж AVR... Вообще по правилам на время преобразования рекомендуется гасить ядро, а по прерыванию от АЦП просыпаться и обрабатывать результат. Хотя 15 это не 1-2 разряда, а все 4. Вряд ли в этом дело. Изменено 20 марта, 2008 пользователем MrYuran Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
galjoen 0 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба А если закоротить вход на землю? Скорее всего просто нету нуля у этого резистора +1 Только нуля нет именно в момент измерения. Я с таким сталкивался, правда не на АВР. АЦП в момент измерения ток вытекающий начинает генерировать. А когда не мереет ничо из него не течёт. А переменный резистор с большим сопротивлением? Нет не в этом дело. У вас в программе ошибка. Ну остаток от деления на 1000 вы на индикатор вывели. А при выводе след. разряда надо из значения АЦП предыдущий * 1000 ( 100, 10) вычетесть, а уж потом остаток считать. Как же у вас вообще всё это работало? Там ведь начиная со следующего после 1го ненулевого разряда ошибка получалась! Попробуйте под отладчиком таким способом 222 (десятичное) вывести - 200 на индикаторе получите. Или я что-то там с вашей программой не понял? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба Если результат стабильно 15, то скорее всего что то с программой, попробуйте сделать как я говорил со светодиодом или как выше предложили, попробуйте просто в вашу переменную ADC_w записывать "0" - что будет на экране? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
azure 0 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба 8 бит мне мало, нудно мерять с точностью 0.1% при штучном ADC_w=0, ноль показывается, ща буду мерять напряжения Или я что-то там с вашей программой не понял? Что-то не понялм :) Там такие опреации: (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() Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
domowoj 0 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба Нужно "засыпать" на время преобразования. Можно попробовать измерить внутренний 0-(MUX=1111). Что-то с землями. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
azure 0 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба Внутренней землей я задавался - был 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. Может это и не верное, но пока решение. Очень и искрене благодарен всем за отклик на помощь. СПС! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
domowoj 0 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба Может дело в данном образце контроллера? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 20 марта, 2008 Опубликовано 20 марта, 2008 · Жалоба Кстати. А что за контроллер? В новых контроллерах вы можете прочитать 0 и Vcc питание. Это позволяет найти смещение и смасштабировать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lexdaw 0 21 марта, 2008 Опубликовано 21 марта, 2008 · Жалоба На Меге16 у меня работают сразу три АЦП без выключения ядра 10 бит и все нормально от 0 до 1023.Единственное что подается сигнал с ОУ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться