Shop OBEX P1 Docs P2 Docs Learn Events
Linear optical encoder missing ticks using Quadrature Encoder Engine — Parallax Forums

Linear optical encoder missing ticks using Quadrature Encoder Engine

hugheshughes Posts: 5
edited 2014-09-12 11:56 in Propeller 1
Hello everyone,

I am building a measuring device. I am trying to read a US Digital EM1 Linear optical encoder with 500 lines per inch resolution. I am using QuadratureEncoderEngine.spin, ASCII0_STREngine.spin & FullDuplexSerial.spin with the code I wrote below at the top object. The code works and displays my height variable as expected on the lcd screen. The height is not accurate though. There seems to be a random error of + or – a handful of ticks as I move through about half an inch of stroke. I put an oscilloscope on the encoder outputs and I am seeing two very clean 5 volt square waves 90 degrees out of phase. I have used resistors to pull up, pull down and capacitors to try and clean up the signal. No matter how I move the square wave around the code misses ticks. I am convinced it’s the code because I tried averaging both channels A & B of the quadrature encoder engine even though they are reading the same pins. This improved accuracy by about 50%. The encoder engine is said to be good to 100,000 ticks/sec that’s well below my input speed. I honestly do not understand Assembly yet, but I believe the problem lies in my Spin code. Any ideas on how I can make this work?

Thanks,

-Hughes

My Top Object file is below:


CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
TX_PIN = 0
BAUD = 19_200
VAR
Long Ticks 'Initialize counter A variable
Long Tocks 'Initialize counter B variable
OBJ
LCD : "FullDuplexSerial.spin" 'Call LCD object
Encoder : "QuadratureEncoderEngine" 'Call encoder engine object
Decimal : "ASCII0_STREngine_1" 'Call ASCII encoder object
PUB Start | idx
LCD.start(TX_PIN, TX_PIN, %1000, 19_200) ' Start LCD on TX pin with a baud rate of 19,200
waitcnt(clkfreq / 100 + cnt) ' Pause for FullDuplexSerial.spin to initialize
lcd.tx($0C) ' Clear LCD screen.
waitcnt(clkfreq / 100 + cnt) ' Pause for LCD to clear screen.
lcd.tx($11) ' backlight on
' Start Up Display
lcd.tx(22)
waitcnt(clkfreq / 100 + cnt) ' Pause for FullDuplexSerial.spin to initialize
LCD.str(string("KEM Equipment")) ' Display Startup string line 1.
lcd.tx(148) ' Move curser to line 2 position 0.
LCD.str(string("Please Tare")) ' Display Startup string line 2.
waitcnt(clkfreq * 1 + cnt) ' Hold startup massage on display for 1 seconds.
PUB Main
lcd.tx($0C) ' Clear LCD screen.
waitcnt(clkfreq / 100 + cnt) ' Pause for LCD to clear screen.
Encoder.QEDEngine ' Start QuadratureEncoderEngine.
Ticks := (Encoder.getDeltaA) ' Get tick count A since startup write value to Ticks.
Tocks := (Encoder.getDeltaB) ' Get tick count B since startup write value to Tocks.
LCD.str(string("Height")) ' Print the word "Height" to screen.
lcd.tx(135) ' Send cursor to line 1 position 14.
LCD.str(string("(in/1000)")) ' Show units
waitcnt(clkfreq * 1 + cnt) ' Pause for display.
repeat
Ticks := Ticks + (Encoder.getDeltaA) ' Set "Ticks" to accumulate encoder delta A
Tocks := Tocks + (Encoder.getDeltaB) ' Set "Tocks" to accumulate encoder delta B
lcd.tx(148) ' Move curser to second line position 0
LCD.str(Decimal.integerToDecimal((Ticks*2), 3)) ' Display Ticks in units of in/1000
LCD.str(Decimal.integerToDecimal((Tocks*2), 3)) ' Display Tocks in units of in/1000
LCD.str(Decimal.integerToDecimal((Ticks+Tocks),3)) ' Display Average of Ticks & Tocks units in/1000
lcd.tx(148) ' Move curser to second line position 0

Comments

  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-08-19 15:07
    hughes wrote: »
    but I believe the problem lies in my Spin code. Any ideas on how I can make this work?

    Normally I'd assume an error made by you or myself before thinking Kye's code could be the problem but in this case I think it's Kye's code causing the problem. Kye's object doesn't keep track of the transitions correctly. Here's a thread on the subject.

    I'd suggest trying a different encoder object. I haven't added my own quadrature code to the OBEX yet. I have an encoder only version attached to post #2 in this thread. The code attached to post #1 includes PWM motor control algorithms.
  • hugheshughes Posts: 5
    edited 2014-08-19 15:23
    Thanks Duane I will read that thread and look at different encoder engines.

    -Hughes
  • Mark_TMark_T Posts: 1,981
    edited 2014-08-20 09:18
    If you want to test my encoder object in anger I'd be grateful, I wrote it as an exercise without
    having an immediate use so its testing wasn't exhaustive.
    http://obex.parallax.com/object/737
    For a single encoder I'd expect it to function up to about 250kHz (10^6 counts/second).

    It should follow the rules correctly and even acrue an error count (catches when A & B
    both change in too short a timespan to detect the order).
  • KyeKye Posts: 2,200
    edited 2014-08-20 11:04
    I think I should put a warning on that object that it's only designed for tracking speed. I never really tested in for doing positional stuff. My main motivator for developing it was to make my String Ray robot have reliable drive speed.

    @ hughes - Sorry about that object wasting your time. Please use the Parallax developed object.
  • hugheshughes Posts: 5
    edited 2014-09-12 11:12
    I finally got a chance to test this yesterday. The "default" object works perfectly for what I want to do. It is accurate to within + or - 1/1000 of an inch, and repeatable. I have some more things to add to my measurement device, but as of now it works better than I had anticipated. Thanks for the help.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-09-12 11:24
    hughes wrote: »
    The "default" object works perfectly

    What's the "default" object?
  • hugheshughes Posts: 5
    edited 2014-09-12 11:34
    By the "default" object I mean the Quadrature Encoder.spin that comes in the Propeller Tool Library.
  • hugheshughes Posts: 5
    edited 2014-09-12 11:56
    I did not need the ability to check speed. I just needed the simple absolute count that the Quadrature Encoder provides. It was actually very easy to port the new encoder into my program. Now I need to have it check the index mark to reset its output if it drifts over time and add a variable frequency square wave output. I intend to read the square wave and convert it back to a height measurement with my ECM calibration software, so I can record this along with other engine parameters. The LCD output is just for ease of use while operators are in the dyno room. The real important part is the measurement accurately coded to a square wave. I should not have any trouble doing this part though.
Sign In or Register to comment.