|
ADC в ATtiny461, калибровка |
|
|
|
Jul 2 2010, 19:24
|

Профессионал
    
Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807

|
Только что закончил небольшшой заказ в 10 устройств на ATtiny461. В каждом устройстве необходимо было мерить как униполярные, так и дифф сигналы. Так как прослеживалась тенденция к повторным заказам, решил приложить определенные усилия к написанию программы калибровки внутреннего ADC. Попытки сделать это чуть не сорвали сроки проекта - оказалось, что ADC ATtiny461 имеют существенные разбросы по параметрам от экз к экз и др. тонкости: 1. Обычное униполярное измерение в 4 экземплярах из 10 показало ошибку в 20 LSB при напряжениях на входе около 2.2 вольт при опоре 2.56 вольт. Вроде требования даташита выполнены - для униполярных сигналов все напряжения в доп пределах. Измерения низких напряжений (в районе 100 mV) были практически идеальны. Насколько я понимаю, ADC в этих 4 экз. имеют слишком большой INL. Как с этим бороться просто не представляю. А если бы устройств было не 10, а 100? Что, делать стенд для отбраковки кристаллов? 2. ADC в AVR по скорости работы и так аутсайдер, но определенные тонкости выявились и при переключениях каналов. Особенно когда есть и униполярные и дифф. (у меня было по 2 сигнала каждого типа). Засада в том, что униполярные мерялись стабильно, но дифф колбасило конкретно, сэмплы отличались почти в два раза. Сначала подумал, что PCB неправильно разведена, но вроде не первый раз развожу, решил искать причину дальше. По-моему, из AVR аппликух была в свое время выдрана некая функция AdcStable(): Код void AdcStable(void){ signed int Vmax,Vmin,V[4]; unsigned char i; //Loop until the ADC value is stable. (Vmax <= (Vmin+1)) for (Vmax=10,Vmin=0;Vmax > (Vmin+1);){ V[3] = V[2];V[2] = V[1];V[1] = V[0];// сдвиг в буфере SETBIT(ADCSRA,ADSC);while(CHKBIT(ADCSRA,ADSC));// получить результат V[0] = ADC; Vmin = V[0]; // Vmin is the lower VOLTAGE Vmax = V[0]; // Vmax is the higher VOLTAGE for (i=0;i<=3;i++){//Save the max and min voltage if (V[i] > Vmax) Vmax=V[i]; if (V[i] < Vmin) Vmin=V[i]; } } } C ней дифф сигналы стали измеряться нормально, но косяк проявился в том, что компилятор IAR v5.50 при оптимизации по скорости сделал так, что цикл в этой функции становился вечным и я не смог разобраться в чем дело. При оптимизации по коду все работало нормально. Однако это наблюдение покоя так и не дало, поэтому данную функцию пришлось выкинуть. В даташите на ATmega324 написано, что при измер дифф сигналов схеме нужно время чтобы прошли переходные процессы переключения и это время указано - 125us. Как только поставил паузу 200us после смены мультиплексора (измерения шли группой, но single conversions) - сразу все начало измеряться нормально. Но горький осадок остался: ADC и так не быстр, скорость выборок падает с увеличением кол-ва сигналов, дак еще и переходные задерживают... Что же делать? Кто как выкручивается? Мне особенно интересно, как все это хозяйство калибруется в серию? Это же все серьезный риск получить приключений на собственное то самое место...
|
|
|
|
|
 |
Ответов
|
Jul 9 2010, 22:27
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата По-моему, из AVR аппликух была в свое время выдрана некая функция AdcStable() такого говнокода не могло быть в AVR аппликухах. Программистов такого уровня в Atmel не держат. Цитата Как только поставил паузу 200us после смены мультиплексора Многократно обсуждалось... При смене канала просто делайте два измерения. Первое выбрасывайте, второе оставляйте.
|
|
|
|
|
Jul 10 2010, 00:44
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(AHTOXA @ Jul 10 2010, 02:47)  Высокого же вы мнения о программистах атмеля  . Да, высокого, вот оригинал по ссылке: Код void Stable_ADC(void) // loop until you have a stable value { int V[4]; char i; int Vmax, Vmin; //Loop until the ADC value is stable. (Vmax <= (Vmin+1)) for (Vmax=10,Vmin= 0;Vmax > (Vmin+1);) { V[3] = V[2]; V[2] = V[1]; V[1] = V[0]; ADCSR |= 0x40; // Start a new A/D conversion while (!(ADCSR & (1<<ADIF))) // wait until ADC is ready ; V[0] = ADC; Vmin = V[0]; // Vmin is the lower VOLTAGE Vmax = V[0]; // Vmax is the higher VOLTAGE /*Save the max and min voltage*/ for (i=0;i<=3;i++) { if (V[i] > Vmax) Vmax=V[i]; if (V[i] < Vmin) Vmin=V[i]; } } } функция написана и отформатирована читаемо по крайней мере. Цитата(singlskv @ Jul 10 2010, 02:44)  Это Вы ерунду "сморозили"... при смене на дифф. каналах нужна просто пауза на 125мкс: Alternatively, conversion results obtained within this period should be discarded. Отнюдь не ерунду, а то самое "alternatively" из ДШ. Только не уточнил что АЦП не разгонять выше 8KSPS (125 мкс --> 8Khz). Вот например как оно делается у меня для дифф каналов: Код #pragma vector=TIMER1_COMPA_vect __interrupt void T1OCAISRHandler(void) { // 1ms timer event (Fd = 1kHz) if (!adcContext.lock) { adcContext.CurrentChan = 0; adcContext.DummyCycle = TRUE; // notify to discard this result as mux channel changes adcContext.SampleSequence += 1; // inc sample id adcStartConversion( adc_GetMuxIndex( adcContext.CurrentChan ) ); adcContext.lock = 1; } else { // overload.... skip current sample on all channels. adcContext.nSampleOffsetErrors += 1; } }
#pragma vector=ADC_vect __interrupt void AdcISRHandler(void) { U16 Val = ADC; if (adcContext.DummyCycle) { // restart current channel adcStartConversion( adc_GetMuxIndex( adcContext.CurrentChan ) ); adcContext.DummyCycle = FALSE; } else {
// handle current conversion result adcUpdateChannel( &adcContext.Channels[ adcContext.CurrentChan ], Val );
// switch to the next channel and launch it adcContext.CurrentChan++; if (adcContext.CurrentChan > MUX_LAST_INDEX) { adcContext.lock = 0; adcContext.CurrentChan = 0; } else { adcStartConversion( adc_GetMuxIndex( adcContext.CurrentChan ) ); adcContext.DummyCycle = TRUE; // mux changes - need to discard the next result }
} } Куда приятнее в прерывании от АЦП просто забирать 100% верный результат, чем натыкивать delay_us() в основном цикле программы убивая при этом ее портируемость и способность к расширению.
|
|
|
|
|
Jul 10 2010, 21:26
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(AHTOXA @ Jul 10 2010, 23:27)  Вы не ответили на мой вопрос. Вы считаете, что если говнокод отформатировать, то он перестанет быть говнокодом? Я считаю, что любой нормальный код можно превратить в говнокод одним лишь форматированием. Например просто - разместить всё в одной строке. Цитата Или даже спрошу ещё более конкретно: считаете ли вы приведённый вами кусок кода от атмеля - говнокодом? Не считаю, потому что код оформлен читаемо - алгоритм читается, править/отладить легко, потенциальный баг видно. Другой вопрос - дубовая (не расширяемая) реализация алгоритма - это сделано специально, т.к. основная задача любого наглядного пособия - донести суть/принцип работы, а не чтобы его можно было взять и бездумно вставить в свой проект. В первом же варианте код не читается, править/отлаживать нереально, и баги не видно - это и делает его говнокодом.
|
|
|
|
|
Jul 10 2010, 22:02
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(defunct @ Jul 11 2010, 03:26)  В первом же варианте код не читается, править/отлаживать нереально, и баги не видно - это и делает его говнокодом. У вас какое-то нестандартное понятие о говнокоде. Обычно под словом "говнокод" понимается всё же содержание, а не форматирование... Причём там (в том куске, который вы назвали "говнокодом") форматирование не экстремально плохое (типа всё в одну строчку), а просто несколько ужатое по сравнению с оригиналом. Короче, я считаю, что вы промахнулись в своём первом утверждении, что "атмель такого не пишет", а дальше просто выкручивались.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 11 2010, 04:04
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(AHTOXA @ Jul 11 2010, 01:02)  Обычно под словом "говнокод" понимается всё же содержание, а не форматирование... Всякий бывает: http://govnokod.ru/cЦитата У вас какое-то нестандартное понятие о говнокоде Возможно. Если бы мы вместе работали, мы бы друг-друга поняли, особенно если бы сделали друг-другу review.  Филисофия простая - "кто ясно мыслит, тот ясно излагает".
|
|
|
|
Сообщений в этой теме
ivainc1789 ADC в ATtiny461 Jul 2 2010, 19:24 sigmaN А на каком именно цикле он зацикливается?
Может с... Jul 3 2010, 07:57 ivainc1789 ЦитатаА если на этом виснет
Кодwhile(CHKBIT... Jul 3 2010, 18:23 Duhas вообще для поточнее и побыстрее ставится внешний А... Jul 4 2010, 09:48 singlskv Цитата(defunct @ Jul 10 2010, 02:27) Мног... Jul 9 2010, 23:44   singlskv Цитата(defunct @ Jul 10 2010, 04:44) Отню... Jul 10 2010, 21:42    defunct Цитата(singlskv @ Jul 11 2010, 00:42) - В... Jul 10 2010, 21:57 xemul Цитата(ivainc1789 @ Jul 2 2010, 23:24) ..... Jul 10 2010, 09:57 sigmaN Ееее. Моя любимая тема - говнокод!
Хоть п... Jul 10 2010, 23:56
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|