This is what I have to far:
Code:
'------------------------------------------------------------------------------
' SPEED 26-36us to execute IF logic '
'------------------------------------------------------------------------------
'
' Change log
' 2024-08-18 Convert from 16F1937
@ ERRORLEVEL -301 ; turn off ADC clock ignored message
@ ERRORLEVEL -306 ; turn off crossing page boundary message
'***********************************************************************
' Default in file: PBP3_1\DEVICES\PIC16F1936.PBPINC *
' List in file: PBP3_1\DEVICE_REFERENCE\PIC16F1936.INFO *
' Note: PIC18 devices, the __CONFIG directive has *
' been superceded by the CONFIG directive *
'***********************************************************************
#CONFIG
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _VCAPEN_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
#ENDCONFIG
;--- Defines -------------------------------------------------------------------
DEFINE OSC 32
DEFINE LCD_DREG PORTB ' Set LCD data port
DEFINE LCD_DBIT 0 ' Set starting data bit
DEFINE LCD_RSREG PORTC ' Set LCD register select port
DEFINE LCD_RSBIT 5 ' Set LCD register select bit
DEFINE LCD_EREG PORTC ' Set LCD enable port
DEFINE LCD_EBIT 4 ' Set LCD enable bit
DEFINE LCD_BITS 4 ' Set LCD bus size
DEFINE LCD_LINES 4 ' Set number of lines on LCD
DEFINE LCD_COMMANDUS 1000 ' Set command delay time in microseconds
DEFINE LCD_DATAUS 50 ' Set data delay time in microseconds
define CCP4_REG PORTC ' PWM Pulse out to LCD contrast
DEFINE CCP4_BIT 1 ' 2N2907 PNP with 1K on base
define CCP5_REG PORTC ' PWM Pulse out to LCD backlight
DEFINE CCP5_BIT 2 ' 2N2222A NPN with 1K on base
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
Define HSER_BAUD 115200
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRGH 0
DEFINE HSER_SPBRG 68
;--- Setup registers -----------------------------------------------------------
SPLLEN CON %1 ' PLL enable
IRCF CON %1110 ' to enable 8 MHz
SCS CON %00 ' system clock determined by FOSC
OSCCON = (SPLLEN << 7) | (IRCF << 3) | SCS
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
;--- Setup analog pins to digital ----------------------------------------------
ANSELA = %00000000
ANSELB = %00000000
'ANSELC = %00000000 ' No analog on port C
'ANSELD = %00000000 ' No port D
'ANSELE = %00000000 ' No analog on port E
;--- Setup Port directions -----------------------------------------------------
TRISA = %00000111 ' Pin A7 = ...available
' Pin A6 = ...available
' Pin A5 = ...available
' Pin A4 = ...available
' Pin A3 = ...available
' Pin A2 = SPST
' Pin A1 = WiperB
' Pin A0 = WiperA
TRISB = %00000000 ' Pin B7 = iCSP clock
' Pin B6 = ICSP data
' Pin B5 = Blink LED1
' Pin B4 = Blink LED2
' Pin B3 = LCD data D7
' Pin B2 = LCD data D6
' Pin B1 = LCD data D5
' Pin B0 = LCD data D4
TRISC = %10000000 ' Pin C7 = RX
' Pin C6 = TX
' Pin C5 = LCD RS
' Pin C4 = LCD EN
' Pin C3 = ...available
' Pin C2 = PWM LCD backlight
' Pin C1 = PWM LCD contrast
' Pin C0 = ...available
'TRISD = %00000000 ' No port D
'
TRISE = %00000000 ' Pin E3 = MCLR
;--- Setup constants -----------------------------------------------------------
;--- Setup pins ----------------------------------------------------------------
Enc1_WiperA var PortA.0
Enc1_WiperB var PortA.1
Enc1_SPST VAR PortA.2
BlinkLED1 VAR LatB.5 ' Switch these ON/OFF to determine time
BlinkLED2 VAR LatB.4 ' required to execute a section of code
;--- Setup variables -----------------------------------------------------------
Enc1_previous var BYTE
Enc1_rotation var BYTE
Enc1_direction VAr BYTE
USARTcounter VAr WORd ' Used to show program is looping
Enc1_counter VAr WORd ' Used to display encoder movement
;--- Program initialization ----------------------------------------------------
BlinkLED1 = 0
BlinkLED2 = 0
HPWM 2,100,1953 ' LCD contrast (V0 pin)
HPWM 1,180,1953 ' LCD backlight (LED anode)
USARTcounter = 0
Enc1_previous = 0
Enc1_rotation = 0
Enc1_direction = 0
Enc1_counter = 0
goto Start
;--- Subroutines ---------------------------------------------------------------
Start:
Pause 500 ' Let PIC and LCD stabilize
LCDOUT $FE, 1 : Pauseus 1
LCDOUT $FE, $80, "ROTARY ENCODER TEST" : Pauseus 1
Mainloop:
BlinkLED1 = 1 ' Top of LOOP on Logic 2 probe
BlinkLED2 = 0
if USARTcounter < 65025 then ' To show program is working
USARTcounter = USARTcounter + 1
else
USARTcounter = 0
endif
' Wiper Chart:
' ============
' A B
' --- ---
' 0 0
' 1 0 /\ CCW
' 1 1
' 0 1 \/ CW
' 0 0
'
' Careful, EC11 30 detents 15 pulses will move from 00 to 11
' EC11 20 detents can move from 00 back to 00 in one click
if Enc1_WiperA = 0 and Enc1_WiperB = 0 then ' See wiper chart above
if Enc1_previous = 01 then ' 2 digits to follow chart better
Enc1_direction = 1 ' 1=CW, 0=CCW
Enc1_rotation = 1 ' Motion occurred
else
if Enc1_previous = 10 then
Enc1_direction = 0 ' 0=CCW
Enc1_rotation = 1 ' Motion occurred
else
Enc1_direction = 0 ' Not relevant without motion
Enc1_rotation = 0 ' No motion occurred
endif
endif
Enc1_previous = 00 ' Save wiper position
endif
if Enc1_WiperA = 1 and Enc1_WiperB = 0 then
if Enc1_previous = 00 then
Enc1_direction = 1
Enc1_rotation = 1
else
if Enc1_previous = 11 then
Enc1_direction = 0
Enc1_rotation = 1
else
Enc1_direction = 0
Enc1_rotation = 0
endif
endif
Enc1_previous = 10
endif
if Enc1_WiperA = 1 and Enc1_WiperB = 1 then
if Enc1_previous = 10 then
Enc1_direction = 1
Enc1_rotation = 1
else
if Enc1_previous = 01 then
Enc1_direction = 0
Enc1_rotation = 1
else
Enc1_direction = 0
Enc1_rotation = 0
endif
endif
Enc1_previous = 11
endif
if Enc1_WiperA = 0 and Enc1_WiperB = 1 then
if Enc1_previous = 11 then
Enc1_direction = 1
Enc1_rotation = 1
else
if Enc1_previous = 00 then
Enc1_direction = 0
Enc1_rotation = 1
else
Enc1_direction = 0
Enc1_rotation = 0
endif
endif
Enc1_previous = 01
endif
if Enc1_rotation = 1 then
if (Enc1_WiperA = 0 and Enc1_WiperB = 0) or _
(Enc1_WiperA = 1 and Enc1_WiperB = 1) then
if Enc1_direction = 1 then
Enc1_counter = Enc1_counter + 1 ' Turned 1 position CW
else
if Enc1_counter > 0 then
Enc1_counter = Enc1_counter - 1 ' Turned 1 position CCW
endif
endif
endif
endif
BlinkLED1 = 0 ' Bottom of IFs on Logic 2 probe
BlinkLED2 = 1
hserout ["#:", DEC5 USARTcounter,_
" C:", dec3 Enc1_counter,_
" A:", DEC1 Enc1_WiperA,_
" B:", DEC1 Enc1_WiperB,_
" SW:", DEC1 Enc1_SPST, 10]
BlinkLED1 = 0 ' After HSEROUT on Logic 2 probe
BlinkLED2 = 0
LCDOUT $FE, $D4, "C:", dec3 Enc1_counter,_
" A:", DEC1 Enc1_WiperA,_
" B:", DEC1 Enc1_WiperB,_
" SW:", DEC1 Enc1_SPST : Pauseus 1
BlinkLED1 = 0 ' After LCDOUT on Logic 2 probe
BlinkLED2 = 0
goto mainloop
end
To put things into perspective, these are the times I've observed so far:
Those encoder readings on channels 0 and 1 were done while turning the encoder as fast as I could. I wanted to see if I could over-run the time it takes the PIC to execute all the encoder code at 32 MHz.
The PIC is not even close to being overwhelmed, so now I know I should be able to process at least 2 encoders at the same time (at least that's what should happen in my mind ).
Bookmarks