Encoder Simulator

Status
Not open for further replies.

Wozzy

Well-known member
A friend asked for my help to create an emulator for an old shaft encoder.
Of course I answered "No problem... A Teensy 3.0 can do that."
But now I'm struggling with the best way to go about it.
While I was finally able to understand the PIC product spec sheets, the Freescale documentation still spins my head around.

The encoder is mounted on a shaft that varies in RPM from 10 to 3000 RPM.
It has 4 outputs which vary in frequency proportional to the shaft RPM.

1) 60/Rev - a 50% square wave with 60 cycles per revolution.
2) 1/Rev - 1 single pulse the same width as 60/rev, and aligned to one of the 60/Rev Cycles.
3) Flip Flop - a square wave that toggles each revolution aligned with the rising edge of the 1/Rev
4) Ramp - and analog sawtooth wave from -10V to +10V that resets on the rising edge of the 1/Rev

See the attached image
Encoder.jpg

He really didn't need the the ramp, but I took the challenge to try and include it... But I'll probably end up using an external function generator chip.
So I've set up an input encoder knob as the RPM adjust, and tried Interval Timer, and assorted PWM functions, but each runs into limitations with range, or resolution.
I looking into using one output to drive a base frequency, then reading it back into other pins as timer/counters, then triggering yet other pins set as outputs.
I'm also considering that I may need to use multiple Teensy 3.0s, or a possibly a different model.

I was hoping you guys could steer me in the right direction so I can save face with my friend.

I promise to share whatever I learn.
Thanks
 
Last edited:
When I wrote the Encoder library, I make a little encoder emulator circuit to test the maximum speed. It's built with a 555 timer and CD4013 dual flip-flop. Details are on the encoder page:

http://www.pjrc.com/teensy/td_libs_Encoder.html

Scroll down to the section "Emulating Quadrature Encoded Signals".

That circuit outputs 2 logic level signals. If you wanted open collector style like most mechanical encoders have, you'd need to add something like 4066 switched or NPN or N-channel transistors.
 
Oh.... looking at those waveforms, it's not a quadrature encoder at all. Opps.

3000 RPM and 60/rev is only a max 3000 pulses per second. That's slow enough to just emulate with software.

I'd just build this with some simplistic code code using digitalWrite and an elapsedMicros variable.

Code:
elapsedMicros us = 0;  // increments automatically at a rate of 1000000/sec
int period = 333;
int pinstate = LOW;
int count = 0;

void loop() {
  if (us >= period) {
    us = us - period;
    if (pinstate == LOW) {
      digitalWrite(pin, HIGH);
      pinstate = HIGH;
    } else {
      digitalWrite(pin, LOW);
      pinstate = LOW;
    }
    count = count + 1;
    if (count >= 60) {
       // do similar stuff to update the other 2 pins
    }
    
    // check for input to modify the period variable
  }

This isn't a complete or tested example. In fact, I just made it up for this message and never tried verifying in any way. It's only meant to explain the idea.

333 us is such a long time for Teensy 3.0, or even Teensy 2.0, that you can just create the waveforms the easy way with digitalWrite.
 
Last edited:
Oh.... looking at those waveforms, it's not a quadrature encoder at all...
That's slow enough to just emulate with software... you can just create the waveforms the easy way with digitalWrite.

Thanks Paul for getting me going...
I have it pretty much working except for the Ramp - for me, not bad for a few hours.

The Teensy is so much faster than what I'm used to working with this was completely doable in software.
I'll clean it up, comment and post the code tomorrow.
It still needs a few tweaks, and perhaps a correction factor.

Here's a photo of the Hardware:
It has a 24 pulse encoder for input and a four digit serial seven segment display for RPM indication.
The 3 LEDs are hooked up to the outputs for now.
Encoder Emulator.jpg


Here's an Image of the output wave forms from my el-cheapo logic analyser.
Encoder DLA.jpg
 
Last edited:
Wozzy -- won't this have a glitch when us wraps ?

Code:
  if (us >= period) {
    us = us - period;[CODE]
 
The ramp should be doable by PWMing a pair of transistors across +/- 10V rails with a non-polarized cap smooth the output would it not? Pretty much half of an H-bridge.
 
Last edited:
Wozzy -- won't this have a glitch when us wraps ?

Code:
  if (us >= period) {
    us = us - period;[CODE][/QUOTE]

No, it will not.  You're thinking of micros(), which hits 32 bit rollover approx every 1.2 hours.

elapsedMicros is a special variable type which increments like micros(), but it's writable.  Since the period is subtracted each time, it will always remain between 0 to 333, or perhaps slightly over 333 occasionally if there is some software latency (eg, from interrupts).  It will never get anywhere near 32 bit rollover.

Internally, elapsedMicros is implemented with C++ operator overloading, using functions that call micros() and properly handle the 32 bit rollover.  That's why I created elapsedMicros and elapsedMillis, to make these types of use much simpler and without having to think carefully about 32 bit rollover every time.  There's more documentation here:

http://www.pjrc.com/teensy/td_timing.html
 
Status
Not open for further replies.
Back
Top