Added full support for DS3231

This commit is contained in:
Vittorio Giovanelli 2016-02-07 21:19:33 +01:00
parent 25585672ae
commit ca104a96ce
2 changed files with 436 additions and 6 deletions

View File

@ -40,9 +40,10 @@ package.loaded["ds3231"]=nil
## setTime()
####Description
Sets the current date and time.
if _disableOscillator_ is set to 1 the oscillator will **stops** on battery.
####Syntax
setTime(second, minute, hour, day, date, month, year)
setTime(second, minute, hour, day, date, month, year, disableOscillator)
####Parameters
second: 00-59
@ -52,6 +53,7 @@ day: 1-7 (Sunday = 1, Saturday = 7)
date: 01-31
month: 01-12
year: 00-99
disableOscillator: (optional) 0-1
####Returns
nil
@ -112,3 +114,241 @@ package.loaded["ds3231"]=nil
```
####See also
**-** []()
<a id="ds3231_setAlarm"></a>
## setAlarm()
####Description
Set an alarm to be triggered on SQW pin:
_alarm1_ has a precision of **seconds**; _alarm2_ has a precision of **minutes** (`second` parameter will be ignored).
Alarms sets gpio.LOW over the SQW pin and let it unchanged until reloaded. When reloaded sets gpio.HIGH.
Alarms trigger **only once**, after that, if you want them to trigger again, you need to call `reloadAlarms()` or `setAlarm(...)` again.
Alarm type set the alarm match conditions:
- `ds3231.EVERYSECOND` works only with _alarm1_ and triggers every second;
- `ds3231.EVERYMINUTE` works only with _alarm2_ and triggers every minute (at 00 seconds);
- `ds3231.SECOND` triggers when time match given `seconds` parameter;
- `ds3231.MINUTE` triggers when time match given `seconds` and `minutes` parameters;
- `ds3231.HOUR` triggers when time match given `seconds`, `minutes`, and `hours` parameters;
- `ds3231.DAY` triggers when time match given `seconds`, `minutes`, and `hours` on week day `date/day` parameters;
- `ds3231.DATE` triggers when time match given `seconds`, `minutes`, and `hours` on date (day of the month) `date/day` parameters;
####Syntax
setAlarm(alarmId, alarmType, seconds, minutes, hours, date/day)
####Parameters
alarmId: 1-2
alarmType: 1-7
seconds: 00-59
minutes: 00-59
hours: 00-23
date/day: 01-31 or 1-7 (Sunday = 1, Saturday = 7)
####Returns
nil
####Example
```lua
ds3231=require("ds3231")
ds3231.init(3, 4)
-- Setting PIN1 to triggers on interrupt when alarm triggers
gpio.mode(1,gpio.INT)
gpio.trig(1,'down',function(level)
print('Time is passing')
-- If not reloaded it will be triggered only once
ds3231.reloadAlarms()
end)
ds3231.setAlarm(2,ds3231.EVERYMINUTE)
-- Don't forget to release it after use
ds3231 = nil
package.loaded["ds3231"]=nil
```
####See also
**-** []()
<a id="ds3231_reloadAlarms"></a>
## reloadAlarms()
####Description
Reload an already triggered alarm. Otherwise it will never be triggered again.
Alarms have to be reloaded both to let them triggers.
####Syntax
reloadAlarms()
####Parameters
nil
####Returns
nil
####Example
```lua
ds3231=require("ds3231")
ds3231.init(3, 4)
-- Setting PIN1 to triggers on interrupt when alarm triggers
gpio.mode(1,gpio.INT)
gpio.trig(1,'down',function(level)
print('Time is passing')
-- If not reloaded it will be triggered only once
ds3231.reloadAlarms()
end)
ds3231.setAlarm(2,ds3231.EVERYMINUTE)
-- Don't forget to release it after use
ds3231 = nil
package.loaded["ds3231"]=nil
```
####See also
**-** []()
<a id="ds3231_enableAlarm"></a>
## enableAlarm()
####Description
Enable an already setted alarm with the previous matching conditions. It reload alarms internally.
####Syntax
enableAlarm(alarmId)
####Parameters
alarmId: 1-2
####Returns
nil
####Example
```lua
ds3231=require("ds3231")
ds3231.init(3, 4)
-- Trigger on x:20:15
ds3231.setAlarm(1,ds3231.MINUTE,15,20)
if badThing == 1 then
ds3231.disableAlarm(1)
end
if goodThing == 1 then
ds3231.enableAlarm(1)
end
-- Don't forget to release it after use
ds3231 = nil
package.loaded["ds3231"]=nil
```
####See also
**-** []()
<a id="ds3231_disableAlarm"></a>
## disableAlarm()
####Description
Disable an already setted alarm with the previous matching conditions.
if _alarmId_ is not 1 or 2 it disables both alarms.
**Warning**: `disableAlarm()` prevent alarms to trigger interrupt over SQW pin but alarm itself will triggers at the matching conditions as it could be seen on _status byte_.
####Syntax
disableAlarm(alarmId)
####Parameters
alarmId: 0-2
####Returns
nil
####Example
```lua
ds3231=require("ds3231")
ds3231.init(3, 4)
-- Trigger on x:20:15
ds3231.setAlarm(1,ds3231.MINUTE,15,20)
if badThing == 1 then
ds3231.disableAlarm(1)
end
if goodThing == 1 then
ds3231.enableAlarm(1)
end
-- Don't forget to release it after use
ds3231 = nil
package.loaded["ds3231"]=nil
```
####See also
**-** []()
<a id="ds3231_getBytes"></a>
## getBytes()
####Description
Get bytes of control, for debug purpose, and status of DS3231. To see what they means check the [Datasheet](http://datasheets.maximintegrated.com/en/ds/DS3231.pdf)
####Syntax
getBytes()
####Parameters
nil
####Returns
control: integer. Control 0-255
status: integer. Status 0-143 (bit 6-5-4 unused)
####Example
```lua
ds3231=require("ds3231")
ds3231.init(3, 4)
control,status = ds3231.getBytes()
print('Control byte: '..control)
print('Status byte: '..status)
-- Don't forget to release it after use
ds3231 = nil
package.loaded["ds3231"]=nil
```
####See also
**-** []()
<a id="ds3231_resetStopFlag"></a>
## resetStopFlag()
####Description
Stop flag on status byte means that the oscillator either is stopped or was stopped for some period and may be used to judge the validity of the timekeeping data.
When setted to 1 this flag keeps that values until changed to 0.
Call `resetStopFlag()` if you need to check validity of time data after that.
####Syntax
resetStopFlag()
####Parameters
nil
####Returns
nil
####Example
```lua
ds3231=require("ds3231")
ds3231.init(3, 4)
control,status = ds3231.getBytes()
if bit.band(bit.rshift(status, 7),1) == 1 then
print('[WARNING] RTC has stopped')
ds3231.resetStopFlag()
end
-- Don't forget to release it after use
ds3231 = nil
package.loaded["ds3231"]=nil
```
####See also
**-** []()

View File

@ -9,6 +9,16 @@ local moduleName = ...
local M = {}
_G[moduleName] = M
-- Constants:
M.EVERYSECOND = 6
M.EVERYMINUTE = 7
M.SECOND = 1
M.MINUTE = 2
M.HOUR = 3
M.DAY = 4
M.DATE = 5
M.DISABLE = 0
-- Default value for i2c communication
local id = 0
@ -16,6 +26,7 @@ local id = 0
local dev_addr = 0x68
local function decToBcd(val)
if val == nil then return 0 end
return((((val/10) - ((val/10)%1)) *16) + (val%10))
end
@ -23,6 +34,11 @@ local function bcdToDec(val)
return((((val/16) - ((val/16)%1)) *10) + (val%16))
end
local function addAlarmBit(val,day)
if day == 1 then return bit.bor(val,64) end
return bit.bor(val,128)
end
-- initialize i2c
--parameters:
--d: sda
@ -32,9 +48,9 @@ function M.init(d, l)
sda = d
scl = l
else
print("iic config failed!") return nil
print("[ERROR] i2c config failed!") return nil
end
print("init done")
print("[LOG] DS3231 init done")
i2c.setup(id, sda, scl, i2c.SLOW)
end
@ -58,7 +74,8 @@ function M.getTime()
end
--set time for DS3231
function M.setTime(second, minute, hour, day, date, month, year)
-- enosc setted to 1 disables oscilation on battery, stopping time
function M.setTime(second, minute, hour, day, date, month, year, disOsc)
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x00)
@ -70,6 +87,179 @@ function M.setTime(second, minute, hour, day, date, month, year)
i2c.write(id, decToBcd(month))
i2c.write(id, decToBcd(year))
i2c.stop(id)
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x0E)
i2c.stop(id)
i2c.start(id)
i2c.address(id, dev_addr, i2c.RECEIVER)
local c = string.byte(i2c.read(id, 1), 1)
i2c.stop(id)
if disOsc == 1 then c = bit.bor(c,128)
else c = bit.band(c,127) end
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x0E)
i2c.write(id, c)
i2c.stop(id)
end
-- Reset alarmId flag to let alarm to be triggered again
function M.reloadAlarms ()
if bit == nil or bit.band == nil or bit.bor == nil then
print("[ERROR] Module bit is required to use alarm function")
return nil
end
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x0F)
i2c.stop(id)
i2c.start(id)
i2c.address(id, dev_addr, i2c.RECEIVER)
local d = string.byte(i2c.read(id, 1), 1)
i2c.stop(id)
-- Both flag needs to be 0 to let alarms trigger
d = bit.band(d,252)
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x0F)
i2c.write(id, d)
i2c.stop(id)
print('[LOG] Alarm '..almId..' reloaded')
end
-- Enable alarmId bit. Let it to be triggered
function M.enableAlarm (almId)
if bit == nil or bit.band == nil or bit.bor == nil then
print("[ERROR] Module bit is required to use alarm function")
return nil
end
if almId ~= 1 and almId ~= 2 then print('[ERROR] Wrong alarm id (1 or 2): '..almId) return end
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x0E)
i2c.stop(id)
i2c.start(id)
i2c.address(id, dev_addr, i2c.RECEIVER)
local c = string.byte(i2c.read(id, 1), 1)
i2c.stop(id)
c = bit.bor(c,4)
if almId == 1 then c = bit.bor(c,1)
else c = bit.bor(c,2) end
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x0E)
i2c.write(id, c)
i2c.stop(id)
M.reloadAlarms()
print('[LOG] Alarm '..almId..' enabled')
end
-- If almID equals 1 or 2 disable that alarm, otherwise disables both.
function M.disableAlarm (almId)
if bit == nil or bit.band == nil or bit.bor == nil then
print("[ERROR] Module bit is required to use alarm function")
return nil
end
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x0E)
i2c.stop(id)
i2c.start(id)
i2c.address(id, dev_addr, i2c.RECEIVER)
local c = string.byte(i2c.read(id, 1), 1)
i2c.stop(id)
if almId == 1 then c = bit.band(c, 254)
elseif almId == 2 then c = bit.band(c, 253)
else
almId = '1 and 2'
c = bit.band(c, 252)
end
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x0E)
i2c.write(id, c)
i2c.stop(id)
print('[LOG] Alarm '..almId..' disabled')
end
-- almId can be 1 or 2;
-- almType should be taken from constants
function M.setAlarm (almId, almType, second, minute, hour, date)
if bit == nil or bit.band == nil or bit.bor == nil then
print("[ERROR] Module bit is required to use alarm function")
return nil
end
if almId ~= 1 and almId ~= 2 then print('[ERROR] Wrong alarm id (1 or 2): '..almId) return end
M.enableAlarm(almId)
second = decToBcd(second)
minute = decToBcd(minute)
hour = decToBcd(hour)
date = decToBcd(date)
if almType == M.EVERYSECOND or almType == M.EVERYMINUTE then
second = addAlarmBit(second)
minute = addAlarmBit(minute)
hour = addAlarmBit(hour)
date = addAlarmBit(date)
elseif almType == M.SECOND then
minute = addAlarmBit(minute)
hour = addAlarmBit(hour)
date = addAlarmBit(date)
elseif almType == M.MINUTE then
hour = addAlarmBit(hour)
date = addAlarmBit(date)
elseif almType == M.HOUR then
date = addAlarmBit(date)
elseif almType == M.DAY then
date = addAlarmBit(date,1)
end
local almStart = 0x07
if almId == 2 then almStart = 0x0B end
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, almStart)
if almId == 1 then i2c.write(id, second) end
i2c.write(id, minute)
i2c.write(id, hour)
i2c.write(id, date)
i2c.stop(id)
print('[LOG] Alarm '..almId..' setted')
end
-- Get Control and Status bytes
function M.getBytes ()
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x0E)
i2c.stop(id)
i2c.start(id)
i2c.address(id, dev_addr, i2c.RECEIVER)
local c = i2c.read(id, 2)
i2c.stop(id)
return tonumber(string.byte(c, 1)), tonumber(string.byte(c, 2))
end
-- Resetting RTC Stop Flag
function M.resetStopFlag ()
if bit == nil or bit.band == nil or bit.bor == nil then
print("[ERROR] Module bit is required to reset stop flag")
return nil
end
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x0F)
i2c.stop(id)
i2c.start(id)
i2c.address(id, dev_addr, i2c.RECEIVER)
local s = string.byte(i2c.read(id, 1))
i2c.stop(id)
s = bit.band(s,127)
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x0F)
i2c.write(id, s)
i2c.stop(id)
print('[LOG] RTC stop flag resetted')
end
return M