Setting the time in rtc with buttons

super_moose

New Member
I have a ds1391 rtc, a 28x2 and a serial lcd. I have a program that can read the time and show it on the lcd but I can't figure out how to set the time with some buttons. I want to have one button to advance the hours and another to advance the minutes.

Can anyone help me with this??

Here is my code it it helps
Code:
hspisetup spimode01, spimedium 

main:

low 6             ;seconds
hspiout ($01)
hspiin  (b0)
high 6
pause 5


bcdtoascii b0,b1,b2



low 6              ;mins  
hspiout ($02)
hspiin  (b3)
high 6
pause 5

bcdtoascii b3,b4,b5

low 6               ;hours
hspiout ($03)
hspiin (b6)
high 6

bcdtoascii b6,b7,b8

low 6                ;milliseconds
hspiout ($00)
hspiin (b9)
high 6

bcdtoascii b9,b10,b11


serout 7 ,T9600_8,($FE,$47,3,1)   ;set screen to 2 blocks in
serout 7 ,T9600_8,(b7,b8)
serout 7 ,T9600_8,(":")
serout 7 ,T9600_8,(b4,b5)
serout 7 ,T9600_8,(":")
serout 7 ,T9600_8,(b1,b2)
serout 7 ,T9600_8,(":")
serout 7 ,T9600_8,(b10,b11)
Thanks for any help.
 

westaust55

Moderator
Welcome to the PICAXE forum.

While I do not have a solution to hand this topic has been discussed before if you were to do a forum search.
In this thread there is a part solution provided by forum member mrburnette at post 9: http://www.picaxeforum.co.uk/showthread.php?20436-Real-Time-Clock-in-PICAXE-hardware

Noted that your clock is SPI based (not i2c) but it is the concept on what to do that counts.

The DS1391 datasheet can be found here: http://datasheets.maximintegrated.com/en/ds/DS1390-DS1394.pdf
The register values are still BCD encoded so the concept needs to be to read in the data from the RTC, convert to decimal values, make the adjustments, convert back to BCD and then write back to the RTC.
 
Last edited:

TAMeyer

Member
SM:

I am working on the same concept as you.
The code attached presents one manner in which this can be done. That is using pushbuttons like those found on an alarm clock.

The code runs fine in the simulator as far as selecting a time, and storing it to local EEPROM.

It lacks:
proper commenting
polished commands for the LCD
commands to write the info to the clock.

But as “westaust55” said, it is the concept you are after.

Good Luck and Merry Christmas,

Terry

Code:
{

#rem
{
V5    
V4    CleanUp
V3    Switched to 14M2
V2    Renamed pushbuttons
V2    Removed "marks" references to LED
V1    Basic mish mash


The pgm allows an user to set the time in a picaxe project
just as they would with an alarm clock


Three pushbuttons (PB)
    
    Up arrow
    Down arrow
    Round button for set routine
    
#endrem

#Picaxe 14M2

SETFREQ M16

                                    
}
                            
    EEPROM 08,(0,0)                    'Write "0" into the Hours default EEPROM address
    EEPROM 09,(0,0)                    'Write "0" into the Mins default EEPROM address
    EEPROM 10,(0,0)                    'Write "0" into the Secs default EEPROM address
 
    SYMBOL PB_UP        = PINC.2
    SYMBOL PB_DN            = PINC.1
    SYMBOL SetButton         = PINC.0

    SYMBOL LCD            = C.4

    Symbol SCL            = PINB.3                                
    Symbol SDA            = PINB.4

    Symbol ProgPrompt        = B1             'Reused VAR, Acts as a type of flag if a button is
                                'held down too long
    Symbol Thresh        = B2             'Threshhold for ProgPrompt


    SYMBOL hours        = B10
    SYMBOL mins            = B11
    SYMBOL secs            = B12




'LET dirsc = %00000000

Let ProgPrompt = 0    
Let Hours = 0
Let Mins = 0
Let Secs = 0

 


Main:



Gosub ShouldTimeBeSet



Goto Main

'--------------------------------------------------------------------------------------------------
{
ShouldTimeBeSet:            
    
        Do
            If SetButton = 1 THEN Inc ProgPrompt : EndIf
            If ProgPrompt > Thresh THEN GoSub SetTime
                Pause 100
        Loop While SetButton = 1
    Return
    }
'--------------------------------------------------------------------------------------------------
SetTime:
{

    Gosub SetHours
    Gosub SetMins    
    Gosub SetSecs
    Gosub SettingDone
}
End

'--------------------------------------------------------------------------------------------------
        SetHours:
{            GoSub ReleaseSetButton
                    
            Let Hours = 0

                Do
                    If PB_UP = 1 Then Inc Hours : EndIf
                        If Hours > 23 Then Let Hours = 0 : EndIf
                
                    
                    If PB_DN = 1 Then Dec Hours : EndIf
                        If Hours =  255 Then Let Hours = 23 : EndIf

                SerOut LCD,T9600_16,("Hours = ",#hours) ; transmit value to serial LCD
                SerOut LCD,T9600_16,("Press Set When Done") ; transmit value to serial LCD
                
                Loop While SetButton = 0    
            
                Write 08,Hours
                Pause 60
            Return    
        }    
'--------------------------------------------------------------------------------------------------    
        SetMins:
{            GoSub ReleaseSetButton
            
            Let Mins = 0

                Do
                    If PB_UP = 1 Then Inc Mins : EndIf
                        If Mins > 59 Then Let Mins = 0 : EndIf
                
                    
                    If PB_DN = 1 Then Dec Mins : EndIf
                        If Mins = 255 Then Let Mins = 59 : EndIf

                SerOut LCD,T9600_16,("Mins = ",#Mins)
                SerOut LCD,T9600_16,("Press Set When Done") ; transmit value to serial LCD
                
                
                Loop While SetButton = 0    
                
                Write 09,Mins
                Pause 60
                
            Return    
            }
'--------------------------------------------------------------------------------------------------    
        SetSecs:
        {    GoSub ReleaseSetButton
            
            Let Secs = 0

                Do
                    If PB_UP = 1 Then Inc Secs : EndIf
                        If Secs > 59 Then Let Secs = 0 : EndIf
                
                    
                    If PB_DN = 1 Then Dec Secs : EndIf
                        If Secs = 255 Then Let Secs = 59 : EndIf
                    
                SerOut LCD,T9600_16,("Secs = ",#Secs)                    
                SerOut LCD,T9600_16,("Press Set When Done") ; transmit value to serial LCD

                Loop While SetButton = 0    
                
        Write 10,Secs
        Pause 60
    
            Return    
            }
'--------------------------------------------------------------------------------------------------    

'--------------------------------------------------------------------------------------------------        
'--------------------------------------------------------------------------------------------------        
ReleaseSetButton:                        'Is the user holding the button too long?
{        Let ProgPrompt = 0
                Do
                    If SetButton = 1 Then Inc ProgPrompt : EndIf    
                    If ProgPrompt > Thresh Then Gosub DisplayReleaseWarning
            
                Loop While SetButton = 1
        Let ProgPrompt = 0
    Return
    }
'--------------------------------------------------------------------------------------------------            
DisplayReleaseWarning:

    SerOut LCD,T9600_16,("Release the Set",13)' transmit value to serial LCD
    SerOut LCD,T9600_16,("button to continue")


Return
'--------------------------------------------------------------------------------------------------            
SettingDone:
            GoSub ReleaseSetButton
        

    SerOut LCD,T9600_16,("Time = ",#hours,":",#mins,":",#Secs,13,10) 'transmit value to serial LCD                    
                    
                    pause 20000    
Return

'--------------------------------------------------------------------------------------------------
 
Hi guys
Have been trawling the forum to find the code posted above to help in a project posted under "using DS1307 with picaxe 18m2".

I think I can adapt it to make it work in my project but a couple of questions...
if I want to add. Date month and year do I pick any EEPROM say 1,2,3, or 11,12,13, ( I note in the comment line "Default eeprom address" ) is this set by some standard or by whoever is programming?).
I am guessing I could use similar lines as in the settime or sethours part to add in a series of event times ( i need 5 or 6 in 24hrs).
having set the time and date etc using the code does the rtc(ds1307) take over or have I missed something?
sorry if this is mundane or stupid but my programming knowledge is very limited, I generally have to find code already written and then try to make it work for me.
many thanks
 

nick12ab

Senior Member
if I want to add. Date month and year do I pick any EEPROM say 1,2,3, or 11,12,13, ( I note in the comment line "Default eeprom address" ) is this set by some standard or by whoever is programming?).
it is set by the programmer.

I am guessing I could use similar lines as in the settime or sethours part to add in a series of event times ( i need 5 or 6 in 24hrs).
having set the time and date etc using the code does the rtc(ds1307) take over or have I missed something?
The DS1307 takes over with the time and date, but it won't do your events.
 

oracacle

Senior Member
how many button are you going to use, i have just built a clock that makes use of 2 botton, but only cycles the time, date, month and year upwards and displays it on 4x 7 segment displays. this code does work on my clock. hope it can of help.

the code takes into account leap years, so it can be programmed on the 29 of feb too
i cant answer you question as i have never used the clock module.

this is a sup-proccedure and is called from the main programme.
Code:
setmins:
	gosub show
		if porta pin0 = 1 then		;check for user incrementing mins
		let mins = mins + 1		;increment mins if needed
			if mins > 59 then		;check for overflow
			let mins = 0		;reset in case of overflow
			endif
		let mten= mins /10		;set variables for display
		let munit = mins //10
		let hten = hour /10
		let hunit = hour //10
		gosub look
		endif
		if porta pin1 = 0 then goto setmins	;check for user input, continue to hours
	pause 150

sethours:
	gosub show
		if porta pin0 = 1 then		;check for user input
		let hour = hour + 1		;add 1 hour
			if hour > 23 then		;check for overflow
			let hour = 0		;reset if overflow occours
			end if
		let hten = hour /10		;set variables for display
		let hunit = hour //10
		let mten= mins /10
		let munit = mins //10
		gosub look
		endif
	if porta pin1 = 0 then goto sethours	;check for iser input
	pause 150
	gosub lookday
		let tempbyte = 40			;set variable to remove deciaml place

setdays:
	gosub show
		if porta pin0 = 1 then		;check for user input
		let days = days + 1		;add 1 day
			if days > 6 then		;check for over flow
			let days = 0		;reset if overflow occours
			end if
		gosub lookday
		end if
	if porta pin1 = 0 then setdays	;check for user input
	let days = days + 1			;correct for writing to DS1307
	pause 150
	
		let hten = 2
		let hunit = 0
		let mten = year/10
		let munit = year//10
		gosub look
	
setyear:
	gosub show
		if porta pin0 = 1 then
		let year = year + 1
			if year > 99 then
			let year = 00
			end if
		let hten = 2
		let hunit = 0
		let mten = year/10
		let munit = year//10
	gosub look		
		end if

	if porta pin1 = 0 then goto setyear

	'put date variable into display variables
	let hten = date/10
	let hunit = date//10
	
	let mten = month/10
	let munit = month //10
	gosub look
	gosub show
	let tempbyte = 0

setmonth:
	gosub show
		if porta pin0 = 1 then
		let month = month + 1
			if month > 12 then
			let month = 1
			end if
		let mten = month /10
		let munit = month //10
		let hten= date /10
		let hunit = date //10
		gosub look
		endif
	if porta pin1 = 0 then goto setmonth
	pause 150

setdate:
	gosub show
	if porta pin0 = 1 then
	let date = date + 1
	let tempbyte = month -1							;correct month for lookup table
	lookup tempbyte, (31,28,31,30,31,30,31,31,30,31,30,31),tempbyte	;lookup days in each month
		if month = 2 then							;check for feburary
	#rem
	research showed the all leap years when divided by 4 were whole numbers, as the picaxe can not make use
	of deicimal place, shifting the decimal place by multipling by 10 and finding the remainder of divideing
	the result by 4 the piacxe can use a simple if statement to dtermine leap years and thus how many days
	in the second month
	#endrem
		let tempyear = year *10						;x10
		let tempyear = tempyear//4					;find remainder of dividing by 4
				if tempyear = 0 then 				;if the answer is 0, then its a leap year
				tempbyte = 29					;set number of day to 29
				end if
		end if	
		if date > tempbyte then
		let date = 1
		end if
		
	
		let hten= date /10
		let hunit = date //10
		let mten = month /10
		let munit = month //10
		gosub look
	endif
	if porta pin1 = 0 then goto setdate
	pause 150
	
write_time:
	gosub bcd									'goto sub procedure
	i2cslave %11010000, i2cslow,i2cbyte					
	writei2c 0, (secs,mins,hour,days,date,month,year,$10)		'write data to clock
	pause 1000									'wait while data is writen
	
	reset
 
Thanks for that!
I have managed to get the picaxe to react to various times set in the program. So now want to set those times with the buttons once that is done the whole thing becomes autonomous.
buttons havn't arrived yet though.
 
sorry oracacle your reply was posted in between mine.
thank you, I was planning 3 buttons Set, Up and Down. I usually manage to go too far when setting times etc!!
when the buttons arrive I will try your code. Setting for leap year makes it even more autonamous.
 
Top