;POND tap controller software ; ;Overview of operation: ; ;There are two switches - a tap fully closed switch called ZeroSW which pulls to ground when ;the tap is fully closed; And a pond water level switch which pulls to ground when the water ;is high (called PondSw) ; ;The Syetem has 5 tap states 1 = slow movement, 2 = fast travel to a target position, 3 = Zero the ;tap position by running tap to closed until zero switch comes on (low) 4 = Shutdown - pump has failed to operate, ;5 = wait - wait until pump has come back online (manual rectification of any problem and manully starting pump) ; ; ;On Powerup the System "waits" (not a MCU wait state) until the AC power has been ok for 10 seconds ;Then it "Zero's" the tap - closes the tap until the ZeroSw comes on (Low) and resets the tap position ;counter to zero. It sets the initial tap target to 1/3 on, and sets the travel mode to "fast". ;In normal operation when there has been a pond switch change, more than a minute since the last ;pond switch change - then a new target is calulated: ;NewTarget = (Tap position when switch went ON + Tap pos when OFF)/4 + Old Target/2 + Offshoot ;Overshoot = (New Target - Current Position of Tap)/4 to provide critical response ; ; ;The tap then travels to this new target "fast" 50pps. Once reached is goes Slow 12.5/speed pps ;It maintains this speed for "SettleTime" minutes after the pond switch change, and then ;accelerates every ReAccTim mins after that. On each pond switch change the tap is slowed ;to 3/4 its current value. Thus the slow movement speed adjusts until the pond switch changes ;on average every TapSettle minutes. If is starts(stops) raining, the tap will come on and stay on ;and so after TapSettle minutes the speed will increase markedly, increaseing the responsiveness ;to the rain. ; Include derivative-specific definitions INCLUDE 'derivative.inc' XREF MCU_init ; export symbols XDEF _Startup, main ; we export both '_Startup' and 'main' as symbols. Either can ; be referenced in the linker .prm file or from C/C++ later on XDEF Port, TapUpDwn, Mode, MShutOff, TapTarget, MeanPos, MShutOff,bMWait,PmpTmr XREF __SEG_END_SSTACK ; symbol defined by the linker for the end of the stack ; variable/data section MY_ZEROPAGE: SECTION SHORT TapTarget: DS.W 1 ; The target position for the tap MeanPos: DS.W 1 ; Mean position of tap MeanTravel: DS.B 3 ; Mean travel of tap (Hich byte, low byte, remainder byte)- third byte is remainder Scratch: DS.B 3 ; gereal purpose scratch pad TapPos: DS.W 1 ; The actual position of the tap PosOn: DS.W 1 ; Tap position when the pond switch last went "on" PosOff: DS.W 1 ; Tap position when the pond switch last went "off" Mode: DS.B 1 ; tap travel Mode 0 = slow, 1 = fast, 2 = zero, 4 = wait Second: DS.B 1 ; Counter for 1 second (50 * 20ms) Minute: DS.B 1 ; Minute counter (60 secs) PondSwitch: DS.B 1 ; pond switch state last time measured SettleTime: DS.B 1 ; Time (minutes) before tap movement comeneces after new target Speed: DS.B 1 ; Speed of tap = 25/speed = pps SpeedCount: DS.B 1 ; loop counter for speed PmpTmr: DS.B 1 ; Time since pump run ; code section MyCode: SECTION TapMax: EQU 18000 ; Maximum tap position ( 18000 steps) TapSettle: EQU 15 ; tap to stay at target for TapSettle minutes after switch change Port: EQU PTAD ; Port A inputs PondSw: EQU PTAD_PTAD2 ; Bit 3 = pond water level switch mPondSw: EQU mPTAD_PTAD2 ZeroSw: EQU PTAD_PTAD5 ; Bit 2 = Tap zero position switch mZeroSw: EQU mPTAD_PTAD5 StpPulse: EQU PTAD_PTAD1 ; Bit 1 = Tap stepper pulse mStpPulse: EQU mPTAD_PTAD1 TapUpDwn: EQU PTAD_PTAD0 ; Bit 0 = stepper direction 1 = close tap mTapUpDwn: EQU mPTAD_PTAD0 MSlow: EQU %00000001 ; Tap action mode assignments - slow adjustments MFast: EQU %00000010 ; Fast travel after switch change to new target MZero: EQU %00000100 ; zero the tap stepper (tap off) MShutOff: EQU %00001000 ; stop - pump fail, so turn tap off under battery MWait: EQU %00010000 ; wait for pump to resume bMSlow: EQU 0 bMFast: EQU 1 ; bit positions bMZero: EQU 2 bMShutOff: EQU 3 bMWait: EQU 4 ACVolt: EQU $43 ; ADC channel 3, enable interupt, compare main: _Startup: LDHX #__SEG_END_SSTACK ; initialize the stack pointer TXS CLR IRQSC JSR MCU_init ; Call generated Device Initialization function LDHX #TapMax ; assume tap is fully open STHX TapPos LDHX #0000 STHX TapTarget MOV #5,Speed ; Initial Speed = 12.5/5 pps MOV Speed,SpeedCount MOV #3,Second ; 50 * 20ms = 1 Second, but do initial second stuff now LDA PTAD ; record initial pond swaitch state AND #mPondSw STA PondSwitch LDHX #9200 ; Initial position of tap when pond switch STHX PosOff ; turns off set to 9200 decimal LDHX #10200 STHX PosOn ; and on position at 10,200 LDHX #9700 STHX MeanPos ; sets initial tap at 1/2 on LDHX #2000 ; start with large travel STHX MeanTravel MOV #60,Minute ; 60 secs = 1 Minute MOV #1,SettleTime ; Stop acceleration for 60 Minutes MOV #MZero,Mode ; inital mode = zero tap CLI MainLoop: STA SRS ; feed the watchdog Timer: BRCLR TPMSC_TOF,TPMSC,Timer ; wait for 20ms BCLR TPMSC_TOF,TPMSC ; reset counter STA SRS ; feed the watchdog BRCLR bMFast,Mode,ChkTgtSkip ; If mode is fast JSR TgtCheck ; check if target has been reached ChkTgtSkip: BRSET bMSlow,Mode,NoStep ; Only output 50pps if tap mode is BRSET bMWait,Mode,NoStep ; fast, zeroing or shutting down JSR Step ; Output a step evey 20ms (50pps) NoStep: DEC Second BNE SlowStep ; 1 second counter MOV #50,Second ; reset - 50 * 20ms = 1 sec JSR OneSec ; go and do one second stuff SlowStep: LDA Second AND #03 ; on every 4 * 20ms (12.5pps) BNE MainLoop DEC SpeedCount ; modulo for speed BNE MainLoop ; If 12.5/speed reached then MOV Speed,SpeedCount ; reset Speed counter AND BRSET bMZero,Mode,MainLoop ; Only if mode is slow or fast BRSET bMShutOff,Mode,MainLoop ; Then BRSET bMWait,Mode,MainLoop JSR Slow ; if slow output a pulse JSR PSwitch ; update pond switch state BRA MainLoop ;**** Subroutines *****) ;* Target Check, checks to see if the target position has been reached ;* if so set tap move mode to slow TgtCheck: BRSET TapUpDwn,Port,DrnDown ; Direction of tap travel? LDHX TapPos ; Up then check for pos > target CPHX TapTarget BGE TargetHit RTS DrnDown: LDHX TapTarget ; Down the check for pos < Target CPHX TapPos BGE TargetHit RTS TargetHit: MOV #MSlow,Mode ; yes then set mode to slow movement RTS ;******END***** ; ;One Second - increments miunte counter, if in wait or fast mode checks Pump frequency, ; if in wait mode check if Pump Ok then change to zero tap mode ; If in zero tap mode check if the tap has reched limit (zero - switch PA1) ; If it has reached closed limit then zero position counter, set targets to ; old targets, set mode to fast ; If in stop mode, if tap has reached closed limit then mode to wait OneSec: DEC Minute ; Is it one minute BNE SecStuff ; no - the go do second stuff only MOV #60,Minute ; yes then reset minute counter and TST SettleTime BEQ SecStuff DEC SettleTime SecStuff: MOV #ACVolt,ADCSC1 ; start conversion of incoming voltage ch3 JSR ZeroMode ; or in Zero mode JSR ShutoffM ; or in stop mode RTS ;******END***** ; ; Zero tap - tap is closed until a switch on PA1 indicates fully closed position ; once there position set to zero, target is set to old target, tap move mode set fast ; ZeroMode BRCLR bMZero,Mode,RTNZ ; if mode is not zero then return BRCLR ZeroSw,Port,AtZero ; If zero switch is on then at zero LDHX TapPos CPHX #-2000 ;makes sure not too far negative (switch fail?) BLT AtZero ; 3000 = 60 seconds @ 50pps BSET TapUpDwn,Port ; make sure we are closing tap RTS ; return AtZero: MOV #MFast,Mode ; Tap is at zero so set tap to fast move BCLR TapUpDwn,Port ; direction = open tap LDHX MeanPos ; set target to old target(which is initalised at STHX TapTarget ; reset, but CPU may not be here from complete power fail) LDHX #0000 STHX TapPos ; reset tap position LDA Port AND #mPondSw STA PondSwitch ; record the current state of the pond level switch MOV #5,Speed ; set slow speed to 12.5/5 = 2.5 step per sec MOV #1,SettleTime ; no accel after new target for 1 mins MOV #90,PmpTmr ; don't check pump for first x minutes RTNZ RTS ;*****END****** ; ;Stop - shut down the system - pump fail ; ShutoffM: BRCLR bMShutOff,Mode,RTNS ; If mode is not stop then return LDHX #0000 STHX TapTarget ; Set Target to Zero BRCLR ZeroSw,Port,ZeroOn ; At zero - go change mode LDHX TapPos CPHX #-2000 ;makes sure not too far negative (switch fail?) BLT AtZero BSET TapUpDwn,Port ; set travel direction close RTS ZeroOn MOV #MWait,Mode ; at fully closed - set mode to wait LDHX #0000 STHX TapPos ; reset position RTNS RTS ;*****END**** ; ;Slow Check tap is within limits, if so output a pulse ; Slow: BRCLR bMSlow,Mode,RTNSLW ; If Mode is not slow then return TST SettleTime BNE RTNSLW BRSET TapUpDwn,Port,Close ; Direction of travel? LDHX #TapMax CPHX TapPos ; Open then if Position > Max BLT RTNSLW JSR Step RTS Close: LDHX TapPos ; Close then if position < 0100 CPHX #0100 ; dont output a step BLT RTNSLW SOut: JSR Step RTNSLW: RTS ;*****END******* ; ;PondSwitch Check for a change of pond water level switch ; PSwitch: LDA Port ;read inputs and mask out Pond switch AND #mPondSw CMP PondSwitch ;see if its changed from last time BEQ RTNSW STA PondSwitch ; yes - then update new state LDA #TapSettle CMP SettleTime BEQ NoNewTgt ; no new target if within 1 minute of last change JSR NewTgt ; otherwise set new target NoNewTgt: MOV #MFast,Mode ; Set tap to move fast (50 pps) MOV #60,Minute ; reset the minute counter MOV #TapSettle,SettleTime ; time before tap starts moving again BRSET PondSw,PondSwitch,SwOff ; So what is the current state of the switch? BSET TapUpDwn,Port ; Switch on, water high, close tap RTS SwOff: BCLR TapUpDwn,Port ; Switch off, water low, open tap up RTNSW: RTS ;*****END******* ; ;Step outputs a step pulse ; Step: BSET StpPulse,Port ; Step Pulse On BRSET TapUpDwn,Port,DWN ; Direction of travel? INC TapPos+1 BNE Delay ; Up then increment position INC TapPos BRA Delay DWN: TST TapPos+1 BNE NZL ; down then decrement position DEC TapPos NZL: DEC TapPos+1 Delay: LDA #255 DelLoop: DECA ; delay 8 cycles @.25uS * 255 = 510us NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP BNE DelLoop BCLR StpPulse,Port ; Step pulser off RTS ;******END****** ; ;New Target = (Last position when switch went on + Last Position when gone off)/4 + OldTarget/2 ; Old Target provides a time decaying smoothing. Critical overshoot is also added ; to improove response. Works well except in very stormy conditions. ; Overshoot = 1/4 difference between current pos & target ; NewTgt: LDHX TapPos BRCLR PondSw,PondSwitch,SwitchOn ; Is Pond Switch off/on (pulls to ground if on = water level high) STHX PosOff ; Off - store tap position in PosOff LDHX MeanTravel ;Tap target = Mean position + 3*Mean Travel/8 STHX Scratch LSR Scratch ROR Scratch+1 LDA MeanTravel+1 ADD Scratch+1 ;for 3/8 de-comment STA Scratch+1 LDA MeanTravel ADC Scratch STA Scratch LSR Scratch ROR Scratch+1 LSR Scratch ROR Scratch+1 LDA MeanPos+1 ADD Scratch+1 STA TapTarget+1 LDA MeanPos ADC Scratch STA TapTarget LDHX #TapMax CPHX TapTarget BGT NT0 STHX TapTarget NT0: JMP SetSpeed SwitchOn: STHX PosOn ; On so store Tap position on PosOn LDA PosOn+1 ;Mean Travel of valve averaged decay half life of about 11 updates SUB PosOff+1 STA Scratch+1 ;MeanTvl = MeanTrvl + ((PosON - PosOff) - MeanTrv)/16 LDA PosOn SBC PosOff ; STA Scratch CLR Scratch+2 LDA Scratch+2 SUB MeanTravel+2 STA Scratch+2 LDA Scratch+1 ;posOn-PosLo SBC MeanTravel+1 STA Scratch+1 LDA Scratch ; - Mean SBC MeanTravel STA Scratch ASR Scratch ROR Scratch+1 ;may be negative ROR Scratch+2 ASR Scratch ROR Scratch+1 ROR Scratch+2 ASR Scratch ROR Scratch+1 ROR Scratch+2 ASR Scratch ROR Scratch+1 ROR Scratch+2 LDA Scratch+2 ADD MeanTravel+2 ;+ mean one byte higher STA MeanTravel+2 LDA Scratch+1 ADC MeanTravel+1 STA MeanTravel+1 LDA Scratch ADC MeanTravel STA MeanTravel LDHX MeanPos STHX Scratch ;mean position = mean position + (((PosOn + Pos Off)/2) - mean pos)/4 LSR MeanPos ROR MeanPos+1 LSR MeanPos ROR MeanPos+1 LDA Scratch+1 SUB MeanPos+1 STA MeanPos+1 LDA Scratch SBC MeanPos STA MeanPos LDHX PosOn STHX Scratch LDA PosOff+1 ADD Scratch+1 STA Scratch+1 LDA PosOff ADC Scratch STA Scratch ROR Scratch ;ROR in case carry set from add ROR Scratch+1 LSR Scratch ROR Scratch+1 LSR Scratch ROR Scratch+1 LDA MeanPos+1 ADD Scratch+1 STA MeanPos+1 LDA MeanPos ADC Scratch STA MeanPos LDHX MeanTravel ;Tap target = Mean position - 3*Mean Travel/8 STHX Scratch LSR Scratch ROR Scratch+1 LDA MeanTravel+1 ADD Scratch+1 ;for 3/8 de-comment STA Scratch+1 LDA MeanTravel ADC Scratch STA Scratch ;scratch = 1.5 * meantravel LSR Scratch ROR Scratch+1 LSR Scratch ROR Scratch+1 LDA MeanPos+1 SUB Scratch+1 STA TapTarget+1 LDA MeanPos SBC Scratch STA TapTarget BPL SetSpeed CLR TapTarget CLR TapTarget+1 SetSpeed: LDHX #0088 ;12.5/speed(pps) * 60 * 15 = 1/2 mean travel; So 22,500/meantrvl = speed TXA ;= 88/meantravel(high byte) LDX MeanTravel BNE NT4 INCX NT4: DIV STA Speed BNE NEWRTN ;so max speed = 12.5 steps per sec; min speed = 7 secs per step INC Speed NEWRTN RTS ;****END*****