diff --git a/lua_modules/ds3231/ds3231.EN.md b/lua_modules/ds3231/ds3231.EN.md index 32b62527..a69e207a 100644 --- a/lua_modules/ds3231/ds3231.EN.md +++ b/lua_modules/ds3231/ds3231.EN.md @@ -39,10 +39,11 @@ package.loaded["ds3231"]=nil ## setTime() ####Description -Sets the current date and time. +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 @@ -110,5 +112,243 @@ ds3231 = nil package.loaded["ds3231"]=nil ``` +####See also +**-** []() + + +## 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 +**-** []() + + +## 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 +**-** []() + + +## 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 +**-** []() + + +## 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 +**-** []() + + +## 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 +**-** []() + + +## 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 **-** []() \ No newline at end of file diff --git a/lua_modules/ds3231/ds3231.lua b/lua_modules/ds3231/ds3231.lua index d13b89e8..a93064ca 100644 --- a/lua_modules/ds3231/ds3231.lua +++ b/lua_modules/ds3231/ds3231.lua @@ -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,10 +48,10 @@ 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") - i2c.setup(id, sda, scl, i2c.SLOW) + print("[LOG] DS3231 init done") + i2c.setup(id, sda, scl, i2c.SLOW) end --get time from DS3231 @@ -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