Par contre j'ai une sorte de jitter sur le signal et je perd de temps en temps un pulse, la valeur moyenne de la fréquence de base restant dans la fourchette indiquée ( problème HW ? ).
En passant par les interruptions, suivant quand se déclenche l'interruption, cela va retarder ou non les changements. Pour peu que la remise à l'heure se fasse, il va y avoir un délai supplémentaire.
En utilisant le circuit PWM présent dans l'Arduino, on a un signal qui est hard, et donc:
- n'est pas influencé par les interruptions
- ne prends pas te temps machine autre que pour le lancement.
C'est analogWrite(), que l'on peut utiliser tel quel si on se contente des valeurs imposées, sinon il suffit de réécrire cette fonction. Pour répondre au problème "Je voudrais réaliser un pwm de fréquence fixe = 200Hz dont la largeur d'impulsion est ajustable", on peut utiliser plusieurs modes, par exemple le mode 14 de la datasheet Atmel "Fast PWM Mode", c'est le premier qui répond au problème.
- Il faut utiliser le mode 1410=11102
- Le timer 0 étant utilisé par le système, je choisis le timer 1 (on peut aussi prendre le timer 2 qui est un 8 bits, avec une précision moindre sur le rapport cyclique)
- Avec le timer 1 on ne peut utiliser que les sorties OC1A ou OC1B. je choisis la première OC1A qui est aussi appelée sortie 9
- Pour l'horloge, je choisis 0,5µs (division de l'horloge système par 8) moins on divise, plus on a un réglage fin, mais point trop n'en faut si on doit compter sur 1 bits? Pour une période de 5mS, on doit compter 10000. On ne peut pas compter 8 fois plus, cela dépasse. En fait il faut compter un de moins que ce que l'on veut soit 9999.
Voici alors un programme avec un PWM de 200Hz, rapport cyclique de 33%:
void setup()
{
pinMode(9, OUTPUT); // OC1A, Uno, sortie PWM du Timer 1
TCCR1A = B10000010; // Sortie OC1A, OC1B non utilisé, Mode 14=fast PWM
TCCR1B = B00011010; // Pas d'interruptions, Mode 14, Horloge 0,5µs
ICR1 = 9999; // Période 5ms ((9999+1) x 0,5µs)
OCR1A = 3333; // Etat haut
}
void loop()
{
}
Pour ajuster la période (elle est à 200Hz si le micro tourne à 16000000,0000Hz). Sinon, il suffit de changer la valeur de ICR1
Pour changer le rapport cyclique, il faut changer la valeur de OCR1A, 0 pour 0%, 10000 pour 100%
Petit bémol avec ce code aussi simple: si on diminue la valeur de OCR1A, il est possible que la comparaison ne se fasse pas si le compteur a une valeur instantanée supérieure à la nouvelle valeur, et on aura un défaut sur une période. Pour éviter cela, si c'est utile, il faut changer la valeur de OCR1A quand le compteur TCNT1 est inférieur à OCR1A. Du fait du temps de traitement, cela risque d'être impossible pour des rapports cycliques inférieurs à 1%.
Le code ci dessus a été testé, maintenant si la valeur vient de analogRead(POTAR), on devrait pouvoir écrire (non testé):
void loop()
{
OCR1A = analogRead(POTAR) * 10; // transformation simple 0-1024 -> 0-10240
}