Encore pour tester le filtre, on aurait pu utiliser le traceur série pour tester le filtre du deuxième ordre numérique, mais on peut aussi utiliser une sortie PWM.
En effet, si l’on désire lire le signal carré ou un signal alternatif est connaitre les résultats du filtre numérique, il est possible d’utiliser une sortie PWM filtré analogiquement par un RC.
Avec une fréquence PWM de 32kHz, et un RC de (10kohms et une capacité de 33nF) donc une fréquence de coupure de 482Hz atténuera l’ondulation de la PWM de
On peut observer l’ondulation pour un rapport cyclique de 50% sur la figure suivante :
Cette ondulation est de 0.075V autour de la valeur moyenne.
Avec un signal sinusoïdal ou carré de 10Hz et la fréquence de coupure de 1Hz, on retrouve bien que la valeur moyenne du signal carré qui est donc bien filtré en réel et dans ISIS.
Mais si l’on met un signal sinusoïdale de fréquence de 1hz, l’atténuation est de 0.35 à la place de 0.7 par contre le déphasage est bien de -90°.
Evidemment pour une fréquence sinusoïdale de 0.1Hz, il n’y a plus d’atténuation et le déphasage est presque à 0°.
Le code avec la pwm et la conversion analogique est le suivant :
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
#include <TimerOne.h>
#include <avr/wdt.h> //chien de garde
#define PWM3 3 // timer2
#define LED13 13
LiquidCrystal lcd(9, 8, 4, 5, 6, 7); // LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// Configuration des variables
unsigned int temps=0;
float entree=0;
float entree1=0;
float entree2=0;
float sortie=0;
float sortie1=0;
float sortie2=0;
float out=0;
const float b1 =2;
const float b2 =1;
const float a1 =-1.911;
const float a2 =0.915;
const float gain =1000;
void setup() {
pinMode(LED13, OUTPUT);
pinMode(PWM3,OUTPUT);
Timer1.initialize(10000); // initialize timer1, and set a 0,1 second period => 100 000 pour 0.01s 10 000
Timer1.attachInterrupt(callback); // attaches callback() as a timer overflow interrupt
lcd.begin(16, 2); //modifier pour un afficheur 20x4
Serial.begin(9600);
TCCR2B = (TCCR2B & 0b11111000) | 0x01; //pin 10 32khz http://playground.arduino.cc/Main/TimerPWMCheatsheet
}
// Interruptions tous les 0.01s fait par le timer1***********************************
void callback() {
/*
temps++;
if (temps>4) //1=singnal carré de 0.1s 5*routine d'interruption*2
{
temps=0; //reset : attention cette boucle doit etre infereir à son temps d'execution
if (entree==1023) {entree=0;} else {entree=1023;}
}//temps>1
*/
/* ----filtre passe pas Butterwoth 3émé ordre pour fc=10hz, fechantillon=1000Hz------ */
entree=analogRead(A0);
//digitalWrite(LED13,HIGH); //permet de mesurer à l'oscillo, le temps du calcul du filtre et le temps de la routine d'interruption
entree2=entree1; //entree(n-2)
entree1=entree; //entree(n-1)
sortie2=sortie1; //sortie(n-2)
sortie1=sortie; //sortie(n-1)
//sortie=entree+entree1*b1+entree2*b2+entree3*b3-sortie1*a1-sortie2*a2-sortie3*a3 ; //filtre passe pas recursif ordre 3
sortie=(entree+entree1*b1+entree2*b2-sortie1*a1-sortie2*a2) ; //filtre passe pas recursif ordre 2
out=sortie/gain; //plus facile de diviser que de multiplier
out = map(out, 0, 1023, 0, 255); //mise à l'echelle
analogWrite(PWM3,out);
//digitalWrite(LED13,LOW);
if (entree>=850) {digitalWrite(LED13,HIGH);} else {digitalWrite(LED13,LOW);} //test de la lecture du signal
/* Serial.print(temps);
Serial.print(";"); //creation du fichier CSV
Serial.print("\t");
*/
Serial.print(entree);
Serial.print(";");
Serial.print("\t");
Serial.print(out);
Serial.print("\t");
Serial.println(";"); //mise à la ligne dans le terminal
}//fin routine
///////////////////////////////////////////// Boucle correspondant à la fonction main
void loop() {
lcd.setCursor(0,0);
lcd.print(entree,0);
lcd.print(" ");
} // fin loop