GitHub: https://github.com/ForceTronics/nRF24L01-Sensor-Network-that-Connects-to-the-Cloud/tree/master
The ForceTronics blog provides tutorials on creating fun and unique electronic projects. The goal of each project will be to create a foundation or jumping off point for amateur, hobbyist, and professional engineers to build on and innovate. Please use the comments section for questions and go to forcetronics.com for information on forcetronics consulting services.
Showing posts with label RTC. Show all posts
Showing posts with label RTC. Show all posts
Thursday, November 3, 2016
Creating a Sensor Network that Connects to the Cloud Part 2
In this three part series we look at how to create a wireless sensor mesh network that stores data on the cloud using the Arduino platform. In part two we look at how to add time stamps to our sensor data and track the battery state of our nodes.
GitHub: https://github.com/ForceTronics/nRF24L01-Sensor-Network-that-Connects-to-the-Cloud/tree/master
GitHub: https://github.com/ForceTronics/nRF24L01-Sensor-Network-that-Connects-to-the-Cloud/tree/master
Labels:
arduino,
cloud,
mesh,
MKR1000,
nRF24L01,
phant,
real time clock,
RTC,
sensor,
temperature,
Tutorial,
WiFi,
wireless
Saturday, September 24, 2016
Reducing Power Consumption on Arduino Zero, MKR1000, or any SAMD21 Arduino Part 1
In this multiple part series we look at how to reduce power consumption for battery powered designs that utilize Arduino's with the Atmel SAMD21 MCU (Zero, MKR1000, etc). In part one we look at how to put the SAMD21 to sleep and wake it up with either the real time clock (RTC) or an external event on an input pin.
//***************Arduino Sketch from the video*********************.
//This code was used for a tutorial on the ForceTronics YouTube channel. It shows how to save power
//by putting Arduino's based on the SAMD21 MCU (MKR1000, Zero, etc) to sleep and how to wake them
//This code is public domain for anybody to use or modify
//#include "RTCZero.h"
#include <RTCZero.h>
/* Create an rtc object */
RTCZero rtc;
/* Change these values to set the current initial time */
const byte seconds = 0;
const byte minutes = 00;
const byte hours = 00;
/* Change these values to set the current initial date */
const byte day = 24;
const byte month = 9;
const byte year = 16;
void setup()
{
delay(5000); //delay so we can see normal current draw
pinMode(LED_BUILTIN, OUTPUT); //set LED pin to output
digitalWrite(LED_BUILTIN, LOW); //turn LED off
rtc.begin(); //Start RTC library, this is where the clock source is initialized
rtc.setTime(hours, minutes, seconds); //set time
rtc.setDate(day, month, year); //set date
rtc.setAlarmTime(00, 00, 10); //set alarm time to go off in 10 seconds
//following two lines enable alarm, comment both out if you want to do external interrupt
rtc.enableAlarm(rtc.MATCH_HHMMSS); //set alarm
rtc.attachInterrupt(ISR); //creates an interrupt that wakes the SAMD21 which is triggered by a FTC alarm
//comment out the below line if you are using RTC alarm for interrupt
// extInterrupt(A1); //creates an interrupt source on external pin
//puts SAMD21 to sleep
rtc.standbyMode(); //library call
//samSleep(); //function to show how call works
}
void loop()
{
//do nothing in main loop
}
//interrupt service routine (ISR), called when interrupt is triggered
//executes after MCU wakes up
void ISR()
{
digitalWrite(LED_BUILTIN, HIGH);
}
//function that sets up external interrupt
void extInterrupt(int interruptPin) {
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(interruptPin, ISR, LOW);
}
//function to show how to put the
void samSleep()
{
// Set the sleep mode to standby
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
// SAMD sleep
__WFI();
}
//**********************Changed "begin" function from RTCZero Library**************
void RTCZero::begin(bool resetTime)
{
uint16_t tmp_reg = 0;
PM->APBAMASK.reg |= PM_APBAMASK_RTC; // turn on digital interface clock
//config32kOSC();
// If the RTC is in clock mode and the reset was
// not due to POR or BOD, preserve the clock time
// POR causes a reset anyway, BOD behaviour is?
bool validTime = false;
RTC_MODE2_CLOCK_Type oldTime;
if ((!resetTime) && (PM->RCAUSE.reg & (PM_RCAUSE_SYST | PM_RCAUSE_WDT | PM_RCAUSE_EXT))) {
if (RTC->MODE2.CTRL.reg & RTC_MODE2_CTRL_MODE_CLOCK) {
validTime = true;
oldTime.reg = RTC->MODE2.CLOCK.reg;
}
}
// Setup clock GCLK2 with OSC32K divided by 32
GCLK->GENDIV.reg = GCLK_GENDIV_ID(2)|GCLK_GENDIV_DIV(4);
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
; /*XOSC32K*/
GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_DIVSEL );
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
;
GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | (RTC_GCLK_ID << GCLK_CLKCTRL_ID_Pos)));
while (GCLK->STATUS.bit.SYNCBUSY)
;
RTCdisable();
RTCreset();
tmp_reg |= RTC_MODE2_CTRL_MODE_CLOCK; // set clock operating mode
tmp_reg |= RTC_MODE2_CTRL_PRESCALER_DIV1024; // set prescaler to 1024 for MODE2
tmp_reg &= ~RTC_MODE2_CTRL_MATCHCLR; // disable clear on match
//According to the datasheet RTC_MODE2_CTRL_CLKREP = 0 for 24h
tmp_reg &= ~RTC_MODE2_CTRL_CLKREP; // 24h time representation
RTC->MODE2.READREQ.reg &= ~RTC_READREQ_RCONT; // disable continuously mode
RTC->MODE2.CTRL.reg = tmp_reg;
while (RTCisSyncing())
;
NVIC_EnableIRQ(RTC_IRQn); // enable RTC interrupt
NVIC_SetPriority(RTC_IRQn, 0x00);
RTC->MODE2.INTENSET.reg |= RTC_MODE2_INTENSET_ALARM0; // enable alarm interrupt
RTC->MODE2.Mode2Alarm[0].MASK.bit.SEL = MATCH_OFF; // default alarm match is off (disabled)
while (RTCisSyncing())
;
RTCenable();
RTCresetRemove();
// If desired and valid, restore the time value
if ((!resetTime) && (validTime)) {
RTC->MODE2.CLOCK.reg = oldTime.reg;
while (RTCisSyncing())
;
}
_configured = true;
}
//***************Arduino Sketch from the video*********************.
//This code was used for a tutorial on the ForceTronics YouTube channel. It shows how to save power
//by putting Arduino's based on the SAMD21 MCU (MKR1000, Zero, etc) to sleep and how to wake them
//This code is public domain for anybody to use or modify
//#include "RTCZero.h"
#include <RTCZero.h>
/* Create an rtc object */
RTCZero rtc;
/* Change these values to set the current initial time */
const byte seconds = 0;
const byte minutes = 00;
const byte hours = 00;
/* Change these values to set the current initial date */
const byte day = 24;
const byte month = 9;
const byte year = 16;
void setup()
{
delay(5000); //delay so we can see normal current draw
pinMode(LED_BUILTIN, OUTPUT); //set LED pin to output
digitalWrite(LED_BUILTIN, LOW); //turn LED off
rtc.begin(); //Start RTC library, this is where the clock source is initialized
rtc.setTime(hours, minutes, seconds); //set time
rtc.setDate(day, month, year); //set date
rtc.setAlarmTime(00, 00, 10); //set alarm time to go off in 10 seconds
//following two lines enable alarm, comment both out if you want to do external interrupt
rtc.enableAlarm(rtc.MATCH_HHMMSS); //set alarm
rtc.attachInterrupt(ISR); //creates an interrupt that wakes the SAMD21 which is triggered by a FTC alarm
//comment out the below line if you are using RTC alarm for interrupt
// extInterrupt(A1); //creates an interrupt source on external pin
//puts SAMD21 to sleep
rtc.standbyMode(); //library call
//samSleep(); //function to show how call works
}
void loop()
{
//do nothing in main loop
}
//interrupt service routine (ISR), called when interrupt is triggered
//executes after MCU wakes up
void ISR()
{
digitalWrite(LED_BUILTIN, HIGH);
}
//function that sets up external interrupt
void extInterrupt(int interruptPin) {
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(interruptPin, ISR, LOW);
}
//function to show how to put the
void samSleep()
{
// Set the sleep mode to standby
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
// SAMD sleep
__WFI();
}
//**********************Changed "begin" function from RTCZero Library**************
void RTCZero::begin(bool resetTime)
{
uint16_t tmp_reg = 0;
PM->APBAMASK.reg |= PM_APBAMASK_RTC; // turn on digital interface clock
//config32kOSC();
// If the RTC is in clock mode and the reset was
// not due to POR or BOD, preserve the clock time
// POR causes a reset anyway, BOD behaviour is?
bool validTime = false;
RTC_MODE2_CLOCK_Type oldTime;
if ((!resetTime) && (PM->RCAUSE.reg & (PM_RCAUSE_SYST | PM_RCAUSE_WDT | PM_RCAUSE_EXT))) {
if (RTC->MODE2.CTRL.reg & RTC_MODE2_CTRL_MODE_CLOCK) {
validTime = true;
oldTime.reg = RTC->MODE2.CLOCK.reg;
}
}
// Setup clock GCLK2 with OSC32K divided by 32
GCLK->GENDIV.reg = GCLK_GENDIV_ID(2)|GCLK_GENDIV_DIV(4);
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
; /*XOSC32K*/
GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_DIVSEL );
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
;
GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | (RTC_GCLK_ID << GCLK_CLKCTRL_ID_Pos)));
while (GCLK->STATUS.bit.SYNCBUSY)
;
RTCdisable();
RTCreset();
tmp_reg |= RTC_MODE2_CTRL_MODE_CLOCK; // set clock operating mode
tmp_reg |= RTC_MODE2_CTRL_PRESCALER_DIV1024; // set prescaler to 1024 for MODE2
tmp_reg &= ~RTC_MODE2_CTRL_MATCHCLR; // disable clear on match
//According to the datasheet RTC_MODE2_CTRL_CLKREP = 0 for 24h
tmp_reg &= ~RTC_MODE2_CTRL_CLKREP; // 24h time representation
RTC->MODE2.READREQ.reg &= ~RTC_READREQ_RCONT; // disable continuously mode
RTC->MODE2.CTRL.reg = tmp_reg;
while (RTCisSyncing())
;
NVIC_EnableIRQ(RTC_IRQn); // enable RTC interrupt
NVIC_SetPriority(RTC_IRQn, 0x00);
RTC->MODE2.INTENSET.reg |= RTC_MODE2_INTENSET_ALARM0; // enable alarm interrupt
RTC->MODE2.Mode2Alarm[0].MASK.bit.SEL = MATCH_OFF; // default alarm match is off (disabled)
while (RTCisSyncing())
;
RTCenable();
RTCresetRemove();
// If desired and valid, restore the time value
if ((!resetTime) && (validTime)) {
RTC->MODE2.CLOCK.reg = oldTime.reg;
while (RTCisSyncing())
;
}
_configured = true;
}
Labels:
arduino,
Atmel,
battery,
interrupt,
MKR1000,
real time clock,
RTC,
SAMD21,
sleep,
Tutorial,
Zero
Subscribe to:
Posts (Atom)