Запуск АЦП Arduino DUE по таймеру (Single Ended Mode)

Конструкції та прграмування ARDUINO DUE
Відповісти
Аватар користувача
radioman
Site Admin
Повідомлень: 92
З нами з: 28 вересня 2020, 12:01
Дякував (ла): 6 разів
Подякували: 2 рази

Запуск АЦП Arduino DUE по таймеру (Single Ended Mode)

Повідомлення radioman »

Для перетворення аналогового сигналу в цифровий в контролері AT91SAM3X8E Arduino DUE є 12 аналогових входів з 12-бітним АЦП. "За замовчуванням" АЦП проводить вимірювання з використанням 10 розрядів. Частота тактування ADC знаходиться між MCK / 2, якщо PRESCAL дорівнює 0, та MCK / 512, якщо для PRESCAL встановлено значення 255 (0xFF): ADCClock = MCK / (( PRESCAL + 1) * 2) ( сторінка 1334даташиту). Рекомендовано встановлювати частоту тактування MIN = 1MHz, MAX = 20 MHZ, що відповідає значенню PRESCAL від 41 до 1. Необхідно пам'ятати, що чим вища частота перетворення тим нижча точність вимірювань; тобто частоту перетворення для досягнення кращого результату потрібно встановлювати мінімально потрібною (принцип "розумної достатності").
Дя синхронізації роботи АЦП використаємо таймери мікроконтролера AT91SAM3X8E. Він має 3 лічильника таймера (TC): TC0, TC1, TC2.
Кожен лічильник таймера містить 3 канали з нумерацією 0, 1 і 2 (разом - 9 каналів). Кожен канал має свої власні лічильники і обробник переривань, які не залежать від інших каналів, іншими словами, кожен канал може розглядатися як окремий "таймер".

Щоб ініціалізувати канал, потрібні такі параметри:
TC0 / TC1 / TC2 - Номер таймера
0/1/2 - Номер каналу в лічильнику таймера

Таймерам "відповідають" контакти Arduino DUE. Так, використаному в прикладі таймеру TC0 на каналі 0 відповітають контакти 2 (порт В.25) та 13 (порт В.27).
Таймери можуть тактуватись частотою, що кратна /2,/8,/32,/128 від робочої частоти мікроконтролера:
TIMER_CLOCK1: 84Mhz/2 = 42.000 MHz
TIMER_CLOCK2: 84Mhz/8 = 10.500 MHz
TIMER_CLOCK3: 84Mhz/32 = 2.625 MHz
TIMER_CLOCK4: 84Mhz/128 = 656.250 KHz
В результаті у нас АЦП буде 2 рази на секунду міряти напругу на вході А0 і переключатись інтегрований світлодіод на 13 виході з частотою 1 Гц.
Для тих, хто хоче самостійно внести деякі зміни в скетч для "самопровірки" роботи АЦП:

Код: Виділити все

/*Додамо ще одну змінну*/
volatile boolean bolTact = false;
...
/*Підключемо послідовний порт та контакт 2 (порт В.25) замість 13*/
Serial.begin(115200);
PIOB->PIO_OER = 1 << 25;
...
/*Кожен такт будемо виводити заміряну напругу на монітор послідовного порту*/
if (bolTact)
{
    bolTact = false;
    Serial.println(intResultA0);
 }
       
...
/*В обробнику переривань також замінимо 13 контакт на 2*/
REG_PIOB_ODSR ^= 1 << 25; 
З'єднаємо між собою вихід 2 та аналоговий вхід А0. Заливаємо скетч і на моніторі послідовного порту спостерігаємо результат вимірювання:
Результат вимірювання
Результат вимірювання
І сам "готовий" код:

Код: Виділити все

#define ADC_REFERENCE_VALUE (3.3)
#define ADC_12BIT_FULL_SCALE_VALUE (4095)

volatile int intResultA0;
volatile boolean bolTact = false;

void setup()
{
  Serial.begin(115200);
  PIOB->PIO_OER = 1 << 25;                            // Встановлюємо 2 контакт Arduino DUE як вихід
  adc_setup();                                        // АЦП
  tc_setup();                                         // Таймер
}

void loop()
/*Виводимо виміряну напругу на монітор послідовного порту*/
{
  if (bolTact)
  {
    bolTact = false;
    Serial.println(intResultA0);
  }
}

/*Configure ADC function*/
void adc_setup() 
{
  PMC->PMC_PCER1 |= PMC_PCER1_PID37;                    
  ADC->ADC_CR = ADC_CR_SWRST;                           

  ADC->ADC_MR |=  ADC_MR_TRGEN_EN |                     
                  ADC_MR_TRGSEL_ADC_TRIG1 |             
                  ADC_MR_LOWRES_BITS_12 |               
                  ADC_MR_SLEEP_NORMAL |                 
                  ADC_MR_PRESCAL(1) |                   
                  ADC_MR_STARTUP_SUT0 |                 
                  ADC_MR_SETTLING_AST9 |                
                  ADC_MR_ANACH_ALLOWED |                
                  ADC_MR_TRACKTIM(10) |                 
                  ADC_MR_TRANSFER(2) |                  
                  ADC_MR_USEQ_NUM_ORDER;                


  ADC->ADC_COR = ADC_COR_OFF7;
  ADC->ADC_IER = ADC_IER_EOC7;
  NVIC_EnableIRQ(ADC_IRQn);

  ADC->ADC_CHER = ADC_CHER_CH7;         
}

/* Timer Counter 0 Channel 0 to generate PWM pulses thru TIOA0 */
void tc_setup() 
{
  PMC->PMC_PCER0 |= PMC_PCER0_PID27;                       
  TC0->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1   
                              | TC_CMR_WAVE                
                              | TC_CMR_WAVSEL_UP_RC        
                              | TC_CMR_ACPA_CLEAR          
                              | TC_CMR_ACPC_SET;           
  TC0->TC_CHANNEL[0].TC_RC = 21000000;                     
  TC0->TC_CHANNEL[0].TC_RA = 10500000;                     			// Від 1 до 20999999
  TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN;  
}

/* Обробка переривань */
void ADC_Handler(void)
{
  intResultA0 = ADC->ADC_CDR[7];
  REG_PIOB_ODSR ^= 1 << 25; 							//переключити (інвертувати) рівень 2 виходу
  bolTact = true;
}
В приєднаному архіві скетчі; в першому проводиться вимірювання напруги на вході А0 кожну секунду в Single Ended Mode, одночасно змінюється рівень на 13 виході, що контролюється миганням світлодіода, в другому - модернізований скетч.
Зверніть увагу:
ст. 1403 дадашиту
1. Use ADC_ACR.IBCTL = 00 for sampling frequency below 500 kHz.
2. Use ADC_ACR.IBCTL = 01 for sampling frequency between 500 kHz and 1 MHz.
PS. Для тих, хто не використовує ардуіно, але хоче ознайомитись з кодом, в архів додадано його лістинг в форматі .doc
Вкладення
A_DUE_ADC_TIMER_s.7z
(8.78 Кіб) Завантажено 31 раз
pawa
Повідомлень: 75
З нами з: 28 вересня 2020, 20:26
Дякував (ла): 1 раз
Подякували: 5 разів

Re: Запуск АЦП Arduino DUE по таймеру

Повідомлення pawa »

radioman писав: 31 жовтня 2020, 12:27..частоту перетворення для досягнення кращого результату потрібно встановлювати мінімально потрібною (принцип "розумної достатності").
А де вказані такі рекомендації?
Аватар користувача
radioman
Site Admin
Повідомлень: 92
З нами з: 28 вересня 2020, 12:01
Дякував (ла): 6 разів
Подякували: 2 рази

Re: Запуск АЦП Arduino DUE по таймеру

Повідомлення radioman »

Власний висновок. Чим вища частота - тим більша дисперсія значень. Колись попадалось дослідження, коли "розганяв" АЦП UNO.
pawa
Повідомлень: 75
З нами з: 28 вересня 2020, 20:26
Дякував (ла): 1 раз
Подякували: 5 разів

Re: Запуск АЦП Arduino DUE по таймеру

Повідомлення pawa »

Тоді треба відмітити що похибка перетворення зростає тільки при перевищенні частоти рекомендованої розробником, а саме 1 МГц.
Аватар користувача
radioman
Site Admin
Повідомлень: 92
З нами з: 28 вересня 2020, 12:01
Дякував (ла): 6 разів
Подякували: 2 рази

Re: Запуск АЦП Arduino DUE по таймеру

Повідомлення radioman »

pawa писав: 31 жовтня 2020, 23:55... похибка перетворення зростає тільки при перевищенні частоти рекомендованої розробником, а саме 1 МГц.
Цікаво, чому всі так говорять про 1 Мгц (на англомовних сайтах теж) 8-)
Ст.2 дадашиту
16-channel 12-bit 1 msps ADC with differential input mode and programmable gain stage
16-канальний 12-бітний АЦП 1 мс / с з диференціальним режимом програмованим ступенем підсилення
Тобто, мова іде про мегасемпли за секунду (частоту дискритезації, а не тактування). Але, перетворення відбувається не за один такт. Наприклад, в АЦП Arduino UNO це займає 13 тактів при 10 розрядах (де взяв дані - не пам'ятаю, але вони збереглися в одному із старих скетчів; за скільки тактів проходить вимірювання у АЦП AT91SAM3X8E мені не відомо):
ADC_UNO.jpg
Також в Arduino UNO при частоті 1МГц отримуємо 8-бітове розрішення, а при 2МГц - 6-бітове.
Але, цілком погоджуюсь, що при опрацюванні синусоїдального сигналу занадто занижувати частоту теж не варто. Так при визначенні фази за допомогою квадратурного детектора буде виникати похибка, пов'язана з часом вимірювання. Тобто, при вимірюванні сигналів, котрі змінюються повільно - необхідно зменшувати частоту для отримання максимальної точності; при опрацюванні сигналів, котрі швидко змінюються у часі - знайти мінімум між двома похибками.
pawa
Повідомлень: 75
З нами з: 28 вересня 2020, 20:26
Дякував (ла): 1 раз
Подякували: 5 разів

Re: Запуск АЦП Arduino DUE по таймеру

Повідомлення pawa »

Всі кажуть про 1Мгц тому що так написано у даташиті. А саме: тактова частота модуля АЦП складає 0,5..22МГц, на одне перетворення буде витрачено 20 тактів, відповідно 20МГц / 20 = 1МГц. У даташиті є і пряме вказання на максимальну частоту перетворень (сторінка 1403):
fADC (ADC Clock Frequency) min - 1MHz , max - 22 MHz
fS (Sampling Frequency) min - 0.05MHz , max - 1 MHz
А якщо тактувати вищою частотою, то буде непередбачувано з'являтися помилка, яка саме передбачити важко.

PS: 1 msps = 1 000 000 sps, тобто ті самі 1 Мс/с.
Відповісти