Hello everyone. This is my first practical project with an Arduino UNO, and the truth is that I have not touched anything easy I need to convert my Arduino into a 14-bit encoder driver for this I need to generate a 14-pulse train to A fixed frequency greater than 30 Khz and to establish between each train a dead time of 50 microseconds, or until a little more.
In all the variants that I have realized I have stumbled on my oscilloscope with an annoying jitter or phase shift in the wave, which should be as clean as possible.
This was my first crude variant:
void setup() {
pinMode(11, OUTPUT);
}
void loop() {
for (int i=0; i<15; i++){
digitalWrite(11, HIGH);
delayMicroseconds(12.5);
digitalWrite(11, LOW);
delayMicroseconds(12.5);
}
delayMicroseconds(50);
}
Then I tried to solve it using the timer to make the wave, and there seems to be a time offset product to stop and summarize the timer to make up the dead time. I use the TimerOne library which I download at: GitHub - PaulStoffregen/TimerOne: TimerOne Library with optimization and expanded hardware support
#include <TimerOne.h>
const byte CLOCKOUT = 11;
volatile long counter=0;
void setup() {
Timer1.initialize(15); //Cada 15 microsegundos cambio el estado del pin en la funcion onda dando un periodo
Timer1.attachInterrupt(Onda); //de 30 microsegundos
pinMode (CLOCKOUT, OUTPUT);
digitalWrite(CLOCKOUT,HIGH);
}
void loop() {
if (counter>=29){ //con 29 cambios logro los pulsos que necesito
Timer1.stop(); //Aqui creo el tiempo muerto, el cual esta debe estar en HIGH
digitalWrite(CLOCKOUT,HIGH);
counter=0;
delayMicroseconds(50);
Timer1.resume();
}
}
void Onda(){
digitalWrite(CLOCKOUT, digitalRead(CLOCKOUT) ^ 1); //Cambio el estado del pin
counter+=1;
}
I even went a little further on the next variant and implemented two timers. Timer2 generates a wave using PWM and Timer1 detects me the 14 pulses and then configures the timer2 so that it generates for a time a wave with a useful cycle of 100% (state in HIGH, it is the dead time), but it does not work:
#include <TimerOne.h>
volatile int counter=0;
volatile int counterD=0;
volatile int counterU=0;
volatile char AS=0;
volatile int counterP=0;
void setup() {
pinMode(11, OUTPUT);
pinMode(11, INPUT);
Timer1.attachInterrupt(DetctrPlsos);
Serial.begin(57600);
Timer1.initialize(4);
digitalWrite(11,HIGH);
TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20); //Regula la frecuencia PWM en pin 11 a 31KHz
TCCR2B = _BV(WGM22) | _BV(CS22);
OCR2A = 2;
}
void loop() {
}
void DetctrPlsos(){
if (AS==0){ //As me dice si estoy generando los 14 pulsos o si estoy en el tiempo muerto
if ((digitalRead(11)==0) && (counterD==0)){ //Leo la misma salida en la cual genero la onda para cambiar de Low a High, counterD y counterU
counterD +=1; //los uso para no entrar mas de una vez en un mismo estado, ya que timer1 va mas rapido en este caso que timer2
counter +=1; //counter me cuenta cuantos pulsos llevo
counterU =0;
}
else if ((digitalRead(11)==1) && (counterU==0)){
counterU +=1;
counterD =0;
}
if (counter==14){ //Si ya se generaron los 14 pulsos cambio la configuracion del timer2 para crear tiempo muerto
counter=0;
TIMSK2 &= ~(1<<TOIE2); //deshabilito el timer 2 para configurarlo
TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM20);
TCCR2B = _BV(CS22);
OCR2A = 255; //ciclo util de 100% es un estado HIGH, es el tiempo muerto
OCR2B = 50;
TIMSK2 |= (1<<TOIE2); //habilito timer2
AS=1; //cuando entre de nuevo al timer1 contara el tiempo muerto
}
}
if (AS==1){
counterP+=1; //ahora cuento en timer1 el tiempo que la onda estara en HIGH
if (counterP==12){ //cd haya transcurrido ese tiempo vuelvo a generar la onda con el timer2
counterP=0;
AS=0;
TIMSK2 &= ~(1<<TOIE2);
TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20);
TCCR2B = _BV(WGM22) | _BV(CS22);
OCR2A = 2;
TIMSK2 |= (1<<TOIE2);
}
}
}
I hope you find a solution. Apologies for the comments in Spanish on the variants, I did not have time to translate them. Thank you very much