Shop OBEX P1 Docs P2 Docs Learn Events
Is there a better way for a countdown timer than this? (code included) — Parallax Forums

Is there a better way for a countdown timer than this? (code included)

mike_smike_s Posts: 42
edited 2006-01-06 01:07 in BASIC Stamp
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!"
·

Comments

  • PJAllenPJAllen Banned Posts: 5,065
    edited 2006-01-02 03:59
    mike_s,

    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) --

    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_smike_s Posts: 42
    edited 2006-01-02 04:34
    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.
  • PJAllenPJAllen Banned Posts: 5,065
    edited 2006-01-02 15:09
    Now he tells me.· lol.gif
  • PJAllenPJAllen Banned Posts: 5,065
    edited 2006-01-02 17:19
    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_smike_s Posts: 42
    edited 2006-01-02 19:25
    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
  • PJAllenPJAllen Banned Posts: 5,065
    edited 2006-01-02 19:47
    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 AllenTracy Allen Posts: 6,658
    edited 2006-01-02 21:04
    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

    Post Edited (Tracy Allen) : 1/2/2006 9:56:49 PM GMT
  • Kaos KiddKaos Kidd Posts: 614
    edited 2006-01-03 17:04
    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
    ·
  • PJAllenPJAllen Banned Posts: 5,065
    edited 2006-01-03 17:26
    I don't think my minutes&seconds program is deficient.· 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 [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.· burger.gif· ]

    ·
  • mike_smike_s Posts: 42
    edited 2006-01-05 09:31
    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_smike_s Posts: 42
    edited 2006-01-05 10:20
    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_smike_s Posts: 42
    edited 2006-01-05 10:25
    sorry about the comment formatting
  • mike_smike_s Posts: 42
    edited 2006-01-05 11:34
    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
  • PJAllenPJAllen Banned Posts: 5,065
    edited 2006-01-05 14:21
    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.)· cool.gif

    Post Edited (PJ Allen) : 1/5/2006 2:31:05 PM GMT
  • mike_smike_s Posts: 42
    edited 2006-01-05 14:57
    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 SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2006-01-05 15:00
    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
  • mike_smike_s Posts: 42
    edited 2006-01-06 01:07
    Points noted. Thanks for the advice.
Sign In or Register to comment.