// created 2015 March 29th by Bertrand VANDEPORTAELE #include #include const int chipSelectPin = 3; //connect to the Chip Select of the TLV5637 const int boutonPin = 9; const int itpin = 8; //used to monitor the activity of the processor during the interrupt, on arduino it is PORTB bit 0 const int filtrepin = 10; //used to monitor the activity of the processor during the interrupt, on arduino it is PORTB bit 2 TLV5637 DAC(chipSelectPin, REF_2048MV_TLV5637); //////////////////////////////////////////////////////////////////////////////////// //Nom du filtre: filtre_RIF //Description du filtre: Un filtre RIF général //////////////////////////////////////////////////////////////////////////////////// //Partie commune aux implémentations en virgule flottante et fixe: //////////////////////////////////////////////////////////////////////////////////// //passe ricrac pour un filtre avec 100 coefficients et à 2khz sur l'arduino en Virgule fixe #define SIZEFILTER_RIF 41 //////////////////////////////////////////////////////////////////////////////////// //Implémentation en virgule flottante double précision: //////////////////////////////////////////////////////////////////////////////////// //mettre ici toutes les constantes et variables définies en double, en indiquant le type dans le nom avec _d_ const double numCoeff_d_FILTRE_RIF[SIZEFILTER_RIF] = { 0.016244657856333, -0.018864421488768, -0.012238782422342, -0.005085409431928, 0.003969691594410, 0.012267146479049, 0.015030618183398, 0.008966346831124, -0.004682203645285, -0.019357735197421, -0.025875762043837, -0.017435787337996, 0.005471034822059, 0.033037851847265, 0.049218355348873, 0.038520192602532, -0.006112347636894, -0.078041093847378, -0.157847718052422, -0.220135476387537, 0.756344281504610, -0.220135476387537, -0.157847718052422, -0.078041093847378, -0.006112347636894, 0.038520192602532, 0.049218355348873, 0.033037851847265, 0.005471034822059, -0.017435787337996, -0.025875762043837, -0.019357735197421, -0.004682203645285, 0.008966346831124, 0.015030618183398, 0.012267146479049, 0.003969691594410, -0.005085409431928, -0.012238782422342, -0.018864421488768, 0.016244657856333}; /*double numCoeff_d_FILTRE_EXEMPLE[SIZEFILTER_RIF]; //Coefficients du numérateur de la fonction de transfert du filtre au format double double ek_d_filtre_exemple[SIZEFILTER_RIF]; //tableau pour stocker les échantillons d'entrée au format double int indice_ecr_d_filtre_rif; void initFiltre_d_filtre_rif() {} double execFiltre_d_filtre_rif(double e) {} */ //////////////////////////////////////////////////////////////////////////////////// //Implémentation en virgule fixe: //////////////////////////////////////////////////////////////////////////////////// //mettre ici toutes les constantes et variables définies en int, en indiquant le type dans le nom avec _i_ short int numCoeff_i_FILTRE_RIF[SIZEFILTER_RIF]; //Coefficients du numérateur de la fonction de transfert du filtre au format virgule fixe short int ek_filtre_i_RIF[SIZEFILTER_RIF]; //tableau pour stocker les échantillons d'entrée au format virgule fixe int indice_ecr_i_filtre_rif; //pour gestion buffer circulaire #define NB_BITS_FRACTIONNAIRE 14 //////////////////////////////////////////////////////////////////////////////////// void initFiltre_i_filtre_rif() { int i; for (i = 0; i < SIZEFILTER_RIF; i++) { numCoeff_i_FILTRE_RIF[i] = floor( (numCoeff_d_FILTRE_RIF[i] * (1<< NB_BITS_FRACTIONNAIRE) )+ 0.5) ; ek_filtre_i_RIF[i]=0; } } //////////////////////////////////////////////////////////////////////////////////// inline short int execFiltre_i_filtre_rif(short int e) { long int temp; // calcul intermediaire sur 32 bits int i; //indice de lecture pour les valeurs des coefficients du filtre int indice_lec_i_filtre_rif = indice_ecr_i_filtre_rif; //indice de lecture pour les échantillons d'entrée short int skout = 0; //valeur pour la sortie calculée ek_filtre_i_RIF[indice_ecr_i_filtre_rif] = e - 512; //rangement de l'echantillon d'entrée dans le buffer circulaire des entrées en référencant par rapport au 0 // indice_ecr_i_filtre_rif = (indice_ecr_i_filtre_rif + 1) % SIZEFILTER_RIF; indice_ecr_i_filtre_rif = (indice_ecr_i_filtre_rif + 1); if (indice_ecr_i_filtre_rif>=SIZEFILTER_RIF) indice_ecr_i_filtre_rif=0; temp = 0; //valeur par défaut pour le résultat for (i = 0; i < SIZEFILTER_RIF; i++) { temp += (long int) numCoeff_i_FILTRE_RIF[i] * (long int)(ek_filtre_i_RIF[indice_lec_i_filtre_rif]); // calcul sur 32 bits indice_lec_i_filtre_rif--; if (indice_lec_i_filtre_rif < 0) indice_lec_i_filtre_rif = SIZEFILTER_RIF - 1; } if (temp & (1<<(NB_BITS_FRACTIONNAIRE-1)) ) // calcul de l'arrondi skout = (temp >> NB_BITS_FRACTIONNAIRE ) + 1; else skout = (temp >> NB_BITS_FRACTIONNAIRE ) ; if (skout > 511 ) // saturation du résultat sur 10 bits skout = 511 ; else if (skout < -512 ) skout = -512 ; return skout + 512; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ISR(TIMER0_COMPA_vect) { //timer0 interrupt 2kHz toggles pin 8 static short int skprec = 0; static short int eksuiv = 0; PORTB |= 1; // visu du temps passé dans l'interruption eksuiv = finishReadADCPolling() ; // valeur de l'echantillon sans valeur moyenne. startReadADCPolling(); //avec prescaler réglé à 1/128, l'acquisition d'un échantillon prend 120us, mais ce temps est utilisé pour commander le dac et calculer la valeur de l'échantillon en cours DAC.writeDACAB(skprec , eksuiv ); //prend 40us PORTB |= 4; // visu du temps passé dans la fonction filtre skprec = execFiltre_i_filtre_rif(eksuiv); PORTB &= (0xFF -4); //fin visu PORTB &= 0xFE; //fin visu } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void setupADCPolling() { ADCSRB=0; //ADCSRA = 1 << ADPS2 | 1 << ADPS1 | 1 << ADPS0 | 1 << ADEN; // prescaler 1/128, enabled, in that case, we use the best resolution, as the ADC conversion will be interlaced with the processing, the time needed is not lost, otherwise, we could use: //ADCSRA = 1 << ADPS2 | 1 << ADPS1 | 1 << ADEN; // prescaler 1/64, enabled ADCSRA = 1 << ADPS2 | 1 << ADPS0 | 1 << ADEN; // prescaler 1/32, enabled ADMUX = 1 << 6; //choix entrée analogique 0 et référence de tension =VCC } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /*! \brief ADC Conversion Routine start */ inline void startReadADCPolling(void) { ADCSRA |= (1 << ADSC); // Start ADC Conversion } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /*! \brief ADC Conversion Routine wait and read */ inline unsigned int finishReadADCPolling(void) { unsigned int result; while ((ADCSRA & (1 << ADIF)) != 0x10); // Wait till conversion is complete result = ADC; // Read the ADC Result ADCSRA |= (1 << ADIF); // Clear ADC Conversion Interrupt Flag return result ; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void setup() { Serial.begin(9600); Serial.println("Bonjour"); pinMode(itpin, OUTPUT); pinMode(filtrepin, OUTPUT); pinMode(boutonPin, INPUT); DAC.powerOn(); // start the tlv5637 library: DAC.speedFast(); initFiltre_i_filtre_rif(); //initialise le filtre cli();//stop interrupts //set timer0 interrupt at 2kHz TCCR0A = 0;// set entire TCCR2A register to 0 TCCR0B = 0;// same for TCCR2B TCNT0 = 0;//initialize counter value to 0 // set compare match register for 2khz increments OCR0A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256) // turn on CTC mode TCCR0A |= (1 << WGM01); // Set CS01 and CS00 bits for 64 prescaler TCCR0B |= (1 << CS01) | (1 << CS00); // enable timer compare interrupt TIMSK0 |= (1 << OCIE0A); setupADCPolling(); startReadADCPolling(); //lance la demande d'acquisition du premier échantillon pour que la première interruption timer ne soit pas bloquée sei();//allows interrupts } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void loop() { Serial.println("Je suis vivant!"); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////