Serial input to set time on DS1307

PFM

New Member
Hello all,

I did the search ad review before putting up this post and was close with a few hints from Hippy but still no luck. I am trying to update or reset the time, if it loses time, through a serin command.

My code is not too pretty but needs help in building the HEX or BCD string to set the clock.
Code:
Set_Time:
sertxd ("Top of Set_Time",ret,lfeed)

high 2		'RED LED
low 3
i2cslave %11010000, i2cslow, i2cbyte     'setup i2c slave port

'sertxd ("setup I2C",ret,lfeed)

readi2c 0, (b13, b12, b11)			'get hours, mins, secs


'Convert BCD to decimal
'bcd_decimal:
	let temp_byte = secs & %11110000 / 16 * 10
	let secs = secs & %00001111 + temp_byte
	let temp_byte = mins & %11110000 / 16 * 10
	let mins = mins & %00001111 + temp_byte
	let temp_byte = hours & %11110000 / 16 * 10
	let hours = hours & %00001111 + temp_byte
'	sertxd (#secs,COM,#mins,COM,#hours,COM,RET,LFEED)

sertxd ("Time Old ",#b11,":")

sertxd (#b12,":")

sertxd (#b13, ret,lfeed)


'sertxd (#b11, ret,lfeed)



sertxd ("enter hour 00-23 ")

b1 = 0
b2 = 0

serin 6,N4800_4, b1,b2	' get two chars convert to decimal hours
b1=b1-48
b1=b1*10
b2=b2-48
b11= b1+b2
sertxd (b11, ret, lfeed)

'sertxd (b2, ret, lfeed)
pause 1000

b1 = 0
b2 = 0
sertxd ("enter next minute 00-59")

serin 6,N4800_4, b1,b2	' get two chars convert to decimal minutes
b1=b1-48
b1=b1*10
b2=b2-48
b12= b1+b2


sertxd (b12, ret, lfeed)

pause 1000

b13 = 0



sertxd ("Set time to ",#b11,":")

sertxd (#b12, ":")


sertxd (#b13, "___ Y", ret,lfeed)



serin 6,N4800,("Y")

sertxd ("Write Time to RTC", ret,lfeed)


' NEED TO CONVERT DECIMAL TO HEX FOR THIS TO WORK OR DO A LOOKUP


'First program the date
	high 5 ' write protect eeprom

	i2cslave %11010000, i2cslow, i2cbyte
	writei2c 0, ($(b13), $(b12), $(b11), $07, $02, $02, $07, $10)
	pause 50

readi2c 0, (b13, b12, b11)			'get hours, mins, secs


'Convert BCD to decimal
'bcd_decimal:
	let temp_byte = secs & %11110000 / 16 * 10
	let secs = secs & %00001111 + temp_byte
	let temp_byte = mins & %11110000 / 16 * 10
	let mins = mins & %00001111 + temp_byte
	let temp_byte = hours & %11110000 / 16 * 10
	let hours = hours & %00001111 + temp_byte
'	sertxd (#secs,COM,#mins,COM,#hours,COM,RET,LFEED)

sertxd ("New Time Set ",#b11,":")

sertxd (#b12,":")

sertxd (#b13, ret,lfeed)

'sertxd (#b13, ret,lfeed)


'sertxd (#b11, ret,lfeed)
Sorry about the old commented code. This was close before I put the () around b13 etc trying to use the $ to convert the data.

I know the DS1307 has been through the wringer here many times but I have not seen this one as yet. All the samples seem to start with the Wizard code so the time is always set or hard coded not taking input from the serin command.

Thanks in advance,

PFM
 
Last edited:

moxhamj

New Member
Buried in the code at http://drvernacula.topcities.com/lcd_clock_for_controlling_pumps_.htm are all the subroutines. This circuit adjusts the clock using two buttons - one scrolls through secs/min/hours/day etc and the other increments. There were not quite enough outputs on a picaxe18 so the outputs were expanded using an HC595 and the LCD driver routine thus ended up a bit more complicated. With a retrospectoscope I realise it may be possible to change input pins on an 18X into output pins - Hippy might be able to advise how to do that. Anyway this circuit works and an HC595 only cost $1.

If you copy the code text into the picaxe editor the formatting should be more legible.
 
Last edited:

PFM

New Member
Dr Acula,

Thanks for the reply, I am not sure how bad I have butchered my code from late last night. I followed your link, nice project by the way, but still struggle with getting data from serin, ASCII data, two bytes. 0-59 miutes, 0-23 hours and convert this into BCD data to load into the DS1307. I do not need the day, month or year for my project. I see you restored the BCD info you retrieved but did not need to swap the data types as I am. A lookup table is looking better and better but that is a lot of numbers to store.

I guess the bottom line is I am still looking to convert ASCII to BCD, I can get the ASCII to decimal easy enough but then to BCD. I found a post from Hippy that was close I need to re-locate it and learn from it.

Thanks again,

PFM
 

lbenson

Senior Member
Suppose your value for seconds is 59 and you have the ascii value of "5" ($35) in b0 and "9" ($39) in b1. To get the binary coded decimal value ($59 in hex representation) into, say, b0, you first subtract ascii "0" ($30) from the value of b0 and multiply the result by 16, thus shifting the value 4 bits to the left (giving you $50). Then subtract "0" from b1 and add it to your previous result. You could try the following in the simulator, replacing the "5" and "9" with any appropriate values (make sure you are looking at the hex representation to see your $59).

b0 = "5"
b1 = "9"
b0 = b0 - $30 * 16 + b1 - $30

or

b0 = b0 - "0" * 16 + b1 - "0"
 
Last edited:

PFM

New Member
Ibenson,

Thank you so much with your tip and about 10 minutes it was done.

Code:
'PICAXE-18X - Serial Time Clock


'Inputs
'Input 0 Pin 17 = Set Clock



' ********************
' ***** Symbols  *****
' ********************

'Symbol definitions
'symbol data0 = b0
symbol temp_byte = b10
symbol hours = b11
symbol mins = b12
symbol secs = b13
symbol COM = 44         'comma
symbol RET = 13         'carriage return
symbol LFEED = 10          'line feed


' ***************************
' ***** Initialisation  *****
' ***************************


Top:


IF Pin0 = 1 Then Set_time

Main:

high 2
high 3	'LED's Off

Gosub Get_Time
pause 10000
goto main

 
Get_Time:


sertxd ("top of Get ",ret,lfeed)

'sertxd ("Get time from DS1307",ret,lfeed)

'sertxd ("Clear Clock variables",ret,lfeed)

b13=0	'clear any old data
b12=0
b11=0


i2cslave %11010000, i2cslow, i2cbyte     'setup i2c slave port

'sertxd ("setup I2C",ret,lfeed)

readi2c 0, (b13, b12, b11)			'get hours, mins, secs


'Convert BCD to decimal
'bcd_decimal:
	let temp_byte = secs & %11110000 / 16 * 10
	let secs = secs & %00001111 + temp_byte
	let temp_byte = mins & %11110000 / 16 * 10
	let mins = mins & %00001111 + temp_byte
	let temp_byte = hours & %11110000 / 16 * 10
	let hours = hours & %00001111 + temp_byte

sertxd ("Time Old ",#b11,":")

sertxd (#b12,":")

sertxd (#b13, ret,lfeed)


Return


Set_Time:
sertxd ("Top of Set_Time",ret,lfeed)

high 2		'RED LED
low 3
i2cslave %11010000, i2cslow, i2cbyte     'setup i2c slave port

'sertxd ("setup I2C",ret,lfeed)

readi2c 0, (b13, b12, b11)			'get hours, mins, secs


'Convert BCD to decimal **** Need a subroutine to stop repeated code
'bcd_decimal:
	let temp_byte = secs & %11110000 / 16 * 10
	let secs = secs & %00001111 + temp_byte
	let temp_byte = mins & %11110000 / 16 * 10
	let mins = mins & %00001111 + temp_byte
	let temp_byte = hours & %11110000 / 16 * 10
	let hours = hours & %00001111 + temp_byte


sertxd ("Time Old ",#b11,":")

sertxd (#b12,":")

sertxd (#b13, ret,lfeed)


sertxd ("enter hour 00-23 ")

b1 = 0
b2 = 0

serin 6,N4800_4, b1,b2	' get two chars convert to BCD Hours

b11 = b1-$30*16+b2-$30

'sertxd (b11, ret, lfeed)

pause 1000

b1 = 0
b2 = 0
sertxd ("enter next minute 00-59")

serin 6,N4800_4, b1,b2	' get two chars convert to BCD Minutes

b12 = b1-$30*16+b2-$30

pause 1000

b13 = 0			'set seconds to zero


sertxd ("Write Time to RTC", ret,lfeed)


'First program the date
	high 5 ' write protect eeprom

	i2cslave %11010000, i2cslow, i2cbyte
	writei2c 0, (b13, b12, b11, $07, $02, $02, $07, $10)
	pause 50

readi2c 0, (b13, b12, b11)			'get hours, mins, secs


'Convert BCD to decimal
'bcd_decimal:
	let temp_byte = secs & %11110000 / 16 * 10
	let secs = secs & %00001111 + temp_byte
	let temp_byte = mins & %11110000 / 16 * 10
	let mins = mins & %00001111 + temp_byte
	let temp_byte = hours & %11110000 / 16 * 10
	let hours = hours & %00001111 + temp_byte
'	sertxd (#secs,COM,#mins,COM,#hours,COM,RET,LFEED)

sertxd ("New Time Set ",#b11,":")

sertxd (#b12,":")

sertxd (#b13, ret,lfeed)


Goto Main

I knew I was on the right track but struggling it has been many years since I did any code work.

I hope this code helps someone else down the road.

Thaks again to all who help here.

PFM
 

TERD

New Member
Simplifing ds1307 time input with a subroutine 'ConvertBytetoBCD'

Here's a simple sub routine that converts a byte value (ie,b0=59) into a bcd value that can be directly inputed into the ds1307:

Code:
Symbol Value = b10
Symbol msb = b12
Symbol lsb = b11
Symbol Result = b9

ConvertBytetoBCD:
	msb = 0
	lsb = 0
	
	do until Value < 10 'count the most significant bits
	inc msb
	Value = Value - 10 
	loop 
	
	lsb = Value 'least significant bits = remaining
	Result = msb * 16 + lsb 'convert to bcd notation
return
here is an example of how to use it to set the time:

Code:
main:
'Gosub GetTime
if pin0=1 then : Gosub SetTime : end if
pause 1000
goto main



Symbol ResultIndex = b8

SetTime:
let ptr= 0 'reset scrathpad pointer

for ResultIndex = 1 to 8 'cycle throu the ds1307's eight settings

Select ResultIndex 
case = 1
sertxd("Enter seconds...0-59",13,10)
case = 2
sertxd("Enter minutes...0-59",13,10)
case = 3
sertxd("Enter hours...0-23",13,10)
case = 4
sertxd("Enter day of week...1-7",13,10)
case = 5
sertxd("Enter day of month...1-31",13,10)
case = 6
sertxd("Enter month...1-12",13,10)
case = 7
sertxd("Enter year 20xx...0-99",13,10)
case = 8
sertxd("Control...",13,10)
end select

serrxd Value 'byte value.  ie, Value = 59 to set the seconds to 59 or, Value = 0 to set to 00


gosub ConvertBytetoBCD 'converts the byte value to bcd
@ptrinc = Result  'store the result's to scratchpad for now
next 


high 3
sertxd("turn off input 0 to start the clock",13,10)
do until pin0=0 'wait for pin0 to go low
pause 2
loop

'set the clock
let ptr = 0 'reset scrathpad pointer
writei2c 0,(@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc)
pause 10
low 3
return
 
Last edited:

BCJKiwi

Senior Member
I've been thinking about configuring various parameters (including the time in a DS1307) in my current project using a TV remote and receiving the data via IRIN (28X1). This could save on configuration buttons and inputs or complications combining buttons into one input.

It seems that your sample code could achieve this with a few mods.
I presume the Input 0 is a switch to start/stop the program mode (as it was for PFM) but is the pin3 simply an indicator LED?

Just not quite sure of the interaction of the input0 and the output3

Thanks
 
Last edited:
Top