Ciao ragazzi,
sono di nuovo alle prese col timer 1 su atmega328.
Il gioco è questo: sul fronte di discesa (falling) di un segnale su external INT0 chiamo una isr (SensorINPUT) ke mi fa partire il timer 1 in compare mode con prescaler 8.
Quando il timer 1 arriva a OCR1A lancia la sua ISR dove deve abbassare il pin 9 (oc1a) di uscita che normalmente ho impostato con pull up nel setup.
Quindi al primo giro entra in (!CoilOff) perchè CoilOff=false e porta pin9 basso perchè nel setup TCCR1A=(1 << COM1A1);
Poi Ricarica OCR1A=4000; per far si che timer1 porti pin9 alto dopo 2ms e lancia il conteggio settando TCCR1B e setta TCCR1A = (1 << COM1A1) | (1 << COM1A0); in modo che pin9 si alzi quando il timer è arrivato alla fine conteggio.
Arrivato a 4000 count la ISR entra dove CoilOff=true dove viene fermato il timer e reimpostato TCCR1A=(1 << COM1A1); in modo che il pin9 vada bassa alla prossima fine conteggio. Qui si carica OCR1A=1000;
All'arrivo del nuovo segnale d'ingresso viene fatto partire il timer che arrivato a 1000 count fa abbassare il pin9.
tutto funziona, ma spesso ho la situazione come visualizzata in foto: segnale d'ingresso blu e uscita giallo.
L'uscita a volte non è presente oppure sta alta più del dovuto.
Qui i link alle immagini
https://postimg.org/image/z5clizqyz/
https://postimg.org/image/hqsdaptu3/
Ho fatto diverse prove ma non riesco a risolvere, e questa configurazione è la più veloce in quanto il timer stesso gestisce il pin9 e non perdo tempo nel alzare e abbassare l'uscita con digitalWrite.
Il problema suddetto non persiste se uso digitalWrite invece di settare TCCR1A.
Dove sbaglio?
void SensorINPUT() //lancia il timer 1: OCR1A è caricato con delay
{
TCCR1B = (1 << WGM12) | (1 << CS11); // CTC, OCR1A as top, prescaler 8, start timer
Actual_time = micros();
CoilOff=false;
}
ISR(TIMER1_COMPA_vect)
{
if (!CoilOff) // turn on coil after Toff (dopo il segnale s_in il contatore quando arrivato a delay di OCR1A entra qui e setta di alzare l'uscita dopo Toff)
{
TCCR1B = 0; // stop timer
TCCR1A = 0;
TCNT1 = 98; // initial value of the timer to compensate delay
TCCR1A = (1 << COM1A1) | (1 << COM1A0); // Set OC1A at compare match
OCR1A = 4000;
TCCR1B = (1 << WGM12) | (1 << CS11); // CTC, OCR1A as top, prescaler 8, start timer
}
else // turn off coil after Delay (setta di abbassare l'uscita dopo il delay di OCR1A)
{
TCCR1B = 0; // stop timer
TCCR1A = 0;
TCNT1 = 98; // initial value of the timer to compensate delay
TCCR1A = (1 << COM1A1); // Clear OC1A at compare match
OCR1A = 1000;
}
CoilOff = !CoilOff;
}