Continue to Site

# OFF-the-wall idea for momentary ON switch

#### MrDEB

##### Well-Known Member
Looking to build a digital kitchen timer that shuts off after timing out and/or a 10 second delay waiting for user input.
Here is the screenshot of the on/off section of the kitchen timer. Going to use an 18Fxxxx pic
maybe need a diode on the pic output pin to prevent applying voltage to the unpowered pic.
unpowered pic?

thanks will make corrections as noted

It would be so rewarding to just once get the idea that some actual understanding of the words had taken place. Just once the light bulb flashed with an "I get it now" but it's foolish of me to expect that. Sigh.

When you mentioned edge cases in post #93 I thought you were referring to if the time was 12:59 and the minutes button (swt_2) was pressed then it would go to 13:00.

Mike.

That's the kind of thing I meant.

I believe in the code if you add a minute to 12 hours, hours resets to zero. Maybe 12 hours is enough but 12:01 is way closer to 12:00 than to 00:01. I didn't examine it closely, but the logic looked a bit messed up. Perhaps assuming "MINIUTES" meant minutes was a bad assumption on my part.

Maybe it means mini-ute, like this one. You, being from down under, know far more about utes than I do.

Code:
    if SWT_0 = 0 then hours = (Hours + 1) end if    //add 1 hour
if hours > 12 then hours = 0 end if             //12 hour limit
if SWT_1 = 0 then Hours = (hours - 1) end if    //subtract hours
if hours > 12 then hours = 0 end if

if swt_3 = 0 then miniutes = (miniutes + 1) end if
if miniutes >= 60 then hours = hours + 1 miniutes = 0 end if      //add 1 to hours
if swt_4 = 0 then miniutes = (miniutes - 1) end if

if swt_5 = 0 then seconds = (seconds + 1)  end if   //add seconds
if seconds = 60 then miniutes = miniutes + 1  seconds = 0 end if
if swt_6 = 0 then seconds = (seconds - 1) end if   //subtract seconds
' if seconds < 0 then seconds = 0 end if
Strange how the switch numbers go 0,1,3,4,5,6 and I mentioned swt_2 - the missing one. Doh.

Note (you too MrDEB) the middle section and work out what it does at 12:59

MrDEB, it might be a good idea to make a subroutine to add time (seconds,minutes,hours) that does adjustment too.

Mike.
Edit, something like (made up basic),
Code:
Sub addTime(secs as byte,mins as byte, hrs as byte)
seconds=seconds+secs
minutes=minutes+mins
hours=hours+hrs
while(seconds>60)
seconds=seconds-60
minutes=minutes+1
wend
while(minutes>60)
minutes=minutes-60
hours=hours+1
wend
if hours>12 then hours=0
return
end sub
Not sure about the hours bit.
Call by doing addTime(0,1,0) to add 1 minute etc.

Last edited:
Thanks
The switch numbering was corrected in post#100
contemplating SIMPLIFY
instead of 6 buttons to set the time desired, look at using a rotary switch, not a rotary encoder (too confusing for senior citizens IMO,
another option I thought of was adding a repeat time function
if baking cookies, just use repeat instead of having to readjust the timer.
need to search my junk drawer for rotary switches and knobs

You have an LCD for feedback, so you could use a single button to select between hours, minutes, or seconds and then a pair of up/down buttons...

If I am interpreting this right?
one button to cycle through HOURS, MINUTES, SECONDS using LCD for indication
two buttons for +/-
going to try that out using only three buttons to select the time amount, one for start and one for START and one for POWER LATCH ON
5 buttons total

USING TUMBLEWEEDS SUGGESTION IN POST#106 I rewrote the code so I only have 3 pushbuttons for time selection instead of 6. Am sure its not the best but? Now add an interrupt timmer.
Code:
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2024 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 1/12/2024                                                      *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2024 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 1/7/2024                                                       *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}
{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2021 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 8/15/2021                                                      *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}

Device = 18F43K22
Clock = 16
// int osc and IO pin libraries
Include "intosc.bas"

#option DIGITALIO_INIT = true       // automatically call setalldigital
Include "setdigitalio.bas"

#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3
Include "LCD.bas"
Include "convert.bas"
Include "utils.bas"
Include "ISRTimer.bas"
//SWITCHES
Dim swt_0 As PORTB.0
Dim SWT_1 As PORTB.1
Dim SWT_2 As PORTB.2
Dim SWT_3 As PORTB.3
Dim SWT_4 As PORTB.4
Dim SWT_5 As PORTB.5
Dim SWT_6 As PORTB.6
Dim SWT_7 As PORTB.7

//LEDS

Dim led0 As PORTC.0  //HOURS+
Dim led1 As PORTC.1  //HOURS-
Dim led2 As PORTC.2  //MINIUTES+
Dim led3 As PORTC.3  //MINIUTES-
Dim led4 As PORTC.4  //SECONDS+
Dim led5 As PORTC.5  //SECONDS-
Dim led6 As PORTC.6
Dim led7 As PORTC.7

Dim x As Byte
Dim TIME As Byte
Dim ms As Byte
Dim Hours As Byte
Dim Minutes As Byte
Dim seconds As Byte
Dim Press As Byte

Sub OnTimer()
Inc(ms)
End Sub

Sub Debounce ()
DelayMS(300)
End Sub

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Sub Hrs()
Repeat
If SWT_1 = 0 Then Hours = (Hours + 1) Debounce()End If     //add 1 hour
If Hours > 12 Then Hours = 0 End If             //12 hour limit
If SWT_2 = 0 Then Hours = (Hours - 1) Debounce()End If    //subtract hours\
If Hours > 12 Then Hours = 0 End If
//TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
//DISPLAY DESIRED TIME
WriteAt(1,1,"HOURS =  ")
' WriteAt(2,1,"               ")   //redresh display
WriteAt(2,1,DecToStr(Hours))
'WriteAt(2,7,DecToStr( Minutes))
'WriteAt(2,14,DecToStr(seconds))
DelayMS(30)
Until
swt_0 = 0
End Sub      //PRESS = 11
//TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

Sub Min()
Repeat
If SWT_1 = 0 Then  Minutes = ( Minutes + 1) Debounce()End If
If  Minutes >= 60 Then Hours = Hours + 1  Minutes = 0 End If      //add 1 to hours
If SWT_2 = 0 Then  Minutes = ( Minutes - 1) Debounce()End If
//TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
//DISPLAY DESIRED TIME
WriteAt(1,1,"MINIUTES =  ")
' WriteAt(2,1,"               ")   //redresh display
' WriteAt(2,1,DecToStr(Hours))
WriteAt(2,1,DecToStr( Minutes))
' WriteAt(2,14,DecToStr(seconds))
DelayMS(30)
Until
swt_0 = 0
End Sub  //PRESS = 2
//TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

Sub Sec()
Repeat
If SWT_1 = 0 Then seconds = (seconds + 1) Debounce() End If   //add seconds
If seconds >= 60 Then  Minutes =  Minutes + 1 seconds = 0 End If
If SWT_2 = 0 Then seconds = (seconds - 1) Debounce()End If   //subtract seconds
If seconds < 0 Then seconds = 0 End If
//TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
//DISPLAY DESIRED TIME
WriteAt(1,1,"SECONDS  =  ")
' WriteAt(2,1,"               ")   //redresh display
'WriteAt(2,1,DecToStr(Hours))
'WriteAt(2,7,DecToStr( Minutes))
WriteAt(2,1,DecToStr(seconds))
DelayMS(30)
Until swt_0 = 0
End Sub     //PRESS = 3
//TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

// set switch port to inputs and enable pullups
TRISB = $ff // set as inputs WPUB =$ff                // enable pullups on all PORTB pins
INTCON2.bits(7) = 0        // set bit RBPU = 0 turns on pullups
TRISC = 0
TRISA = 0
TRISD = 0

Press = 1
Hours = 0
Minutes = 0
seconds = 0

//set all portc LED off
PORTC = 0
//PRESS INDICATES DESIRED HOURS, MINIUTE, SECONDS SELECTION

While (true)
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//ENTER DESIRED TIME ROUTINE
If Press = 1 Then Hrs()End If      //pRESS TO KEEP TRACK OF MENU SELECTION
Press = Press + 1
If Press = 2 Then Min() End If
Press = Press + 1
If Press = 3 Then Sec() End If
Press = 1
Wend

One important item I forgot. AFTER THE LATCH turns off.
need to detect if ANY input has been entered.

Can I ask if OnTimer is a built in function that gets called from an interrupt every millisecond or does it need to be setup?

Mike.

the interrupt is called after the START button is pressed

Can I ask if OnTimer is a built in function that gets called from an interrupt every millisecond or does it need to be setup?
The file ISRTimer contains a timer-based interrupt that allows you to register callback events, and it needs to be setup to do that. As it is right now, the "Sub OnTimer()" isn't called by anything since the Timer has not been setup or enabled.

the interrupt is called after the START button is pressed
...which must be in code that you haven't shown.

I realize that. I have yet to insert that section of code. My plan is to experiment with timer interrupts etc, first.

The file ISRTimer contains a timer-based interrupt that allows you to register callback events, and it needs to be setup to do that. As it is right now, the "Sub OnTimer()" isn't called by anything since the Timer has not been setup or enabled.
That's why I wondered if it was a built in routine. I was going to suggest reading the keys on interrupt (with repeat and rollover) and placing them in a fifo buffer for use as needed. Sounds like a bad idea now.

Mike.

After considering all the options, I don't think I really need the interrupt.
just a countdown timer and a counter that counts in seconds

After considering all the options, I don't think I really need the interrupt.
just a countdown timer and a counter that counts in seconds
You're keeping track of hours,minutes,secs so I would think you'd want a timer interrupt to keep basic time for you. ISRTimer provides an easy way to do that.

I was going to suggest reading the keys on interrupt (with repeat and rollover) and placing them in a fifo buffer for use as needed. Sounds like a bad idea now.
Maybe not, Mike. The Timer module allows you to create and manage multiple timers and events, so you could easily have a timer to keep track of time and another to handle key presses.

However, in this case it'll likely just confuse things and require an additional 10+ pages of posts

been attempting to display the COUNT DOWN portion of this mess
the sub COUNTDWN is displaying binary (255) instead of actual seconds, minutes.
I slowed the code down = reason for delayms(1500) suggestions?
Code:
Device = 18F43K22
Clock = 16
// int osc and IO pin libraries
Include "intosc.bas"
Include "ISRTimer.bas"

#option DIGITALIO_INIT = true       // automatically call setalldigital
Include "setdigitalio.bas"

#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3
Include "LCD.bas"
Include "convert.bas"
Include "utils.bas"
Include "ISRTimer.bas"
//SWITCHES
Dim Sel As PORTB.0
Dim Plus As PORTB.1
Dim Minus As PORTB.2
Dim SWT_3 As PORTB.3    //start countdown
Dim SWT_4 As PORTB.4
Dim SWT_5 As PORTB.5
Dim SWT_6 As PORTB.6
Dim SWT_7 As PORTB.7

//LEDS

Dim led0 As PORTC.0  //HOURS+
Dim led1 As PORTC.1  //HOURS-
Dim led2 As PORTC.2  //MINIUTES+
Dim led3 As PORTC.3  //MINIUTES-
Dim led4 As PORTC.4  //SECONDS+
Dim led5 As PORTC.5  //SECONDS-
Dim led6 As PORTC.6
Dim led7 As PORTC.7

Dim Desired_Time As Byte
Dim x As Byte
Dim TIME As Byte
Dim ms As Byte
Dim Hours As Byte
Dim Minutes As Byte
Dim seconds As Byte
Dim Press As Byte

Sub Countdwn()
Repeat
WriteAt(1,1,"HRS   MIN   SEC")

If  seconds >= 60 Then minutes = minutes - 1  End If      //subtract 1 minute

WriteAt(2,1,DecToStr(Hours))
minutes = minutes - 1
WriteAt(2,7,DecToStr(Minutes))
seconds = seconds - 1
WriteAt(2,14,DecToStr(seconds))
DelayMS(1500)                 //set this for a 1 second interval
Until
Hours = 0 and
minutes = 0 and
seconds = 0

End Sub

Sub OnTimer()
led2 = 1
DelayMS(500)
led2 = 0
DelayMS(500)
End Sub

Sub Debounce ()
DelayMS(300)
End Sub

// OnTimer event, flash LED...

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Sub Hrs()
Repeat
If Plus = 0 Then Hours = (Hours + 1) Debounce()End If     //add 1 hour
If Hours > 12 Then Hours = 0 End If             //12 hour limit
If Minus = 0 Then Hours = (Hours - 1) Debounce()End If    //subtract hours\
If Hours > 12 Then Hours = 0 End If
' H_rs = (hours * 360000)   //number of MS in 1 hour
//TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
//DISPLAY DESIRED TIME
WriteAt(1,1,"HOURS =  ")
WriteAt(2,1,DecToStr(Hours))
DelayMS(30)
Until
Sel = 0       //select Miniutes desired
End Sub      //PRESS = 11
//TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

Sub Min()
Repeat
If Plus = 0 Then  Minutes = ( Minutes + 1) Debounce()End If
If  Minutes >= 60 Then Hours = Hours + 1  Minutes = 0 End If      //add 1 to hours
If Minus = 0 Then  Minutes = ( Minutes - 1) Debounce()End If
' M_in = (minutes * 60000)
//TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
//DISPLAY DESIRED TIME
WriteAt(1,1,"MINIUTES =  ")
WriteAt(2,1,DecToStr( Minutes))
DelayMS(30)
Until
Sel = 0    //select seconds desired
End Sub  //PRESS = 2
//TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

Sub Sec()
Repeat
If Plus = 0 Then seconds = (seconds + 1) Debounce() End If   //add seconds
If seconds >= 60 Then  Minutes =  Minutes + 1 seconds = 0 End If
If Minus = 0 Then seconds = (seconds - 1) Debounce()End If   //subtract seconds
If seconds < 0 Then seconds = 0 End If
'  S_ec = (seconds * 1000)
//TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
//DISPLAY DESIRED TIME
WriteAt(1,1,"SECONDS  =  ")
WriteAt(2,1,DecToStr(seconds))
DelayMS(30)
Until Sel = 0        // desired time selected
End Sub     //PRESS = 3
//TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

// set switch port to inputs and enable pullups
TRISB = $ff // set as inputs WPUB =$ff                // enable pullups on all PORTB pins
INTCON2.bits(7) = 0        // set bit RBPU = 0 turns on pullups
TRISC = 0
TRISA = 0
TRISD = 0

Press = 1
Hours = 0
Minutes = 0
seconds = 0

//set all portc LED off
PORTC = 0
//PRESS INDICATES DESIRED HOURS, MINIUTE, SECONDS SELECTION

While (true)

I can't solve all your problems, but maybe this will help.

"this mess
the sub COUNTDWN is displaying binary (255) instead of actual seconds, minutes."

1. Could you explain exactly what this means? 255 is not a binary number, so I don't have a clue what you're talking about.

2. Previous versions of the code had the following statements when writing to the display. Unfortunately it's commented out there and removed from the most recent listing, so you don't understand why it's necessary....

Code:
' WriteAt(2,1,"               ")   //redresh display
[Edited to add code tags to preserve formating]

When you write to an LCD display, only the characters you're printing are changed. Anything that was displayed previously longer than the new text is not erased.

So if you write a long line, followed by a short line, you'll have garbage on the screen.

Say you write "ABCDEFGHIJKLMNOP" followed by "123456", the display will show

123456GHIJKLMNOP

because it wasn't cleared out between writes.

By the way, you might want to fix your spelling errors:

WriteAt(1,1,"MINIUTES = ")

3. As has been explained hundreds of times, delay statements are going to cause problems when you're trying to keep track of time.

Last edited:
The code in post 117 won't compile as is, so it's hard to help you fix it.

That is so weird. I edited my post above because "the aystem" deleted all of the blank spaces.

This is what I typed AND what I saw when I clicked edit:

but this is what the finished post displayed:

So apologies to those who saw the "system reformatted" version and thought I was crazy.

To add a little explanation. When writing to an LCD, only the characters specified are changed. So a long message followed by a short message will leave remnants of the first message. By printing a message with the same number of blanks as the number of characters on the display between messages, the line is basically erased.

Code:
WriteAt (1,1, "                ")
'number of spaces equal to the number of characters  on the display, usually 16 or 20

This writes 16 spaces on the top line of the display.

Replies
16
Views
2K
Replies
5
Views
686
Replies
43
Views
5K
Replies
9
Views
4K
Replies
6
Views
2K