When my Boron wakes up after being in ULP mode the LED will breath dark blue and it pretty much does not do anything. It is hung up in this weird not really awake mode.
I have a IOT publish that goes out right before it goes to sleep. It will eventually wake up just enough to sent that and it is back to sleep. The rest of the program is not running. It does not even bring the digital inputs/outputs back up to where they will function. I have a DO that controls a transistor to control the LCD, pressure transmitter, and temperature sensor, it is not pulling that back up enough to drive the transistor on all the way. Watching my Log.info my digital inputs are functional. It is almost like it forgets void setup when it starts back up and the output to fire up the other devices does not come back. Except for the cellular will turn on, cloud connect, start the sleep timer, publish that it is going to sleep, and back out it goes.
I have the sleep time set at 3600000 which is winding up being about 3 hours.
Now if I power cycle or push the reset button it will fire up and work just like expected the first time.
I did find a document about the device blinking dark blue when the setup flag is not done. I tried it anyway and that did not help. This LED is “breathing” and not “blinking”
Log.info is sending info out. This ones comes out every time my block of info logs and I am not sure what it is or if it is helpful in figuring this out.
Below is the last string of Log.info as it went to sleep. This time around it never connected back to the cloud. Only had dark blue breathing the entire time. I wish I could figure out how to have the serial monitor fire back up as soon as it wakes up. When it woke up this time it woke from the digital input wakebutton going low. It did not wake up on its own from time. I still have not figured out how to get it to wake at specific times.
Thank you.
/* SHOWER TRAILER MONITOR
* Monitor door position, water level low and LOWLOW switches
* Monitor temperature via I2C sendor and gas bottle pressure via analog input
* Send information to cloud 2 times a day at 0400, 1200
* Board to sleep mode between transmissions turning off LCD and cellular. Will wake on door switch or wake button
* When board has been woken up it is to stay awake for 20 minutes, transmit status when woken up and prior to returning to sleep.
* THINGS TO DO: Sleep mode, debounce DI's,
* Sleep mode, will go to sleep after 20 minutes, can be woken up by wake button, low & low low water, and door switch.
* Sleep mode ULP with only pins active will be the pins that can wake. Cellular off.
*/
#include "AnalogSmoother.h"
#include "Arduino.h"
#include "Debounce.h"
#include <Wire.h>
#include "LiquidCrystal_I2C_Spark.h"
#include <SparkFun_Qwiic_Humidity_AHT20.h>
#include "Adafruit_IO_Client.h"
#include "Adafruit_IO_Particle.h"
#include "Particle.h"
AHT20 humiditySensor;
// WAKE BUTTON
int wake_sw = 8;
int last_wake_sw;
bool wake_new_value = true;
int wake_sw_value = digitalRead(wake_sw);
int go_to_sleep = 0;
// DOOR SWITCHES
int door_sw = 6;
// WATER LEVEL SWITCHES
int water_low_sw = 4;
int water_LOWLOW_sw = 5;
int last_water_level = 0;
// LCD
int lcd_power = D3;
LiquidCrystal_I2C *lcd;
// ON BOARD LED
int idiot_LED = D7;
// BATTERY MONITORING
AnalogSmoother battery(A1, 10);
int batteryPin = A1;
int batteryValue = 0;
int batteryScaled = 0;
int last_batteryScaled = 0;
// GAS PRESSURE
AnalogSmoother gas_pressure(A0, 10);
int transmitter_lcd_power = D2;
int gas_pressurePin = A0;
int gas_pressureValue = 0;
float gas_pressureScaled = 0;
int last_gas_pressureScaled = 0;
// TEMPERATURE
float last_Ftemp = 0;
// CLOUD CONNECTION
int last_cloud_connected;
SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);
// ADAFRUIT IO CONNECTIONS ###### need to move username and key into seperate library ################
#define AIO_USERNAME
#define AIO_KEY
TCPClient client; // TCP Client used by Adafruit IO library
// Create the AIO client object
Adafruit_IO_Client AIOClient = Adafruit_IO_Client(client, AIO_KEY);
// Create a feed object to send and get data
Adafruit_IO_Feed ST0000temperaturefeed = AIOClient.getFeed("ST-0000-temperature-feed");
Adafruit_IO_Feed ST0000batteryfeed = AIOClient.getFeed("ST-0000-batteryfeed");
Adafruit_IO_Feed ST0000waterlevelLOWfeed = AIOClient.getFeed("ST-0000-water-level-LOW-feed");
Adafruit_IO_Feed ST0000waterlevelLOWLOWfeed = AIOClient.getFeed("ST-0000-water-level-LOWLOW-feed");
Adafruit_IO_Feed ST0000gasPfeed = AIOClient.getFeed("ST-0000-gasPfeed");
Adafruit_IO_Feed ST0000doorfeed = AIOClient.getFeed("ST-0000-doorfeed");
Adafruit_IO_Feed ST0000sleepfeed = AIOClient.getFeed("ST-0000-sleepfeed");
// TIMER FOR PUBLISHING
int publish_data = 1;
unsigned int publish_timer_period = (1000 * 60 * 10); // 10 minute interval
Timer publish_timer(publish_timer_period, time_to_publish);
void time_to_publish() {
Log.info("time to publish=%d", publish_data++);
}
// System Sleep
SystemSleepConfiguration config;
int sleep_duration = 0;
// LOG handler
SerialLogHandler logHandler(LOG_LEVEL_TRACE);
// TIME
#define ONE_DAY_MILLIS (24 * 60 * 60 * 1000)
unsigned long lastSync = millis();
int lastSecond = 0;
unsigned int sleep_timer_period = (1000 * 60 * 30); // 30 minutes
Timer sleep_timer(sleep_timer_period, time_to_go_to_sleep); // set at 30 minutes
// SLEEP TIMER ACTIONS
void time_to_go_to_sleep() {
Log.info("going to sleep=%d", go_to_sleep++);
}
void setup() // SETUP ############################################
{
// PINS AND PIN MODES
pinMode(door_sw, INPUT_PULLDOWN); // pin low when door open
pinMode(water_low_sw, INPUT_PULLDOWN); // pin low when water level LOW
pinMode(water_LOWLOW_sw, INPUT_PULLDOWN); // pin low when water level LOW LOW
pinMode(wake_sw, INPUT_PULLUP); // pin low when wake switch pressed
pinMode(idiot_LED, OUTPUT); // just an idiot light
pinMode(transmitter_lcd_power, OUTPUT);
digitalWrite(transmitter_lcd_power, HIGH); // lcd powered when awake, will turn off when in sleep mode
(void)logHandler; // just to eliminate the unused variable warning
AIOClient.begin(); // Adafruit IO client
Serial.begin(115200);
gas_pressure.fill();
battery.fill();
lcd = new LiquidCrystal_I2C(0x3f, 20, 4);
lcd->init();
lcd->backlight();
lcd->clear();
lcd->setCursor(0,0);
lcd->print("SHOWER TRAILER 0000");
lcd->setCursor(0,1);
lcd->print("STARTING UP");
sleep_timer.start(); // timer for system to go to sleep after 30 minutes
publish_timer.start(); // timer for publishing to cloud
delay(2000);
Wire.setSpeed(20000);
Wire.begin();
//Check if the AHT20 will acknowledge
if (humiditySensor.begin() == false) {
Log.info("AHT20 not detected. Please check wiring. Freezing.");
}
else{
}
Log.info("AHT20 acknowledged.");
// Turning on cellular and connecting to the cloud
if(Cellular.isOff() == true) {
Cellular.on();
waitFor(Cellular.isOn, 30000);
}
Cellular.connect();
if(Particle.connected() == false) {
Particle.connect();
Log.info("Connecting to skynet");
lcd->setCursor(0,1);
lcd->print("CLOUD: CONNECTING");
waitFor(Particle.connected, (90000));
lcd->setCursor(0,3);
switch (Particle.connected())
{
case 0:
Log.info("CLOUD: NOT CONNECTED");
lcd->print("CLOUD: NOT CONNECTED");
break;
case 1:
Log.info("CLOUD: CONNECTED");
lcd->print("CLOUD: CONNECTED");
break;
}
}
// CLOCK
if (millis() - lastSync > ONE_DAY_MILLIS) {
// Request time synchronization from the Particle Device Cloud ###### need to change to get local time ######
Particle.syncTime();
lastSync = millis();
}
lcd->clear();
}
void loop() // LOOP #######################################
{
if(Cellular.isOff() == true) {
Cellular.on();
Log.info("Cellular turning back on");
lcd->clear();
lcd->print("CELLULAR TURNING BACK ON");
waitFor(Cellular.isOn, 30000);
Cellular.connect();
}
else {
}
// if (humiditySensor.available() == true)
Log.info("ST 0000");
lcd->setCursor(0,0);
lcd->print("ST 0000");
// TIME on LCD
if (Time.second() != lastSecond) {
Log.info(Time.timeStr() );
lcd->setCursor(8,0);
Time.zone(-6);
lcd->print(Time.hour() < 10? " 0" : " ");
lcd->print(Time.hour());
lcd->print(Time.minute() < 10? ":0": ":");
lcd->print(Time.minute());
lastSecond = Time.second();
}
// Temperature and Battery
float temperature = humiditySensor.getTemperature();
float Ftemp = round(((temperature * 9/5)+32));
Log.info("Temp:=%f", Ftemp);
batteryValue = battery.read();
float batteryScaled = map(batteryValue,1125,4000,5,16);
Log.info("BATT:=%f ",batteryScaled);
Log.info("Battery AI:=%d", batteryValue);
lcd->setCursor(0,1);
lcd->print("TEMP:");
lcd->print(Ftemp, 0);
lcd->print("F");
lcd->print(" Batt:");
lcd->print(batteryScaled, 2);
lcd->print("V");
// WATER LEVEL SWITCHES
int Water_Level = digitalRead(water_low_sw) + digitalRead(water_LOWLOW_sw);
int Water_level_low = digitalRead(water_low_sw);
int Water_level_LOWLOW = digitalRead(water_LOWLOW_sw);
lcd->setCursor(0,2);
{
switch (Water_Level)
{
case 0:
Log.info("WTR:MIN! ");
lcd->print("WTR:MIN!");
break;
case 1:
Log.info("WTR:LOW ");
lcd->print("WTR:LOW ");
break;
case 2:
Log.info("WTR:GOOD ");
lcd->print("WTR:GOOD");
break;
default:
Log.info("WTR:ERR! ");
lcd->print("WTR:ERR!");
break;
}
last_water_level = Water_Level;
Log.info("WATER LOW:%d", Water_level_low);
Log.info("WATER LEVEL LOWLOW:%d", Water_level_LOWLOW);
delay(1000);
}
// DOOR POSITION SWITCHES
int door_pos = digitalRead(door_sw);
lcd->setCursor(10,2);
{
switch (door_pos)
{
case 0:
Log.info("DOOR:OPEN ");
lcd->print("DOOR:OPEN");
break;
case 1:
Log.info("DOOR:CLSD ");
lcd->print("DOOR:CLSD");
break;
}
Log.info("door_pos:=%d", door_pos);
delay(1000);
}
// WAKE BUTTON
int wake_sw_lvl = digitalRead(wake_sw);
{
switch (wake_sw_lvl)
{
case 0:
Log.info("WAKE SWITCH: AWAKEN");
sleep_timer.reset(); // Sleep timer reset
digitalWrite(idiot_LED, LOW);
break;
case 1:
Log.info("WAKE SWITCH: NOT");
break;
}
last_wake_sw = wake_sw_lvl;
Log.info("wake_sw_lvl:=%d", wake_sw_lvl);
delay(1000);
}
// GAS PRESSURE TROUBLE and PRESSURE VALUES
if(gas_pressureValue < 500) {
Log.info("Gas P AI:=%d", gas_pressureValue);
gas_pressureValue = gas_pressure.read();
gas_pressureScaled = map(gas_pressureValue,600,3000,1,3000);
lcd->setCursor(0,3);
lcd->print("GAS:");
lcd->print("TRBL ");
}
else
{
Log.info("GAS_pressure_Value:=%d",gas_pressureValue);
lcd->setCursor(0,3);
lcd->print("GAS:");
lcd->print(gas_pressureScaled);
lcd->print("PSI");
delay(1000);
}
if(gas_pressureScaled < 1) {
Log.info("GAS PRESSURE BAD");
}
else
Log.info("GAS PRESSURE SCALED:%f", gas_pressureScaled);
Serial.println();
// CLOUD CONNECTED
int cloud_connected = Particle.connected();
lcd->setCursor(12,3);
{
switch (cloud_connected)
{
case 0:
Log.info("CLOUD NOT CONNECTED");
lcd->print("CLD:NOT");
break;
case 1:
Log.info("CLOUD CONNECTED");
lcd->print("CLD:CON");
break;
}
last_cloud_connected = cloud_connected;
}
// PUBLISHING DATA TO CLOUD NEED TO MAKE PUBLISH ONE TIME, then only if there is a change. Publish limit once per minute
// Trigger the integration
// Log info for bool troubleshooting
if ((Particle.connected() == true) & (publish_data == 1)) {
String Stemp = String::format("%.2f", Ftemp);
ST0000temperaturefeed.send(Stemp);
delay(30000);
String Sbatt = String::format("%.2f", batteryScaled);
ST0000batteryfeed.send(Sbatt);
delay(30000);
String SgasP = String::format("%.f", gas_pressureScaled);
ST0000gasPfeed.send(SgasP);
delay(30000);
ST0000waterlevelLOWfeed.send(Water_level_low);
delay(30000);
ST0000waterlevelLOWLOWfeed.send(Water_level_LOWLOW);
delay(30000);
ST0000doorfeed.send(door_pos);
delay(30000);
publish_data = 0;
publish_timer.reset();
}
else {
}
Log.info("PUBLISH DATA:%d", publish_data);
// setting sleep duration to wake at 0400, 1200, 1800
sleep_duration = (3600000*1);
Log.info("Sleep Duration TIME:%d", sleep_duration / 3600000);
Log.info("SLEEP STATUS:=%d", go_to_sleep);
// SLEEP TIMER ACTIONS
switch (go_to_sleep == 1) {
case 0:
break;
case 1:
digitalWrite(idiot_LED, HIGH);
lcd->clear(); // clear LCD
lcd->print("GOING TO SLEEP"); // write on LCD going to sleep
Log.info("GOING TO SLEEP"); // log entry for sleep
ST0000sleepfeed.send(1);
delay(30000);
Particle.disconnect(); // disconnect from cloud
delay(6000);
Cellular.off(); // turn cellular off
delay(6000);
digitalWrite(transmitter_lcd_power, LOW); // turn off gas pressure transmitter
digitalWrite(lcd_power, LOW); // turn off lcd
digitalWrite(idiot_LED, LOW);
sleep_timer.reset();
go_to_sleep = 0;
config.mode(SystemSleepMode::ULTRA_LOW_POWER).duration(sleep_duration) // wakeup at 0400, 1200, 1800 CST
.gpio(water_low_sw, FALLING) // wake up if water_low_sw opens on low water
.gpio(water_LOWLOW_sw, FALLING) // wake up if water_LOWLOW_sw opens on LOW LOW water level
.gpio(door_sw, FALLING) // wake up if door_sw opens on open door condition
.gpio(wake_sw, FALLING); // wake up if wake_sw opens when depressed
System.sleep(config); // going to sleep
break;
}
delay(6000);
}
Log.info
0036814780 [app] INFO: CLOUD NOT CONNECTED
0036818994 [app] INFO: PUBLISH DATA:26
0036818995 [app] INFO: Sleep Duration TIME:1
0036818995 [app] INFO: SLEEP STATUS:=1
0036828027 [app] INFO: GOING TO SLEEP
0036846187 [ncp.at] TRACE: > AT+CIMI
0036846214 [ncp.at] TRACE: < 234104099952405
0036846214 [ncp.at] TRACE: < OK
0036871435 [system.nm] TRACE: Request to power off the interface
0036871435 [net.pppncp] TRACE: NCP event 3
0036871436 [net.pppncp] TRACE: NCP power state changed: IF_POWER_STATE_POWERING_DOWN
0036871436 [ncp.client] TRACE: Try powering modem off using AT command
0036871437 [ncp.at] TRACE: > AT+CPWROFF
0036871438 [system.nm] INFO: State changed: IFACE_DOWN -> DISABLED
0036874259 [ncp.at] TRACE: < OK
0036874260 [ncp.client] TRACE: Waiting the modem to be turned off...
0036874300 [net.pppncp] TRACE: NCP event 3
0036874300 [net.pppncp] TRACE: NCP power state changed: IF_POWER_STATE_DOWN
0036874300 [system.nm] TRACE: Interface 4 power state changed: 1
0036874301 [ncp.client] TRACE: It takes 41 ms to power off the modem.
0036874301 [mux] INFO: Stopping GSM07.10 muxer
0036874302 [mux] INFO: Gracefully stopping GSM07.10 muxer
0036874302 [mux] INFO: Closing all muxed channels
0036874302 [mux] INFO: Closing mux channel 1
0036874303 [mux] INFO: Muxed channel 2 already closed
0036874303 [mux] INFO: Muxed channel 3 already closed
0036874303 [mux] INFO: Muxed channel 4 already closed
0036874304 [mux] INFO: GSM07.10 muxer thread exiting
0036874304 [mux] INFO: GSM07.10 muxer stopped
0036874305 [ncp.client] TRACE: Setting UART voltage translator state 0
0036874305 [ncp.client] TRACE: Soft power off modem successfully
0036874305 [ncp.client] TRACE: Deinit modem serial.
0036874306 [ncp.client] TRACE: Modem already off
0036874306 [ncp.client] TRACE: Setting UART voltage translator state 0
0036874307 [ncp.client] TRACE: Soft power off modem successfully
0036874307 [ncp.client] TRACE: Deinit modem serial.
0036874307 [ncp.client] TRACE: NCP state changed: 0
0036874308 [net.pppncp] TRACE: NCP event 1
0036877435 [system.sleep] TRACE: Entering system_sleep_ext()
0036877436 [system.sleep] TRACE: Interface 4 is off already
0036877436 [system.sleep] TRACE: Interface 3 is off already