Previous Topic

Next Topic

Book Contents

Book Index

Program code

This product is not currently available for general sale

The program code is reproduced below. You should master the Multitasking tutorial before attempting to understand this code!

;mdrv2.spt   Example motor drive program using SPice10213
;This program is written for an MMi99/200 with LCD, but can easily
;be ported to an MS12

;The program uses front panel push button inputs as follows:

;    Input  Function
;       12      + speed
;       11      - speed
;       10      Stop/Start
;        9      Forward/Reverse
;        8      Not used

;The program consists of 3 tasks:

;SPD    (Speed) Simply monitors the + and - buttons and generates a target speed value
;DRV    (Drive) Ramps the motor speed (PWM) towards the target speed
;MSQ    (Motor sequencer) Master sequencer for stop/start, forward/reverse. Uses DRV
;                       for actual PWM generation.

;The 3 tasks are written as independent tasks witin a multitasking structure.
;You need to understand the material in the multitasking tutorial to make sense of this

;=============== Constants ====================
SPD_Increment   EQU             10      ;Inc/Dec speed by this amount for each button push
StopTime        EQU             10      ; x 10mS. Time allowed for motor to stop with dynamic braking

;============== I/O allocations ==============
;Alter for MS12
;----------- Inputs ----------------
iSPeedUp        iEQU            12
iSpeedDn        iEQU            11
iStopStart      iEQU            10
iFwdRev         iEQU            9

;----------- Outputs ---------------
oDirection      oEQU            16

;========= RAM ==============
;-------- Semaphores (1-bit variables) in 1st 8 bytes ---------------
Direction       sEQU            0
DRV_Accelerate  sEQU            1
Tick10          sEQU            2
MSQ_DirFWD      sEQU            3
MSQ_RevFlag     sEQU            4       

;-------- Other RAM ------------
MSQ_Addr        mEQU            20      ;2 bytes. Suspend address for MSQ
SPD_Target      mEQU            22      ;Target PWM
DRV_Addr        mEQU            23      ;2 bytes. Suspend address for DRV
DRV_PWM         mEQU            25      ;Current PWM value 
SPD_Count       mEQU            26
MSQ_Count       mEQU            27
MSQ_State       mEQU            28

;-------------------------------------------------------------

Start:
                setu            0,1             ;set spice connector pin 4 as DO
                setu            3,1             ;set spice connector pin 7 as DO        
                setu            4,4             ;set spice connector pin 8 as PWM output
                setu            5,4             ;set spice connector pin 9 as PWM output
                SpiceConfigU

                GoSub           SPD_Init        ;Initialize tasks
                GoSub           DRV_Init
                GoSub           MSQ_Init

MainLoop:
                GetTick10                       ;Generate 10mS heartbeat
                StoreS          Tick10
                GoSub           SPD_UpDate      ;Run task
                GoSub           DRV_UpDate      ;Run task
                GoSub           MSQ_UpDate      ;Run task

;Debug: Display the MSQ state number
                OBLCD_SetCur    1,13
                OBLCD_UDecDispMFW       MSQ_State

                GoTo            MainLoop

;====================================================================
;----------- Motor sequencer ---------------------

;Short name     MSQ

;Entry points
;               MSQ_Init        Initialize
;               MSQ_Update      Update


MSQ_UpDate:
                Resume          MSQ_Addr

MSQ_Init:

;State 0 is the idle state.
MSQ_Set0:
                SetMem          MSQ_State,0             ;For debugging monitor
MSQ_0:
                Suspend         MSQ_Addr
                GoIfInK         iStopStart,MSQ_Set1     ;Test stop/start button
                GoSub           MSQ_ReadFR              ;Test and process F/R
                GoTo            MSQ_0

;In state 1 we set the relay for the correct direction, then wait for it to settle
;prior to starting up the PWM drive
MSQ_Set1:
                SetMem          MSQ_State,1             ;For debugging monitor
                RecallS         MSQ_RevFlag             ;Set direction relay ...
                Output          oDirection              ;... according to direction flag

;Here we mark off two timer ticks to ensure at least a 10mS pause while the relay settles.
MSQ_1:
                Suspend         MSQ_Addr
                GoIfSF          Tick10,GenRet           ;Sync to timer tick
                Suspend         MSQ_Addr
                GoIfInK         iStopStart,MSQ_Set0     ;Test stop/start button
                GoIfSF          Tick10,GenRet           ;Wait for next tick

;State 2 is the run state. the DRV task may well be accelerating, but that does
;not concern us one way or the other here.
MSQ_Set2:
                SetMem          MSQ_State,2             ;For debugging monitor
                GoSub           DRV_Run                 ;Start ramping up speed
MSQ_2:
                Suspend         MSQ_Addr
                GoIfInK         iStopStart,MSQ_Set3     ;Test stop/start button
                GoSub           MSQ_ReadFR              ;Test and process F/R
                GoIfF           MSQ_2                   ;G/ not pressed

;State 6 is decellerating prior to reversing direction.
MSQ_Set6:
                SetMem          MSQ_State,6             ;For debugging monitor
                GoSub           DRV_Stop                ;Commence stop process
MSQ_6:
                Suspend         MSQ_Addr
                GoIfInK         iStopStart,MSQ_Set8     ;Test stop/start button
                GoSub           DRV_Get_ZPWM            ;Test if PWM is zero
                GoIfT           MSQ_Set7
                GoSub           MSQ_ReadFR              ;Test and process F/R
                GoIfF           MSQ_6                   ;G/ not pressed
                GoTo            MSQ_Set2
        
;State 3 is decellerating prior to stopping     
MSQ_Set3:
                SetMem          MSQ_State,3             ;For debugging monitor
                GoSub           DRV_Stop
MSQ_3:
                Suspend         MSQ_Addr
                GoIfInK         iStopStart,MSQ_Set2     ;Test stop/start button
                GoSub           DRV_Get_ZPWM
                GoIfT           MSQ_Set4
                GoSub           MSQ_ReadFR              ;Test and process F/R
                GoIfF           MSQ_3                   ;G/ not pressed

;State 5 is if F/R is pushed while decellerating for a stop
MSQ_Set5:
                SetMem          MSQ_State,5             ;For debugging monitor
MSQ_5:
                Suspend         MSQ_Addr
                GoIfInK         iStopStart,MSQ_6        ;Test stop/start button
                GoSub           DRV_Get_ZPWM
                GoIfT           MSQ_Set4
                GoSub           MSQ_ReadFR              ;Test and process F/R
                GoIfF           MSQ_5                   ;G/ not pressed
                GoTo            MSQ_3

;State 8 is if Stop/start is hit while decelleration prior to reversing
MSQ_Set8:
                SetMem          MSQ_State,8             ;For debugging monitor
MSQ_8:
                Suspend         MSQ_Addr
                GoIfInK         iStopStart,MSQ_6        ;Test stop/start button
                GoSub           DRV_Get_ZPWM
                GoIfT           MSQ_Set4
                GoTo            MSQ_8           

;State 4 is timing the dynamic braking interval after a stop.
MSQ_Set4:
                SetMem          MSQ_State,4             ;For debugging monitor
                InputO          oDirection              ;Read back direction relay
                NOT
                Output          oDirection
                SetMem          MSQ_Count,StopTime
MSQ_4:
                Suspend         MSQ_Addr
                GoSub           MSQ_ReadFR              
                GoIfSF          Tick10,MSQ_4
                DMGNZ           MSQ_Count,MSQ_4
                GoTo            MSQ_Set0

;State 7 is timing the dynamic braking interval foir stopping during reversal
MSQ_Set7:
                SetMem          MSQ_State,7             ;For debugging monitor
                RecallS         MSQ_RevFlag
                Output          oDirection
                SetMem          MSQ_Count,StopTime
MSQ_7:
                Suspend         MSQ_Addr
                GoSub           MSQ_ReadFR              
                GoIfSF          Tick10,MSQ_7
                DMGNZ           MSQ_Count,MSQ_7
                GoTo            MSQ_Set2

;----- Read and process F/R button. Return True if pressed      
MSQ_ReadFR:
                InputK          iFwdRev
                Push
                RetIfF
                RecallS         MSQ_RevFlag
                NOT
                StoreS          MSQ_RevFlag
                Return

;----------- Drive Task --------------------------
;This task is responsible for ramping the PWM up and down to the target speed
;(when enabled). In essence it simply makes the actual PWM track the target PWM,
;with ramping. There is a coding option for sudden stop or smooth stop.

;Short name     DRV

;Uses lcd 1,0 through 1,3

;Entry points

;               DRV_Init        Initialize
;               DRV_Update      Update. 
;               DRV_Run         Start ramping up. Simply updates DRV_Accelerate semaphore
;               DRV_Stop        Start ramping down. Simply updates DRV_Accelerate semaphore
;               DRV_Get_ZPWM    Return true if PWM=0

DRV_Get_ZPWM:
                Recall          DRV_PWM
                Push
                OR
                NOT
                Return

DRV_Update:
                Resume          DRV_Addr

DRV_Init:
DRV_Set0:
                SetMem          DRV_PWM,0
                GoSub           DRV_PWMOut
DRV_0:
                Suspend         DRV_Addr
                GoIfST          DRV_Accelerate,DRV_Set1 ;Test for RUN command
                GoTo            DRV_0

DRV_Set1:               ;Here on RUN command
                Suspend         DRV_Addr

;Which of the following 2 code lines determines whether the controller
;executes sudden stops, with dynamic braking, or smooth stop (ramping down the speed)
;Comment out the line you don't want.

;This line for sudden stop:
                GoIfSF          DRV_Accelerate,DRV_Set0 ;Test for STOP command
;This line for smooth stop:
                GoIfSF          DRV_Accelerate,DRV_Set2 ;Test for STOP command


                GoIfSF          Tick10,DRV_Set1         ;wait for time tick
                GoSub           SPD_GetSpeed            ;Target PWM
                Recall          DRV_PWM                 ;Actual PWM
                CompareR                                ;Compare Target to actual
                BranchR                                 ;Test result
                Target          DRV_Set1                ;On target
                Target          DRV_1_Dec               ;PWM too high
                Target          DRV_1_Inc               ;PWM too low

DRV_1_Dec:              ;Here to decrement PWM
                DecM            DRV_PWM
                GoSub           DRV_PWMOut
                GoTo            DRV_Set1

DRV_1_Inc:              ;Here to increment PWM
                IncM            DRV_PWM                 ;
                GoSub           DRV_PWMOut
                GoTo            DRV_Set1

DRV_Set2:               ;Here on stop command
                Suspend         DRV_Addr
                GoIfST          DRV_Accelerate,DRV_Set1 ;Test for RUN command
                GoIfSF          Tick10,DRV_Set2         ;wait for time tick
                GoIfMZ          DRV_PWM,DRV_Set0
                DecM            DRV_PWM
                GoSub           DRV_PWMOut
                GoTo            DRV_Set2


DRV_Run:
                SetS            DRV_Accelerate
                Return

DRV_Stop:
                ClrS            DRV_Accelerate
                Return

DRV_PWMOut:             ;Output the PWM
                Recall          DRV_PWM
                AnOutJ                          ;Alter for MS12
                OBLCD_SetCur    1,0
                OBLCD_UDecDispMFW       DRV_PWM
                Return
                

;----------- Speed task ---------------------------
;This task maintains the target speed.
;Short name     SPD

;Uses lcd 0,0 through 0,3

;Entry points

;               SPD_Init        Initialize
;               SPD_UpDate      Service push buttons, update target accordingly
;               SPD_Get_Speed   return current target speed in X

SPD_Init:
                Return

SPD_GetSpeed:
                Recall          SPD_Target
                Return

SPD_UpDate:
                GoIfInK         iSpeedUp,SPD_Up
                GoIfInK         iSpeedDn,SPD_Dn
GenRet: Return

SPD_Dn:
                SetMem          SPD_Count,SPD_Increment
SPD_DnA:
                GoIfMZ          SPD_Target,SPD_Show
                DecM            SPD_Target
                DMGNZ           SPD_Count,SPD_DnA
                

SPD_Show:
                OBLCD_SetCur    0,0
                OBLCD_UDecDispMFW       SPD_Target
                Return

SPD_Up:
                SetMem          SPD_Count,SPD_Increment
SPD_UpA:
                GoIfMEQ         SPD_Target,255,SPD_Show
                IncM            SPD_Target
                DMGNZ           SPD_Count,SPD_UpA
                GoTo            SPD_Show

Previous Topic

Next Topic