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: AustraliaPosts: 6101 |
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 |