Bonjour tout le monde,
Je viens vers vous, car depuis une semaine, je travaille (et comme toujours) mes accéléromètres. Le cahier des charges se définit de plus en plus. Néanmoins, cette semaine ci, ainsi que la semaine passée, je m'attarde sur mon ADC...
J'ai 4 accéléromètres et je dois récupérer son ADC, pour en analyser son peak-to-peak, l'intégrer (numériquement ?) pour obtenir sa vitesse RMS...
On m'a demandé de travailler avec les interruptions, donc j'ai réécrit tout mon code.
Je travaille avec un atmega169 et je simule avec proteus pour le moment, (pas le choix, car ça un cout matériel, donc il ne faut pas se planter... )
Sachant que je recevrais un signal dont les harmoniques peuvent atteindre 5KHz (je mettrais un filtre anti-aliasing en entrée) avant la patte de l'ADC, je dois échantillonner à 2x la fréquence maximale (Théorème de Shannon-Nyquist). En industrie, on utilise même 2.56 (je ne sais pas d'où ça sort...).
Si je travaille à 8MHz, je prends un prescaler de /64, ce qui me donne 125KHz, donc je dois rediviser par 12 pour obtenir mes 10Khz. Ca ne fonctionne pas, ma fréquence d'échantillonnage est trop basse pourquoi ?
De plus je ne retrouve pas 10x le sinus 5KHz dans mon signal 500Hz, comment se fait il ?
Voici le code que j'ai écrit, d'après, il n'y a pas d'erreurs, mais je reste bloqué depuis un bon petit temps (1 semaine). Il prend 250 échantillons et il affiche tout sur l'USART au final.
Pour tester mon timer, j'ai mis un oscilloscope virtuel sur la led et j'ai une période de 10*20µ à l'état haut, et le même à l'état bas. Pour moi la fréquence est donc 1/(10*20µ) donc 5KHz. pourquoi ça ne correspond pas à mes calculs?
Qu'en pensez vous ?Code:#include "lcd.h" #include "fonctions.h" #include <avr/interrupt.h> //#define CPUCLK 16000000 #define CPUCLK 8000000 #define NB_ECH 250 #include <util/delay.h> #include <stdlib.h> volatile uint16_t resultat_RAM1[],resultat_RAM2[],resultat_RAM3[],resultat_RAM4[]; void ActiverADC() { // Digital Input Disable DIDR0 = 0xFF; // Mode 1.1V //ADMUX=(1<<REFS1)|(1<<REFS0); //Mode VCC externe ADMUX= (1<< REFS0); // Ajouter Prescaler et on rend enable l'ADC (8Mhz/64 = 125Khz) OK ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); // on attend pour que la stabilisation de la tension soit faite. _delay_ms(100); } uint16_t mesure_accelerometre(uint8_t voie) //int mesure_accelerometre(uint8_t voie) { // 0xF8 permet d'effacer préalablement les 3 bits et on ajoute la voie qu'on veut. ADMUX = (ADMUX & 0xF8)|voie; // F8, car maximum 7 accéléromètres 0bxxxxx000 //On met le microcontroleur en mode sleep ADC MCUCR=16; ADCSRA|=(1<<ADSC); // Je commence ma conversion // On attend tant que ADIF n'est pas à 1 (conversion terminée) //while(!(ADCSRA & (1<<ADIF))); //On peut utiliser ADSC également while(ADCSRA & (1<<ADSC)); //on s'assure de remettre ADIF à 0 (effet inverse) ADCSRA|=(1<<ADIF); //return(ADCW); volatile uint16_t res; res=ADCL+ADCH*256; return res; } uint16_t resultat; char variable[(NB_ECH/4)]; static int i,j,j1,j2,j3,j4; int min1 = 1023; int max1 = 0; int min2 = 1023; int max2 = 0; int min3 = 1023; int max3 = 0; int min4 = 1023; int max4 = 0; ISR(TIMER0_COMP_vect) { //TCNT0 = 254-12; // compteur à 0 //TIFR0 |= (1 << OCF1A); DDRB = 0xFF; //inverse led PORTB ^= (1 << 0); i++; //cycle ACC 1 2 3 4 j++; resultat = 0; if(i == 1) { j1++; resultat = mesure_accelerometre(1); if(resultat < min1) { min1 = resultat; } if(resultat > max1) { max1 = resultat; } resultat_RAM1[j1] = resultat; } if(i==1) { i=0; // Futur : on loop, utile si on prend pour les 4 ( if i%4 --> i =0) } if(j==NB_ECH) { j1=0; j2=0; j3=0; j4=0; while(j1<NB_ECH) // on boucle l'accéléromètre 1 sur l'USART { intoa(resultat_RAM1[j1],variable); sendString(variable); sendString("\r"); j1++; } } } int main() { ActiverADC(); ActiverUsart(); sendString("Bienvenue dans l'hyperterminal "); //USART sendString("\r"); lcd_init(); PORTA = 0; PORTB = 0; lcd_home(); lcd_string(" "); _delay_ms(200); lcd_clrscr(); //effacer le LCD lcd_string("Enregistrement \n dans 200 ms."); _delay_ms(200); lcd_clrscr(); // TIMER 8bits utilisé Timer0 // MODE CTC // fréquence nominale CPU 8MHz // Mode CTC TCCR0A |= (1 << WGM01); //Prescaler / 64; [8MHz/64 = 125KHz] TCCR0A |= (1 << CS01) |(1<< CS00); // Interruption activée overflow. //TIMSK0|=(1<<TOIE0); TCCR0A |= (1<<FOC0A); // Force le Output Compare TIMSK0 |= (1 << OCIE0A); // interruption lors de la comparaison OCR0A =12; //TCNT0 = 254-12; //(8MHZ/64 = 125Khz)/ 12 = 10.4Khz sei(); while(1) { // On attend les interruptions. } }
Sur mon schéma :
Aref a un condo à la masse à 100nF.
AVcc est relié à 3.3V directement.
Mes résultats : je retrouve bien 2x 10Hz dans un 1x 5Hz, mais à 5KHz, il est à 2, 3 X dans 500Hz...
Je vous remercie sincèrement de l'aide que vous pourrez m'apporter.
-----