Is there a better way for a countdown timer than this? (code included)
mike_s
Posts: 42
Hi,
I'm just a poor electrician struggling with the programming side of the stamp.
I have been attempting first to get an LCD running which worked finally for me but only in 8 bit mode.
The end purpose will be to replace my microwaves mechanical timer with a digital control. While you can pick up something like this for as little as
80 dollars Australian because I work in the appliance field this interests me as a starting point.
Having mastered the operation of the Hitachi style 2x16 display The next phase is the countdown timer.
I have achieved that I believe after much head banging but was wondering if my code is ok or if there is a better way to tackle it.
Keep·in mind that the time will be set by keypad when completed. I have the keypad just about ready(But for plugs on the end of the wires)
For testing purposes the countdown time is entered by the program.
If this code is ok will I be able to successfully add another block of code for the keypad to enter the time?
I·was going to add a time of day clock but changed my mind because I wouldn't know how to integrate a 555 timer with the stamp or if this would even work.
' =========================================================================
' File...... Countdown timer.BS2
' Purpose... Countdown timer for Parallel LCD Display
' Author.... Mike Seiler
' E-mail.... ms767210@bigpond.net.au
' {$PBASIC 2.5}
' {$STAMP BS2}
'
[noparse][[/noparse] I/O Definitions ]
··· E CON 6 ' Enable Pin For LCD
··· RW CON 5 ' R/W Pin For LCD
··· RS CON 4 ' LCD Register Select· 0 = Instruction, 1 = Text
'
[noparse][[/noparse] Variables ]
··· char VAR Byte········ ' Character To Send To LCD
··· index VAR Nib
··· tens_minutes VAR Nib
··· minutes VAR Nib
··· tens_seconds VAR Nib
··· seconds VAR Nib
··· tens_minutes = 0····· 'Preset time
··· minutes = 1·········· 'within program
··· tens_seconds = 0····· 'temporary till keypad
··· seconds = 0·········· 'and code is added
'
[noparse][[/noparse] Constants ]
··· Clr_Display CON %00000001···· ' Clear the display
··· Rtrn_Home CON %00000010······ 'Return Home without clearing display
··· EntryMode_Set CON %00000100·· 'Still don't understand this function?
··· Display_Off CON %00001000···· ' Turn display off
··· Display_On CON %00001100····· ' Turn display on
··· Modeset CON %00111000········ ' Set 8 bit mode 2 lines and 5x7 characters
' Initialise I/O
··· DIRB = %1110················· 'set pins 4,5 and 6 as outputs
··· OUTB = %0000················· 'clear them
··· DIRH = %11111111············· 'set pins 8-15 as outputs(unfortunately I had no success in running it in 4 bit mode
··· OUTH = %00000000············· 'but will have to complete this task yet to free up needed pins
main:
··· PAUSE 200············ 'delay till power reaches desired level ON powerup
··· char = Modeset······· 'I think there is enough info about on this sequence
··· GOSUB lcdcmd
··· char = Display_Off
··· GOSUB LCDcmd
··· char = Display_On
··· GOSUB LCDcmd
··· char = Clr_Display
··· GOSUB LCDcmd
··· char = EntryMode_Set
··· GOSUB LCDcmd
··· GOSUB Update_display
··· tens_seconds = 6
Countdown:
· FOR seconds = 9 TO 0···· 'Main loop consists of many conditionals essential to maintaining proper time display
· IF seconds = 9 THEN tens_seconds = tens_seconds - 1
· IF seconds = 9 AND tens_seconds = 15 THEN minutes = minutes - 1
· IF seconds = 9 AND tens_seconds = 5 THEN minutes = minutes - 1
· IF seconds = 9 AND tens_seconds = 5 AND minutes = 9 AND tens_minutes <>0 THEN tens_minutes = tens_minutes - 1
· IF seconds = 9 AND tens_seconds = 15 AND minutes = 15 AND tens_minutes <> 0 THEN tens_minutes = tens_minutes - 1
· IF tens_seconds = 15 THEN tens_seconds = 5
· IF minutes = 15 THEN minutes = 9
· PAUSE 990
· GOSUB Update_display
· IF tens_minutes = 0 AND minutes = 0 AND tens_seconds = 0 AND seconds = 0 THEN finished
· NEXT
· IF seconds = 15 THEN Countdown
LCDcmd:
··· OUTH = char············ 'Send an instruction to LCD
··· LOW RS
··· PULSOUT E, 1
··· RETURN
LCDwr:
··· OUTH = char············ 'Send data to LCD
··· HIGH RS
··· PULSOUT E, 1
··· RETURN
Update_display:
·· char = Rtrn_Home························· 'Return Home and rewrite
·· GOSUB LCDcmd
·· char = tens_minutes + 48················· 'value 48 is added to display correct numeric character as part of time remaining display
·· GOSUB LCDwr
·· char = minutes + 48······················ 'character
·· GOSUB LCDwr
·· char = 58································ ': character of the time remaining display
·· GOSUB LCDwr
·· char = tens_seconds + 48················· 'etc..
·· GOSUB LCDwr
·· char = seconds + 48
·· GOSUB LCDwr
·· RETURN
·· Finished:
DEBUG "DONE!"
·
I'm just a poor electrician struggling with the programming side of the stamp.
I have been attempting first to get an LCD running which worked finally for me but only in 8 bit mode.
The end purpose will be to replace my microwaves mechanical timer with a digital control. While you can pick up something like this for as little as
80 dollars Australian because I work in the appliance field this interests me as a starting point.
Having mastered the operation of the Hitachi style 2x16 display The next phase is the countdown timer.
I have achieved that I believe after much head banging but was wondering if my code is ok or if there is a better way to tackle it.
Keep·in mind that the time will be set by keypad when completed. I have the keypad just about ready(But for plugs on the end of the wires)
For testing purposes the countdown time is entered by the program.
If this code is ok will I be able to successfully add another block of code for the keypad to enter the time?
I·was going to add a time of day clock but changed my mind because I wouldn't know how to integrate a 555 timer with the stamp or if this would even work.
' =========================================================================
' File...... Countdown timer.BS2
' Purpose... Countdown timer for Parallel LCD Display
' Author.... Mike Seiler
' E-mail.... ms767210@bigpond.net.au
' {$PBASIC 2.5}
' {$STAMP BS2}
'
[noparse][[/noparse] I/O Definitions ]
··· E CON 6 ' Enable Pin For LCD
··· RW CON 5 ' R/W Pin For LCD
··· RS CON 4 ' LCD Register Select· 0 = Instruction, 1 = Text
'
[noparse][[/noparse] Variables ]
··· char VAR Byte········ ' Character To Send To LCD
··· index VAR Nib
··· tens_minutes VAR Nib
··· minutes VAR Nib
··· tens_seconds VAR Nib
··· seconds VAR Nib
··· tens_minutes = 0····· 'Preset time
··· minutes = 1·········· 'within program
··· tens_seconds = 0····· 'temporary till keypad
··· seconds = 0·········· 'and code is added
'
[noparse][[/noparse] Constants ]
··· Clr_Display CON %00000001···· ' Clear the display
··· Rtrn_Home CON %00000010······ 'Return Home without clearing display
··· EntryMode_Set CON %00000100·· 'Still don't understand this function?
··· Display_Off CON %00001000···· ' Turn display off
··· Display_On CON %00001100····· ' Turn display on
··· Modeset CON %00111000········ ' Set 8 bit mode 2 lines and 5x7 characters
' Initialise I/O
··· DIRB = %1110················· 'set pins 4,5 and 6 as outputs
··· OUTB = %0000················· 'clear them
··· DIRH = %11111111············· 'set pins 8-15 as outputs(unfortunately I had no success in running it in 4 bit mode
··· OUTH = %00000000············· 'but will have to complete this task yet to free up needed pins
main:
··· PAUSE 200············ 'delay till power reaches desired level ON powerup
··· char = Modeset······· 'I think there is enough info about on this sequence
··· GOSUB lcdcmd
··· char = Display_Off
··· GOSUB LCDcmd
··· char = Display_On
··· GOSUB LCDcmd
··· char = Clr_Display
··· GOSUB LCDcmd
··· char = EntryMode_Set
··· GOSUB LCDcmd
··· GOSUB Update_display
··· tens_seconds = 6
Countdown:
· FOR seconds = 9 TO 0···· 'Main loop consists of many conditionals essential to maintaining proper time display
· IF seconds = 9 THEN tens_seconds = tens_seconds - 1
· IF seconds = 9 AND tens_seconds = 15 THEN minutes = minutes - 1
· IF seconds = 9 AND tens_seconds = 5 THEN minutes = minutes - 1
· IF seconds = 9 AND tens_seconds = 5 AND minutes = 9 AND tens_minutes <>0 THEN tens_minutes = tens_minutes - 1
· IF seconds = 9 AND tens_seconds = 15 AND minutes = 15 AND tens_minutes <> 0 THEN tens_minutes = tens_minutes - 1
· IF tens_seconds = 15 THEN tens_seconds = 5
· IF minutes = 15 THEN minutes = 9
· PAUSE 990
· GOSUB Update_display
· IF tens_minutes = 0 AND minutes = 0 AND tens_seconds = 0 AND seconds = 0 THEN finished
· NEXT
· IF seconds = 15 THEN Countdown
LCDcmd:
··· OUTH = char············ 'Send an instruction to LCD
··· LOW RS
··· PULSOUT E, 1
··· RETURN
LCDwr:
··· OUTH = char············ 'Send data to LCD
··· HIGH RS
··· PULSOUT E, 1
··· RETURN
Update_display:
·· char = Rtrn_Home························· 'Return Home and rewrite
·· GOSUB LCDcmd
·· char = tens_minutes + 48················· 'value 48 is added to display correct numeric character as part of time remaining display
·· GOSUB LCDwr
·· char = minutes + 48······················ 'character
·· GOSUB LCDwr
·· char = 58································ ': character of the time remaining display
·· GOSUB LCDwr
·· char = tens_seconds + 48················· 'etc..
·· GOSUB LCDwr
·· char = seconds + 48
·· GOSUB LCDwr
·· RETURN
·· Finished:
DEBUG "DONE!"
·
Comments
Here is how I would do the COUNTDOWN part.
How about a VAR named SEC [noparse][[/noparse]however that gets entered is fine] and a count-down sub-routine called CNTDWN.· Let's say that someone enters 990 (990 seconds) --
This is how the time is displayed at present:
01:00 is one minute countdown. I can enter in the code up to 59:59 and it will countdown as a normal stopwatch or countdown timer would.
This is the method used on all microwaves sold that I've seen.
Post Edited (PJ Allen) : 1/2/2006 5:28:37 PM GMT
Although now I'm thinking I can probably write minutes first as a 2 digit value and then seconds as a 2 digit value instead of breaking it up into four separate digits as I have in my code. It certainly looks easier to follow than all those conditional statements I used.
I like the look of what you've offered and I will work with it.
Unfortunately I'm back to work this morning so it'll have to wait till I get home.
Much appreciated.
All the best to you PJ
· Happy to collaborate.
· I didn't re-write your whole program, just the Count-down.· Adding the display of Minutes and Seconds should be "academic."
· I haven't seen a microwave that gets set to tenths of seconds (1/10 sec), that would look like a blur on an LCD (or·like a ghost·"8".)
· I used PAUSE 1000 and that number might have to be tweaked a little, because the time that it takes to update the LCD·(and other stuff) will add up.· If you set it to time 59 minutes, it'll probably take a little more than that (1msec here and there X 3600 = "inaccuracy".)
When you have to read in mm:ss data from your keypad, a simple formula wil convert the entries to seconds2go:
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
Post Edited (Tracy Allen) : 1/2/2006 9:56:49 PM GMT
Use a simplifed var within the program, preventing conversion as the program works...
Convert only as needed (ie for display or on input)...
Any conversion errors are limited and not propagated (spelling...) throughout the lifespan of the running program.
..Ok, .02 cents worth...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Until our bytes cross again, may your chips never smoke, your bits never fall off, your parts bin never be empty and your jumpers never fall off.
KK
·
It's pretty easy to buy into, by just looking it over.· It clears out the initial seconds entered, then it converts each remaining minute to seconds and counts them out.·
The only improvements would be those which would result in quicker execution (owing to fewer operations) or programming space [noparse][[/noparse]which Tracy Allen's might -- I haven't compared them by RUNning them.]
I don't like writing LCD instructions (can anything in·life get more tedious?), I always·use serial LCDs (PICanLCD, LCDBug): some things are better left to hardware.··[noparse][[/noparse] If mike_s had used a serial LCD, then I would've taken care of all that, too.· · ]
·
I know I'll find why. Just haven't had a lot of time now I'm back at work. Unfortunately work comes home with me as well : (
I should point out that tens_seconds in my code is not tenths of seconds but tens of seconds which is conventional time setting on microwaves.
Thanks for the help will let you know when I have the task completed by posting in the projects forum.
Mike
Here is how I made it fit. I'm reasonably happy with it much neater than before.
And the proof is there of an improvement from 27% memory used to 19% heaps left to play with : )
Here it is. I left out the declarations and display init routines.
Btn_loop:
BUTTON 1, 0, 255, 0, btnMin, 1, Mins
BUTTON 0, 0, 255, 0, btnSec, 1, Secs
BUTTON 3, 0, 255, 0, btnMin, 1, Dwnmin
PAUSE 200
GOTO Btn_loop
Mins:
mm = mm + 1
IF mm = 60 THEN mm = 0
GOSUB Update_display
GOTO Btn_loop
Secs:
ss = ss + 10
IF ss = 60 THEN ss = 0
GOSUB Update_display
GOTO Btn_loop
Dwnmin:
IF ss > 0 THEN DwnSec
IF mm = 0 AND ss = 0 THEN Finished
mm = mm - 1
ss = 59
GOSUB Update_display
GOTO Dwnmin
dwnsec:
IF ss = 0 THEN dwnmin
PAUSE 999
ss = ss - 1
GOSUB Update_display
GOTO Dwnmin
LCDcmd:
OUTH = char 'Send an instruction to LCD
LOW RS
PULSOUT E, 1
RETURN
LCDwr:
OUTH = char 'Send data to LCD
HIGH RS
PULSOUT E, 1
RETURN
Update_display:
tens_minutes = (mm / 10)
minutes = (mm // 10)
tens_seconds = (ss / 10)
seconds = (ss // 10)
char = Rtrn_Home 'Return Home and rewrite
GOSUB LCDcmd
char = tens_minutes + 48 'value 48 is added to display correct numeric character as part of time remaining display
GOSUB LCDwr
char = minutes + 48 'character
GOSUB LCDwr
char = 58 ': character of the time remaining display
GOSUB LCDwr
char = tens_seconds + 48 'etc..
GOSUB LCDwr
char = seconds + 48
GOSUB LCDwr
RETURN
Finished:
PAUSE 2000
char = 1
GOSUB LCDcmd
FOR index = 0 TO 11
READ msg + index, char
GOSUB LCDwr
NEXT
END
here is the fix
Dwnmin:
IF ss > 0 THEN DwnSec
IF mm = 0 AND ss = 0 THEN Finished
mm = mm - 1
ss = 60 'changed from 59 to 60 here and deleted a call to the update display routine
GOTO Dwnmin
dwnsec:
IF ss = 0 THEN dwnmin
PAUSE 999
ss = ss - 1
GOSUB Update_display
GOTO Dwnsec 'changed branch to dwnsec although it probably just changes the program cycle without affecting the counter
My microwave has 3 buttons for entering time with: a 5-minutes button, a 1-minute button, and a 15-seconds button (you get multiples of each with each press.)
See, I didn't read your original post super-critically, because I thought that I'd read "Austrian", but·you wrote·"Australian."
So, that prompts a question: Which way does the carousel in your microwave turn (clockwise or counter-clockwise)?
Like you, I figure -- "why buy something when you can make it for so much more?"· Because you learn something when you make something (priceless.)·
Post Edited (PJ Allen) : 1/5/2006 2:31:05 PM GMT
But I know what you mean. It isn't affected by what hemisphere you live in like the old plughole in the sink.
: )
·· If you use the "insert formatted code" button (The pound sign) the alignment of your code should stay intact.· Also when posting full programs attaching is always preferred over pasting the whole thing into a message, especially when you're constantly changing the code.· For one it's neater in the messages, and two it allows those of us who always have our Stamp Editor handy to open the message right into the editor and have syntax checking/highlighting and the ability to easily test the code.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chris Savage
Parallax Tech Support
csavage@parallax.com