Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 02:45 29 Nov 2024 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 : PCF8563 RTC alarm and timer

Author Message
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6101
Posted: 07:51pm 08 Mar 2014
Copy link to clipboard 
Print this post

I have been playing with the timer and alarm functions of the PCF8563 RTC

The PFC8563 can be used to interrupt (or wake) the MicroMite every x minutes/ seconds
Using the alarm functions, it can interrupt the MicroMite at a set time each day or every Tuesday etc.

The Interrupt pin on the PCF8563 needs a resistor to 3.3V. I used 47k but 10k is probably a better choice.
The Interrupt pin is then connected to a suitable MicroMite pin - I used pin 5 in the example.

The timer function allows you to count down a maximum of 255 either seconds or minutes.
The counter runs continuously without any need to reset it each time.


To do something useful, the code reads a BMP085 pressure transducer and a BH1750 light meter. Those functions can be remmed out as required.

Some of the sensors take a long time to do their thing.
In real life, I would consider starting the Light meter, doing the Pressure stuff and then going back to get the finished light reading.

' I2C devices PCF8563, BMP085, BH1750
' TassyJim 09 MAR 2014

dim RTCbuffer(16)
PCF8563address = &h51

Dim LightData(2)
BH1750address = &H23 ' BH1750 address

Dim BMPData(2) ' store data from BMP085
dim cal(11) ' calibration data
oss = 0 ' over sampling 0 to 3
alt = 240 ' put your altitude in metres here
BMP085calMEM = &HAA ' start of 11 calibration values
BMP085address = &H77 ' BMP085 address
BMP085control = &HF4 ' BMP085 control register
BMP085temp = &H2E ' BMP085 temperature command
BMP085pres = &H34 ' BMP085 pressure command
BMP085pres = BMP085pres + oss*&H40 ' adjust command for oversampling
BMP085reading = &HF6 ' register for results of reading

' setRTC() ' only do this if the MicroMite clock has been set first
rtc gettime
print "Startup at ";time$;" ";date$

I2C open 400, 200 ' Enable I2C. use slow speeds for long leads
pause 20

'r=setRTCint(10,2) ' set RTC to interrupt every 10 seconds
r=setRTCint(1,3) ' set RTC to interrupt every 1 minutes
'r=setRTCalarm(16,01) ' set the once a day alarm

z = Calibrate() ' read the calibration data
setpin 5, intl, doread ' set the interupt routine
doread ' do an initial reading

do
k$=inkey$
loop until k$=CHR$(27)

end

sub doread
r= clearRTCalarm()
t=temperature()
p=pressure(oss)
p0=Psl(p,alt)
L= lux()
rtc gettime ' keep the MicroMite time correct
print time$;" T:";str$(t,0,1);" P:";str$(p/100,0,1);" P(sl):";str$(p0/100,0,1);" Light: ";str$(l,0,0)
end sub

function Calibrate()
' needs to be called once for each BMP085 module.
' safest to do it on every program start.
local n, calMEM
I2C write BH1750address, 0, 1, &H01 ' Power on
pause 250
I2C write BH1750address, 0, 1, &H07 ' Reset

calMEM= BMP085calMEM
for n = 1 to 11
I2C write BMP085address, 0, 1, calMEM ' first calibration location
pause 1
I2C read BMP085address, 0, 2, BMPData(0)
cal(n) = BMPData(0)*256 + BMPData(1)
if n < 4 or n > 6 then ' need to convert some to signed numbers
if cal(n) > 32767 then
cal(n) = cal(n) - 65536
endif
endif
pause 1
calMEM=calMEM+2 ' advance to the next calibration location
next n
end function

function temperature()
' returns the temperature in degrees C to one decimal place
local UT, x1, x2, b5
I2C write BMP085address, 0, 2, BMP085control, BMP085temp
pause 5
I2C write BMP085address, 0, 1, BMP085reading
I2C read BMP085address, 0, 2, BMPData(0)
UT = BMPData(0)*256 + BMPData(1)
'calculate true temperature
x1= int( (UT-cal(6))*cal(5)/32768)
x2=int( cal(10)*2048/(x1+cal(11)))
b5=x1+x2
temperature = int((b5+8)/16)/10
end function

function pressure(oss)
' returns the pressure in pascals. Divide by 100 for millibars
' recalculates the temperature.
' time could be saved by reading the temperature once every 10 minutes
' when taking readings at short intervals
local UT, UP, x1, x2, x3, b5, b6, b7, pres, p
pres = BMP085pres + oss*&H40
I2C write BMP085address, 0, 2, BMP085control, BMP085temp
pause 5
I2C write BMP085address, 0, 1, BMP085reading
I2C read BMP085address, 0, 2, BMPData(0)
UT = BMPData(0)*256 + BMPData(1)
I2C write BMP085address, 0, 2, BMP085control, pres
if oss = 0 then ' different oversampling requires different
pause 5 ' reading times
elseif oss = 1 then
pause 8
elseif oss = 2 then
pause 14
else
pause 26
endif
I2C write BMP085address, 0, 1, BMP085reading
I2C read BMP085address, 0, 2, BMPData(0)
UP = BMPData(0)*256 + BMPData(1)
I2C write BMP085address, 0, 1, BMP085reading+2
I2C read BMP085address, 0, 1, BMPData(0)
UP=(UP*256+BMPData(0))/2^(8-oss)
'calculate true temperature
x1= int( (UT-cal(6))*cal(5)/32768)
x2=int( cal(10)*2048/(x1+cal(11)))
b5=x1+x2
t=int((b5+8)/16)/10
'print "Temperature: ",t
'calculate true atmospheric pressure
b6 = b5 - 4000
x1 = int((cal(8)*(b6*b6/4096))/2048)
x2 = int(cal(2)*b6/2048)
x3 = x1 + x2
b3 = int(((cal(1)*4+x3)*2^oss +2)/4)
x1 = int(cal(3)*b6/8192)
x2 = int((cal(7)*(b6*b6/4096))/65536)
x3 = int(((x1+x2)+2)/4)
b4 = int(cal(4)*x3/32768+cal(4))
b7 = int((UP - b3)*(50000/2^oss))
p = int((b7*2)/b4)
x1 = int(int(p/256)*int(p/256))
x1 = int((x1*3038)/65536)
x2 = int((-7357*p)/65536)
pressure = int(p+(x1 + x2 + 3791)/16)
end function

function Psl(p, alt)
'given local pressure and altitude, returns pressure at sea level
Psl= p/(1-alt/44330)^5.255
end function

function lux()
I2C write BH1750address, 0, 1, &H01 ' Power on
pause 50
I2C write BH1750address, 0, 1, &H20 ' 1 lx scaling, single reading
pause 150
I2C Read BH1750address, 0, 2, LightData(0)
lux= (LightData(0)*256 + LightData(1))/1.2
end function

function setRTCint(count,scale)
' scale: 2 = seconds, 3 = minutes
local t_ctrl
t_ctrl = 128 + scale
I2C write PCF8563address,0,1, &H00 ' set the starting address for a read
i2c read PCF8563address,0,16,RTCbuffer(0)
I2C write PCF8563address,0,2, &H01, &H11
I2C write PCF8563address,0,3, &H0E, t_ctrl, count' timer control register
setRTCint=RTCbuffer(1)
end function

function setRTCalarm(hour, minute,day,WkDay)
local alarmH,alarmM,alarmD,alarmWD
alarmH=int(hour/10)*16+(hour mod 10)
'alarmH=128 ' not used (once an hour)
alarmM=int(minute/10)*16+(minute mod 10)
'alarmD=int(day/10)*16+(day mod 10)
alarmD=128 ' not used (every day)
'alarmWD=WkDay
alarmWD=128 ' not used (every day)
I2C write PCF8563address,0,1, &H00
i2c read PCF8563address,0,16,RTCbuffer(0)
I2C write PCF8563address,0,2, &H01, &H12
I2C write PCF8563address,0,5, &H09, alarmM, alarmH,alarmD, alarmWD
setRTCint=RTCbuffer(1)
end function

FUNCTION setRTC()
' set the RTC to MicroMite time
local newtime$, year, month, day, hour, min, sec
newtime$= time$ ' make a copy to stop time changing while we set the clock
year = val(mid$(date$,9))
month = val(mid$(date$,4,2))
day = val(mid$(date$,1,2))
hour = val(mid$(newtime$,1,2))
min = val(mid$(newtime$,4,2))
sec = val(mid$(newtime$,7,2))
rtc settime year,month,day,hour,min,sec
END FUNCTION

function clearRTCalarm()
' two bits indicate if alarm or timer triggered the interupt
' we clear them both
local x
I2C write PCF8563address,0,1, &H00
i2c read PCF8563address,0,2,RTCbuffer(0)
x = (RTCbuffer(1) and &H13)
I2C write PCF8563address,0,2, &H01, x
clearRTCalarm=RTCbuffer(1) and &H0C ' 8 = alarm and 4 = timer
end function



All this clock watching takes up a lot of time....

Jim

VK7JH
MMedit   MMBasic Help
 
Print this page


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

© JAQ Software 2024