Quadrature Encoder Signal Generator

Hi

I am currently looking to create an artificial encoder signal for simulation. I was reading through this http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM and am not sure if this is the right area to look at!

Being new to Arduino doesnt help too much either.

Thanks for any advice!

What encoder are you trying to simulate? PWM will just keep running at a fixed frequency without intervention once started, is this what you need or do you want it to start/stop at your command or maybe run at different frequencies. We basically need more information on what your trying to do.

Hi

What encoder are you trying to simulate?

I am trying to generate a RS422 pulse.

PWM will just keep running at a fixed frequency without intervention once started, is this what you need or do you want it to start/stop at your command or maybe run at different frequencies.

Yes, I would like to Start and Stop based on a digital input. Frequencies - I would run a constant frequency but having an option to change would be nice but not essential!

Thank you

vmax711: What encoder are you trying to simulate?

I am trying to generate a RS422 pulse.

Sorry, I must be having a blonde moment here in understanding but RS422 is just a specification for electrical signals of communications equipment, I cannot see how this relates to a 'Quadrature Encoder' unless your using RS422 to transmit the signals some distance to the decoder?

Assuming the encoder is 2 channels then you could do it with a timer interrupt set to 4x the required frequency so you can toggle the A & B signals 25% out of phase. You could then connect a RS422 line driver chip and output theses signals at the levels required (assuming your using the arduino to simulate the encoder). Simple software could control on/off of the encoder signals, direction and alter the frequency by adjusting the timer timebase.

For finer control you could use DDS with a phase register of 8 or more bits. If you need to simulate variable speed and acceleration this is a flexible approach (and can be used to generate analog quadrature as well if you want).

Riva: Sorry, I must be having a blonde moment here in understanding but RS422 is just a specification for electrical signals of communications equipment, I cannot see how this relates to a 'Quadrature Encoder' unless your using RS422 to transmit the signals some distance to the decoder?

Assuming the encoder is 2 channels then you could do it with a timer interrupt set to 4x the required frequency so you can toggle the A & B signals 25% out of phase. You could then connect a RS422 line driver chip and output theses signals at the levels required (assuming your using the arduino to simulate the encoder). Simple software could control on/off of the encoder signals, direction and alter the frequency by adjusting the timer timebase.

The blonde moment was totally mine!

Yes the encoder I am trying to simulate is a 2 channel out of phase but I am really at loss on how to generate the pulse train as an output of Arduino.

Thank you!

Below is the core of a possible way to generate the signal. Obviously you would need to adjust the code to suit your needs. I have also attached an LA image so you can see if it’s correct.

#include <avr/interrupt.h>   

#define T2Speed 50

const int LED = 13;
const int channelA = 2;
const int channelB = 3;

volatile byte tmrCount = 0;
//Timer2 overflow interrupt vector handler
ISR(TIMER2_OVF_vect) {
  TCNT2 = T2Speed;      //reset timer
  digitalWrite(LED,HIGH);
  switch (tmrCount) {
  case 0:
    digitalWrite(channelA,HIGH);
    break;
  case 1:
    digitalWrite(channelB,HIGH);
    break;
  case 2:
    digitalWrite(channelA,LOW);
    break;
  case 3:
    digitalWrite(channelB,LOW);
  }
  tmrCount++;
  if (tmrCount >= 4) {
    tmrCount = 0;
  }
  digitalWrite(LED,LOW);
  TIFR2 = 0x00;
};  

void setup() {
  Serial.begin(115200);
  pinMode(LED,OUTPUT);   // UNO LED, just for show
  pinMode(channelA,OUTPUT);
  pinMode(channelB,OUTPUT);

  TCCR2A = 0;           //Timer2 Settings: WGM mode 0
  TCCR2B = _BV(CS22);   //Timer2 Settings: Timer Prescaler /64
  TIMSK2 = _BV(TOIE2);  //Timer2 Overflow Interrupt Enable 
  TCNT2 = T2Speed;      //reset timer
}

void loop() {
}

That signal is what I want ! :smiley: Thank you!

Just checking if I have understood the code right :

#include <avr/interrupt.h>    //Include the Interrupt Library

#define T2Speed 50            // Setting the Interrupt Speed?

const int LED = 13;            // Setting the pin number for LED as 13?
const int channelA = 2;      // Setting the pin number for channel A as 2 (Since I have an Arduino Mega I assume this would pin 2 PWM?)
const int channelB = 3;      // Setting the pin number for channel A as 3

volatile byte tmrCount = 0; //Timer2 overflow interrupt vector handler
ISR(TIMER2_OVF_vect) {
  TCNT2 = T2Speed;          //reset timer
  digitalWrite(LED,HIGH);
  switch (tmrCount) {
  case 0:
    digitalWrite(channelA,HIGH);
    break;
  case 1:
    digitalWrite(channelB,HIGH);
    break;
  case 2:
    digitalWrite(channelA,LOW);
    break;
  case 3:
    digitalWrite(channelB,LOW);
  }
  tmrCount++;
  if (tmrCount >= 4) {
    tmrCount = 0;
  }
  digitalWrite(LED,LOW);
  TIFR2 = 0x00;
};  

void setup() {
  Serial.begin(115200);
  pinMode(LED,OUTPUT);   // UNO LED, just for show
  pinMode(channelA,OUTPUT); 
  pinMode(channelB,OUTPUT);

  TCCR2A = 0;           //Timer2 Settings: WGM mode 0
  TCCR2B = _BV(CS22);   //Timer2 Settings: Timer Prescaler /64
  TIMSK2 = _BV(TOIE2);  //Timer2 Overflow Interrupt Enable 
  TCNT2 = T2Speed;      //reset timer
}

void loop() {
}

Nvm! I have managed to get it working to generate the oscilloscope signal like the one above, by connecting the PWM pins 2 & 3… I s there any sort of limit to the frequency of the pulsing this can achieve? I can seem to get more than 2.6 KHz whereas I am looking to achieve something closer to 1MHz.

vmax711: Nvm! I have managed to get it working to generate the oscilloscope signal like the one above, by connecting the PWM pins 2 & 3... I s there any sort of limit to the frequency of the pulsing this can achieve? I can seem to get more than 2.6 KHz whereas I am looking to achieve something closer to 1MHz.

First off sorry for the late reply, I have been away for the week. Second, sorry for not including comments in the code.

Timer2 is an 8 bit timer that's counting up to 255 where it overflows and causes the interrupt vector to be called. T2Speed sets the initial value for this timer so the higher the value the less time it takes to count to 255 and overflow.

TCCR2B = _BV(CS22) sets the timer pre-scale to 64 if T2Speed gets close to 255 you could reduce the pre-scale to give finer control of timings.

Ah that makes sense! And please dont be sorry!

So the T2Speed is limited to the overflow value right? If so then I should be able to change the overflow limit to a lower value, so that there is fewer counts per interrupt and when T2Speed equals Overflow value I get max frequency?

Am I right in making the above assumption?

vmax711: Ah that makes sense! And please dont be sorry!

So the T2Speed is limited to the overflow value right? If so then I should be able to change the overflow limit to a lower value, so that there is fewer counts per interrupt and when T2Speed equals Overflow value I get max frequency?

Am I right in making the above assumption?

T2Speed need increasing to speed up the interrupt. Timer2 overflows and generates an interrupt when it tries to increment beyond 255, the T2Speed value is what sets the start value for Timer2 and is loaded in the Timer2 overflow interrupt routine. The higher the value of T2Speed (but always less than 255) the less time between it's value and Timer2 overflow. T2Speed = 100 means there is 156 (256 - 100) increments before overflow. T2Speed = 200 means there is only 56 (256 - 200) increments before overflow. quicker.

Nick Gammon has a good article on Timers here that may be of interest though he uses the comparator method that is more logical to use but slightly more work to setup.

If anyone still cares, I wrote a hardware quadrature generator for the Arduino UNO. Once started, it uses no CPU cycles and is driven completely by the hardware timer. It can run up to 4Mhz and is as accurate as the Arduino clock oscillator, even with interrupts running.

Here is the code…