Sunday, 13 July 2025
     
 
Main Menu
Home Home
Shop Shop
News News
BASCOM-AVR BASCOM-AVR
BASCOM-8051 BASCOM-8051
Products Products
Application Notes Application Notes
Publications Publications
Links Links
Support Center Support Center
Downloads Downloads
Forum Forum
Resellers Resellers
Contact Us Contact Us
Updates Updates
MCS Wiki MCS Wiki
Online Help
BASCOM-AVR Help BASCOM-AVR Help
BASCOM-8051 Help BASCOM-8051 Help
Contents in Cart
Show Cart
Your Cart is currently empty.
Search the Shop

Products Search

User Login
Username

Password

If you have problem after log in with disappeared login data, please press F5 in your browser

RSS News
 
     
 

 
   
     
 
AN #115 - Quadrature Decoder/Counter and Display Print
Quadrature Decoder/Counter and Display

Application note submitted by Ger Langezaal.


Here is some additional comment from Ger: 

For the encoder I used the one from an old "mouse". There are two of them in each mouse.
The resolution of both axes is 0.05 mm and the display lloks like this:  [ X  -106.45 mm ] for example
 
For each ax I used an AT90S2313-10 with display(16 x 1).
The problem of the "missing pulse" during a change of the direction within a pulsewidth,
I solved with software. Encoder phase-A generates an interrupt for both edges.
INT0 and INT1 are connected because the 2313 does not have a toggle interrupt like the 4433.
In the ISR only the phase-B and phase-A need to be compared with each other.
If A = B then increment counter otherwise decrement counter.
The counter value converting to a value in mm is dependend of the used encode and mechanical construction.
 
For the signal conditioning between the encoder and AVR I used a 74HC14.

Download the source code. It is also shown below:


'-------------------------------------------------------------------------------
' Filename : QuadrDec_1.0.bas
' Purpose : Quadrature Decoder/Counter and Display
' Author : Ger langezaal
' Date : 5 April 2002
' Compiler : BASCOM-AVR Rev. 1.11.6.5
'
'-------------------------------------------------------------------------------
'
' Algorithm:
' Interrupt on both edges of phase A
' Test phase B in ISR
' When phase B <> phase A then decrement counter
' When phase B = phase A then increment counter
' Convert counter value to displacment units
' Format value in string and display
'
'-------------------------------------------------------------------------------
'
' Setup for AT90S2313-10
'
' INT0 edge is set to rising edge
' INT1 edge is set to falling edge
' Encoder phase A to INT0 and INT1 (PD2 and PD3)
' Encoder phase B to PD4
' Pushbutton between Portd.5 and GND (display zero)
' LCD at PortB
'
' Example for PROXXON KT150 XY table:
' Displacement/rev = 2 mm
' Encoder resolution = 20 pulses/rev
' Interrupt on both pulse edges = 40 interrupts/rev
' Dial resolution: 2 mm / 40 = 0.05 mm
' The optical encoder came from a used mouse (two available)
'
'-------------------------------------------------------------------------------
'
' Options/Compiler/Chip:
' HW Stack 48
' Soft Stack 8
' Framesize 16
'
'-------------------------------------------------------------------------------
'
$regfile = "2313def.dat"
$crystal = 10000000 '10 MHz

Dim X_axis As String * 8 'LCD format string
Dim Axis_raw As Integer 'optical pulse counter
Dim Axis_mm As Integer 'counter value converted to mm
' 'range: -327.65 to +327.65 mm

Const Enc_res = 20 * 2 'encoder resolution * 2
Const Conv_mm = 200 / Enc_res 'dial resolution = 0.05 mm

Config Portb = Output
Config Portd = Input
Portd = 255 'enable Portd pullup's

Config Lcdbus = 4
Config Lcd = 16 * 1
Config Lcdpin = Pin , Db4 = Pb.4 , Db5 = Pb.5 , Db6 = Pb.6 , Db7 = Pb.7 , E = Pb.3 , Rs = Pb.2
Cls
Cursor Off

Phase_a
Alias Pind.2 'INT0 also connected to Pind.3 = INT1
Phase_b
Alias Pind.4
Axis_rst
Alias Pind.5 'reset counter if low

'---[ Set Interrupt logic ]-----------------------------------------------------

Mcucr = &B00001011 'set interrupt edges
On Int0 Phase_a_edge 'ISR on rising edge
On Int1 Phase_a_edge 'ISR on falling edge
Enable Int0
Enable Int1
Enable Interrupts

'---[ Initialization ]----------------------------------------------------------

Lcd "X-Axis Rev.1.0"
Waitms 1000
Cls
Axis_raw
= 0

'---[ Main program loop ]-------------------------------------------------------

Do
 
If Axis_rst = 0 Then Axis_raw = 0 'reset counter if low

 Axis_mm
= Axis_raw * Conv_mm 'convert to mm
 X_axis
= Str(axis_mm) '
 X_axis
= Format(x_axis , " +0.00") 'format without leading zero's
' X_axis = Format(x_axis , "+000.00") 'format with leading zero's

 
Locate 1 , 1
 
Lcd "X " ; X_axis ; " mm" 'display
 
Waitms 200
Loop

'-------------------------------------------------------------------------------
End

'---[ Interrupt Service Routine ]-----------------------------------------------

Phase_a_edge
: 'Interrupt on rising and falling edge
 
If Phase_b <> Phase_a Then 'test phase B
 
Decr Axis_raw 'CCW
 
Else
 
Incr Axis_raw 'CW
 
End If
Return

'-------------------------------------------------------------------------------