John R McAlpine V Mac
Published © CC BY-NC

You've-Got-Mail

Notifications aren't just for email any more! Get real time alerts from a solar powered Particle Argon with IFTTT.

IntermediateFull instructions provided6 hours4,627
You've-Got-Mail

Things used in this project

Hardware components

Photon
Particle Photon
×1
TP4056 LIPO charge board
×1

Software apps and online services

Maker service
IFTTT Maker service
ThingSpeak API
ThingSpeak API

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

asciicad

Code

old sleep api Particle Argon Code

Arduino
Particle Argon youve got mail system
/*This sketch experiments with low power for battery/solar operation and thingspeak.
 a magnetic reed switch is connected to D0.  The particle sleeps and wakes on a falling edge interrupt at D0.
 if triggered it publishes a notification that can be detected by IFTTT and sends a notification
 to your device.
 on every interrupt and on wakeup a update is published to thingspeak with voltage, RSSI and # of triggers.
 
 Power consumption connected to wifi, approx 35mA
 Charging Lipo, approx 500mA + 35mA
 Stop mode(sleep) 1.5mA, retains variables and program state when stopped.
 Resumes on timeout or pin change interrupt (mail door open)
                                       +-----+
 *                          +----------| USB |---------+
 *                          | O        +-----+      O  |
 *                          | [ ] RESET                |
 *                          | [ ] 3V3                  |         
 *                          | [ ] MODE                 |          
 *                          | [ ] GND                  |   
 *                          | [ ] A0          Lipo [ ] |       
 *                          | [ ] A1  +-------+ EN [ ] |         
 *                          | [ ] A2  |   *   | VIN[ ] |-------\
 *   TP4056 Pin 2 curr sense| [*] A3  | ARGON | D8 [ ] |       |
 *      /------batt sense-> | [*] A4  |       | D7 [ ] |       |  
 *    10K - batt sense gnd->| [*] A5  +-------+ D6 [ ] |       |  
 *                          | [ ] D13           D5 [ ] |       |  
 *                          | [ ] D12           D4 [ ] |       |
 *                          | [ ] D11           D3 [ ] |       10K
 *                          | [ ] D10           D2 [ ] |       |
 *                          | [ ] D9            D1 [ ] |       |
 *                          | [ ] NC            D0 [*] |-------/
 *                          |   WIFI0         0NFC     |
 *                          |O                        O|
 *                          +--------------------------+
 *
 *
 */

/*  begin particle webhook code snippit to add to particle webhook interface on console
{
    "event": "thingSpeakWrite_",
    "url": "https://api.thingspeak.com/update",
    "requestType": "POST",
    "form": {
        "api_key": "{{k}}",
        "field1": "{{1}}",
        "field2": "{{2}}",
        "field3": "{{3}}",
        "field4": "{{4}}",
        "field5": "{{5}}",
        "field6": "{{6}}",
        "field7": "{{7}}",
        "field8": "{{8}}",
        "lat": "{{a}}",
        "long": "{{o}}",
        "elevation": "{{e}}",
        "status": "{{s}}"
    },
    "mydevices": true,
    "noDefaults": true
}
*/

ApplicationWatchdog wd(120000, System.reset);

char publishString[40];
int mailpin = D2;
int volttestpin = A4;
int voltpowerpin = A5;
int currentsensepin = A3;
int mailpinstate = 0;
int lastmailpinstate = 0;
float chargecurrent = 0;
float batteryvolts = 0;
const int sleepytime = 600;//1800; //seconds to sleep 3600=1hr
const int longsleepytime = 3600; //seconds to sleep 3600=1hr

const String key = "your_thingspeak_KEY";


float rssival = 0;
float rssipct = 0;
volatile bool mailsend = FALSE;
volatile bool rssisend = FALSE;
int mailtriggers = 0;
long waketime = 0;
//SYSTEM_THREAD(ENABLED); //enable multitasking.  allows the ability to catch the mailpin trigger and send the message
//SYSTEM_MODE(AUTOMATIC);  //run code. then connect     
     
void rssi_update()
{
    //delay (2000);
    static int count = 0;
    Serial.println(count++);
    //rssival = WiFi.RSSI();  //measure RSSI
    WiFiSignal sig = WiFi.RSSI();
    rssival = sig.getStrengthValue();
    rssipct = sig.getStrength();

    
    chargecurrent = analogRead(currentsensepin)*3.3/4096;   //measure solar charge current (A)
    batteryvolts = checkbattery();  //measure battery voltage
    
    sprintf(publishString,"%d",rssival);
    
    //sprintf(publishString,"%d",strength);
    //bool success = Particle.publish("RSSI",publishString);
    bool success = Particle.publish("RSSI",String(rssival));
    
    sprintf(publishString, "%1.4f", batteryvolts);

       Particle.publish("thingSpeakWrite_All", +
     "{ \"1\": \"" + String(rssival) + "\"," +
       "\"2\": \"" + String(batteryvolts) + "\"," +
       "\"3\": \"" + String(mailtriggers) + "\"," +
       "\"5\": \"" + String(chargecurrent) + "\"," +  //channel 5 due to a legacy SOC channel being calculated on thingspeak via a react.
     //"\"5\": \"" + String(var4) + "\"," +
       "\"k\": \"" + key + "\" }", 60, PRIVATE, WITH_ACK);
       

    if (success == TRUE) {
        //delay(10000);
        rssisend = FALSE; //if sent, then turn of the send flag, otherwise let it try again.
    }
}


void enablemailsend(void){
    mailsend=TRUE;
    digitalWrite(D7,1);
}

void setup() {
    //setADCSampleTime(ADC_SampleTime_239Cycles5);  //sets adc to longest time for low noise
    Time.zone(-4);  //set eastern time zone
    pinMode(mailpin,INPUT);
    pinMode(voltpowerpin, INPUT);
    pinMode(currentsensepin, INPUT);
    pinMode(D7, OUTPUT);
    attachInterrupt(mailpin, enablemailsend, FALLING);
    Particle.variable("mailtrig", mailtriggers);
    rssisend = TRUE;
    //Mesh.on();
    RGB.brightness(32);
    //LEDStatus status;
}


void loop() {
     wd.checkin();  //watchdog checkin
     //status.on(); // Turns the LED on
     //do not checkin the watchdog.  the counter seems to reset each time the system boots.  The watchdog
     //should therefore only cause a reset if the system is stuck, on and cant connect to wifi.
     
     
    if ((Particle.connected())&&(mailsend == TRUE))
    {
        mailnotification();
    }
    
    if ((Particle.connected())&&(rssisend == TRUE))
    {
        rssi_update();
    }
    

    if ((millis()-waketime > 30000))// && (mailsend == FALSE) && (rssisend == FALSE)) //if everything sent ok under 30 seconds, then sleep for short time
    {
        //Mesh.off();
        
        //System.sleep(mailpin,RISING,30); 
        // https://community.particle.io/t/battery-drains-faster-when-argon-sleeping/50684/3
        Particle.disconnect();
        waitUntil(Particle.disconnected);
        WiFi.off();
        Particle.process();
        delay(4000);
        
        //delay(100);
        System.sleep(mailpin,FALLING,sleepytime);
        WiFi.on();
        Particle.connect();
      //  pinMode(mailpin,INPUT); // this may need resetting after sleep.
        waketime = millis();  //millis haults when sleeping.  find out the time on boot and compare from there.
        rssisend = TRUE;  //on wakeup report rssi but do not report mail trigger
        mailsend = FALSE;
        //delay(20); //wait to check if mail rx.. could be some debouncing
        if (System.sleepResult().reason() == WAKEUP_REASON_PIN){
                enablemailsend();
        }
        
    mailpinstate = digitalRead(mailpin); //read the mail state pin during the normal loop. 
    
    if ((lastmailpinstate == HIGH) && (mailpinstate == LOW))  {  //this test finds the signal edge HIGH to LOW using one int of memory
            enablemailsend();
            lastmailpinstate = mailpinstate; //reset last mail pin state to be the current state
            delay(100);
        } 
    } 
    
    /*if ((millis()-waketime > 60000)) //if photon awake for over 60 seconds then go back to sleep for long time. (unable to send, maybe lost wifi)
        {
            //Particle.disconnect();
        
            //System.sleep(mailpin,RISING,30); 
            //delay(100);
            System.sleep(mailpin,FALLING,longsleepytime);
            pinMode(mailpin,INPUT); // this may need resetting after sleep.
            waketime = millis();  //millis haults when sleeping.  find out the time on boot and compare from there.
            rssisend = TRUE;  //on wakeup report rssi but do not report mail trigger
            mailsend = FALSE;
            delay(20); //wait to check if mail rx.. could be some debouncing 
            if (System.sleepResult().reason() == WAKEUP_REASON_PIN){
                enablemailsend();
            }
            /*old strategy to detect if particle was woken by mail trigger or by time
            if (digitalRead(mailpin) == LOW) {  //this test triggers a mail send if woken up by the mailpen being drawn low
                enablemailsend();
            } 
            */
            
//        }
    

}

float checkbattery(){
    float battvolts;
    pinMode(volttestpin, INPUT);  
    pinMode(voltpowerpin, OUTPUT); //sent power pin as output
    digitalWrite(voltpowerpin, 0); //send a 0, or LOW to turn on voltage test
    delay(1); //wait for volts to settle good measure
   int battcounts = analogRead(volttestpin); //sample voltage
    //battvolts = float(battvolts)*3.3/4096.0*2.0*3.85/3.827*4.06/4.08;  //calibrate voltage reading
    battvolts = float(battcounts)*3.3/4096.0*2.0;  //calibrate voltage reading
    pinMode(voltpowerpin, INPUT); //disable powerpin and set as high Z input
    return(battvolts); //return calibrated battery voltage
}

void mailnotification(void){
    digitalWrite(D7,1);
    rssi_update();
    sprintf(publishString, "%1.4f", checkbattery());
    Particle.publish("mail/volts", publishString,60,PRIVATE);
    
    //sprintf(publishString, "%d", mailtriggers);
    bool success = Particle.publish("youve-got-mail", Time.format(Time.now(), "%I:%M%p"), 60, PUBLIC, WITH_ACK);
    //delay(1000);
    if (success == TRUE) {
        mailtriggers++;
        mailsend = FALSE; //if sent, then turn off the send flag, otherwise let it try again.
        digitalWrite(D7,0);
        }
}

thingspeak schema

PHP
{
    "event": "thingSpeakWrite_",
    "url": "https://api.thingspeak.com/update",
    "requestType": "POST",
    "form": {
        "api_key": "{{k}}",
        "field1": "{{1}}",
        "field2": "{{2}}",
        "field3": "{{3}}",
        "field4": "{{4}}",
        "field5": "{{5}}",
        "field6": "{{6}}",
        "field7": "{{7}}",
        "field8": "{{8}}",
        "lat": "{{a}}",
        "long": "{{o}}",
        "elevation": "{{e}}",
        "status": "{{s}}"
    },
    "mydevices": true,
    "noDefaults": true
}

thingspeak app code

MATLAB
calculates battery state of charge from battery voltage
% Reads voltage and converts to an approximate state of charge level
% writes this level back to the channel


% Channel ID to read data from
readChannelID = [ENTER YOUR CHANNEL ID HERE];
% Temperature Field ID
VoltsFieldID = 2;

% Channel Read API Key 
% If your channel is private, then enter the read API
% Key between the '' below: 
readAPIKey = 'ENTER YOUR READ KEY HERE';

% To store the battery state of charge, based on battery voltage
% than the one used for reading data. To write to a channel, assign the
% write channel ID to the 'writeChannelID' variable, and the write API Key
% to the 'writeAPIKey' variable below. Find the write API Key in the right
% side pane of this page.

% TODO - Replace the [] with channel ID to write data to:
writeChannelID = [ENTER YOUR CHANNEL ID HERE];
% TODO - Enter the Write API Key between the '' below:
writeAPIKey = 'ENTER YOUR WRITE KEY HERE';

% Read latest temperature data from the MathWorks Weather Station Channel.
% Learn more about the THINGSPEAKREAD function by going to the Documentation tab on
% the right side pane of this page.

volts = thingSpeakRead(readChannelID, 'Fields', VoltsFieldID, 'ReadKey', readAPIKey);

% Convert to battery percentage
%volts = str2double(volts);
battvolts = volts;

%soclookupvolts   = [3.0  3.55 3.60  3.69  3.75  3.80 3.95  4.15];  
%soclookuppercent = [0    5    10    20    50    60   80    100 ];
%soclevel = 0;
%soclevel == tablelookup(soclookupvolts, soclookuppercent, battlevel);

x = battvolts;
y = -287.33*x^3 + 3484.7*x^2 - 13880*x + 18212;
soclevel = y;

display(battvolts, 'Volts');
display(soclevel, 'Percent');

% Write the temperature in Fahrenheit to another channel specified by the
% 'writeChannelID' variable

display(['Note: To successfully write data to another channel, ',...
    'assign the write channel ID and API Key to ''writeChannelID'' and ',...
    '''writeAPIKey'' variables above. Also uncomment the line of code ',...
    'containing ''thingSpeakWrite'' (remove ''%'' sign at the beginning of the line.)'])

% Learn more about the THINGSPEAKWRITE function by going to the Documentation tab on
% the right side pane of this page.

thingSpeakWrite(writeChannelID, 'Fields',[4],'Values',soclevel, 'Writekey', writeAPIKey);

*old* macsboost youve-got-mail particle photon code

Arduino
load on the particle IDE
/*This sketch experiments with low power for battery/solar operation and thingspeak.
 a magnetic reed switch is connected to D0.  The particle sleeps and wakes on a falling edge interrupt at D0.
 if triggered it publishes a notification that can be detected by IFTTT and sends a notification
 to your device.
 on every interrupt and on wakeup a update is published to thingspeak with voltage, current, RSSI and # of triggers.
                                       +-----+
 *                          +----------| USB |----------+
 *                          |          +-----+       *  |
 *       /------------------| [ ] VIN           3V3 [ ] |---------
 *      |                   | [ ] GND           RST [ ] |         \
 *    10K                   | [ ] TX           VBAT [ ] |          |
 *      |                   | [ ] RX  [S]   [R] GND [*] |-------   |
 *      |                   | [ ] WKP            D7 [ ] |       \  |
 *       \                  | [ ] DAC +-------+  D6 [ ] |       |  |  
 *       /------batt sense->| [*] A5  |   *   |  D5 [ ] |       |  |
 *    10K - batt sense gnd->| [*] A4  |Photon |  D4 [ ] |     10K  |
 *  TP4056 Pin 2 curr sense | [*] A3  |       |  D3 [ ] |       |  |
 *                          | [ ] A2  +-------+  D2 [ ] |       |  |
 *                          | [ ] A1             D1 [ ] |       |  /
 *                          | [ ] A0             D0 [*] |<-magnetic reed (door) switch
 *                          |                           |
 *                           \    []         [______]  /
 *                            \_______________________/
 *
 *
 */

/*  begin particle webhook code snippit to add to particle webhook interface on console
{
    "event": "thingSpeakWrite_",
    "url": "https://api.thingspeak.com/update",
    "requestType": "POST",
    "form": {
        "api_key": "{{k}}",
        "field1": "{{1}}",
        "field2": "{{2}}",
        "field3": "{{3}}",
        "field4": "{{4}}",
        "field5": "{{5}}",
        "field6": "{{6}}",
        "field7": "{{7}}",
        "field8": "{{8}}",
        "lat": "{{a}}",
        "long": "{{o}}",
        "elevation": "{{e}}",
        "status": "{{s}}"
    },
    "mydevices": true,
    "noDefaults": true
}
*/

ApplicationWatchdog wd(120000, System.reset);

char publishString[40];
int mailpin = D0;
int volttestpin = A5;
int voltpowerpin = A4;
int currentsensepin = A3;
float chargecurrent = 0;
float batteryvolts = 0;
const int sleepytime = 1800; //seconds to sleep 3600=1hr
const int longsleepytime = 3600; //seconds to sleep 3600=1hr

const String key = "THINGSPEAK_KEY";


int rssival = 0;
volatile bool mailsend = FALSE;
volatile bool rssisend = FALSE;
int mailtriggers = 0;
long waketime = 0;
SYSTEM_THREAD(ENABLED); //enable multitasking.  allows the ability to catch the mailpin trigger and send the message
SYSTEM_MODE(AUTOMATIC);  //run code. then connect     
     
void rssi_update()
{
    //delay (2000);
    static int count = 0;
    Serial.println(count++);
    rssival = WiFi.RSSI();  //measure RSSI
    chargecurrent = analogRead(currentsensepin)*3.3/4096;   //measure solar charge current (A)
    batteryvolts = checkbattery();  //measure battery voltage
    sprintf(publishString,"%d",rssival);
    bool success = Particle.publish("RSSI",publishString);
    
    sprintf(publishString, "%1.4f", batteryvolts);

       Particle.publish("thingSpeakWrite_All", +
     "{ \"1\": \"" + String(rssival) + "\"," +
       "\"2\": \"" + String(batteryvolts) + "\"," +
       "\"3\": \"" + String(mailtriggers) + "\"," +
       "\"5\": \"" + String(chargecurrent) + "\"," +  //channel 5 due to a legacy SOC channel being calculated on thingspeak via a react.
     //"\"5\": \"" + String(var4) + "\"," +
       "\"k\": \"" + key + "\" }", 60, PRIVATE);
       

    if (success == TRUE) {
        //delay(10000);
        rssisend = FALSE; //if sent, then turn of the send flag, otherwise let it try again.
    }
}


void enablemailsend(void){
    mailsend=TRUE;
    digitalWrite(D7,1);
}

void setup() {
    //setADCSampleTime(ADC_SampleTime_239Cycles5);  //sets adc to longest time for low noise
    Time.zone(-4);  //set eastern time zone
    pinMode(mailpin,INPUT);
    pinMode(voltpowerpin, INPUT);
    pinMode(currentsensepin, INPUT);
    pinMode(D7, OUTPUT);
    attachInterrupt(mailpin, enablemailsend, FALLING);
    Particle.variable("mailtrig", mailtriggers);
    rssisend = TRUE;
}


void loop() {
     //wd.checkin();  //watchdog checkin
     //do not checkin the watchdog.  the counter seems to reset each time the system boots.  The watchdog
     //should therefore only cause a reset if the system is stuck, on and cant connect to wifi.
     
     
    if ((Particle.connected())&&(mailsend == TRUE)&&WiFi.ready()) 
    {
        mailnotification();
    }
    
    if ((Particle.connected())&&(rssisend == TRUE)&&WiFi.ready()) 
    {
        rssi_update();
    }
    

    if ((millis()-waketime > 30000) && (mailsend == FALSE) && (rssisend == FALSE)) //if everything sent ok under 30 seconds, then sleep for short time
    {
        Particle.disconnect();
        
        //System.sleep(mailpin,RISING,30); 
        delay(100);
        System.sleep(mailpin,FALLING,sleepytime);
        pinMode(mailpin,INPUT); // this may need resetting after sleep.
        waketime = millis();  //millis haults when sleeping.  find out the time on boot and compare from there.
        rssisend = TRUE;  //on wakeup report rssi but do not report mail trigger
        mailsend = FALSE;
        delay(20); //wait to check if mail rx.. could be some debouncing
        if (digitalRead(mailpin) == LOW) {  //this test triggers a mail send if woken up by the mailpen being drawn low
            enablemailsend();
        } 
    } 
    
    if ((millis()-waketime > 60000)) //if photon awake for over 60 seconds then go back to sleep for long time. (unable to send, maybe lost wifi)
        {
            Particle.disconnect();
        
            //System.sleep(mailpin,RISING,30); 
            delay(100);
            System.sleep(mailpin,FALLING,longsleepytime);
            pinMode(mailpin,INPUT); // this may need resetting after sleep.
            waketime = millis();  //millis haults when sleeping.  find out the time on boot and compare from there.
            rssisend = TRUE;  //on wakeup report rssi but do not report mail trigger
            mailsend = FALSE;
            delay(20); //wait to check if mail rx.. could be some debouncing 
            if (digitalRead(mailpin) == LOW) {  //this test triggers a mail send if woken up by the mailpen being drawn low
                enablemailsend();
            } 
        }


    
    if (Particle.connected() == false) 
    {
        Particle.connect();
    }
    /*if (waitFor(Particle.connected, 20000))
    {
    }
    */
}

float checkbattery(){
    float battvolts;
    pinMode(volttestpin, INPUT);  
    pinMode(voltpowerpin, OUTPUT); //sent power pin as output
    digitalWrite(voltpowerpin, 0); //send a 0, or LOW to turn on voltage test
    delay(1); //wait for volts to settle good measure
    battvolts = analogRead(volttestpin); //sample voltage
    battvolts = float(battvolts)*3.3/4096.0*2.0*3.85/3.827*4.06/4.08;  //calibrate voltage reading
    pinMode(voltpowerpin, INPUT); //disable powerpin and set as high Z input
    return(battvolts); //return calibrated battery voltage
}

void mailnotification(void){
    digitalWrite(D7,1);
    rssi_update();
    sprintf(publishString, "%1.4f", checkbattery());
    Particle.publish("mail/volts", publishString,60,PRIVATE);
    
    //sprintf(publishString, "%d", mailtriggers);
    bool success = Particle.publish("youve-got-mail", Time.format(Time.now(), "%I:%M%p"), 60, PUBLIC);
    delay(1000);
    if (success == TRUE) {
        mailtriggers++;
        mailsend = FALSE; //if sent, then turn off the send flag, otherwise let it try again.
        digitalWrite(D7,0);
        }
}

particle argon code with updated sleep api

Arduino
/*This sketch experiments with low power for battery/solar operation and thingspeak.
 a magnetic reed switch is connected to D2.  The particle sleeps and wakes on a falling edge at D2.
 if triggered it publishes a notification that can be detected by IFTTT and sends a notification
 to your device. on every wakeup a update is published to thingspeak with voltage, RSSI and # of triggers.
 
 Power consumption connected to wifi, approx 35mA
 Charging Lipo, approx 500mA + 35mA
 solar panel v3 is approx 350ma output
 Stop mode(sleep) 1.5mA, retains variables, gpio and program state when stopped.
 Resumes on timeout or pin change on D2 (mail door open)
                                       +-----+
 *                          +----------| USB |---------+
 *                          | O        +-----+      O  |
 *                          | [ ] RESET                |
 *                          | [ ] 3V3                  |         
 *                          | [ ] MODE                 |          
 *                          | [ ] GND                  |   
 *                          | [ ] A0          Lipo [ ] |       
 *                          | [ ] A1  +-------+ EN [ ] |         
 *                          | [ ] A2  |   *   | VIN[ ] |-------\
 *   TP4056 Pin 2 curr sense| [*] A3  | ARGON | D8 [ ] |       |
 *      /------batt sense-> | [*] A4  |       | D7 [ ] |       |  
 *    10K - batt sense gnd->| [*] A5  +-------+ D6 [ ] |       |  
 *                          | [ ] D13           D5 [ ] |    reed door sw  
 *                          | [ ] D12           D4 [ ] |       |
 *                          | [ ] D11           D3 [ ] |       10K
 *                          | [ ] D10           D2 [*] |-------/       
 *                          | [ ] D9            D1 [ ] |       
 *                          | [ ] NC            D0 [ ] |
 *                          |   WIFI0         0NFC     |
 *                          |O                        O|
 *                          +--------------------------+
 *
 *
 */

/*  begin particle webhook code snippit to add to particle webhook interface on console
{
    "event": "thingSpeakWrite_",
    "url": "https://api.thingspeak.com/update",
    "requestType": "POST",
    "form": {
        "api_key": "{{k}}",
        "field1": "{{1}}",
        "field2": "{{2}}",
        "field3": "{{3}}",
        "field4": "{{4}}",
        "field5": "{{5}}",
        "field6": "{{6}}",
        "field7": "{{7}}",
        "field8": "{{8}}",
        "lat": "{{a}}",
        "long": "{{o}}",
        "elevation": "{{e}}",
        "status": "{{s}}"
    },
    "mydevices": true,
    "noDefaults": true
}
*/

ApplicationWatchdog wd(120000, System.reset);

char publishString[100];
int mailpin = D2;
int volttestpin = A4;
int voltpowerpin = A5;
int currentsensepin = A3;
int mailpinstate = 0;
int lastmailpinstate = 0;
float chargecurrent = 0;
float batteryvolts = 0;
int sleepnow = 0;
const int sleepytime = 600;//1800; //seconds to sleep 3600=1hr
const int longsleepytime = 3600; //seconds to sleep 3600=1hr

const String key = "putyourkeyhere";


float rssival = 0;
float rssipct = 0;
volatile bool mailsend = FALSE;     //variable if true means a door event was detected and we need to publish an update to the web.
volatile bool rssisend = FALSE;
int mailtriggers = 0;
long waketime = 0;
SYSTEM_THREAD(ENABLED); //enable multitasking.  i.e run code before connecting to internet.
//SYSTEM_MODE(AUTOMATIC);  //run code. then connect     

     
void rssi_update()
{
    //delay (2000);
    static int count = 0;
    Serial.println(count++);
    //rssival = WiFi.RSSI();  //measure RSSI
    WiFiSignal sig = WiFi.RSSI();
    rssival = sig.getStrengthValue();
    rssipct = sig.getStrength();

    
    chargecurrent = analogRead(currentsensepin)*3.3/4096;   //measure solar charge current (A)
    batteryvolts = checkbattery();  //measure battery voltage
    
    //sprintf(publishString,"%d",rssival);
    
    //sprintf(publishString,"%d",strength);
    //bool success = Particle.publish("RSSI",publishString);
    bool success = Particle.publish("RSSI",String(rssival));
    delay(1000);
    sprintf(publishString, "%1.4f", batteryvolts);  //format battery volts in form of X.XXXX

       Particle.publish("thingSpeakWrite_All", +
     "{ \"1\": \"" + String(rssival) + "\"," +
       "\"2\": \"" + String(batteryvolts) + "\"," +
       "\"3\": \"" + String(mailtriggers) + "\"," +
       "\"5\": \"" + String(chargecurrent) + "\"," +  //channel 5 due to a legacy SOC channel being calculated on thingspeak via a react.
     //"\"5\": \"" + String(var4) + "\"," +
       "\"k\": \"" + key + "\" }", 60, PRIVATE, WITH_ACK);
       

    if (success == TRUE) {
        //delay(10000);
        //rssisend = FALSE; //if sent, then turn of the send flag, otherwise let it try again.
        sleepnow =1; //ok to go to sleep earlier if done
    }
}




void setup() {
    //setADCSampleTime(ADC_SampleTime_239Cycles5);  //sets adc to longest time for low noise
    Time.zone(-4);  //set eastern time zone
    pinMode(mailpin,INPUT);
    pinMode(voltpowerpin, INPUT);
    pinMode(currentsensepin, INPUT);
    pinMode(D7, OUTPUT);
    //attachInterrupt(mailpin, enablemailsend, FALLING);
    Particle.variable("mailtrig", mailtriggers);
    rssisend = TRUE;
    //Mesh.on();
    RGB.brightness(32);
    //LEDStatus status;
}


void loop() {
     wd.checkin();  //watchdog checkin
     sleepnow = 0;
     //status.on(); // Turns the LED on
     //do not checkin the watchdog.  the counter seems to reset each time the system boots.  The watchdog
     //should therefore only cause a reset if the system is stuck, on and cant connect to wifi.
     
     
    if ((Particle.connected())&&(mailsend == TRUE))
    {
        mailnotification();
    }
    
    if ((Particle.connected())&&(rssisend == TRUE))
    {
        rssi_update();
    }
    

    if ((millis()-waketime > 30000)|| sleepnow)// && (mailsend == FALSE) && (rssisend == FALSE)) //if everything sent or if it stays awake over 30 seconds, then sleep 
    {
  
        
        //  ** Begin go to sleep routine
        // wake after GPIO falling edge on pin D2
        // wake after 10 minute timer
        digitalWrite(D7,0); //turn off led before sleeping.
        SystemSleepConfiguration config;    //new api command
        config.mode(SystemSleepMode::STOP)
            .gpio(D2, FALLING)  //same as before
            .duration(10min);   //wakeup after 10 minutes if no gpio trigger
        System.sleep(config);
 
        // ** End go to sleep routine
        
        
        //* After sleep, need to turn wifi radio back on, then ask to connect to the particle cloud
        
        if (mailsend == TRUE){ //turn led back on after sleep if need to mailsend.
            digitalWrite(D7,1); //turn off led before sleeping.
        }
        WiFi.on();
        Particle.connect();
        // * End after sleep routine
        
  
        waketime = millis();  //millis haults when sleeping.  find out the time on boot and compare from there.
        rssisend = TRUE;  //on wakeup report rssi but do not report mail trigger
        mailsend = FALSE;

        if (System.sleepResult().reason() == WAKEUP_REASON_PIN){    // if particle wakes from a GPIO or pin then do this
                mailtriggers++;  //if sent increment the mailtriggers counter
                mailsend=TRUE;
                digitalWrite(D7,1);
        }
        
    } 


}

float checkbattery(){
    float battvolts;
    pinMode(volttestpin, INPUT);  
    pinMode(voltpowerpin, OUTPUT); //sent power pin as output
    digitalWrite(voltpowerpin, 0); //send a 0, or LOW to turn on voltage test
    delay(1); //wait for volts to settle good measure
   int battcounts = analogRead(volttestpin); //sample voltage
   
    battvolts = float(battcounts)*3.3/4096.0*2.0;  //calibrate voltage reading
    pinMode(voltpowerpin, INPUT); //disable powerpin and set as high Z input
    return(battvolts); //return calibrated battery voltage
}

void mailnotification(void){
    digitalWrite(D7,1);
    rssi_update();
    //sprintf(publishString, "%1.4f", checkbattery());
    //Particle.publish("mail/volts", publishString,60,PRIVATE);
    delay(1000);
    
    //sprintf(publishString, "%d", mailtriggers);
    bool success = Particle.publish("youve-got-mail", Time.format(Time.now(), "%I:%M%p"), 60, PUBLIC, WITH_ACK);
    //delay(1000);
    if (success == TRUE) {
        mailsend = FALSE; //if sent, then turn off the send flag, otherwise let it try again.
        digitalWrite(D7,0);  //if sent, turn off the LED.
        }
}

Credits

John R McAlpine V Mac

John R McAlpine V Mac

17 projects • 87 followers
www.MACSBOOST.com Assistant Teaching Professor at UNC Charlotte MEGR3171 Instrumentation, Motorsports Research

Comments