Salut,
Suite à ta demande, je te mets mes configs servo ici...
Pour commencer, pour les servos, j'utilise malheureusement le timer1, car il faut impérativement un timer 16 bits en hard pour avoir un minimum de précision (l'unité que j'ai trouvé donne 1 <=> 500ns). Dans ton cas, c'est pas mal, puisque ça correspond à la précision de la mesure de ton signal PPM, le transfert de la mesure dans les servos se fait donc sans conversion de temps, c'est la bonne nouvelle.
Qui dit bonne nouvelle dit donc mauvaise, il faudra que tu orientes ta détection PPM sur le timer2, mais là, je te retourne ton idée (que j'ai pas encore testé mais qui devrait marcher) : étendre le timer2 en 16 bits logiciel.
Problème non solvable : seul le timer1 possède une ICP, mais je ne pense pas que ça mettra en doute la précision (il suffit de mettre moins de 500ns entre l'INT déclenchée par le PPM et le relevé de TCNT2, sans traîner, c'est jouable, ça devrait ne prendre que 6 cycles d'horloge, soit 375ns, on a 8 cycles pour basculer de l'INT à la lecture de TCNT2)
La config servo :
Servo_setup(){
TCCR1A = 0x02; // (WGM1 = Fast PWM)
TCCR1A += 0x80; // COM1A = 2, servo1 sur OC1A
TCCR1A += 0x60; // COM1B = 2, servo2 sur OC1B
TCCR1B = 0x18; // (WGM1 = Fast PWM)
TCCR1B += 0x02; // démarrage du timer 1 : Prescaler = 1/8, Fclk = 2MHz, T = 0.5µs
ICR1 = 35000; // période servo à ajuster à souhait : (30000 = 15ms, 40000 = 20ms)
}
L'"écriture" des commandes servo se fait par OCR1A = value1 et OCR1B = value2 à n'importequel moment, elle sera matériellement prise en compte dès que TCNT1 = 0 (càd lorse-que timer1 aura fini son tour).
La période servo (ICR1) est importante, j'ai remarqué que l'asservissement interne des servos (de base) se fait au rythme de la période du signal de commande, si cette période est trop lente, alors le servo atteindra sa position en "escalier" cadencé au rythme du signal.
Pour l'extension du timer2 :
volatile byte T2_MSB; // extention logicielle de timer2
volatile word TCNT2_New, TCNT2_Old; // nouvelle et ancienne mesure de timer2
Void Timer2_setup(){
TCCR2A = 0x00; // normal port operation
TCCR2B = 0x00; // Clock = 0Hz
TIMSK2 = 0x01; // int sur OverFlow
TCCR2B = 0x02; // démarrage T2 : Clock = 2MHz, T = 0.5µs
DDRD &= 0xFB; // pin PPM en entrée (port D2, pin N°2)
EICRA = 0x02; // autoriser INT0 pour lecture PPM <= à vérifier, je crois qu'il faut ICS0=1 dans ton cas, voir page 72 du datasheet
}
ISR(T2_OVF){ // extention logicielle de T2 en 16 bits
T2_MSB++;
if (T2_MSB = 0) { // débordement, le compteur 16 bits vient de faire un tour complet!
// a définir
}
}
ISR(INT0_VECT){ // réception impulsion PPM
TCNT2_New = TCNT2 + (T2_MSB << 8); // lecture Timer2
/* code de RAZ timer2 :
TCNT2 = 0; // mise à zéro timer2
T2_MSB = 0; // mise à zéro timer2
*/
// ici le traitement de TCNT2_New
}
En fait, c'est rigolo, car ces codes, je les ai écrits hier pour mon multiplicateur d'impulsions, et je n'ai eu qu'à changer deux lignes pour que ça corresponde à ton projet...