Link to GitHub library and sketch code from video https://github.com/ForceTronics/nRF24L01-Sensor-Network-that-Connects-to-the-Cloud
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.
Wednesday, October 26, 2016
Creating a Sensor Network that Connects to the Cloud Part 1
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 one we will look at the architecture of the network and how to get started sending sensor data to the cloud.
Link to GitHub library and sketch code from video https://github.com/ForceTronics/nRF24L01-Sensor-Network-that-Connects-to-the-Cloud
Link to GitHub library and sketch code from video https://github.com/ForceTronics/nRF24L01-Sensor-Network-that-Connects-to-the-Cloud
Friday, October 14, 2016
Utilizing Advanced ADC Capabilities on Arduino’s with the SAMD21 (Zero, MKR1000, etc) Part 1
We are all familiar with the Arduino "analogRead()" function, but there is a lot more to the SAMD21 ADC then just taking simple readings. In this video series we look at some of the more advanced ADC capabilities of the SAMD21 and how to use them. In part 1 we look at how to use the window monitoring capability of the ADC.
//*******************Arduino code from the video*********************
//This sketch is from a tutorial on the ForceTronics YouTube Channel called
//Utilizing Advanced ADC Capabilities on Arduino’s with the SAMD21 (Zero, MKR1000, etc)
//This code is public domain and free to anyone to use or modify at your own risk
//declare const for window mode settings
const byte DISABLE = 0;
const byte MODE1 = 1;
const byte MODE2 = 2;
const byte MODE3 = 3;
const byte MODE4 = 4;
void setup() {
//call this function to start the ADC in window and define the window parameters
ADCWindowBegin(MODE1, 512, 750); //Do not use the Arduino analog functions until you call ADCWindowEnd()
Serial.begin(57600);
}
void loop() {
delay(1500);
Serial.println(readADC()); //the "readADC()" function can be used to get ADC readings while in Window mode
Serial.println();
}
//This is the interrupt service routine (ISR) that is called
//if an ADC measurement falls out of the range of the window
void ADC_Handler() {
digitalWrite(LED_BUILTIN, HIGH); //turn LED off
ADC->INTFLAG.reg = ADC_INTFLAG_WINMON; //Need to reset interrupt
}
//this function sets up the ADC window mode with interrupt
void ADCWindowBegin(byte mode, int upper, int lower) {
setMeasPin(); //function sets up ADC pin A0 as input
setGenClock(); //setup ADC clock, using internal 8MHz clock
setUPADC(); //configure ADC
setADCWindow(mode, upper, lower); //setup ADC window mode
setUpInterrupt(0); //setup window mode interrupt with highest priority
enableADC(1); //enable ADC
}
void ADCWindowEnd() {
NVIC_DisableIRQ(ADC_IRQn); //turn off interrupt
enableADC(0); //disable ADC
}
//setup measurement pin, using Arduino ADC pin A3
void setMeasPin() {
// Input pin for ADC Arduino A3/PA04
REG_PORT_DIRCLR1 = PORT_PA04;
// Enable multiplexing on PA04
PORT->Group[0].PINCFG[4].bit.PMUXEN = 1;
PORT->Group[0].PMUX[1].reg = PORT_PMUX_PMUXE_B | PORT_PMUX_PMUXO_B;
}
//Function sets up generic clock for ADC
//Uses built-in 8MHz clock
void setGenClock() {
// Enable the APBC clock for the ADC
REG_PM_APBCMASK |= PM_APBCMASK_ADC;
configOSC8M(); //this function sets up the internal 8MHz clock that we will use for the ADC
// Setup clock GCLK3 for no div factor
GCLK->GENDIV.reg |= GCLK_GENDIV_ID(3)| GCLK_GENDIV_DIV(1);
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
//configure the generator of the generic clock, which is 8MHz clock
GCLK->GENCTRL.reg |= GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC8M | GCLK_GENCTRL_ID(3) | GCLK_GENCTRL_DIVSEL;
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
//enable clock, set gen clock number, and ID to where the clock goes (30 is ADC)
GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(3) | GCLK_CLKCTRL_ID(30);
while (GCLK->STATUS.bit.SYNCBUSY);
}
//Function that does general settings for ADC
//sets it for a single sample
//Uses internal voltage reference
//sets gain factor to 1/2
void setUPADC() {
// Select reference, internal VCC/2
ADC->REFCTRL.reg |= ADC_REFCTRL_REFSEL_INTVCC1; // VDDANA/2, combine with gain DIV2 for full VCC range
// Average control 1 sample, no right-shift
ADC->AVGCTRL.reg |= ADC_AVGCTRL_ADJRES(0) | ADC_AVGCTRL_SAMPLENUM_1;
// Sampling time, no extra sampling half clock-cycles
REG_ADC_SAMPCTRL |= ADC_SAMPCTRL_SAMPLEN(0);
// Input control: set gain to div by two so ADC has measurement range of VCC, no diff measurement so set neg to gnd, pos input set to pin 0 or A0
ADC->INPUTCTRL.reg |= ADC_INPUTCTRL_GAIN_DIV2 | ADC_INPUTCTRL_MUXNEG_GND | ADC_INPUTCTRL_MUXPOS_PIN4;
while (REG_ADC_STATUS & ADC_STATUS_SYNCBUSY);
// PS16, 8 MHz, ADC_CLK = 500 kHz, ADC sampling rate, single eded, 12 bit, free running, DIV2 gain, 7 ADC_CLKs, 14 usec
ADC->CTRLB.reg |= ADC_CTRLB_PRESCALER_DIV16 | ADC_CTRLB_RESSEL_10BIT | ADC_CTRLB_FREERUN; // Run ADC continously, 7 ADC_CLKs, 14 usec
while (REG_ADC_STATUS & ADC_STATUS_SYNCBUSY);
}
//This function is used to setup the ADC windowing mode
//inputs are the mode, upper window value, and lower window value
//
void setADCWindow(byte mode, int upper, int lower) {
ADC->WINCTRL.reg = mode; //set window mode
while (ADC->STATUS.bit.SYNCBUSY);
ADC->WINUT.reg = upper; //set upper threshold
while (ADC->STATUS.bit.SYNCBUSY);
ADC->WINLT.reg = lower; //set lower threshold
while (ADC->STATUS.bit.SYNCBUSY);
}
//This function sets up an ADC interrupt that is triggered
//when an ADC value is out of range of the window
//input argument is priority of interrupt (0 is highest priority)
void setUpInterrupt(byte priority) {
ADC->INTENSET.reg |= ADC_INTENSET_WINMON; // enable ADC window monitor interrupt
while (ADC->STATUS.bit.SYNCBUSY);
NVIC_EnableIRQ(ADC_IRQn); // enable ADC interrupts
NVIC_SetPriority(ADC_IRQn, priority); //set priority of the interrupt
}
//function allows you to enable or disable ADC
void enableADC(bool en) {
if(en) ADC->CTRLA.reg = 2; //2 is binary 010 which is register bit to enable ADC
else ADC->CTRLA.reg = 0; //0 disables ADC
}
//This function will return the latest ADC reading made during free run window mode
//must first start the ADC before calling this function
unsigned int readADC() {
// Free running, wait for conversion to complete
while (!(REG_ADC_INTFLAG & ADC_INTFLAG_RESRDY));
// Wait for synchronization before reading RESULT
while (REG_ADC_STATUS & ADC_STATUS_SYNCBUSY);
return REG_ADC_RESULT;
}
//function enables the 8MHz clock used for the ADC
void configOSC8M()
{
SYSCTRL->OSC8M.reg |= SYSCTRL_OSC8M_ENABLE;
}
//*******************Arduino code from the video*********************
//This sketch is from a tutorial on the ForceTronics YouTube Channel called
//Utilizing Advanced ADC Capabilities on Arduino’s with the SAMD21 (Zero, MKR1000, etc)
//This code is public domain and free to anyone to use or modify at your own risk
//declare const for window mode settings
const byte DISABLE = 0;
const byte MODE1 = 1;
const byte MODE2 = 2;
const byte MODE3 = 3;
const byte MODE4 = 4;
void setup() {
//call this function to start the ADC in window and define the window parameters
ADCWindowBegin(MODE1, 512, 750); //Do not use the Arduino analog functions until you call ADCWindowEnd()
Serial.begin(57600);
}
void loop() {
delay(1500);
Serial.println(readADC()); //the "readADC()" function can be used to get ADC readings while in Window mode
Serial.println();
}
//This is the interrupt service routine (ISR) that is called
//if an ADC measurement falls out of the range of the window
void ADC_Handler() {
digitalWrite(LED_BUILTIN, HIGH); //turn LED off
ADC->INTFLAG.reg = ADC_INTFLAG_WINMON; //Need to reset interrupt
}
//this function sets up the ADC window mode with interrupt
void ADCWindowBegin(byte mode, int upper, int lower) {
setMeasPin(); //function sets up ADC pin A0 as input
setGenClock(); //setup ADC clock, using internal 8MHz clock
setUPADC(); //configure ADC
setADCWindow(mode, upper, lower); //setup ADC window mode
setUpInterrupt(0); //setup window mode interrupt with highest priority
enableADC(1); //enable ADC
}
void ADCWindowEnd() {
NVIC_DisableIRQ(ADC_IRQn); //turn off interrupt
enableADC(0); //disable ADC
}
//setup measurement pin, using Arduino ADC pin A3
void setMeasPin() {
// Input pin for ADC Arduino A3/PA04
REG_PORT_DIRCLR1 = PORT_PA04;
// Enable multiplexing on PA04
PORT->Group[0].PINCFG[4].bit.PMUXEN = 1;
PORT->Group[0].PMUX[1].reg = PORT_PMUX_PMUXE_B | PORT_PMUX_PMUXO_B;
}
//Function sets up generic clock for ADC
//Uses built-in 8MHz clock
void setGenClock() {
// Enable the APBC clock for the ADC
REG_PM_APBCMASK |= PM_APBCMASK_ADC;
configOSC8M(); //this function sets up the internal 8MHz clock that we will use for the ADC
// Setup clock GCLK3 for no div factor
GCLK->GENDIV.reg |= GCLK_GENDIV_ID(3)| GCLK_GENDIV_DIV(1);
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
//configure the generator of the generic clock, which is 8MHz clock
GCLK->GENCTRL.reg |= GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC8M | GCLK_GENCTRL_ID(3) | GCLK_GENCTRL_DIVSEL;
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
//enable clock, set gen clock number, and ID to where the clock goes (30 is ADC)
GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(3) | GCLK_CLKCTRL_ID(30);
while (GCLK->STATUS.bit.SYNCBUSY);
}
//Function that does general settings for ADC
//sets it for a single sample
//Uses internal voltage reference
//sets gain factor to 1/2
void setUPADC() {
// Select reference, internal VCC/2
ADC->REFCTRL.reg |= ADC_REFCTRL_REFSEL_INTVCC1; // VDDANA/2, combine with gain DIV2 for full VCC range
// Average control 1 sample, no right-shift
ADC->AVGCTRL.reg |= ADC_AVGCTRL_ADJRES(0) | ADC_AVGCTRL_SAMPLENUM_1;
// Sampling time, no extra sampling half clock-cycles
REG_ADC_SAMPCTRL |= ADC_SAMPCTRL_SAMPLEN(0);
// Input control: set gain to div by two so ADC has measurement range of VCC, no diff measurement so set neg to gnd, pos input set to pin 0 or A0
ADC->INPUTCTRL.reg |= ADC_INPUTCTRL_GAIN_DIV2 | ADC_INPUTCTRL_MUXNEG_GND | ADC_INPUTCTRL_MUXPOS_PIN4;
while (REG_ADC_STATUS & ADC_STATUS_SYNCBUSY);
// PS16, 8 MHz, ADC_CLK = 500 kHz, ADC sampling rate, single eded, 12 bit, free running, DIV2 gain, 7 ADC_CLKs, 14 usec
ADC->CTRLB.reg |= ADC_CTRLB_PRESCALER_DIV16 | ADC_CTRLB_RESSEL_10BIT | ADC_CTRLB_FREERUN; // Run ADC continously, 7 ADC_CLKs, 14 usec
while (REG_ADC_STATUS & ADC_STATUS_SYNCBUSY);
}
//This function is used to setup the ADC windowing mode
//inputs are the mode, upper window value, and lower window value
//
void setADCWindow(byte mode, int upper, int lower) {
ADC->WINCTRL.reg = mode; //set window mode
while (ADC->STATUS.bit.SYNCBUSY);
ADC->WINUT.reg = upper; //set upper threshold
while (ADC->STATUS.bit.SYNCBUSY);
ADC->WINLT.reg = lower; //set lower threshold
while (ADC->STATUS.bit.SYNCBUSY);
}
//This function sets up an ADC interrupt that is triggered
//when an ADC value is out of range of the window
//input argument is priority of interrupt (0 is highest priority)
void setUpInterrupt(byte priority) {
ADC->INTENSET.reg |= ADC_INTENSET_WINMON; // enable ADC window monitor interrupt
while (ADC->STATUS.bit.SYNCBUSY);
NVIC_EnableIRQ(ADC_IRQn); // enable ADC interrupts
NVIC_SetPriority(ADC_IRQn, priority); //set priority of the interrupt
}
//function allows you to enable or disable ADC
void enableADC(bool en) {
if(en) ADC->CTRLA.reg = 2; //2 is binary 010 which is register bit to enable ADC
else ADC->CTRLA.reg = 0; //0 disables ADC
}
//This function will return the latest ADC reading made during free run window mode
//must first start the ADC before calling this function
unsigned int readADC() {
// Free running, wait for conversion to complete
while (!(REG_ADC_INTFLAG & ADC_INTFLAG_RESRDY));
// Wait for synchronization before reading RESULT
while (REG_ADC_STATUS & ADC_STATUS_SYNCBUSY);
return REG_ADC_RESULT;
}
//function enables the 8MHz clock used for the ADC
void configOSC8M()
{
SYSCTRL->OSC8M.reg |= SYSCTRL_OSC8M_ENABLE;
}
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
Thursday, September 15, 2016
Reducing Power Consumption on the Arduino Enabled ESP8266
In this tutorial we look at how to reduce the power consumption of your Arduino enabled ESP8266 WiFi module for battery powered applications.
//**************Arduino code: ESP8266_Sleep_Example *************
/*
This sketch was created for a tutorial on saving power using the ESP8266 with the Arduino IDE
That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to use
at their own risk
*/
#include <Arduino.h>
#include <ESP8266WiFi.h> //not using WiFi but need for some of the sleep commands
const int LED_PIN = 5; // Thing's onboard, green LED
const int sleepTimeS = 5; //sets deepsleep time to 5 sec
void setup()
{
pinMode(LED_PIN,OUTPUT); //setup LED pin
flashLED(); //function that flashes LED on and off
WiFi.forceSleepBegin(0); //this function turns on modem sleep mode (turns off RF but not CPU)
flashLED();
WiFi.forceSleepWake(); //wakes modem up from sleep mode
flashLED();
// deepSleep time is defined in microseconds. Multiply seconds by 1e6
ESP.deepSleep(sleepTimeS * 1000000); //Can also add mode setting: WAKE_RF_DEFAULT, WAKE_RFCAL, WAKE_NO_RFCAL, WAKE_RF_DISABLED
//ESP.deepSleep(0,WAKE_RF_DEFAULT); //In Deep-sleep mode, the chip can be woken up and initialized by a low-level pulse
//generated on the EXT_RSTB pin via an external IO
}
void loop()
{ //do nothing in the loop
}
//function that flashes LED at 1.5sec intervals
void flashLED() {
digitalWrite(LED_PIN, HIGH);
delay(1500);
digitalWrite(LED_PIN, LOW);
delay(1500);
}
//**************Arduino code: ESP8266_Sleep_Cloud_Example *************
/*
This sketch was used for a tutorial on saving power with the ESP8266 using Arduino IDE
That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to
use or modify at your own risk
Note that this code was leveraged from a Sparkfun example
on using their cloud service Phant
*/
#include <Arduino.h>
// Include the ESP8266 WiFi library.
#include <ESP8266WiFi.h>
// Include the SparkFun Phant library.
#include <Phant.h>
//Set your network name and password
const char WiFiSSID[] = "YourNetwork";
const char WiFiPSK[] = "YourPassword";
//define constants for pin control and node number
const int LED_PIN = 5; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int NODE_NUM = 1; //node identifier
//declare phant address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char PublicKey[] = "YourPublicKey";
const char PrivateKey[] = "YourPrivateKey";
//specify the rate that you post data to cloud
const unsigned long postRate = 15000;
unsigned long lastPost = 0;
const int sleepTimeS = 15;
void setup()
{
initHardware(); //setup arduino hardware
connectWiFi(); //Connect your WiFi network
digitalWrite(LED_PIN, HIGH);
while (postToPhant() != 1) //post to cloud in setup code because we will reset after sleep
{
delay(100);
}
digitalWrite(LED_PIN, LOW);
// deepSleep time is defined in microseconds. Multiply
// seconds by 1e6
ESP.deepSleep(sleepTimeS * 1000000); //This is where we go to sleep, will reset upon waking up
}
void loop()
{ //do nothing here
}
//function used to connect to WiFi network and where we set transmit power level
void connectWiFi()
{
byte ledStatus = LOW;
//Set transmit power level
WiFi.setOutputPower(0.0); //sets transmit power to 0dbm to lower power consumption, but reduces usable range
// Set WiFi mode to station (as opposed to AP or AP_STA)
WiFi.mode(WIFI_STA);
// WiFI.begin([ssid], [passkey]) initiates a WiFI connection
// to the stated [ssid], using the [passkey] as a WPA, WPA2,
// or WEP passphrase.
WiFi.begin(WiFiSSID, WiFiPSK);
// Use the WiFi.status() function to check if the ESP8266
// is connected to a WiFi network.
while (WiFi.status() != WL_CONNECTED)
{
// Blink the LED
digitalWrite(LED_PIN, ledStatus); // Write LED high/low
ledStatus = (ledStatus == HIGH) ? LOW : HIGH;
// Delays allow the ESP8266 to perform critical tasks
// defined outside of the sketch. These tasks include
// setting up, and maintaining, a WiFi connection.
delay(100);
// Potentially infinite loops are generally dangerous.
// Add delays -- allowing the processor to perform other
// tasks -- wherever possible.
}
}
//function that sets up some initial hardware states
void initHardware()
{
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
}
//this function takes data and posts it to the cloud
int postToPhant()
{
// LED turns on when we enter, it'll go off when we
// successfully post.
digitalWrite(LED_PIN, HIGH);
// Declare an object from the Phant library - phant
Phant phant(PhantHost, PublicKey, PrivateKey);
//These functions build data and field string that will be sent to phant cloud
phant.add("adcdata", analogRead(ANALOG_PIN));
phant.add("wifinode", NODE_NUM);
// Now connect to data.sparkfun.com, and post our data:
WiFiClient client; //declare client object that will post the data
const int httpPort = 80; //specify port to post through
if (!client.connect(PhantHost, httpPort)) //attempt to connect to phant
{
// If we fail to connect, return 0.
return 0;
}
//Send post to phant
client.print(phant.post());
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
//Serial.print(line); // Trying to avoid using serial
}
// Before we exit, turn the LED off.
digitalWrite(LED_PIN, LOW);
return 1; // Return success
}
//**************Arduino code: ESP8266_Sleep_Example *************
/*
This sketch was created for a tutorial on saving power using the ESP8266 with the Arduino IDE
That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to use
at their own risk
*/
#include <Arduino.h>
#include <ESP8266WiFi.h> //not using WiFi but need for some of the sleep commands
const int LED_PIN = 5; // Thing's onboard, green LED
const int sleepTimeS = 5; //sets deepsleep time to 5 sec
void setup()
{
pinMode(LED_PIN,OUTPUT); //setup LED pin
flashLED(); //function that flashes LED on and off
WiFi.forceSleepBegin(0); //this function turns on modem sleep mode (turns off RF but not CPU)
flashLED();
WiFi.forceSleepWake(); //wakes modem up from sleep mode
flashLED();
// deepSleep time is defined in microseconds. Multiply seconds by 1e6
ESP.deepSleep(sleepTimeS * 1000000); //Can also add mode setting: WAKE_RF_DEFAULT, WAKE_RFCAL, WAKE_NO_RFCAL, WAKE_RF_DISABLED
//ESP.deepSleep(0,WAKE_RF_DEFAULT); //In Deep-sleep mode, the chip can be woken up and initialized by a low-level pulse
//generated on the EXT_RSTB pin via an external IO
}
void loop()
{ //do nothing in the loop
}
//function that flashes LED at 1.5sec intervals
void flashLED() {
digitalWrite(LED_PIN, HIGH);
delay(1500);
digitalWrite(LED_PIN, LOW);
delay(1500);
}
//**************Arduino code: ESP8266_Sleep_Cloud_Example *************
/*
This sketch was used for a tutorial on saving power with the ESP8266 using Arduino IDE
That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to
use or modify at your own risk
Note that this code was leveraged from a Sparkfun example
on using their cloud service Phant
*/
#include <Arduino.h>
// Include the ESP8266 WiFi library.
#include <ESP8266WiFi.h>
// Include the SparkFun Phant library.
#include <Phant.h>
//Set your network name and password
const char WiFiSSID[] = "YourNetwork";
const char WiFiPSK[] = "YourPassword";
//define constants for pin control and node number
const int LED_PIN = 5; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int NODE_NUM = 1; //node identifier
//declare phant address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char PublicKey[] = "YourPublicKey";
const char PrivateKey[] = "YourPrivateKey";
//specify the rate that you post data to cloud
const unsigned long postRate = 15000;
unsigned long lastPost = 0;
const int sleepTimeS = 15;
void setup()
{
initHardware(); //setup arduino hardware
connectWiFi(); //Connect your WiFi network
digitalWrite(LED_PIN, HIGH);
while (postToPhant() != 1) //post to cloud in setup code because we will reset after sleep
{
delay(100);
}
digitalWrite(LED_PIN, LOW);
// deepSleep time is defined in microseconds. Multiply
// seconds by 1e6
ESP.deepSleep(sleepTimeS * 1000000); //This is where we go to sleep, will reset upon waking up
}
void loop()
{ //do nothing here
}
//function used to connect to WiFi network and where we set transmit power level
void connectWiFi()
{
byte ledStatus = LOW;
//Set transmit power level
WiFi.setOutputPower(0.0); //sets transmit power to 0dbm to lower power consumption, but reduces usable range
// Set WiFi mode to station (as opposed to AP or AP_STA)
WiFi.mode(WIFI_STA);
// WiFI.begin([ssid], [passkey]) initiates a WiFI connection
// to the stated [ssid], using the [passkey] as a WPA, WPA2,
// or WEP passphrase.
WiFi.begin(WiFiSSID, WiFiPSK);
// Use the WiFi.status() function to check if the ESP8266
// is connected to a WiFi network.
while (WiFi.status() != WL_CONNECTED)
{
// Blink the LED
digitalWrite(LED_PIN, ledStatus); // Write LED high/low
ledStatus = (ledStatus == HIGH) ? LOW : HIGH;
// Delays allow the ESP8266 to perform critical tasks
// defined outside of the sketch. These tasks include
// setting up, and maintaining, a WiFi connection.
delay(100);
// Potentially infinite loops are generally dangerous.
// Add delays -- allowing the processor to perform other
// tasks -- wherever possible.
}
}
//function that sets up some initial hardware states
void initHardware()
{
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
}
//this function takes data and posts it to the cloud
int postToPhant()
{
// LED turns on when we enter, it'll go off when we
// successfully post.
digitalWrite(LED_PIN, HIGH);
// Declare an object from the Phant library - phant
Phant phant(PhantHost, PublicKey, PrivateKey);
//These functions build data and field string that will be sent to phant cloud
phant.add("adcdata", analogRead(ANALOG_PIN));
phant.add("wifinode", NODE_NUM);
// Now connect to data.sparkfun.com, and post our data:
WiFiClient client; //declare client object that will post the data
const int httpPort = 80; //specify port to post through
if (!client.connect(PhantHost, httpPort)) //attempt to connect to phant
{
// If we fail to connect, return 0.
return 0;
}
//Send post to phant
client.print(phant.post());
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
//Serial.print(line); // Trying to avoid using serial
}
// Before we exit, turn the LED off.
digitalWrite(LED_PIN, LOW);
return 1; // Return success
}
Monday, September 5, 2016
Combining Arduino, Android, and the Cloud Part 3
In this 3 part series we look at how to create an Android app to monitor and control multiple WiFi enabled Arduinos using the cloud. In part 3 the finale we will look at how to send control data to the cloud using an Android App to control the Arduino WiFi nodes. To download the Android App .aia file to load into MIT App Inventor II use the following link: https://dl.dropboxusercontent.com/u/26591541/CloudHomeAutoEx2.aia
//Arduino MKR1000 Code****************************************************
/*
This sketch was created for a tutorial called Combining Arduino, Android, and the Cloud Part 3
That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to
use or modify at your own risk
Note that this code was leveraged from the Arduino WiFi101 examples and from a Sparkfun example
on using their cloud service Phant
*/
#include <SPI.h>
#include <WiFi101.h>
char ssid[] = "YourNetwork"; // your network SSID (name)
char pass[] = "YourPassword"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
bool pData = false; //used to toggle between posting data and getting data
int status = WL_IDLE_STATUS;
//define some constant variables for pins and node number
const int LED_PIN = 6; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int NODE_NUM = 2; //node identifier
const char parseKey[] = "stamp";
//define areas for phant cloud address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char pPublicKey[] = "PublicKeyForPosting";
const char pPrivateKey[] = "PrivateKeyForPosting";
const char gPublicKey[] = "PublicKeyForGetting";
const char gPrivateKey[] = "PublicKeyForGetting";
//The following variables are from Phant library created by Sparkfun.
String _pub;
String _prv;
String _host;
String _params;
static const char HEADER_POST_URL1[] PROGMEM = "POST /input/";
static const char HEADER_POST_URL2[] PROGMEM = ".txt HTTP/1.1\n";
static const char HEADER_PHANT_PRV_KEY[] PROGMEM = "Phant-Private-Key: ";
static const char HEADER_CONNECTION_CLOSE[] PROGMEM = "Connection: close\n";
static const char HEADER_CONTENT_TYPE[] PROGMEM = "Content-Type: application/x-www-form-urlencoded\n";
static const char HEADER_CONTENT_LENGTH[] PROGMEM = "Content-Length: ";
//timing for posting to the phant cloud
const unsigned long postRate = 15000;
unsigned long lastPost = 0;
void setup() {
pinMode(LED_PIN, OUTPUT); //setup LED pin
digitalWrite(LED_PIN, LOW); //Turn off LED
Serial.begin(9600);
while (!Serial) { //Note the code will not cont unless you open serial monitor
; // wait for serial port to connect. Needed for native USB port only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus(); //Print info about the WiFi network that you are connected to
}
void loop() {
//Delay for set time then post and get data from Phant cloud
if (lastPost + postRate <= millis())
{
if(pData) {
if (postToPhant()) lastPost = millis();
else lastPost = millis(); //Even if we fail delay whole cycle before we try again
}
else {
if (getFromPhant()) lastPost = millis();
else lastPost = millis(); //Even if we fail delay whole cycle before we try again
}
}
}
//function that handles posting and getting data from phant cloud
int getFromPhant()
{
//Set phant data
phant(PhantHost, gPublicKey, gPrivateKey);
WiFiClient client; //Create client object to communicate with the phant server
if (!client.connect(PhantHost, 80)) { //Attempt to connect to phant server using port 80
// If we fail to connect, return 0.
return 0;
}
//Get data from phant cloud
client.print(phantGet());
client.println();
Serial.println("sent get request.....");
int cTrack = 0; //variable that tracks count to spell stamp
bool match = false; //tracks when we have a match with "stamp" and we can then get control data
int pCount = 0; //variable used to track whe we have control data
while(1) { //loop until we get data and server closes connection
if (client.available()) { //if data is available from phant server
char c = client.read(); //read a bite of data from server
if(!match) { //if true than we have not found the word "stamp" so keep looking
if(c == parseKey[cTrack]) //check if we have a character match with word "stamp"
{
if(cTrack == (sizeof(parseKey)-2)) match = true; //if true it means we found a match for "stamp" in data from phant cloud
cTrack++; //iterate this count if a character match was found
}
else { //if true means no character match so reset count
cTrack = 0;
}
}
else { //if true it means we found a match to "stamp" and we are ready to get control data
if(pCount == 3) { //if true we are at the point in the data to read control data for node oen
Serial.print(c);
int dControl = c - '0'; //convert char data to an int by subtract an ASCII zero
if(dControl == 1 | dControl == 0) digitalWrite(LED_PIN, dControl); //make sure data is a one or zer and set LED pin with it
}
pCount++; //iterate the parse counter
}
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop(); //stop client, if you don't have this you will create too many clients and server won't let you connect anymore
break; //This is how we get out of the loop
}
}
pData = true; //set to true so we post data to cloud next loop
return 1; // Return success
}
//function used to post data to phant cloud
int postToPhant()
{
// Declare an object from the Phant library - phant
phant(PhantHost, pPublicKey, pPrivateKey);
//These calls build the web communication strings with Phant
phantAdd("adcdata", analogRead(ANALOG_PIN)); //specify field and data used in that field
phantAdd("wifinode", NODE_NUM);
WiFiClient client; //Create client object to communicate with the phant server
if (!client.connect(PhantHost, 80)) { //Attempt to connect to phant server using port 80
// If we fail to connect, return 0.
pData = false; //set to false so we get data from cloud next loop
return 0;
}
//Send post to phant server
client.print(phantPost());
// if there are incoming bytes available
// from the server, read them and print them:
while (client.available()) {
String line = client.readStringUntil('\r');
//Do something with data
}
client.stop();
pData = false; //set to false so we get data from cloud next loop
return 1; // Return success
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
Serial.println();
}
//This is from phant library, initializes variables
void phant(String host, String publicKey, String privateKey) {
_host = host;
_pub = publicKey;
_prv = privateKey;
_params = "";
}
//From phant library, builds string of field and data
void phantAdd(String field, int data) {
_params += "&" + field + "=" + String(data);
}
//From phant library, builds string to get data from Phant cloud
String phantGet() {
String result = "GET /output/" + _pub + ".csv?page=1 HTTP/1.1\n";
result += "Host: " + _host + "\n";
result += "Connection: close\n";
return result;
}
//From phant library, builds the string used to post data to phant over web services
String phantPost() {
String params = _params.substring(1);
String result;
//String result = "POST /input/" + _pub + ".txt HTTP/1.1\n";
for (int i=0; i<strlen(HEADER_POST_URL1); i++)
{
result += (char)pgm_read_byte_near(HEADER_POST_URL1 + i);
}
result += _pub;
for (int i=0; i<strlen(HEADER_POST_URL2); i++)
{
result += (char)pgm_read_byte_near(HEADER_POST_URL2 + i);
}
result += "Host: " + _host + "\n";
//result += "Phant-Private-Key: " + _prv + "\n";
for (int i=0; i<strlen(HEADER_PHANT_PRV_KEY); i++)
{
result += (char)pgm_read_byte_near(HEADER_PHANT_PRV_KEY + i);
}
result += _prv + '\n';
//result += "Connection: close\n";
for (int i=0; i<strlen(HEADER_CONNECTION_CLOSE); i++)
{
result += (char)pgm_read_byte_near(HEADER_CONNECTION_CLOSE + i);
}
//result += "Content-Type: application/x-www-form-urlencoded\n";
for (int i=0; i<strlen(HEADER_CONTENT_TYPE); i++)
{
result += (char)pgm_read_byte_near(HEADER_CONTENT_TYPE + i);
}
//result += "Content-Length: " + String(params.length()) + "\n\n";
for (int i=0; i<strlen(HEADER_CONTENT_LENGTH); i++)
{
result += (char)pgm_read_byte_near(HEADER_CONTENT_LENGTH + i);
}
result += String(params.length()) + "\n\n";
result += params;
_params = "";
return result;
}
//This function convers the ADC level integer value into float voltage value.
//The inputs are the measured ADC value and the ADC reference voltage level
//The formula used was obtained from the data sheet: (ADC value / 1024) x ref voltage
float convertToVolt(float refVal, int aVAL) {
return (((float)aVAL/1024)*refVal);
}
//this function calculates temp in F from TMP36 temp sensor
//see TMP36 datasheet to understand algorithm used
float calculateTempF(float v1) {
float temp = 0;
//calculate temp in C, .75 volts is 25 C. 10mV per degree
if (v1 < .75) { temp = 25 - ((.75-v1)/.01); } //if below 25 C
else if (v1 == .75) {temp = 25; }
else { temp = 25 + ((v1 -.75)/.01); } //if above 25
//convert to F
temp =((temp*9)/5) + 32;
return temp;
}
//Arduino ESP8266 Code****************************************************
/*
This sketch was created for a tutorial called Combining Arduino, Android, and the Cloud Part 3
That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to
use or modify at your own risk
Note that this code was leveraged from a Sparkfun example
on using their cloud service Phant
*/
// Include the ESP8266 WiFi library. (Works a lot like the
// Arduino WiFi library.)
#include <ESP8266WiFi.h>
// Include the SparkFun Phant library.
#include <Phant.h>
//Set your network name and password
const char WiFiSSID[] = "YourNetwork";
const char WiFiPSK[] = "YourPassword";
//define constants for pin control and node number
const int LED_PIN = 5; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int NODE_NUM = 1; //node identifier
const char parseKey[] = "stamp";
bool pData = false; //used to toggle between posting data and getting data
//declare phant address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char pPublicKey[] = "PublicKeyForPosting";
const char pPrivateKey[] = "PrivateKeyForPosting";
const char gPublicKey[] = "PublicKeyForGetting";
const char gPrivateKey[] = "PublicKeyForGetting";
//specify the rate that you post data to cloud
const unsigned long postRate = 15000;
unsigned long lastPost = 0;
void setup()
{
initHardware(); //setup arduino hardware
connectWiFi(); //Connect your WiFi network
digitalWrite(LED_PIN, HIGH);
}
void loop()
{ //loop until it is time to post data to phant cloud
if (lastPost + postRate <= millis())
{
if(pData) {
if (postToPhant()) lastPost = millis();
else lastPost = millis(); //Even if we fail delay whole cycle before we try again
}
else {
if (getFromPhant()) lastPost = millis();
else lastPost = millis(); //Even if we fail delay whole cycle before we try again
}
}
}
//function used to connect to WiFi network
void connectWiFi()
{
byte ledStatus = LOW;
// Set WiFi mode to station (as opposed to AP or AP_STA)
WiFi.mode(WIFI_STA);
// WiFI.begin([ssid], [passkey]) initiates a WiFI connection
// to the stated [ssid], using the [passkey] as a WPA, WPA2,
// or WEP passphrase.
WiFi.begin(WiFiSSID, WiFiPSK);
// Use the WiFi.status() function to check if the ESP8266
// is connected to a WiFi network.
while (WiFi.status() != WL_CONNECTED)
{
// Blink the LED
digitalWrite(LED_PIN, ledStatus); // Write LED high/low
ledStatus = (ledStatus == HIGH) ? LOW : HIGH;
// Delays allow the ESP8266 to perform critical tasks
// defined outside of the sketch. These tasks include
// setting up, and maintaining, a WiFi connection.
delay(100);
// Potentially infinite loops are generally dangerous.
// Add delays -- allowing the processor to perform other
// tasks -- wherever possible.
}
}
//function that sets up some initial hardware states
void initHardware()
{
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
}
//function that handles posting and getting data from phant cloud
int getFromPhant()
{
//Set phant data
Phant phant(PhantHost, gPublicKey, gPrivateKey);
WiFiClient client; //Create client object to communicate with the phant server
if (!client.connect(PhantHost, 80)) { //Attempt to connect to phant server using port 80
// If we fail to connect, return 0.
return 0;
}
//Get data from phant cloud
client.print(phant.get());
client.println();
int cTrack = 0; //variable that tracks count to spell stamp
bool match = false; //tracks when we have a match with "stamp" and we can then get control data
int pCount = 0; //variable used to track whe we have control data
while(1) { //loop until we get data and server closes connection
if (client.available()) { //if data is available from phant server
char c = client.read(); //read a bite of data from server
if(!match) { //if true than we have not found the word "stamp" so keep looking
if(c == parseKey[cTrack]) //check if we have a character match with word "stamp"
{
if(cTrack == (sizeof(parseKey)-2)) match = true; //if true it means we found a match for "stamp" in data from phant cloud
cTrack++; //iterate this count if a character match was found
}
else { //if true means no character match so reset count
cTrack = 0;
}
}
else { //if true it means we found a match to "stamp" and we are ready to get control data
if(pCount == 1) { //if true we are at the point in the data to read control data for node oen
int dControl = c - '0'; //convert char data to an int by subtract an ASCII zero
if(dControl == 1 | dControl == 0) digitalWrite(LED_PIN, dControl); //make sure data is a one or zer and set LED pin with it
}
pCount++; //iterate the parse counter
}
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
client.stop(); //stop client, if you don't have this you will create too many clients and server won't let you connect anymore
break; //This is how we get out of the loop
}
}
pData = true; //set to true so we post data to cloud next loop
return 1; // Return success
}
//this function takes data and posts it to the cloud
int postToPhant()
{
// Declare an object from the Phant library - phant
Phant phant(PhantHost, pPublicKey, pPrivateKey);
//These functions build data and field string that will be sent to phant cloud
phant.add("adcdata", analogRead(ANALOG_PIN));
phant.add("wifinode", NODE_NUM);
// Now connect to data.sparkfun.com, and post our data:
WiFiClient client; //declare client object that will post the data
const int httpPort = 80; //specify port to post through
if (!client.connect(PhantHost, httpPort)) //attempt to connect to phant
{
// If we fail to connect, return 0.
return 0;
}
//Send post to phant
client.print(phant.post());
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
//Serial.print(line); // Trying to avoid using serial
}
pData = false; //set to false so we get data from cloud next loop
return 1; // Return success
}
//Arduino MKR1000 Code****************************************************
/*
This sketch was created for a tutorial called Combining Arduino, Android, and the Cloud Part 3
That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to
use or modify at your own risk
Note that this code was leveraged from the Arduino WiFi101 examples and from a Sparkfun example
on using their cloud service Phant
*/
#include <SPI.h>
#include <WiFi101.h>
char ssid[] = "YourNetwork"; // your network SSID (name)
char pass[] = "YourPassword"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
bool pData = false; //used to toggle between posting data and getting data
int status = WL_IDLE_STATUS;
//define some constant variables for pins and node number
const int LED_PIN = 6; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int NODE_NUM = 2; //node identifier
const char parseKey[] = "stamp";
//define areas for phant cloud address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char pPublicKey[] = "PublicKeyForPosting";
const char pPrivateKey[] = "PrivateKeyForPosting";
const char gPublicKey[] = "PublicKeyForGetting";
const char gPrivateKey[] = "PublicKeyForGetting";
//The following variables are from Phant library created by Sparkfun.
String _pub;
String _prv;
String _host;
String _params;
static const char HEADER_POST_URL1[] PROGMEM = "POST /input/";
static const char HEADER_POST_URL2[] PROGMEM = ".txt HTTP/1.1\n";
static const char HEADER_PHANT_PRV_KEY[] PROGMEM = "Phant-Private-Key: ";
static const char HEADER_CONNECTION_CLOSE[] PROGMEM = "Connection: close\n";
static const char HEADER_CONTENT_TYPE[] PROGMEM = "Content-Type: application/x-www-form-urlencoded\n";
static const char HEADER_CONTENT_LENGTH[] PROGMEM = "Content-Length: ";
//timing for posting to the phant cloud
const unsigned long postRate = 15000;
unsigned long lastPost = 0;
void setup() {
pinMode(LED_PIN, OUTPUT); //setup LED pin
digitalWrite(LED_PIN, LOW); //Turn off LED
Serial.begin(9600);
while (!Serial) { //Note the code will not cont unless you open serial monitor
; // wait for serial port to connect. Needed for native USB port only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus(); //Print info about the WiFi network that you are connected to
}
void loop() {
//Delay for set time then post and get data from Phant cloud
if (lastPost + postRate <= millis())
{
if(pData) {
if (postToPhant()) lastPost = millis();
else lastPost = millis(); //Even if we fail delay whole cycle before we try again
}
else {
if (getFromPhant()) lastPost = millis();
else lastPost = millis(); //Even if we fail delay whole cycle before we try again
}
}
}
//function that handles posting and getting data from phant cloud
int getFromPhant()
{
//Set phant data
phant(PhantHost, gPublicKey, gPrivateKey);
WiFiClient client; //Create client object to communicate with the phant server
if (!client.connect(PhantHost, 80)) { //Attempt to connect to phant server using port 80
// If we fail to connect, return 0.
return 0;
}
//Get data from phant cloud
client.print(phantGet());
client.println();
Serial.println("sent get request.....");
int cTrack = 0; //variable that tracks count to spell stamp
bool match = false; //tracks when we have a match with "stamp" and we can then get control data
int pCount = 0; //variable used to track whe we have control data
while(1) { //loop until we get data and server closes connection
if (client.available()) { //if data is available from phant server
char c = client.read(); //read a bite of data from server
if(!match) { //if true than we have not found the word "stamp" so keep looking
if(c == parseKey[cTrack]) //check if we have a character match with word "stamp"
{
if(cTrack == (sizeof(parseKey)-2)) match = true; //if true it means we found a match for "stamp" in data from phant cloud
cTrack++; //iterate this count if a character match was found
}
else { //if true means no character match so reset count
cTrack = 0;
}
}
else { //if true it means we found a match to "stamp" and we are ready to get control data
if(pCount == 3) { //if true we are at the point in the data to read control data for node oen
Serial.print(c);
int dControl = c - '0'; //convert char data to an int by subtract an ASCII zero
if(dControl == 1 | dControl == 0) digitalWrite(LED_PIN, dControl); //make sure data is a one or zer and set LED pin with it
}
pCount++; //iterate the parse counter
}
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop(); //stop client, if you don't have this you will create too many clients and server won't let you connect anymore
break; //This is how we get out of the loop
}
}
pData = true; //set to true so we post data to cloud next loop
return 1; // Return success
}
//function used to post data to phant cloud
int postToPhant()
{
// Declare an object from the Phant library - phant
phant(PhantHost, pPublicKey, pPrivateKey);
//These calls build the web communication strings with Phant
phantAdd("adcdata", analogRead(ANALOG_PIN)); //specify field and data used in that field
phantAdd("wifinode", NODE_NUM);
WiFiClient client; //Create client object to communicate with the phant server
if (!client.connect(PhantHost, 80)) { //Attempt to connect to phant server using port 80
// If we fail to connect, return 0.
pData = false; //set to false so we get data from cloud next loop
return 0;
}
//Send post to phant server
client.print(phantPost());
// if there are incoming bytes available
// from the server, read them and print them:
while (client.available()) {
String line = client.readStringUntil('\r');
//Do something with data
}
client.stop();
pData = false; //set to false so we get data from cloud next loop
return 1; // Return success
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
Serial.println();
}
//This is from phant library, initializes variables
void phant(String host, String publicKey, String privateKey) {
_host = host;
_pub = publicKey;
_prv = privateKey;
_params = "";
}
//From phant library, builds string of field and data
void phantAdd(String field, int data) {
_params += "&" + field + "=" + String(data);
}
//From phant library, builds string to get data from Phant cloud
String phantGet() {
String result = "GET /output/" + _pub + ".csv?page=1 HTTP/1.1\n";
result += "Host: " + _host + "\n";
result += "Connection: close\n";
return result;
}
//From phant library, builds the string used to post data to phant over web services
String phantPost() {
String params = _params.substring(1);
String result;
//String result = "POST /input/" + _pub + ".txt HTTP/1.1\n";
for (int i=0; i<strlen(HEADER_POST_URL1); i++)
{
result += (char)pgm_read_byte_near(HEADER_POST_URL1 + i);
}
result += _pub;
for (int i=0; i<strlen(HEADER_POST_URL2); i++)
{
result += (char)pgm_read_byte_near(HEADER_POST_URL2 + i);
}
result += "Host: " + _host + "\n";
//result += "Phant-Private-Key: " + _prv + "\n";
for (int i=0; i<strlen(HEADER_PHANT_PRV_KEY); i++)
{
result += (char)pgm_read_byte_near(HEADER_PHANT_PRV_KEY + i);
}
result += _prv + '\n';
//result += "Connection: close\n";
for (int i=0; i<strlen(HEADER_CONNECTION_CLOSE); i++)
{
result += (char)pgm_read_byte_near(HEADER_CONNECTION_CLOSE + i);
}
//result += "Content-Type: application/x-www-form-urlencoded\n";
for (int i=0; i<strlen(HEADER_CONTENT_TYPE); i++)
{
result += (char)pgm_read_byte_near(HEADER_CONTENT_TYPE + i);
}
//result += "Content-Length: " + String(params.length()) + "\n\n";
for (int i=0; i<strlen(HEADER_CONTENT_LENGTH); i++)
{
result += (char)pgm_read_byte_near(HEADER_CONTENT_LENGTH + i);
}
result += String(params.length()) + "\n\n";
result += params;
_params = "";
return result;
}
//This function convers the ADC level integer value into float voltage value.
//The inputs are the measured ADC value and the ADC reference voltage level
//The formula used was obtained from the data sheet: (ADC value / 1024) x ref voltage
float convertToVolt(float refVal, int aVAL) {
return (((float)aVAL/1024)*refVal);
}
//this function calculates temp in F from TMP36 temp sensor
//see TMP36 datasheet to understand algorithm used
float calculateTempF(float v1) {
float temp = 0;
//calculate temp in C, .75 volts is 25 C. 10mV per degree
if (v1 < .75) { temp = 25 - ((.75-v1)/.01); } //if below 25 C
else if (v1 == .75) {temp = 25; }
else { temp = 25 + ((v1 -.75)/.01); } //if above 25
//convert to F
temp =((temp*9)/5) + 32;
return temp;
}
//Arduino ESP8266 Code****************************************************
/*
This sketch was created for a tutorial called Combining Arduino, Android, and the Cloud Part 3
That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to
use or modify at your own risk
Note that this code was leveraged from a Sparkfun example
on using their cloud service Phant
*/
// Include the ESP8266 WiFi library. (Works a lot like the
// Arduino WiFi library.)
#include <ESP8266WiFi.h>
// Include the SparkFun Phant library.
#include <Phant.h>
//Set your network name and password
const char WiFiSSID[] = "YourNetwork";
const char WiFiPSK[] = "YourPassword";
//define constants for pin control and node number
const int LED_PIN = 5; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int NODE_NUM = 1; //node identifier
const char parseKey[] = "stamp";
bool pData = false; //used to toggle between posting data and getting data
//declare phant address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char pPublicKey[] = "PublicKeyForPosting";
const char pPrivateKey[] = "PrivateKeyForPosting";
const char gPublicKey[] = "PublicKeyForGetting";
const char gPrivateKey[] = "PublicKeyForGetting";
//specify the rate that you post data to cloud
const unsigned long postRate = 15000;
unsigned long lastPost = 0;
void setup()
{
initHardware(); //setup arduino hardware
connectWiFi(); //Connect your WiFi network
digitalWrite(LED_PIN, HIGH);
}
void loop()
{ //loop until it is time to post data to phant cloud
if (lastPost + postRate <= millis())
{
if(pData) {
if (postToPhant()) lastPost = millis();
else lastPost = millis(); //Even if we fail delay whole cycle before we try again
}
else {
if (getFromPhant()) lastPost = millis();
else lastPost = millis(); //Even if we fail delay whole cycle before we try again
}
}
}
//function used to connect to WiFi network
void connectWiFi()
{
byte ledStatus = LOW;
// Set WiFi mode to station (as opposed to AP or AP_STA)
WiFi.mode(WIFI_STA);
// WiFI.begin([ssid], [passkey]) initiates a WiFI connection
// to the stated [ssid], using the [passkey] as a WPA, WPA2,
// or WEP passphrase.
WiFi.begin(WiFiSSID, WiFiPSK);
// Use the WiFi.status() function to check if the ESP8266
// is connected to a WiFi network.
while (WiFi.status() != WL_CONNECTED)
{
// Blink the LED
digitalWrite(LED_PIN, ledStatus); // Write LED high/low
ledStatus = (ledStatus == HIGH) ? LOW : HIGH;
// Delays allow the ESP8266 to perform critical tasks
// defined outside of the sketch. These tasks include
// setting up, and maintaining, a WiFi connection.
delay(100);
// Potentially infinite loops are generally dangerous.
// Add delays -- allowing the processor to perform other
// tasks -- wherever possible.
}
}
//function that sets up some initial hardware states
void initHardware()
{
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
}
//function that handles posting and getting data from phant cloud
int getFromPhant()
{
//Set phant data
Phant phant(PhantHost, gPublicKey, gPrivateKey);
WiFiClient client; //Create client object to communicate with the phant server
if (!client.connect(PhantHost, 80)) { //Attempt to connect to phant server using port 80
// If we fail to connect, return 0.
return 0;
}
//Get data from phant cloud
client.print(phant.get());
client.println();
int cTrack = 0; //variable that tracks count to spell stamp
bool match = false; //tracks when we have a match with "stamp" and we can then get control data
int pCount = 0; //variable used to track whe we have control data
while(1) { //loop until we get data and server closes connection
if (client.available()) { //if data is available from phant server
char c = client.read(); //read a bite of data from server
if(!match) { //if true than we have not found the word "stamp" so keep looking
if(c == parseKey[cTrack]) //check if we have a character match with word "stamp"
{
if(cTrack == (sizeof(parseKey)-2)) match = true; //if true it means we found a match for "stamp" in data from phant cloud
cTrack++; //iterate this count if a character match was found
}
else { //if true means no character match so reset count
cTrack = 0;
}
}
else { //if true it means we found a match to "stamp" and we are ready to get control data
if(pCount == 1) { //if true we are at the point in the data to read control data for node oen
int dControl = c - '0'; //convert char data to an int by subtract an ASCII zero
if(dControl == 1 | dControl == 0) digitalWrite(LED_PIN, dControl); //make sure data is a one or zer and set LED pin with it
}
pCount++; //iterate the parse counter
}
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
client.stop(); //stop client, if you don't have this you will create too many clients and server won't let you connect anymore
break; //This is how we get out of the loop
}
}
pData = true; //set to true so we post data to cloud next loop
return 1; // Return success
}
//this function takes data and posts it to the cloud
int postToPhant()
{
// Declare an object from the Phant library - phant
Phant phant(PhantHost, pPublicKey, pPrivateKey);
//These functions build data and field string that will be sent to phant cloud
phant.add("adcdata", analogRead(ANALOG_PIN));
phant.add("wifinode", NODE_NUM);
// Now connect to data.sparkfun.com, and post our data:
WiFiClient client; //declare client object that will post the data
const int httpPort = 80; //specify port to post through
if (!client.connect(PhantHost, httpPort)) //attempt to connect to phant
{
// If we fail to connect, return 0.
return 0;
}
//Send post to phant
client.print(phant.post());
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
//Serial.print(line); // Trying to avoid using serial
}
pData = false; //set to false so we get data from cloud next loop
return 1; // Return success
}
Saturday, August 27, 2016
Combining Arduino, Android, and the Cloud Part 2
In this 3 part series we look at how to create an Android app to monitor and control multiple WiFi enabled Arduinos using the cloud. In part 2 we will look at how to grab the Arduino data from the cloud using a custom Android App.
To download the Android App .aia file to load into MIT App Inventor II use the following link: https://dl.dropboxusercontent.com/u/26591541/CloudHomeAutoEx.aia
To download the Android App .aia file to load into MIT App Inventor II use the following link: https://dl.dropboxusercontent.com/u/26591541/CloudHomeAutoEx.aia
Labels:
Android,
app,
arduino,
cloud,
ESP8266,
IoT,
light sensor,
MKR1000,
temperature sensor,
TMP36,
Tutorial,
WiFi
Wednesday, August 24, 2016
Combining Arduino, Android, and the Cloud Part 1
In this 3 part series we look at how to create an Android app to monitor and control multiple WiFi enabled Arduinos using the cloud. In part 1 we will look at how to send data to the cloud from an Arduino MKR1000 and an Arduino ESP8266.
//**********************Arduino ESP8266 Code****************
/*
This sketch was created for a tutorial called Combining Arduino, Android, and the Cloud Part 1
That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to
use or modify at your own risk
Note that this code was leveraged from a Sparkfun example
on using their cloud service Phant
*/
// Include the ESP8266 WiFi library. (Works a lot like the
// Arduino WiFi library.)
#include <ESP8266WiFi.h>
// Include the SparkFun Phant library.
#include <Phant.h>
//Set your network name and password
const char WiFiSSID[] = "Yournetwork";
const char WiFiPSK[] = "Yourpassword";
//define constants for pin control and node number
const int LED_PIN = 5; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int NODE_NUM = 1; //node identifier
//declare phant address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char PublicKey[] = "yourpublickey";
const char PrivateKey[] = "yourprivatekey";
//specify the rate that you post data to cloud
const unsigned long postRate = 15000;
unsigned long lastPost = 0;
void setup()
{
initHardware(); //setup arduino hardware
connectWiFi(); //Connect your WiFi network
digitalWrite(LED_PIN, HIGH);
}
void loop()
{ //loop until it is time to post data to phant cloud
if (lastPost + postRate <= millis())
{
if (postToPhant())
lastPost = millis();
else
delay(100);
}
}
//function used to connect to WiFi network
void connectWiFi()
{
byte ledStatus = LOW;
// Set WiFi mode to station (as opposed to AP or AP_STA)
WiFi.mode(WIFI_STA);
// WiFI.begin([ssid], [passkey]) initiates a WiFI connection
// to the stated [ssid], using the [passkey] as a WPA, WPA2,
// or WEP passphrase.
WiFi.begin(WiFiSSID, WiFiPSK);
// Use the WiFi.status() function to check if the ESP8266
// is connected to a WiFi network.
while (WiFi.status() != WL_CONNECTED)
{
// Blink the LED
digitalWrite(LED_PIN, ledStatus); // Write LED high/low
ledStatus = (ledStatus == HIGH) ? LOW : HIGH;
// Delays allow the ESP8266 to perform critical tasks
// defined outside of the sketch. These tasks include
// setting up, and maintaining, a WiFi connection.
delay(100);
// Potentially infinite loops are generally dangerous.
// Add delays -- allowing the processor to perform other
// tasks -- wherever possible.
}
}
//function that sets up some initial hardware states
void initHardware()
{
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
}
//this function takes data and posts it to the cloud
int postToPhant()
{
// LED turns on when we enter, it'll go off when we
// successfully post.
digitalWrite(LED_PIN, HIGH);
// Declare an object from the Phant library - phant
Phant phant(PhantHost, PublicKey, PrivateKey);
//These functions build data and field string that will be sent to phant cloud
phant.add("adcdata", analogRead(ANALOG_PIN));
phant.add("wifinode", NODE_NUM);
// Now connect to data.sparkfun.com, and post our data:
WiFiClient client; //declare client object that will post the data
const int httpPort = 80; //specify port to post through
if (!client.connect(PhantHost, httpPort)) //attempt to connect to phant
{
// If we fail to connect, return 0.
return 0;
}
//Send post to phant
client.print(phant.post());
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
//Serial.print(line); // Trying to avoid using serial
}
// Before we exit, turn the LED off.
digitalWrite(LED_PIN, LOW);
return 1; // Return success
}
//**********************Arduino MKR1000 Code****************
/*
This sketch was created for a tutorial called Combining Arduino, Android, and the Cloud Part 1
That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to
use or modify at your own risk
Note that this code was leveraged from the Arduino WiFi101 examples and from a Sparkfun example
on using their cloud service Phant
*/
#include <SPI.h>
#include <WiFi101.h>
char ssid[] = "YourNetwork"; // your network SSID (name)
char pass[] = "YourPassword"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
//define some constant variables for pins and node number
const int LED_PIN = 6; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int NODE_NUM = 2; //node identifier
//define areas for phant cloud address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char PublicKey[] = "YourKey";
const char PrivateKey[] = "YourKey";
String _pub;
String _prv;
String _host;
String _params;
static const char HEADER_POST_URL1[] PROGMEM = "POST /input/";
static const char HEADER_POST_URL2[] PROGMEM = ".txt HTTP/1.1\n";
static const char HEADER_PHANT_PRV_KEY[] PROGMEM = "Phant-Private-Key: ";
static const char HEADER_CONNECTION_CLOSE[] PROGMEM = "Connection: close\n";
static const char HEADER_CONTENT_TYPE[] PROGMEM = "Content-Type: application/x-www-form-urlencoded\n";
static const char HEADER_CONTENT_LENGTH[] PROGMEM = "Content-Length: ";
//timing for posting to the phant cloud
const unsigned long postRate = 15000;
unsigned long lastPost = 0;
void setup() {
pinMode(LED_PIN, OUTPUT); //setup LED pin
digitalWrite(LED_PIN, LOW);
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();
}
void loop() {
if (lastPost + postRate <= millis())
{
if (postToPhant())
lastPost = millis();
else
lastPost = millis(); //Even if we fail delay whole cycle before we try again
}
}
int postToPhant()
{
// LED turns on when we enter, it'll go off when we successfully post.
digitalWrite(LED_PIN, HIGH);
// Declare an object from the Phant library - phant
phant(PhantHost, PublicKey, PrivateKey);
//These calls build the web communication strings with Phant
phantAdd("adcdata", analogRead(ANALOG_PIN)); //specify field and data used in that field
phantAdd("wifinode", NODE_NUM);
WiFiClient client; //Create client object to communicate with the phant server
if (!client.connect(PhantHost, 80)) { //Attempt to connect to phant server using port 80
// If we fail to connect, return 0.
return 0;
}
//Send post to phant server
client.print(phantPost());
// if there are incoming bytes available
// from the server, read them and print them:
while (client.available()) {
String line = client.readStringUntil('\r');
//Do something with data
}
client.stop();
// Before we exit, turn the LED off.
digitalWrite(LED_PIN, LOW);
return 1; // Return success
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
Serial.println();
}
//This is from phant library, initializes variables
void phant(String host, String publicKey, String privateKey) {
_host = host;
_pub = publicKey;
_prv = privateKey;
_params = "";
}
//From phant library, builds string of field and data
void phantAdd(String field, int data) {
_params += "&" + field + "=" + String(data);
}
//From phant library, builds the string used to post data to phant over web services
String phantPost() {
String params = _params.substring(1);
String result;
//String result = "POST /input/" + _pub + ".txt HTTP/1.1\n";
for (int i=0; i<strlen(HEADER_POST_URL1); i++)
{
result += (char)pgm_read_byte_near(HEADER_POST_URL1 + i);
}
result += _pub;
for (int i=0; i<strlen(HEADER_POST_URL2); i++)
{
result += (char)pgm_read_byte_near(HEADER_POST_URL2 + i);
}
result += "Host: " + _host + "\n";
//result += "Phant-Private-Key: " + _prv + "\n";
for (int i=0; i<strlen(HEADER_PHANT_PRV_KEY); i++)
{
result += (char)pgm_read_byte_near(HEADER_PHANT_PRV_KEY + i);
}
result += _prv + '\n';
//result += "Connection: close\n";
for (int i=0; i<strlen(HEADER_CONNECTION_CLOSE); i++)
{
result += (char)pgm_read_byte_near(HEADER_CONNECTION_CLOSE + i);
}
//result += "Content-Type: application/x-www-form-urlencoded\n";
for (int i=0; i<strlen(HEADER_CONTENT_TYPE); i++)
{
result += (char)pgm_read_byte_near(HEADER_CONTENT_TYPE + i);
}
//result += "Content-Length: " + String(params.length()) + "\n\n";
for (int i=0; i<strlen(HEADER_CONTENT_LENGTH); i++)
{
result += (char)pgm_read_byte_near(HEADER_CONTENT_LENGTH + i);
}
result += String(params.length()) + "\n\n";
result += params;
_params = "";
return result;
}
//**********************Arduino ESP8266 Code****************
/*
This sketch was created for a tutorial called Combining Arduino, Android, and the Cloud Part 1
That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to
use or modify at your own risk
Note that this code was leveraged from a Sparkfun example
on using their cloud service Phant
*/
// Include the ESP8266 WiFi library. (Works a lot like the
// Arduino WiFi library.)
#include <ESP8266WiFi.h>
// Include the SparkFun Phant library.
#include <Phant.h>
//Set your network name and password
const char WiFiSSID[] = "Yournetwork";
const char WiFiPSK[] = "Yourpassword";
//define constants for pin control and node number
const int LED_PIN = 5; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int NODE_NUM = 1; //node identifier
//declare phant address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char PublicKey[] = "yourpublickey";
const char PrivateKey[] = "yourprivatekey";
//specify the rate that you post data to cloud
const unsigned long postRate = 15000;
unsigned long lastPost = 0;
void setup()
{
initHardware(); //setup arduino hardware
connectWiFi(); //Connect your WiFi network
digitalWrite(LED_PIN, HIGH);
}
void loop()
{ //loop until it is time to post data to phant cloud
if (lastPost + postRate <= millis())
{
if (postToPhant())
lastPost = millis();
else
delay(100);
}
}
//function used to connect to WiFi network
void connectWiFi()
{
byte ledStatus = LOW;
// Set WiFi mode to station (as opposed to AP or AP_STA)
WiFi.mode(WIFI_STA);
// WiFI.begin([ssid], [passkey]) initiates a WiFI connection
// to the stated [ssid], using the [passkey] as a WPA, WPA2,
// or WEP passphrase.
WiFi.begin(WiFiSSID, WiFiPSK);
// Use the WiFi.status() function to check if the ESP8266
// is connected to a WiFi network.
while (WiFi.status() != WL_CONNECTED)
{
// Blink the LED
digitalWrite(LED_PIN, ledStatus); // Write LED high/low
ledStatus = (ledStatus == HIGH) ? LOW : HIGH;
// Delays allow the ESP8266 to perform critical tasks
// defined outside of the sketch. These tasks include
// setting up, and maintaining, a WiFi connection.
delay(100);
// Potentially infinite loops are generally dangerous.
// Add delays -- allowing the processor to perform other
// tasks -- wherever possible.
}
}
//function that sets up some initial hardware states
void initHardware()
{
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
}
//this function takes data and posts it to the cloud
int postToPhant()
{
// LED turns on when we enter, it'll go off when we
// successfully post.
digitalWrite(LED_PIN, HIGH);
// Declare an object from the Phant library - phant
Phant phant(PhantHost, PublicKey, PrivateKey);
//These functions build data and field string that will be sent to phant cloud
phant.add("adcdata", analogRead(ANALOG_PIN));
phant.add("wifinode", NODE_NUM);
// Now connect to data.sparkfun.com, and post our data:
WiFiClient client; //declare client object that will post the data
const int httpPort = 80; //specify port to post through
if (!client.connect(PhantHost, httpPort)) //attempt to connect to phant
{
// If we fail to connect, return 0.
return 0;
}
//Send post to phant
client.print(phant.post());
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
//Serial.print(line); // Trying to avoid using serial
}
// Before we exit, turn the LED off.
digitalWrite(LED_PIN, LOW);
return 1; // Return success
}
//**********************Arduino MKR1000 Code****************
/*
This sketch was created for a tutorial called Combining Arduino, Android, and the Cloud Part 1
That was presented on the ForceTronics YouTube Channel. This code is public domain for anybody to
use or modify at your own risk
Note that this code was leveraged from the Arduino WiFi101 examples and from a Sparkfun example
on using their cloud service Phant
*/
#include <SPI.h>
#include <WiFi101.h>
char ssid[] = "YourNetwork"; // your network SSID (name)
char pass[] = "YourPassword"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
//define some constant variables for pins and node number
const int LED_PIN = 6; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int NODE_NUM = 2; //node identifier
//define areas for phant cloud address and security keys
const char PhantHost[] = "data.sparkfun.com";
const char PublicKey[] = "YourKey";
const char PrivateKey[] = "YourKey";
String _pub;
String _prv;
String _host;
String _params;
static const char HEADER_POST_URL1[] PROGMEM = "POST /input/";
static const char HEADER_POST_URL2[] PROGMEM = ".txt HTTP/1.1\n";
static const char HEADER_PHANT_PRV_KEY[] PROGMEM = "Phant-Private-Key: ";
static const char HEADER_CONNECTION_CLOSE[] PROGMEM = "Connection: close\n";
static const char HEADER_CONTENT_TYPE[] PROGMEM = "Content-Type: application/x-www-form-urlencoded\n";
static const char HEADER_CONTENT_LENGTH[] PROGMEM = "Content-Length: ";
//timing for posting to the phant cloud
const unsigned long postRate = 15000;
unsigned long lastPost = 0;
void setup() {
pinMode(LED_PIN, OUTPUT); //setup LED pin
digitalWrite(LED_PIN, LOW);
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();
}
void loop() {
if (lastPost + postRate <= millis())
{
if (postToPhant())
lastPost = millis();
else
lastPost = millis(); //Even if we fail delay whole cycle before we try again
}
}
int postToPhant()
{
// LED turns on when we enter, it'll go off when we successfully post.
digitalWrite(LED_PIN, HIGH);
// Declare an object from the Phant library - phant
phant(PhantHost, PublicKey, PrivateKey);
//These calls build the web communication strings with Phant
phantAdd("adcdata", analogRead(ANALOG_PIN)); //specify field and data used in that field
phantAdd("wifinode", NODE_NUM);
WiFiClient client; //Create client object to communicate with the phant server
if (!client.connect(PhantHost, 80)) { //Attempt to connect to phant server using port 80
// If we fail to connect, return 0.
return 0;
}
//Send post to phant server
client.print(phantPost());
// if there are incoming bytes available
// from the server, read them and print them:
while (client.available()) {
String line = client.readStringUntil('\r');
//Do something with data
}
client.stop();
// Before we exit, turn the LED off.
digitalWrite(LED_PIN, LOW);
return 1; // Return success
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
Serial.println();
}
//This is from phant library, initializes variables
void phant(String host, String publicKey, String privateKey) {
_host = host;
_pub = publicKey;
_prv = privateKey;
_params = "";
}
//From phant library, builds string of field and data
void phantAdd(String field, int data) {
_params += "&" + field + "=" + String(data);
}
//From phant library, builds the string used to post data to phant over web services
String phantPost() {
String params = _params.substring(1);
String result;
//String result = "POST /input/" + _pub + ".txt HTTP/1.1\n";
for (int i=0; i<strlen(HEADER_POST_URL1); i++)
{
result += (char)pgm_read_byte_near(HEADER_POST_URL1 + i);
}
result += _pub;
for (int i=0; i<strlen(HEADER_POST_URL2); i++)
{
result += (char)pgm_read_byte_near(HEADER_POST_URL2 + i);
}
result += "Host: " + _host + "\n";
//result += "Phant-Private-Key: " + _prv + "\n";
for (int i=0; i<strlen(HEADER_PHANT_PRV_KEY); i++)
{
result += (char)pgm_read_byte_near(HEADER_PHANT_PRV_KEY + i);
}
result += _prv + '\n';
//result += "Connection: close\n";
for (int i=0; i<strlen(HEADER_CONNECTION_CLOSE); i++)
{
result += (char)pgm_read_byte_near(HEADER_CONNECTION_CLOSE + i);
}
//result += "Content-Type: application/x-www-form-urlencoded\n";
for (int i=0; i<strlen(HEADER_CONTENT_TYPE); i++)
{
result += (char)pgm_read_byte_near(HEADER_CONTENT_TYPE + i);
}
//result += "Content-Length: " + String(params.length()) + "\n\n";
for (int i=0; i<strlen(HEADER_CONTENT_LENGTH); i++)
{
result += (char)pgm_read_byte_near(HEADER_CONTENT_LENGTH + i);
}
result += String(params.length()) + "\n\n";
result += params;
_params = "";
return result;
}
Labels:
arduino,
cloud,
encryption,
ESP8266,
internet of things,
IoT,
MKR1000,
phant,
sparkfun,
Tutorial,
web,
WiFi
Subscribe to:
Posts (Atom)