PDA

View Full Version : Is there a better way for a countdown timer than this? (code included)



mike_s
01-02-2006, 09:16 AM
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 (mailto:ms767210@bigpond.net.au)
' {$PBASIC 2.5}
' {$STAMP BS2}
' -----[ 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
' -----[ 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
' -----[ 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!"
·

PJ Allen
01-02-2006, 10:59 AM
mike_s,

Here is how I would do the COUNTDOWN part.

How about a VAR named SEC [however that gets entered is fine] and a count-down sub-routine called CNTDWN.· Let's say that someone enters 990 (990 seconds) --



SEC = 990

CNTDWN:
PAUSE 1000 'timing 1 second
SEC = SEC - 1 'subtracts ea. pass till SEC = 0
IF SEC = 0 THEN GOTO DONE 'end of time, RAUS
GOTO CNTDWN 'if it gets here then do more time/re-cycle

DONE:
(turn off the microwave)

mike_s
01-02-2006, 11:34 AM
Yes thanks. However I wish to display it as normal time instead of 100's of 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.

PJ Allen
01-02-2006, 10:09 PM
Now he tells me.· http://forums.parallax.com/images/smilies/lol.gif

PJ Allen
01-03-2006, 12:19 AM
How about this --

MM VAR Byte ' minutes
SS VAR Byte ' seconds

DWNMIN:
IF SS > 0 THEN DWNSEC
IF MM = 0 AND SS = 0 THEN DONE
MM = MM - 1
SS = 59
GOSUB DWNSEC
GOTO DWNMIN

DWNSEC:
IF SS = 0 THEN DWNMIN
PAUSE 1000
SS = SS - 1
GOTO DWNSEC

DONE:
' turn off microwave

Post Edited (PJ Allen) : 1/2/2006 5:28:37 PM GMT

mike_s
01-03-2006, 02:25 AM
I'll try it thanks but I think a few more lines will be needed for the LCD to interprete seconds as tens of seconds and minutes as tens of minutes as well?
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

PJ Allen
01-03-2006, 02:47 AM
mike_s,

· 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".)

Tracy Allen
01-03-2006, 04:04 AM
I'd agree with PJ's first suggestion, to implement the count down simply in seconds. Then, convert those seconds2go to standard minutes:seconds on the fly using tricky time math shown below in the display subroutine...


seconds2go VAR Word
seconds2go = 990
DO
seconds2go=seconds2go-1
GOSUB display
PAUSE 980
LOOP WHILE seconds2go
END

display:
' convert to hours:minutes:seconds
hours = seconds2go/3600 ...
minutes = seconds2go//3600/60 ' 3600 seconds per hour, 60 per minute
seconds = seconds2go//3600//60 ' remainder
DEBUG DEC2 hours, ":", DEC2 minutes, ":" , DEC2 seconds ' debug display
' convert to LCD nibs...
tens_minutes = minutes/10 ' for LCD 10s digit minutes
ones_minutes = minutes//10 " for LCD 1s minutes
tens_seconds = seconds/10 ' for LCD 10s seconds
ones_seconds = seconds//10 ' for LCD 1s seconds
' ... LCD display ...
RETURN




When you have to read in mm:ss data from your keypad, a simple formula wil convert the entries to seconds2go:


seconds2go = tens_minutes * 10 + ones minutes * 6 + tens_seconds * 10 + ones_seconds ' computes strictly left to right

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com (http://www.emesystems.com)

Post Edited (Tracy Allen) : 1/2/2006 9:56:49 PM GMT

Kaos Kidd
01-04-2006, 12:04 AM
With all the programming I do, as well as my nominal day to day work, I would agree with Tract Allen (was that Dr Allen?)...
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
·

PJ Allen
01-04-2006, 12:26 AM
I don't think my minutes&seconds program is deficient.· http://forums.parallax.com/images/smilies/cool.gif

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 [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.··[ If mike_s had used a serial LCD, then I would've taken care of all that, too.· http://forums.parallax.com/images/smilies/burger.gif· ]

·

mike_s
01-05-2006, 04:31 PM
Ok haven't had a chance to look at Tracy's code but I used your bit of code and integrated it. I can set the time but the start button doesn't function quite yet.
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

mike_s
01-05-2006, 05:20 PM
Ok start button works again with Pj's code migrated.
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

mike_s
01-05-2006, 05:25 PM
sorry about the comment formatting

mike_s
01-05-2006, 06:34 PM
Wish I'd spotted this bug befor I posted. The time misses a second on reaching zero. I mean the counter would go from say 1:01 to 0:59 missing 1:00
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

PJ Allen
01-05-2006, 09:21 PM
Glad it's taking shape.

mike_s said...
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.

Oh, I see.
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.)· http://forums.parallax.com/images/smilies/cool.gif

Post Edited (PJ Allen) : 1/5/2006 2:31:05 PM GMT

mike_s
01-05-2006, 09:57 PM
That isn't such a silly question. The turntable will turn in either direction. When I say that it doesn't go in one direction and then reverse but each time the turntable is stopped and started it has the possibility of turnng one way or the other.
But I know what you mean. It isn't affected by what hemisphere you live in like the old plughole in the sink.
: )

Chris Savage
01-05-2006, 10:00 PM
mike_s said...
sorry about the comment formatting
Mike,

·· 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 (mailto:csavage@parallax.com)

mike_s
01-06-2006, 08:07 AM
Points noted. Thanks for the advice.