Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 12:52 07 Jul 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Sample Code switch timer

Author Message
atmega8

Guru

Joined: 19/11/2013
Location: Germany
Posts: 724
Posted: 10:54am 09 Oct 2014
Copy link to clipboard 
Print this post

Hi mmbasic Fan's,

i would like to program a timer that can do some(3-5) switch cycles per day.
It should be based on the internal time$ variable.
Has someone please a code sample or a conceptual approach for this?

I am a little bit stuck in my ideas;-(((

THX,

Dietmar
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 02:25pm 09 Oct 2014
Copy link to clipboard 
Print this post

You may be able to get some ideas from this.

Time$ & Date$ have previously been set daily via a battery backed DS1307 real time clock chip using Jman's I2C code and there's a little Nokia 5110 LCD displaying time (updated each second) and status of the door. Also Time$ & Date$ are automatically reset if it powers down or there's a reset.

Greg

TimeOpen$ = "07:00:00" 'Door open & close times
TimeClose$ = "22:00:00"
.
.
SETTICK 1000,Time_Update,1 'Update LCD time display each second
SUB Time_Update
PosX=36: PosY=1: LCD_GotoXY
Text$ = TIME$
Lookup
LCD_StringOut
END SUB

'Main loop - Servo time checking

TIMER = Secs_from_Midnight(TIME$)*1000 'Sync TIMER & real time
AMopen = Secs_from_Midnight(TimeOpen$) *1000
PMclose = Secs_from_Midnight(TimeClose$) *1000

red = 9: green = 10 'LED pins: red=closed, green=open
SETPIN red,DOUT: SETPIN green,DOUT
PIN(red) =1: PIN(green) =1 'Turn both LEDs ON
Status$ = ""
SETTICK 5000,Check_Time,2 'Check door posn every five secs
SETTICK 2000,Flash_LED,3 'Flash LEDs every two secs

DO 'programs loops in here waiting for timer interrupts
LOOP

SUB Flash_LED
IF Status$ = "IN ONLY" THEN PIN(red)=1: PIN(green)=0
IF Status$ = "OPEN" THEN PIN(red)=0: PIN(green)=1
PAUSE 100: PIN(red)=0: PIN(green)=0 'Flash LED for 0.1 secs
END SUB

SUB Check_Time
Ti = TIMER 'Ti - variable to minimise TIMER calls
IF Ti => 86400000 THEN TIMER = 1 'Reset TIMER at midnight
IF Ti < AMopen THEN
SERVO 2,50,2.1
Status$ = "IN ONLY" 'IN ONLY = closed
ELSEIF Ti => AMopen AND Ti < PMclose THEN
SERVO 2,50,1.4
Status$ = "OPEN"
ELSEIF Ti => PMclose THEN
SERVO 2,50,2.1
Status$ = "IN ONLY"
ENDIF

PosX=0: PosY=5: LCD_GotoXY 'display the door status
Text$ = "----"+ Status$ +"----"
Lookup
LCD_Stringout

END SUB

FUNCTION Secs_from_Midnight(convert$)
conv1 = VAL(MID$(convert$,1,2)) *3600
conv2 = VAL(MID$(convert$,4,2)) *60
conv3 = VAL(MID$(convert$,7,2))
Secs_from_Midnight = conv1 + conv2 + conv3
END FUNCTION

'------------------------------------------
 
viscomjim
Guru

Joined: 08/01/2014
Location: United States
Posts: 925
Posted: 02:42pm 09 Oct 2014
Copy link to clipboard 
Print this post

Hi Atmega8,

Here is a quick and dirty little program I use for the break and lunch time alert at my office / shop. No display as it sits in a closet, but you could easily add one. There are two relays that just pulse a buzzer in one of two locations... The shop and the office. The if time$ then statements are the times when I want them to buzz. Notice the subs use over 1 second delays therefore by the time it returns the time has changed. Like I said, quick and dirty, and has been working for a long long time. I am using the cheapo DS3231 I2C RTC to keep time and the uMite time is updated every hours. Recovers well after power failure. Hope this helps....

OPTION AUTORUN ON
SetPin 3, DOUT 'relay 1
SetPin 5, DOUT 'rekay 2
SETPIN 16, OOUT 'heartbeat led - just to show life
Pin(3)=0
Pin(5)=0
PIN(16)=0
DIM RTCBUFF(7)
SETMCLOCK


SETTICK 3600000,SETMCLOCK,1 'update uMite clock every hour
SETTICK 250, HEARTBEAT,3

Do
IF TIME$ = "08:45:00" THEN SHOP 'pulse shop buzzer relay
IF TIME$ = "09:00:00" THEN SHOP
IF TIME$ = "12:30:00" THEN SHOP
IF TIME$ = "13:00:00" THEN SHOP
IF TIME$ = "14:00:00" THEN SHOP
IF TIME$ = "14:15:00" THEN SHOP
If Time$ = "08:15:00" THEN OFFICE 'pulse office buzzer relay
LOOP

SUB HEARTBEAT
PULSE 16, 125
END SUB


'**********************************************
SUB OFFICE
PULSE 5, 250
PAUSE 1050
END SUB


'**********************************************
SUB SHOP
PULSE 3, 250
PAUSE 1050
END SUB


'**********************************************
SUB SETMCLOCK
I2caddr = &h68 ' DS3231 I2C address
I2C open 100,100 ' Enable I2C
I2C write I2caddr, 0, 1, 0
I2C Read i2caddr, 0, 7, RTCbuff(0) ' Read Time
I2C Close

BCDTEMP = RTCBuff(0)
BCDtoDec BCDTEMP
SEC$ = Str$(decimal)

BCDTEMP = RTCBuff(1)
BCDtoDec BCDTEMP
MIN$ = Str$(decimal)

BCDTEMP = RTCBuff(2)
BCDtoDec BCDTEMP
HOURS$ = Str$(decimal)

BCDTEMP = RTCBuff(3)
BCDtoDec BCDTEMP
DAYOFWEEK = decimal

BCDTEMP = RTCBuff(4)
BCDtoDec BCDTEMP
DAY$ = Str$(decimal)

bcdtemp = rtcbuff(5)
BCDtoDec BCDTEMP
MONTH$ = Str$(decimal)

bcdtemp = rtcbuff(6)
BCDtoDec BCDTEMP
YEAR$ = Str$(decimal + 2000 )

T$ = HOURS$+":"+MIN$+":"+SEC$
D$ = DAY$+"/"+MONTH$+"/"+YEAR$
Time$ = T$
Date$ = D$
END SUB


'**********************************************
Sub BCDtoDec (BCDTEMP)
Decimal = Fix(BCDTemp / 16) * 10
Decimal = Decimal + (BCDTEMP And &hF)
End Sub


'**********************************************
SUB SETDS3231
' SET DS3231
' MMBasic Time$ and Date$ must be set first!!!!!!!!

' get seconds
X = VAL(RIGHT$(TIME$, 2))
SECONDS = (X\10)*16 + X mod 10

' get minutes
X = VAL(MID$(TIME$, 4, 2))
MINUTES = (X\10)*16 + X mod 10

' get hours
X = VAL(LEFT$(TIME$, 2))
HOURS = (X\10)*16 + X mod 10

' get day of month
DD = VAL(LEFT$(DATE$, 2))
DOM = (DD\10)*16 + DD mod 10

' get month
MM = VAL(MID$(DATE$, 4, 2))
MONTH = (MM\10)*16 + MM mod 10

' get year
YY = VAL(RIGHT$(DATE$, 2))
YEAR = (YY\10)*16 + YY mod 10

' get day of the week
YYYY = VAL(RIGHT$(DATE$, 4))
A = (14-MM)\12
M = MM + 12*A - 2
Y = YYYY - A
DOW = (DD + Y + Y\4 - Y\100 + Y\400 + 31*M\12) mod 7 + 1

I2C open 100,100
I2C write &H68, 0, 8, 0,SECONDS,MINUTES,HOURS,DOW,DOM,MONTH,YEAR
If MM.I2C <> 0 then
print "I2C error = "; MM.I2C
end
Endif
I2C close
END SUB
Edited by viscomjim 2014-10-11
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 03:16pm 09 Oct 2014
Copy link to clipboard 
Print this post

Hi Jim,
I've always assumed a PAUSE would halt SETTICK interrupts, but that can't be so if your code is working OK. Also have you ever noticed whether any of the set-points are missed, given that each is only valid for a second?

Greg
 
viscomjim
Guru

Joined: 08/01/2014
Location: United States
Posts: 925
Posted: 03:37pm 09 Oct 2014
Copy link to clipboard 
Print this post

Hi Paceman, so far this hasn't missed a beat for a long time. In the manual it says... "This process will run independently of the main program which could be doing something completely unrelated". I basically just made the assumption that the pause was "unrelated". I hope I didn't miss something here, but the unit does work every day. Maybe I just got lucky....

Edit...

Now you got me curious. I will try and time how many times that do loop actually checks the time$ every second. I just assumed it would be quite a few times and that I wouldn't miss anything. Again, Lucky???? Next time I guess I could use a flag to see if the sub was called instead of wasting 1050ms. Kind of sloppy code, but it serves it purpose considering I had a very short period of time to make this.Edited by viscomjim 2014-10-11
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 05:57pm 09 Oct 2014
Copy link to clipboard 
Print this post

Well looks like I might have been unnecessarily complicating a few things if a PAUSE doesn't stop SETTICK interrupts, but then at what point is the program "re-PAUSED". Does it just execute the target interrupt routine and "re-PAUSE" when it returns via the IRETURN or when? What happens if another SETTICK command is within the first interrupt routine (probably pretty poor practice but...) What happens if another interrupt occurs during this same period? Hmmm....

If you see any lost alarms when you have a look at your code try assigning the first TIME$ call to a variable and then use that for the rest of the IF's to see if it makes a difference.

GregEdited by paceman 2014-10-11
 
atmega8

Guru

Joined: 19/11/2013
Location: Germany
Posts: 724
Posted: 08:45pm 09 Oct 2014
Copy link to clipboard 
Print this post

Hello,

thank you very much, for your fast response and help with your sample code.
As we can see, this is not as trivial as one can think .
Beside the question, if settick will be stoped by a pause or interrupts, i see another problem.

Lets assume, we switch on a light at 8:00 and turn it off at 11:00.
If we have a powerdown, reset or similar between this switchpoints, then we will will not get the correct state of the light ( depending on the signal logic / portstate).

So we have to check for the state within an intervall of switchpoint, like " if time $ > 8:00 and < 11:00 then light on".
It will get more complicated if we implement a dynamic number of switchpoints..

But this can not be done with the string variable time$, so we have to convert it to a number, which should be easy when we convert it to minutes from midnight........

Hope we will get a code that will be able to avoid all this problems.
Maybe we can expand the code library with a sample programm for a switchtimer.
THX


 
atmega8

Guru

Joined: 19/11/2013
Location: Germany
Posts: 724
Posted: 08:57pm 09 Oct 2014
Copy link to clipboard 
Print this post

Aha...

I see that pacemans code will do all the things i mentioned above.
He converts to milliseconds since midnight and he decides based on intervall between switchpoints and not only on one point of time.

Cool pacemann, this will help.

THX, pacemann and visconjim !
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3282
Posted: 10:47pm 09 Oct 2014
Copy link to clipboard 
Print this post

Just to clarify, interrupts will continue to occur even inside a pause. Other delays associated with hardware (such as DS18B20()) do block interrupts.

A subtle distinction.

Geoff
Geoff Graham - http://geoffg.net
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 10:58pm 09 Oct 2014
Copy link to clipboard 
Print this post

Hi Geoff,
How 'far' do they execute? Do they effectively 'turn off' a PAUSE that's been turned 'on' in the main program or do they only execute to the end of the interrupt routine?

Greg
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3282
Posted: 03:51am 11 Oct 2014
Copy link to clipboard 
Print this post

Wow, that question reads like a foreign language and don't understand any of it.

The pause command constantly checks for an interrupt condition and if one has occurred it will execute the interrupt routine. On return from the interrupt the pause commend will continue with the pause but any time spent in the interrupt routine will be subtracted from the pause time so that the pause would be the same with or without the interrupt.

You can also use pause in an interrupt routine although that cannot be interrupted because you are already in an interrupt.

Did that answer the question?

Geoff
Geoff Graham - http://geoffg.net
 
viscomjim
Guru

Joined: 08/01/2014
Location: United States
Posts: 925
Posted: 04:39am 11 Oct 2014
Copy link to clipboard 
Print this post

Maybe that explains why my somewhat cheezy program runs ok. I really like the way interrupts were set up and how they work. They come in quite handy.
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 06:09pm 11 Oct 2014
Copy link to clipboard 
Print this post

That answers it perfectly thanks Geoff.

Greg
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025