реклама на сайте
подробности

 
 
> ADC в ATtiny461, калибровка
ivainc1789
сообщение Jul 2 2010, 19:24
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 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 и так не быстр, скорость выборок падает с увеличением кол-ва сигналов, дак еще и переходные задерживают... Что же делать? Кто как выкручивается?
Мне особенно интересно, как все это хозяйство калибруется в серию? Это же все серьезный риск получить приключений на собственное то самое место...
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
defunct
сообщение Jul 9 2010, 22:27
Сообщение #2


кекс
******

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



Цитата
По-моему, из AVR аппликух была в свое время выдрана некая функция AdcStable()

такого говнокода не могло быть в AVR аппликухах. Программистов такого уровня в Atmel не держат.

Цитата
Как только поставил паузу 200us после смены мультиплексора

Многократно обсуждалось...
При смене канала просто делайте два измерения. Первое выбрасывайте, второе оставляйте.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 9 2010, 23:47
Сообщение #3


фанат дивана
******

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



Цитата(defunct @ Jul 10 2010, 04:27) *
такого говнокода не могло быть в AVR аппликухах. Программистов такого уровня в Atmel не держат.

Высокого же вы мнения о программистах атмеляsmile.gif. Однако этот код именно из их аппноты ( avr450 smile.gif )


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 10 2010, 00:44
Сообщение #4


кекс
******

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



Цитата(AHTOXA @ Jul 10 2010, 02:47) *
Высокого же вы мнения о программистах атмеляsmile.gif.

Да, высокого, вот оригинал по ссылке:

Код
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() в основном цикле программы убивая при этом ее портируемость и способность к расширению.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 10 2010, 08:55
Сообщение #5


фанат дивана
******

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



Цитата(defunct @ Jul 10 2010, 06:44) *
Да, высокого, вот оригинал по ссылке:
функция написана и отформатирована читаемо по крайней мере.

biggrin.gif То есть, по-вашему, отформатированный говнокод перестаёт быть говнокодом?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 10 2010, 19:45
Сообщение #6


кекс
******

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



Цитата(AHTOXA @ Jul 10 2010, 11:55) *
То есть, по-вашему, отформатированный говнокод перестаёт быть говнокодом?

критериями которые дают повод назвать код говнокодом в т.ч. есть и форматирование.
Когда функция хорошо читается в ней легче разглядеть потенциальную ошибку.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 10 2010, 20:27
Сообщение #7


фанат дивана
******

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



Цитата(defunct @ Jul 11 2010, 01:45) *
критериями которые дают повод назвать код говнокодом в т.ч. есть и форматирование.
Когда функция хорошо читается в ней легче разглядеть потенциальную ошибку.

Вы не ответили на мой вопрос. Вы считаете, что если говнокод отформатировать, то он перестанет быть говнокодом?
Или даже спрошу ещё более конкретно: считаете ли вы приведённый вами кусок кода от атмеля - говнокодом?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 10 2010, 21:26
Сообщение #8


кекс
******

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



Цитата(AHTOXA @ Jul 10 2010, 23:27) *
Вы не ответили на мой вопрос. Вы считаете, что если говнокод отформатировать, то он перестанет быть говнокодом?

Я считаю, что любой нормальный код можно превратить в говнокод одним лишь форматированием. Например просто - разместить всё в одной строке.

Цитата
Или даже спрошу ещё более конкретно: считаете ли вы приведённый вами кусок кода от атмеля - говнокодом?

Не считаю, потому что код оформлен читаемо - алгоритм читается, править/отладить легко, потенциальный баг видно.
Другой вопрос - дубовая (не расширяемая) реализация алгоритма - это сделано специально, т.к. основная задача любого наглядного пособия - донести суть/принцип работы, а не чтобы его можно было взять и бездумно вставить в свой проект.

В первом же варианте код не читается, править/отлаживать нереально, и баги не видно - это и делает его говнокодом.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- 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
||- - AHTOXA   Цитата(defunct @ Jul 11 2010, 03:26) В пе...   Jul 10 2010, 22:02
||- - defunct   Цитата(AHTOXA @ Jul 11 2010, 01:02) Обычн...   Jul 11 2010, 04:04
|- - 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


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 03:09
Рейтинг@Mail.ru


Страница сгенерированна за 0.02596 секунд с 7
ELECTRONIX ©2004-2016