Как убрать джиттер в последовательности импульсов в Arduino UNO?

Это мой первый практический проект с Arduino UNO, и правда в том, что я не прикасался ни к чему простому :( Мне нужно преобразовать мой Arduino в 14-битный драйвер энкодера, для этого мне нужно сгенерировать 14-импульсную последовательность для A фиксированная частота больше 30 кГц и установить между каждым поездом мертвое время 50 мкс, или пока немного больше.Во всех вариантах, которые я реализовал, я наткнулся на свой осциллограф с раздражающим дрожанием или фазовым сдвигом в волне, который должен быть максимально чистым Это был мой первый грубый вариант:

void setup() {
    pinMode(11, OUTPUT);
}

void loop() {
    for (int i=0; i<15; i++){
        digitalWrite(11, HIGH);
        delayMicroseconds(12);
        digitalWrite(11, LOW);
        delayMicroseconds(12);
    }
delayMicroseconds(50);
}

Затем я попытался решить эту проблему, используя таймер, чтобы создать волну, и, похоже, есть продукт смещения времени, чтобы остановить и суммировать таймер, чтобы компенсировать мертвое время. Я использую библиотеку TimerOne, которую загружаю по адресу: https://github.com/PaulStoffregen/TimerOne.

#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;
}

person cgalcala    schedule 21.12.2016    source источник
comment
К вашему сведению, вы можете попробовать обратиться на Arduino.   -  person Johnny Mopp    schedule 21.12.2016


Ответы (1)


Я нашел лучшее решение, используя timer2 в режиме CTC.

#include <avr/io.h>
#include <avr/interrupt.h>

volatile byte counter=0;

void setup() {
   pinMode(11, OUTPUT);
   Serial.begin(57600);
   digitalWrite(11,HIGH);

   noInterrupts(); 


     TCCR2A = 0;
     TCCR2B = 0;
     TCNT2 = 0;

     TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20);
     TCCR2B = _BV(WGM22) | _BV(CS22);
     OCR2A = 4;
     TIMSK2 |= (1 << OCIE2A);

     interrupts(); // enable all interrupts

      }
    ISR (TIMER2_COMPA_vect){   
          counter+=1;
          if (counter==31){
            //PORTB = B00001000;
             OCR2A = 110;
              }
           else{
             if (counter>31){
                OCR2A = 6;
               counter=0;
                 }
             }

          }

      void loop() {
        Serial.print(counter);


        }
person cgalcala    schedule 27.12.2016
comment
вы должны количественно лучше - person Piglet; 28.12.2016