PDA

View Full Version : another state machine example



richard
- 19th October 2021, 10:36
on the other forum this was asked


I'd like to create a millisecond counter with a range from 5 milliseconds to 40 milliseconds. It does not have to be resolved to a single millisecond; e.g. need to know when it's hit each in a series of N+5 (5,10,15,20,25,30,35,40) milliseconds known. There'll be a photo interrupter reading an aperture in a disk and possibly be 8 LEDs each designating those 8 positions. Sort of like how an LED guitar tuner displays; 1st LED=5ms, 2nd=10ms, 3rd=15ms, etc.
Will I need a subroutine to avoid inaccuracy? Can I get by with PULSIN?
http://support.melabs.com/forum/picbasic-pro-compiler-3-0-and-later/pbp3-picbasic-pro-3-0/8323-millisecond-counter#post8333

no complete code solution was asked for. seemed a waste so i will post my idea here as an example of a state machine solution rather than waste the effort
the asm code is a leftover of first implementing a full charlieplexer for the leds , until i realized there was never a need to show more than one at any one time
and cut it down to a charlie with no plexer

9096


;@ 12f1822#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
__config _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_ON & _BORV_19 & _LVP_OFF
#ENDCONFIG




goto overasm
asm
pc_val ;led charlieplex lata data
addwf PCL, F
retlw 2
retlw 1
retlw 1
retlw 4
retlw 1
retlw 32
retlw 2
retlw 4
retlw 2
tc_val ;led charlieplex trisa data
addwf PCL, F
retlw 252
retlw 252
retlw 250
retlw 250
retlw 222
retlw 222
retlw 249
retlw 249
retlw 221
_LDS ;SHOW LED X=1 TO 9
BANKSEL LATA ;start with all LEDS off
clrf LATA
BANKSEL TRISA
movlw 0xff
IORWF TRISA,F
BANKSEL 0
decf _ledx ,w
L?CALL tc_val ;lookup tris value
BANKSEL TRISA
MOVWF TRISA
BANKSEL _ledx
decf _ledx,W
L?CALL pc_val ;lookup port value
BANKSEL LATA
MOVWF LATA ;ignite the led
BANKSEL 0
RETURN
endasm
overasm:


DEFINE OSC 16
OSCCON = $78
ANSELA = 0


TRIGGER VAR PORTa.4 ;timer gate control pin
timer var word ext ;the result in uS
ledx var byte bank0 ;current led to ignite 1-9
tmp var word ;temporary store
state VAR BYTE ;current state of machine 0, uninitialised 1, seeking pulse 2, pulse detected 3, good result 4, error
old_state VAR BYTE ;previous state of machine
@timer = TMR1L ;alias tmr1 to timer var
clear


'post
FOR ledx= 1 TO 9
CALL LDS ;SHOW LEDx
pause 80
NEXT


IOCAN.4 = 1 ;SET FALLING EDGE DETECTION INT ON TRIGGER PIN
T1CON = $20 ;timer off
T1GCON = $c0 ;timer gate control to count on high gate
state = 1 ;all done lets go


MAIN:
if state != old_state then ;manage state change
if state == 1 then 'reset timer
pir1.0 = 0
TIMER = 0
T1CON.0 = 1
ledx= 9 ;led 9 on
CALL LDS
IOCAF=0
elseif state == 2 then ;evaluate result
if pir1.0 then ;timer overflow
ledx= 4 ;led overflow on
state = 4
elseif timer < 4800 then ;too short
ledx= 8 ;led UNDER on
state = 4
elseif timer > 40200 then ;too long
ledx= 1 ;led OVER on
state = 4
else ;goldilocks
TMP = TIMER / 5000 - 1
IF TIMER // 5000 > 2499 THEN TMP = TMP + 1 ;round up
ledx= 8 - TMP ;led ledx on
state = 3
endif
CALL LDS ;SHOW LEDx
TMP=1500 ;15 sec timeout to show result then reset
endif
old_state = state
endif
select case state ;manage current state
case 1 ;SEEKING A PULSE CAPTURE EVENT
IF IOCAF.4 || pir1.0 THEN ;FALLING EDGE ON TRIGGER PIN DETECTED or overflow
T1CON.0 = 0 ;stop timer no retriggering
LATA = 0 'led9 oFF show pulse captured
state = 2
endif
case 3 ;good result show it
if tmp then ;15 sec timeout then reset
TMP = TMP - 1
else
state = 1 ;then reset
endif
case 4 ;error condition flash ledx
if tmp then ;15 sec timeout countdown then reset
if tmp//50==0 then LATA = 0
if tmp//50==25 then CALL LDS
TMP = TMP - 1
else
state = 1 ;then reset
endif
end select
PAUSE 10 ;set loop to 10 mS
GOTO MAIN

Ioannis
- 19th October 2021, 12:23
A great piece of programming example that shows what a tiny PIC can do!

Thanks Richard for the lessons!

Ioannis

Ioannis
- 19th October 2021, 12:27
And while on Finite State Machine, here is a great tutorial on this subject by Tracey Allen:

http://emesystems.com/OLDSITE/BS2fsm.htm

Ioannis