Help with DS1307

Krafter

Member
I'm working on a new project with a DS1307. My end goal is to have a GoPro start recording on the time of day by using a servo and a DS1307 RTC. I have the RTC working but I'd like to be able to set the time via the serial port. I've been trying to modify the code from this thread. The problem I'm having is in the conversion between ASCII output from the terminal window and the BCD input the the RTC is expecting. So when I enter a 1 for the variable "mins", I get back a 31 which is the hex value for 1. I've been trying to find a solution to this but have failed so far.

Any tips would be wonderful. Thanks.


Code:
'########################################
'# For PICAXE-28X1 and MAXIM DS1307 RTC #
'########################################
#picaxe 20m2
SetFreq m8
'########################################

symbol sec  = b3
symbol mins = b4
symbol hrs  = b5
symbol dow  = b6
symbol day  = b7
symbol mth  = b8
symbol yr   = b9

#rem
sec = $0
mins = $0
hrs = $1
dow = $2
day = $3
mth = $4
yr = $14
#endrem

serrxd("set "), mins ', mins, hrs, dow, day, mth, yr
Main:
 

'DS1307 CODE
pause 2000
' Set up i2c for device 
 hi2csetup i2cmaster, %11010000, i2cslow_8, i2cbyte   '%11010000 is device i2c bus address
 

 '''hi2cout 0, ($00,$27,$23,$04,$20,$07,$16,%00010000)
 hi2cout 0, (sec, mins, hrs, dow, day, mth, yr, %00010000)

 
DS1307:
pause 1800
 
 hi2cin 6,(b0)
 bcdtoascii b0, b1, b2   ' DS1307 stores data in BCD format
 sertxd ("Date/Time:- Yr:",b1,b2) ' Write output to terminal
 
 hi2cin 5,(b0)    ' Month Read from register 5
 bcdtoascii b0, b1, b2
 sertxd ("  Mo:", b1, b2)
 
 hi2cin 4,(b0)    ' Day Read from register 4
 bcdtoascii b0, b1, b2
 sertxd ("  Day:", b1, b2)
 
 hi2cin 3,(b0)    ' DoW Read from register 3
 bcdtoascii b0, b1, b2
 If     b2 = "1" then sertxd ("  DoW:","Su") 'convert Ascii 1-7 Day of Week number to Text
 elseif b2 = "2" then sertxd ("  DoW:","Mo")
 elseif b2 = "3" then sertxd ("  DoW:","Tu")
 elseif b2 = "4" then sertxd ("  DoW:","We")
 elseif b2 = "5" then sertxd ("  DoW:","Th")
 elseif b2 = "6" then sertxd ("  DoW:","Fr")
 elseif b2 = "7" then sertxd ("  DoW:","Sa")
 EndIf
 
 hi2cin 2,(b0)    ' Hour Read from register 2
 bcdtoascii b0, b1, b2
 sertxd ("  Hr:", b1, b2)
 
 hi2cin 1,(b0)    ' Minute Read from register 1
 bcdtoascii b0, b1, b2
 sertxd ("  Min:", b1, b2)
 
 hi2cin 0,(b0)    ' Second Read from register 0
 bcdtoascii b0, b1, b2
 sertxd ("  Sec:", b1, b2)
 
  sertxd ("  min = ", mins, cr, lf)
 
 'goto DS1307
 

BESQUEUT

Senior Member
I'm working on a new project with a DS1307. My end goal is to have a GoPro start recording on the time of day by using a servo and a DS1307 RTC. I have the RTC working but I'd like to be able to set the time via the serial port. I've been trying to modify the code from this thread. The problem I'm having is in the conversion between ASCII output from the terminal window and the BCD input the the RTC is expecting. So when I enter a 1 for the variable "mins", I get back a 31 which is the hex value for 1. I've been trying to find a solution to this but have failed so far.

Any tips would be wonderful. Thanks.
There are two answers :
If for a Pixaxe X2 : use BINTOBCD
Else look at this code : (To be run with simulator...)
Code:
 [color=Navy]#simspeed 100
 #picaxe [/color][color=Black]20X2
 
 
 [/color][color=Blue]do
       sertxd ([/color][color=Navy]13[/color][color=Black],[/color][color=Navy]10[/color][color=Black],[/color][color=Red]"Value to convert "[/color][color=Blue])
       serrxd [/color][color=Purple]b3
       b0[/color][color=DarkCyan]=[/color][color=Blue]bintobcd [/color][color=Purple]b3
       b4[/color][color=DarkCyan]=[/color][color=Purple]b3[/color][color=DarkCyan]//[/color][color=Navy]10
       [/color][color=Purple]b4[/color][color=DarkCyan]=[/color][color=Purple]b3[/color][color=DarkCyan]/[/color][color=Navy]10[/color][color=DarkCyan]*[/color][color=Navy]16[/color][color=DarkCyan]+[/color][color=Purple]b4
       
   [/color][color=Blue]bcdtoascii [/color][color=Purple]b0[/color][color=Black], [/color][color=Purple]b1[/color][color=Black], [/color][color=Purple]b2
   [/color][color=Blue]sertxd ([/color][color=Red]"b3="[/color][color=Black],#[/color][color=Purple]b3[/color][color=Black],[/color][color=Red]"("[/color][color=Black],[/color][color=Purple]b3[/color][color=Black],[/color][color=Red]") b4="[/color][color=Black],#[/color][color=Purple]b4[/color][color=Black],[/color][color=Red]" b0="[/color][color=Black],#[/color][color=Purple]b0[/color][color=Black],[/color][color=Red]" "[/color][color=Black],[/color][color=Purple]b1[/color][color=Black],[/color][color=Purple]b2[/color][color=Black],[/color][color=Navy]13[/color][color=Black],[/color][color=Navy]10[/color][color=Blue])
 loop[/color]
Note that b4 and b0 have same value ; use one or the other depending what Picaxe you are using.

Also, note that the conversion from ASCII to BIN is done by the serrxd command.

If your input is really ASCII, (say b5,b6) then
b3=b5-48*10+b6-48 '(decimal value)

or
b4=b5-48*16+b6-48 '(BCD value)

BUT : in that case you have to deal with non numeric characters and CR/LF...
 
Last edited:

eggdweather

Senior Member
When drone FPV started and the GoPro was the camera of choice, there were many cables available on the market that enabled the camera to be turned on / off from standby using a spare servo channel, the cable was quite simple, it was Ground and Trigger, often they had a simple push switch that when pushed, grounded the trigger pin and the camera started recorded, you could simulate this, by pulling a Picaxe output low with a wire to the trigger pin on the camera via a connector. I'm sure the cables are still available.
 

johnlong

Senior Member
Hi Krafter
I myself struggled with the ds1309 (I must update my programer as in my sec2 basic commands i can not find that bintoaschii only bintobcd)
So I had a look around as everything I could see was lot of typing came across a thread by Hippy that delt nicely with it so I, use the following for programming the ds1309 from a keypad
Code:
#simspeed 100
 #picaxe 20X2
 

 serrxd b3
  do 
 	
       sertxd (13,10,"Value to convert ")    
       
   b0 = b3 / 16 * $FA + b3 'This converts b3 to bcd b0 for the ds1309
                    
 b3 = b0 / 10 * 6 + b0    'Converts b0 back to decimel for b3 from the ds1309
 b4=b3
 sertxd ("b3=",#b3,"  ", "b4=",#b4,"  ","b0=",#b0," ",13,10)'The #before the variable 
   inc b3                                                    'sortout the aschii for you
     loop
The thread by Hippy is a good read get you into that 15-16 thing but my apologies as I do not remember its title
regards
john
 

Krafter

Member
Thank you guys. I will play with the code provied and go from there.

@eggdweather

I think you may have saved me a serious headache! I've googled and googled for a way to auto start a recording and didn't find anything other than a post (which I can't find again) that described using a servo to physically press the button. But after reading your reply and including the keyword "trigger", I found the following pinout from here. Now to find a cable.

Code:
Here is the 30-pin pinout at least up to the 3+, and I'm sure the same with the 4:


PIN Function
1 GND
2 PB/Cb Video Out
3 G,Y Video Out
4 B, Pr/Cr Video Out
5 USB Power
6 USB Power
7 USB Data +
8 USB Data -
9 GND
10 R Audio Out
11 L Audio Out
12 Power/Mode Button
13 Playback
14 R Audio In
15 L Audio In
16 IR in
17 Trigger
18 GND
19 ID1
20 ID2
21 ID3
22 ID4
23 Power Out Standby
24 Power Out
25 Battery In
26 Battery In
27 GND
28 I2C Data
29 I2C Clock
30 GND

Edit: Well, well what do you know? With very little keying modifications to an iPhone 4 charging/sync cable, it fits perfectly into the GoPro 30 pin connector! I even took apart the connector end of the cable and come to find out, the pins were just held in with glue. I was able to free the glue and I should be able to put them in the correct position according to the GoPro pinout! If this works, it's going to make my project much easier.
 
Last edited:

eggdweather

Senior Member
Happy to help, nearly all FPV setups use such a cable and a spare Rx channel via a servo channel switch to take photos, etc.
 

Krafter

Member
A quick update. The pinout above is misleading. The "Trigger" pin isn't as it sounds. It is an output of some sort and not an input. I've had luck with powering on the camera by grounding pin 12 but I cannot get it to power off with the some pin. My original thought since I can't start recording via the trig pin, was to set the camera up for One Button Mode but since I can't power it off again, that's pretty much useless. So, either I need to get a "Battery Eliminator" for a GoPro and interrupt that electronically or explore an I2C option which may have some hope at doing what I want and more.
 

Krafter

Member
I've been all over the internet. I can't imagine that cable using anything other than GND and pin 12. Everything I'm reading says to send pin 12 low to turn on and off. I've read posts that says it works great and even found guides on how to do it. I've also read other posts describing the problem I'm having with not being able to turn the camera back off. I've also been reading up on the I2C for GoPro accessories/hacking. Address 0 of a valid accessory has to be equal to 0x9. Maybe it's looking for a valid device before it excepts the power off command? The connector I have wont work to experiment with because I can't get the pins to sit in the housing next to each other without shorting out so I ordered one of these.

Anyway, I've drifted way off from the original post so I'm going to get back to the DS1307 and setting the clock which is part of this on going project. If I can get this working as I won't it to, be either by using I2c commands or by using pin 12 to power it on with and interrupting the power source to power off, then I'll be sure to post a guide on how it's done.
 

Krafter

Member
I'm back with some confusion. I've been working on the code for my project. I've hooked up a 2x16 LCD to display the time and a couple of pushbuttons to set the time. When pinc.5 is high, the first thing I do is load the current value for each setting (dow, mth, day, etc.) into b1 to avoid starting from 0 to set each if not necessary and increment the value with pinc.4 from there. Then I move b1 into a variable (set_dow, set_mth, set_day, etc.) depending on where it's at in the case statement. That works great unless I either let it sit for a while or power cycle the unit. During those scenarios and when I attempt to set the time again, each loaded value appears to be passed into b1 but by the time case 7 is reached in the program, all those variables return 0s. That is verified by line 288.

I've been scratching my head on this one. I'd appreciate a quick look from the community to see if something obvious can be spotted.


Code:
symbol set_sec  = b4
symbol set_mins = b5
symbol set_hrs  = b6
symbol set_dow  = b7
symbol set_day  = b8
symbol set_mth  = b9
symbol set_yr   = b10

symbol sec     = b11
symbol mins    = b12
symbol hrs     = b13
symbol dow     = b14
symbol day     = b15
symbol mth     = b16
symbol yr      = b17

symbol set_enb = b18
symbol ons     = b19 'one shot

'inputs
symbol alm_1_set   = pinb.0
symbol set_time_pb = pinc.7
symbol next_pb     = pinc.5
symbol enter_pb    = pinc.4

'outputs
symbol lcd = c.1

int:
hi2csetup i2cmaster, %11010000, i2cslow_8, i2cbyte
#picaxe 20m2
SetFreq m8
pause 1000
serout lcd, T9600_8, ($FE, $01, $FE, $01) 'clear LCD. get ready for command.
serout lcd, T9600_8, ($FE, $0C)
pause 2000

Main:

gosub get_time

gosub cam_stat

If     dow = "1" then serout lcd, T9600_8, ($FE, 128, "Sun") 'convert Ascii 1-7 Day of Week number to Text
elseif dow = "2" then serout lcd, T9600_8, ($FE, 128, "Mon")
elseif dow = "3" then serout lcd, T9600_8, ($FE, 128, "Tue")
elseif dow = "4" then serout lcd, T9600_8, ($FE, 128, "Wed")
elseif dow = "5" then serout lcd, T9600_8, ($FE, 128, "Thu")
elseif dow = "6" then serout lcd, T9600_8, ($FE, 128, "Fri")
elseif dow = "7" then serout lcd, T9600_8, ($FE, 128, "Sat")
else serout lcd, T9600_8, ($FE, 128, "ERR")
EndIf

if hrs < 10 then
	serout lcd, T9600_8, ($FE, 132, "0", #hrs)
else
	serout lcd, T9600_8, ($FE, 132, #hrs)
endif

if mins < 10 then
	serout lcd, T9600_8, ($FE, 134, ":0", #mins)
else
	serout lcd, T9600_8, ($FE, 134, ":", #mins)
endif

if sec < 10 then
	serout lcd, T9600_8, ($FE, 137, ":0", #sec)
else
	serout lcd, T9600_8, ($FE, 137, ":", #sec)
endif

if mth < 10 then
	serout lcd, T9600_8, ($FE, 192, "0", #mth)
else
	serout lcd, T9600_8, ($FE, 192, #mth)
endif

if day < 10 then
	serout lcd, T9600_8, ($FE, 194, "/0", #day)
else
	serout lcd, T9600_8, ($FE, 194, "/", #day)
endif

if yr < 10 then
	serout lcd, T9600_8, ($FE, 197, "/0", #yr)
else
	serout lcd, T9600_8, ($FE, 197, "/", #yr)
endif

if set_time_pb = 1 then
	serout c.1, T9600_8, ($FE, $01, "Time Set")
	b0 = 0
	b2 = 1
	set_enb = 1
	gosub set_time
endif

goto main



get_time:
hi2cin 6, (b0)
bcdtoascii b0, b1, b2   ' DS1307 stores data in BCD format
yr = b1 - 48 * 10 + b2 - 48

hi2cin 5, (b0)    ' Month Read from register 5
bcdtoascii b0, b1, b2
mth = b1 - 48 * 10 + b2 - 48

hi2cin 4, (b0)    ' Day Read from register 4
bcdtoascii b0, b1, b2
day = b1 - 48 * 10 + b2 - 48

hi2cin 3,(b0)    ' DoW Read from register 3
bcdtoascii b0, b1, b2
dow = b2

hi2cin 2, (b0)    ' Hour Read from register 2
bcdtoascii b0, b1, b2
hrs = b1 - 48 * 10 + b2 - 48

hi2cin 1, (b0)    ' Minute Read from register 1
bcdtoascii b0, b1, b2
mins = b1 - 48 * 10 + b2 - 48

hi2cin 0,(b0)    ' Second Read from register 0
bcdtoascii b0, b1, b2
sec = b1 - 48 * 10 + b2 - 48

pause 200

return

set_time:
do while set_enb = 1
	if enter_pb = 1 then
		b0 = b0 + 1
		do while enter_pb = 1
			ons = 0
		loop
	endif

	select case b0
		case 0
			if ons = 0 then
				b1 = dow - 48
				ons = 1
			endif
			if b1 < 10 then
				serout c.1, T9600_8, ($FE, 192, "DoW 0", #b1)
			else
				serout c.1, T9600_8, ($FE, 192, "DoW ", #b1)
			endif
			if pinc.5 = 1 then
				b1 = b1 + 1
				b2 = b1 / 10 * 16
				set_dow = b1 // 10 or b2
				if b1 >= 8 then
					b1 = 0
				endif
				pause 500
			endif

		case 1
			if ons = 0 then
				b1 = mth
				ons = 1
			endif
			if b1 < 10 then
				serout c.1, T9600_8, ($FE, 192, "Mth 0", #b1)
			else
				serout c.1, T9600_8, ($FE, 192, "Mth ", #b1)
			endif
			if pinc.5 = 1 then
				b1 = b1 + 1
				b2 = b1 / 10 * 16
				set_mth = b1 // 10 or b2
				if b1 >= 13 then
					b1 = 0
				endif
				pause 500
			endif
		
		case 2
			if ons = 0 then
				b1 = day
				ons = 1
			endif
			if b1 < 10 then
				serout c.1, T9600_8, ($FE, 192, "Day 0", #b1)
			else
				serout c.1, T9600_8, ($FE, 192, "Day ", #b1)
			endif
			if pinc.5 = 1 then
				b1 = b1 + 1
				b2 = b1 / 10 * 16
				set_day = b1 // 10 or b2
				if b1 >= 32 then
					b1 = 0
				endif
				pause 500
			endif
		
		case 3
			if ons = 0 then
				b1 = yr
				ons = 1
			endif
			if b1 < 10 then
				serout c.1, T9600_8, ($FE, 192, " Yr 0", #b1)
			else
				serout c.1, T9600_8, ($FE, 192, " Yr ", #b1)
			endif
			if pinc.5 = 1 then
				b1 = b1 + 1
				b2 = b1 / 10 * 16
				set_yr = b1 // 10 or b2
				if b1 >= 21 then
					b1 = 0
				endif
				pause 500
			endif

		case 4
			if ons = 0 then
				b1 = hrs
				ons = 1
			endif
			if b1 < 10 then
				serout c.1, T9600_8, ($FE, 192, " Hr 0", #b1)
			else
				serout c.1, T9600_8, ($FE, 192, " Hr ", #b1)
			endif
			if pinc.5 = 1 then
				b1 = b1 + 1
				b2 = b1 / 10 * 16
				set_hrs = b1 // 10 or b2
				if b1 >= 24 then
					b1 = 0
				endif
				pause 500
			endif
		
		case 5
			if ons = 0 then
				b1 = mins
				ons = 1
			endif
			if b1 < 10 then
				serout c.1, T9600_8, ($FE, 192, "Min 0", #b1)
			else
				serout c.1, T9600_8, ($FE, 192, "Min ", #b1)
			endif
			if pinc.5 = 1 then
				b1 = b1 + 1
				b2 = b1 / 10 * 16
				set_mins = b1 // 10 or b2
				if b1 >= 60 then
					b1 = 0
				endif
				pause 500
			endif

		case 6
			if ons = 0 then
				b1 = sec
				ons = 1
			endif
			if b1 < 10 then
				serout c.1, T9600_8, ($FE, 192, "Sec 0", #b1)
			else
				serout c.1, T9600_8, ($FE, 192, "Sec ", #b1)
			endif
			if pinc.5 = 1 then
				b1 = b1 + 1
				b2 = b1 / 10 * 16
				set_sec = b1 // 10 or b2
				if b1 >= 60 then
					b1 = 0
				endif
				pause 500
			endif

		case 7
			pause 500

			sertxd (#set_sec, #set_mins, #set_hrs, #set_dow, #set_day, #set_mth, #set_yr, cr, lf)
			hi2cout 0, (set_sec, set_mins, set_hrs, set_dow, set_day, set_mth, set_yr, %00010000)
			set_enb = 0
	endselect
loop
b1 = 0
serout c.1, T9600_8, ($FE, $01)
return

cam_stat:
serout c.1, T9600_8, ($FE, 201, "Cam Off")
return

edit:
Another problem. I want to create what I call a "debounce timer". In other words, when an input goes high, wait for a time period before doing something. If the input goes low before the time period is elapsed then do nothing. I'm having trouble trying to find a way of doing that.

edit edit:
............. Getting a memory full error after adding settings for time on and time off. :( I either need to rob my 20x2 from another project, buy another x2 or scrap everything and use my Raspberry Pi......
 
Last edited:
Top