disco4now Guru Joined: 18/12/2014 Location: AustraliaPosts: 1003
Posted: 02:00pm 27 Jul 2019
Copy link to clipboard
Print this post
Quote '================================================================================================ ' Program Title Block '================================================================================================ ' Name: VaccuFlush VT2500 Monitor ' ' ' Author: Gerry Allardice ' Runtime is 40 seconds when empty ' '================================================================================================ ' Option settings '================================================================================================ option explicit option default NONE OPTION BASE 0 OPTION AUTORUN ON DIM string Prog$( 3 ) length 20 Prog$(0 ) = "VT2500 Monitor" Prog$(1 ) = "v1.0.0" Prog$(2 ) = "14-Jun-2019" '================================================================================================ ' LCD and Touch Initialisation and Test Commands from command prompt '================================================================================================ 'SPI CLK 25 'SPI MOSI 3 'LCD d/C 9 'LCD RST 7 'LCD CS 10 Sub mm.startup 'MX170 on VT2500 board ST7789 9 , 7 , 10 , 2 'DCpin, RESETpin, CSpin, orientation (1-4) End Sub '================================================================================================ ' 47L04/47C04/47L16/47C16 (47XXX) is a 4/16 Kbit SRAM with EEPROM backup '================================================================================================ CONST EERAMcr= &h18 ' address of 47x04/47x16 control register with A0=0 and A1=0 CONST SRAMcb= &h50 ' address of 47x04/47x16 data register forSRAM with A0=0 and A1=0 ' ' these are not I2C device addresses but are sent after the device address CONST COMMANDreg= &h55 ' address of 47x04/47x16 command register CONST STATUSreg= &h00 ' address of 47x04/47x16 status register ' CONST S_store= &h33 ' these are the two command register commands CONST S_recall= &hdd CONST SRAMsize = 512 ' size 2048 for 47x16, use 512 for 47x04 if (readstatus() AND &b10 ) = &b10 then ? "EEPROM OK" else ? "EEPROM Initialised " +setup() ' we only have to do this once for each chip endif ' '? setup() ' we only have to do this once for each chip '? chr$(255),chr$(254) 'z$ = readDATA$(10,8) ' 8 bytes starting at address 10 (any address will do) 'PRINT "Last shutdown occurred at "+readDATA$(0,1) 't$ = TIME$ 'PRINT TIME$ '? writeDATA(0,"A") ' ' '================================================================================================ ' Data Variables '================================================================================================ DIM Integer startup= 0 ,pumpdisable= 1 ,runtime= 2 ,buttonstart= 3 ' flag allocation for timers 0-9+10 DIM Integer buttondown= 11 ,buttonup= 12 ,pumpstatechange= 13 ,buttonafter= 14 ' other flag allocation DIM Integer ON= 1 ,true= 1 ,OFF= 0 ,false= 0 ,r,s DIM INTEGER pumptimemax= 15 ,pumptimeindex= 0 ,thisruntime DIM INTEGER pumptime(pumptimemax) DIm String temp$ dim integer laststate = 1 dim integer buttontimer '================================================================================================ 'Initialisation DOUT to control pump relay '================================================================================================ dim integer PumpPin = 22 ' Pin number for the push button input PIN(PumpPin)=OFF SetPin PumpPin,DOUT '================================================================================================ 'Initialisation of ACS712 current sensor and array for reading/storing pump current '================================================================================================ DIM FLOAT pc( 10 ) DIM INTEGER pumpcurrentindex= 0 dim integer VRefPin= 24 SetPin VRefPin,AIN dim integer ACS712Pin= 26 DIM INTEGER pumpstate= 0 SetPin ACS712Pin,AIN for r= 0 to 9 pc(r)=5.0 next r '================================================================================================ 'Initialisation and Setup of timers 0-9 (SETTICK) AND PumpCurrent monitoring '================================================================================================ 'Option Base 0 Dim Integer TMRctr( 9 ),TMRini( 9 ),Flags= 0 SETTICK 100 ,CoreTMR, 4 ' service timers every 100mS '================================================================================================ 'Initialisation Button and Polling via (SETTICK) '================================================================================================ dim integer SwPin = 21 ' Pin number for the push button input Dim Integer btnUPctr ' counter to hold the shifts dim integer buttonstate= 0 ,buttoncount= 0 SetPin SwPin,DIN,PULLUP SETTICK 20 ,ButtonTest, 3 ' check button status every 20mS '================================================================================================ ' Program Initialisation '================================================================================================ CPU 20 CLS text 20 , 20 ,chr$( 1 ),, 7 After 30 ,startup ' 20*100ms i.e 3 seconds ? pin(ACS712Pin) ? pin(VRefPin) '================================================================================================ ' MAIN LOOP '================================================================================================ 'It is all interupt/timer driven but we need to action any flags that have been 'set here in the main loop so interupts are kept short do If FlagTest(startup) Then ' start delay timer expired FlagRes startup ShowStartScreen temp$=readDATA$( 0 , 17 ) pumptimeindex= ASC (mid$(temp$, 17 , 1 )) for r= 0 to 15 pumptime(r)=ASC (mid$(temp$,r+ 1 , 1 )) '+45*(r+1) next r showgraph pumptimeindex ShowLed( 1 ,RGB(GREEN)) endif If FlagTest(pumpdisable) Then ' FlagRes pumpdisable PumpOff 'disable pump endif 'If FlagTest(pumpenable) Then ' the start pump delay expired ' FlagRes pumpenable ' ShowLed(2,RGB(GREEN)) ' PumpOn 'endif If FlagTest(pumpstatechange) Then ' FlagRes pumpstatechange if pumpstate= 0 then ShowLed(5 ,RGB(RED)) After 50 ,pumpdisable ' 50*100ms i.e 5 seconds thisruntime= 6000 -remain(runtime) thisruntime= max( 3 ,MIN( 4 *thisruntime\ 10 , 160 )) '? thisruntime pumptimeindex=pumptimeindex- 1 if pumptimeindex< 0 then pumptimeindex=pumptimemax pumptime(pumptimeindex)=thisruntime showgraph pumptimeindex r= writeDATA( 16 ,chr$(pumptimeindex)) r= writeDATA(pumptimeindex,chr$(thisruntime)) elseif pumpstate= 1 then ShowLed(5 ,RGB(GREEN)) r= remain(pumpdisable) 'stop timer as pump is running After 6000 ,runtime ' 600*100ms i.e 600 seconds else ShowLed(5 ,RGB(YELLOW)) endif endif If FlagTest(buttondown) Then ' ShowLed( 2 ,RGB(RED)) ShowLed( 3 ,RGB(RED)) if FlagTest(buttonafter)= 0 then After 2 ,buttonstart ' 2*100ms FlagSet buttonafter FlagRes buttonup 'FlagRes buttondown endif If FlagTest(buttonup) Then ' if buttonstate= 0 then 'down 'ShowLed(5,RGB(GREEN)) 'buttoncount=buttoncount+1 'text 200,10,str$(buttoncount) elseif buttonstate= 1 then 'SHORT PRESS ShowLed( 2 ,RGB(GREEN)) ShowLed( 3 ,RGB(YELLOW)) if pumpstate=on then pumpoff else pumpon After 50 ,pumpdisable ' 50*100ms i.e 5 seconds end if '? pin(ACS712Pin) 'buttoncount=buttoncount+1 'text 200,10,str$(buttoncount) '? buttoncount elseif buttonstate= 2 then 'LONG PRESS ShowLed( 2 ,RGB(YELLOW)) ShowLed( 3 ,RGB(GREEN)) if pumpstate=on then pumpoff else pumpon After 50 ,pumpdisable ' 50*100ms i.e 5 seconds end if 'buttoncount=buttoncount+1 'text 200,10,str$(buttoncount) pumptimeindex= 0 r= writeDATA(16 ,chr$( 0 )) for r= 0 to 15 pumptime(r)=0 s= writeDATA(r,chr$(0 )) next r endif 'After 3,buttonstart ' 20*100ms i.e 2 seconds FlagRes buttonup endif If FlagTest(buttonstart) Then FlagRes buttonstart FlagRes buttondown FlagRes buttonafter endif Loop '================================================================================================ ' Procedures providing program functionality components '================================================================================================ SUB ShowStartScreen CLS BOX 0 , 0 ,MM.HRES, MM.VRES,,RGB(GREEN) TEXT 5 , 10 , Prog$( 0 ) TEXT 5 , 30 , "Software " +Prog$( 1 ) TEXT 5 , 50 , "Date " +Prog$( 2 ) ShowLed( 1 ,RGB(YELLOW)) ShowLed( 2 ,RGB(YELLOW)) ShowLed( 3 ,RGB(YELLOW)) ShowLed( 4 ,RGB(YELLOW)) ShowLed( 5 ,RGB(YELLOW)) END SUB sub showgraph(index as integer) local integer i,j,k 'cls box 2 , 25 , 237 , 160 ,,RGB(black),RGB(black) for i= 0 to pumptimemax j=(i+index) MOD 16 'k=4*pumptime(j)\10 k=pumptime(j) 'k=mIN(k,160) box 200 - 12 *i, 185 -k, 6 ,k,,RGB(YELLOW),RGB(YELLOW) next i end sub SUB ShowLed(i as integer, c as integer) CIRCLE 40 *i, 205 , 13 , 1 , 1 ,c,c END SUB Sub PumpOn ShowLed( 4 ,RGB(GREEN)) pin(PumpPin)=ON ' pumpstate=on End Sub Sub PumpOff ShowLed( 4 ,RGB(RED)) pin(PumpPin)=OFF ' pumpstate=OFF End Sub Sub ButtonTest 'STATIC integer laststate =1 'STATIC integer buttontimer local integer buttontemp,b btnUPctr=btnUPctr<< 1 Xor Pin(SwPin) And &h7ff ' sample the input pin and shift the bit into the counter ' If this loop is fast, increase the &h1f so we sample more bits... reduce it if the main loop is slower - tune it for your purposes ' If we shift enough zeroes in, the button has been pressed. ' Any bounce (back to 1) will shift a one in and "spoil" our counter for which will start again. 'If FlagTest(buttonchange)=0 Then Select Case btnUPctr Case 0 'button down If FlagTest(buttondown)= 0 Then buttonstate= 0 if laststate<>buttonstate then FlagSet(buttondown) laststate=buttonstate buttontimer= timer endif endif 'After 2,buttonstart ' 20*100ms i.e 2 seconds Case &h7ff 'button up b = TIMER - buttontimer ' this is how long the button was down IF b < 1500 THEN ' short press buttontemp= 1 else buttontemp=2 endif if laststate= 0 then FlagSet(buttonup) buttonstate=buttontemp laststate=buttonstate endif 'After 2,buttonstart ' 20*100ms i.e 2 seconds Case Else 'neither up nor down 'buttonstate=2 End Select ' endif End sub ' '================================================================================================ ' Timer functions '================================================================================================ 'Usage: ' After 10,1 ' 10 seconds using timer 1 ' Every 1 ,2 ' count 1 second intervals using timer 2 ' Every 2 ,3 ' count 2 second intervals using timer 3 'Variable Descriptions: 'TMRctr() maintains the count for a given timer 'TMRini()holds the timer type and its initialization value. '- bits 0-61 store the initial value value '- bits 63&62 store the format of the counter: '0=disabled '1=(actually 0x4000000000000000) indicates a one shot "AFTER x" type counter '2=(actually 0x8000000000000000) indicates a repetitive "EVERY x" type counter SUB CoreTMR ' needs to run on a ticker at whatever interval is required - this is also the multiple of timer counts If FlagTest( 10 ) Then Exit Sub Local Integer n,f,v For n= 0 To 9 f=TMRini(n) And &hC000000000000000 ' extract the top 2 bits Select Case f Case 0 , &hC000000000000000 'disabled or invalid FlagRes(n) Case &h4000000000000000 ' AFTER If TMRctr(n)> 0 then TMRctr(n)=TMRctr(n)-1 If TMRctr(n)= 0 Then FlagSet(n) ' indicate the timer has expired EndIf Case &h8000000000000000 ' EVERY If TMRctr(n)> 0 then TMRctr(n)=TMRctr(n)-1 If TMRctr(n)= 0 Then FlagSet(n) ' indicate the timer has expired TMRctr(n)=TMRini(n) And &h3FFFFFFFFFFFFFFF ' reset the timer EndIf EndIf End Select Next STATIC Integer lastpumpstate=off pc(pumpcurrentindex)=pin(ACS712Pin) pumpcurrentindex=pumpcurrentindex+1 : if pumpcurrentindex= 10 then pumpcurrentindex= 0 if MIN(pc( 0 ),pc( 1 ),pc( 2 ),pc( 3 ),pc( 4 ),pc( 5 ),pc( 6 ),pc( 7 ),pc( 8 ),pc( 9 ))< 2.40 then 'if pin(ACS712Pin)<2.45 then pumpstate=on if pumpstate<>lastpumpstate then FlagSet(pumpstatechange) lastpumpstate=pumpstate else pumpstate=off if pumpstate<>lastpumpstate then FlagSet(pumpstatechange) lastpumpstate=pumpstate endif END SUB Sub After(Interval As Integer,Tmr As Integer) ' starts a one-shot timer TMRini(Tmr)=Interval OR &h4000000000000000 :TMRctr(Tmr)=Interval And &h3FFFFFFFFFFFFFFF :FlagRes(Tmr) End Sub Sub Every(Interval As Integer,Tmr As Integer) ' starts a repetitive timer TMRini(Tmr)=Interval OR &h8000000000000000 :TMRctr(Tmr)=Interval And &h3FFFFFFFFFFFFFFF :FlagRes(Tmr) End Sub Sub At(dt$,Tmr As Integer) ' trigger at a specific date/time - assumes the core timer is running in seconds 'dt$ must be a datetime formatted as dd/mm/yyyy hh:mm:ss Local Integer x x= UnixTime (Now())- UnixTime (dt$) If x< 2 then FlagSet Tmr' if he difference is less than 2 seconds, trigger the alarm immediately Else After x,Tmr' otherwise set a one-shot for the difference EndIf End Sub Function Remain(Tmr As Integer) As Integer ' stops a timer and returns the remaining whole counts in the counter TMRini(Tmr)=TMRini(Tmr) And &h3FFFFFFFFFFFFFFF Remain=TMRctr(Tmr) End Function Sub DI FlagSet 10 End Sub Sub EI FlagRes 10 End Sub '================================================================================================ ' Bit manipulation functions '================================================================================================ 'Set a bit SUB FlagSet(bit AS INTEGER) FLAGS=FLAGS OR ( 2 ^bit) END SUB 'Clear a bit SUB FlagRes(bit AS INTEGER) FLAGS=(FLAGS OR ( 2 ^bit)) XOR ( 2 ^bit) END SUB 'Set bit equal to value passed SUB FlagEq(bit As Integer,v as integer) IF v= 0 THEN FlagRes(bit) ELSE FlagSet(bit) ENDIF END SUB 'Test if bit is set FUNCTION FlagTest(bit AS INTEGER) AS INTEGER FlagTest= ABS ( SGN (FLAGS AND ( 2 ^bit))) END FUNCTION '================================================================================================ ' 47L04/47C04/47L16/47C16 (47XXX) is a 4/16 Kbit SRAM with EEPROM backup '================================================================================================ FUNCTION setup() as string local integer x,r r = readstatus() ' get the current status register x = x OR &b10 ' set bit 2 leaving the rest alone PRINT BIN$(x, 8 ) r= writeCMD(STATUSreg,x) ' set autostore r = readstatus() PRINT BIN$(r, 8 ) END FUNCTION FUNCTION writeDATA(addr as integer,D$ as string) as integer ' write string D$ to EERAM starting at addr LOCAL integer L addr = addr MOD SRAMsize ' keep address within chip capacity d$ = CHR$(addr\ 256 )+CHR$(addr MOD 256 )+D$ L = LEN (D$) ON ERROR SKIP 1 I2C OPEN 400 , 1000 I2C WRITE SRAMcb, 0 ,L,D$ I2C CLOSE END FUNCTION FUNCTION readDATA$(addr as integer,L as integer) as string ' read string from EERAM starting at addr, L bytes LOCAL string D$ addr = addr MOD SRAMsize ' keep address within chip capacity ON ERROR SKIP 1 I2C OPEN 400 , 1000 I2C WRITE SRAMcb, 1 , 2 ,addr\ 256 ,addr MOD 256 'Reset memory pointer to addr I2C READ SRAMcb, 0 ,L,D$ readDATA$ = D$ END FUNCTION FUNCTION writeCMD(reg as integer,EERAMcmd as integer) as integer 'write command to the command or status register ON ERROR SKIP 1 I2C OPEN 400 , 1000 I2C WRITE EERAMcr, 0 , 2 ,reg,EERAMcmd I2C CLOSE END FUNCTION FUNCTION readSTATUS() as integer 'read status register LOCAL integer status ON ERROR SKIP 1 I2C OPEN 400 , 1000 'I2C WRITE EERAMcr,1,2,STATUSreg,0 I2C READ EERAMcr, 0 , 1 ,status I2C CLOSE readSTATUS = status END FUNCTION '================================================================================================ ' Library code '================================================================================================ Latest F4 Latest H7 FotS