MKR1000 runs loop once on battery but then doesn't run anymore

I'm a little perplexed. I have a weather station I've built. The code runs great on USB plug in. Even runs well when plugged into LIPO, but here's the thing: On USB the loop runs the way it's supposed to reconnect every 50 seconds. On LIPO, it runs once and never runs again (despite the fact that the board and all connected devices remain powered.)
The code is below. Any thoughts?

#include <Wire.h>                                                   //Import the required libraries
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <SPI.h>
#include <WiFi101.h>
#include <ThingSpeak.h>

#define windSen 0
//#define uS_TO_S_FACTOR 1000000ULL                        //Conversion factor for micro seconds to seconds NOT USED
//#define TIME_TO_SLEEP  20                                           //Time ESP32 will go to sleep (in seconds) 9.5 minutes / 590 seconds NOT USED
#define BME_CS 13
#define BME_MOSI 12
#define BME_MISO 11
#define BME_SCK 10
#define lightSen 5

int status = WL_IDLE_STATUS;

Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);                                                

WiFiClient client;                                                  //WiFi connection details
char ssid[] = "###MASKED FOR PRIVACY####";                                               //WiFi Name
char pass[] = "###MASKED FOR PRIVACY####";                                               //WiFi Password

unsigned long myChannelNumber = "###MASKED FOR PRIVACY####";                              //Thingspeak channel number
const char * myWriteAPIKey = "###MASKED FOR PRIVACY####";                                //Thingspeak API write key

int light = 0;                                                      //Variables to store sensor readings
int temp = 0;
int humid = 0;
int pressure = 0;
int wind = 0;

int windMap[2][32] = {{2000,1400,1000,600,500,400,320,280,240,220,200,180,170,160,150,140,130,120,110,100,90,80,70,60,50,40,38,36,34,32,30,28},{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,23,25,29,34,41,51,54,57,60,64,68,73}};

unsigned long startTime = 0;
unsigned long endTime = 0;
int counter = 0;                                                     //Counter to keep track of the number of wind speed revolutions 

unsigned long lastConnectionTime = 0;                                // last time you connected to the server, in milliseconds
const unsigned long postingInterval = 10L * 1000L;                   // delay between updates, in milliseconds


void setup()                                                         //Setup function - only function that is run in deep sleep mode
{

}

void loop()                                                          //Loop function 
{
  Serial.begin(9600);
  pinMode(windSen, INPUT_PULLUP);
  pinMode(lightSen, INPUT);                                          //Define pin functions
  counter = 0;                                                       //Reset wind speed counter
  unsigned status;
  delay(200);                                                        //Allow BME sensor to startup
  status = bme.begin();                                              //Connect to BME sensor
  if (!status)
  {
    Serial.println("Could not find a valid BME280 sensor");
  }
  int lastState = 0;                                                 //Variable to store the last state of wind sensor input
  for (int i=0; i<= 6000; i++)
  {
    if (digitalRead(windSen) == HIGH && lastState == 0)
    {
      counter++;
      lastState = 1;
    }
    else if (digitalRead(windSen) == LOW && lastState == 1)
    {
      lastState = 0;
    }
    delay(1);
  }
  recTempHumid ();                                                   //Take readings from BME sensor
  recPress ();    
  recLight ();                                      
  calcWind ();
  Serial.print("Temp: ");
  Serial.println(temp);
  Serial.print("Humidity: ");
  Serial.println(humid);
  Serial.print("Pressure: ");
  Serial.println(pressure);
  Serial.print("Wind: ");
  Serial.println(wind);
  Serial.print("Light: ");
  Serial.println(light);
  WiFi.begin(ssid, pass);                                            //Connect to WiFi network
  int timeout = 0;
  while (WiFi.status() != WL_CONNECTED  && timeout < 20)
  {
    delay(500);
    Serial.print(".");
    timeout++;
  }
  if(WiFi.status() == WL_CONNECTED)
  {
    Serial.println("");
    Serial.println("WiFi connected");
    ThingSpeak.begin(client);                                        //Initialise ThingSpeak
    updateThingSpeak();                                             //Post the data to Thingspeak
  }
  else
  {
    Serial.println("");
    Serial.println("WiFi connection failed");
  }
  Serial.flush();
  Serial.println("Waiting until next check");
  delay(50000);
}

void recTempHumid()                                                 //Function to record the temperature and humidity
{
  temp = bme.readTemperature();
  temp = temp * 9 / 5 + 32; // Convert C to F
  humid = bme.readHumidity();
}

void recLight ()                                                     //Function to record the light level
{
  light = analogRead(lightSen);
}


void recPress()                                                     //Function to record the pressure
{  
  int presstemp = bme.readPressure();
  pressure = presstemp / 3386.39;    // Convert hPa to in/Hg
}

void calcWind()                                                     //Function to calculate the wind speed
{
  int ave = 2000;
  if(counter > 1)                                                    //Check that at least two ticks have been registered, one is meaningless
  {
    ave = 6000/(counter-1);                                          //Calculate the average time between ticks
  }
  Serial.print("Average Tick Time: ");
  Serial.println(ave);
  if (ave < 28)                                                      //Discard readings faster than 102kph
    ave = 28;
  int index = 0;
  while (ave < windMap[0][index])                                    //Search through the windMap array for the corressponding wind value
    index++;
  wind = windMap[1][index];
  int mphconv;
  mphconv = ((wind * 10000L + 5)/ 16090);                                                      //Convert the wind speed to mph
  wind = mphconv;                                                             
  Serial.print("Wind Speed: ");
  Serial.println(wind);
}

void updateThingSpeak()                                             //Function to post data to Thingspeak
{
  ThingSpeak.setField(1, temp);
  ThingSpeak.setField(2, humid);
  ThingSpeak.setField(3, pressure);
  ThingSpeak.setField(4, wind);
  ThingSpeak.setField(5, light);
  int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
  if(x == 200)
  {
    Serial.println("Channel update successful.");
  }
  else
  {
    Serial.println("Problem updating channel. HTTP error code " + String(x));
  }
}

1 Like
void loop()                                                          //Loop function 
{
  Serial.begin(9600);

Why is serial.begin in loop()? It only needs to be run one time in setup() after that the setting is set.

How do you know the code only runs once?

Post your wiring diagram.

I left the Serial.begin in there by mistake.

I know the code only runs once because it is supposed to post to ThingSpeak. I see it post once when on LIPO and it doesn't post again. But when on USB, it posts every 50 seconds, just as it's supposed to.

Why is this in loop() when it should be in setup()?

Why is this in loop() when it should be in setup()?

If the code runs with USB but not on LiPo the issue is most likely LiPo.

Looking at the schematic... No wait you did not post one.

Ok.

Looking at the image of the project... Oh wait you did not post a project image all wired up and not working.

Here's my schematic. Pardon the crudenesss. I've never created one before.

I don't exactly have pictures of it all assembled. It's more like a mishmash of wires everywhere until I package it all together into the housings I've 3D printed.

Did you load up a blink the internal led sketch and see if it runs on the mkr with the LiPo?

The solar panel should have a diode on the V+ line to prevent reverse current flow at night through the solar cell.

Yes. It worked fine, but only ran one cycle of the loop.

This I had not considered. I changed the wiring on this to use the 5V pins on the board out instead of the USB out (after looking at the documentation on the solar power manager). Those will provide power from either the battery, the solar panel or both depending on the votage available. ~ Thank you.

post your blink code. Did you disconnect the rest of the components when you ran blink? What was the blink code you used?

... so it really didn't work fine? The LED blinks once?

I misunderstood about blink code that Idahowalker was talking about (I'm pretty new to playing around with arduino). I see what you guys are talking about now.
Here's what I am uploading to test with (which I got from here: https://create.arduino.cc/projecthub/user02442502/with-your-smart-phone-and-arduino-mkr1000-blink-a-led-3842e4):

#include <SPI.h>
#include <WiFi101.h>

// Setup  WIFI 
char ssid[] = "xx";       //  your network SSID (name)
char pass[] = "xx";   // your network password
int status = WL_IDLE_STATUS;
WiFiServer server(80);
//int keyIndex = 0;           // your network key Index number (needed only for WEP)

//Setup your inputs and/or outputs
int ledPin = 6;

//Setup general variables
int val = 0;
int val_AnalogIn_A = 0;
int var = 0;

//Main setup section
void setup() {
  Serial.begin(9600);      // initialize serial communication
  delay(5000);

  //Setup start
  Serial.println("Setup Start, wait...");

  //setup input and output pins, this case is for Arduino MKR1000
  pinMode(ledPin, OUTPUT);    
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);

  
  
  // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to Network named: ");
    Serial.println(ssid);                   // print the network name (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);
  }
  server.begin();                           // start the web server on port 80
  printWifiStatus();                        // you're connected now, so print out the status
}



void loop(void) {

  //in case you have sensors connected to Analog Input (A1 and A2) here will be read and send to the serial monitor.
  read_Analog_input();
  
  // Check if module is still connected to WiFi.
  if (WiFi.status() != WL_CONNECTED) {
    while (WiFi.status() != WL_CONNECTED) {
      
    }
  }

  WiFiClient client = server.available();

  if (client) {
    
    Serial.println("Client connected.");

    while (client.connected()) {
      if (client.available()) {
        char command = client.read();
        if (command == 'H') {
          digitalWrite(ledPin, HIGH);
          Serial.println("LED is now on.");
        }
        else if (command == 'L') {
          digitalWrite(ledPin, LOW);
          Serial.println("LED is now off.");
        }
      }
    }
    Serial.println("Client disconnected.");
    client.stop();
  }

}


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.println("it means:");
  Serial.println("-30 dBm Amazing");
  Serial.println("-67 dBm Very Good");
  Serial.println("-70 dBm Okay");
  Serial.println("-80 dBm Not Good");
  Serial.print(rssi);
  Serial.println(" dBm, now we have!!!");
  // print where to go in a browser:
  Serial.print("To see the app in action, use IP-Address in your Phone app GUI: ");
  
  Serial.println(ip);
  delay(10000);

  
}

void read_Analog_input()
{
  while(var < 10)
  {
    if (var == 0)
    {
      Serial.println("In case to have sensors here are printed the Values in Analog Input");
    }
  // do something repetitive x times
  val_AnalogIn_A = analogRead(A1);
  Serial.print("Analog In A1 :");
  Serial.println(val_AnalogIn_A);
  delay(100);
  var++;  
  }  
}

So, I'll try this and let you know.

This code is not great. If you disconnect then you just sit in this loop forever... it doesn't try to reconnect. Can you put a print statement in here to see if that's where you are getting stuck?

Ok, instead I decided to use this:

/*
  Titre      : blink
  Auteur     : Anis Aliouachene
  Date       : 11/01/2022
  Description: Blink LED externe 
  Version    : 0.0.1
*/

#include <Arduino.h>

void blink (int Pin, int temp);

const int LedPin = 13; 
const int tmp = 1000;

void setup() {
  
  pinMode(LedPin, OUTPUT);

}

void loop() {

blink (LedPin, tmp);

}

// Fonction Blink 
void blink (int Pin, int temp){

  digitalWrite(Pin, HIGH);
	delay(temp);

	digitalWrite(Pin, LOW);
	delay(temp);
}

It works well on USB (never stops), on LiPO - direct (never stops), and with the solar array with the LiPO plugged in (never stops). I would like to set that same code up so I can test to make sure it works with the WiFi somehow, but not sure I need to do that. I think the problem is most likely more in my weather station code. Likely that everything is in the Loop? I'll play with putting the right things in Setup and the right things in Loops and test again and let you know.

OK, so that at least proves that the LiPo is providing some power.

WiFi will use a lot more power than an LED. What if you add the WiFi connection code to the setup routine of your new blink sketch? Does the LED still blink is all cases?

Ok, So, here's the code I did, and it's working (I turned off my router to confirm that it doesn't blink when it can't connect). It blinks on USB, LiPO, and the solar array setup.


#include <Arduino.h>
#include <SPI.h>
#include <WiFi101.h>

// Setup  WIFI 
char ssid[] = "###MASKED FOR PRIVACY####";       //  your network SSID (name)
char pass[] = "###MASKED FOR PRIVACY####";   // your network password
int status = WL_IDLE_STATUS;


void blink (int Pin, int temp);

const int LedPin = 13; 
const int tmp = 1000;

void setup() {
  
  pinMode(LedPin, OUTPUT);

  WiFi.begin(ssid, pass);                                            //Connect to WiFi network
}



void loop() {  
 
  int timeout = 0;

  while (WiFi.status() != WL_CONNECTED  && timeout < 20)
    {
      delay(500);
      Serial.print(".");
      timeout++;
    }
    if(WiFi.status() == WL_CONNECTED)
    {
    Serial.println("");
    Serial.println("WiFi connected - starting blink");
    blink (LedPin, tmp);                              //start blinking if it is          
    }
}

// Function Blink 
void blink (int Pin, int temp){

  digitalWrite(Pin, HIGH);
	delay(temp);

	digitalWrite(Pin, LOW);
	delay(temp);
}

Are the other components still connected?

Try adding them back one at a time and repeat the test.

They weren't connected. I'm cleaning up the code now - putting things in Setup that should be there. I'll try testing again in a few min and let you know the results.

It's definitely connecting over with USB. But no-go with LiPO or the solar array.

Here's the code:

#include <Wire.h>                                                   //Import the required libraries
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <SPI.h>
#include <WiFi101.h>
#include <ThingSpeak.h>

#define windSen 0
#define uS_TO_S_FACTOR 1000000ULL                                   //Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP  20                                           //Time ESP32 will go to sleep (in seconds) - 9.5 minutes / 590 seconds
#define BME_CS 13
#define BME_MOSI 12
#define BME_MISO 11
#define BME_SCK 10
#define lightSen 5

int status = WL_IDLE_STATUS;

Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);                                                

WiFiClient client;                                                  //WiFi connection details
char ssid[] = "###MASKED FOR PRIVACY####";                                               //WiFi Name
char pass[] = "###MASKED FOR PRIVACY####";                                               //WiFi Password

unsigned long myChannelNumber = ###MASKED FOR PRIVACY####;                               //Thingspeak channel number
const char * myWriteAPIKey = "###MASKED FOR PRIVACY####";                                //Thingspeak API write key

int light = 0;                                                      //Variables to store sensor readings
int temp = 0;
int humid = 0;
int pressure = 0;
int wind = 0;

int windMap[2][32] = {{2000,1400,1000,600,500,400,320,280,240,220,200,180,170,160,150,140,130,120,110,100,90,80,70,60,50,40,38,36,34,32,30,28},{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,23,25,29,34,41,51,54,57,60,64,68,73}};

unsigned long startTime = 0;
unsigned long endTime = 0;
int counter = 0;                                                     //Counter to keep track of the number of wind speed revolutions 

unsigned long lastConnectionTime = 0;                                // last time you connected to the server, in milliseconds
const unsigned long postingInterval = 10L * 1000L;                   // delay between updates, in milliseconds


void setup()                                                         //Setup function 
{
  Serial.begin(9600);
  WiFi.begin(ssid, pass);                                            //Connect to WiFi network
  pinMode(windSen, INPUT_PULLUP);
  pinMode(lightSen, INPUT);                                          //Define pin functions
  unsigned status;
  delay(200);                                                        //Allow BME sensor to startup
  status = bme.begin();                                              //Connect to BME sensor
  if (!status)
  {
    Serial.println("Could not find a valid BME280 sensor");
  }
}

void loop()                                                          //Loop function 
{
  counter = 0;                                                       //Reset wind speed counter

  int lastState = 0;                                                 //Variable to store the last state of wind sensor input
  for (int i=0; i<= 6000; i++)
  {
    if (digitalRead(windSen) == HIGH && lastState == 0)
    {
      counter++;
      lastState = 1;
    }
    else if (digitalRead(windSen) == LOW && lastState == 1)
    {
      lastState = 0;
    }
    delay(1);
  }
  recTempHumid ();                                                   //Take readings from BME sensor
  recPress ();    
  recLight ();                                      
  calcWind ();
  Serial.print("Temp: ");
  Serial.println(temp);
  Serial.print("Humidity: ");
  Serial.println(humid);
  Serial.print("Pressure: ");
  Serial.println(pressure);
  Serial.print("Wind: ");
  Serial.println(wind);
  Serial.print("Light: ");
  Serial.println(light);
  
  int timeout = 0;
  while (WiFi.status() != WL_CONNECTED  && timeout < 20)
  {
    delay(500);
    Serial.print(".");
    timeout++;
  }
  if(WiFi.status() == WL_CONNECTED)
  {
    Serial.println("");
    Serial.println("WiFi connected");
    ThingSpeak.begin(client);                                        //Initialise ThingSpeak
    updateThingSpeak();                                             //Post the data to Thingspeak
  }
  else
  {
    Serial.println("");
    Serial.println("WiFi connection failed");
  }
  Serial.flush();
  Serial.println("Waiting until next check");
  delay(30000);
}

void recTempHumid()                                                 //Function to record the temperature and humidity
{
  temp = bme.readTemperature();
  temp = temp * 9 / 5 + 32; // Convert C to F
  humid = bme.readHumidity();
}

void recLight ()                                                     //Function to record the light level
{
  light = analogRead(lightSen);
}


void recPress()                                                     //Function to record the pressure
{  
  int presstemp = bme.readPressure();
  pressure = presstemp / 3386.39;    // Convert hPa to in/Hg
}

void calcWind()                                                     //Function to calculate the wind speed
{
  int ave = 2000;
  if(counter > 1)                                                    //Check that at least two ticks have been registered, one is meaningless
  {
    ave = 6000/(counter-1);                                          //Calculate the average time between ticks
  }
  Serial.print("Average Tick Time: ");
  Serial.println(ave);
  if (ave < 28)                                                      //Discard readings faster than 102kph
    ave = 28;
  int index = 0;
  while (ave < windMap[0][index])                                    //Search through the windMap array for the corressponding wind value
    index++;
  wind = windMap[1][index];
  int mphconv;
  mphconv = ((wind * 10000L + 5)/ 16090);
  wind = mphconv;
  Serial.print("Wind Speed: ");
  Serial.println(wind);
}

void updateThingSpeak()                                             //Function to post data to Thingspeak
{
  ThingSpeak.setField(1, temp);
  ThingSpeak.setField(2, humid);
  ThingSpeak.setField(3, pressure);
  ThingSpeak.setField(4, wind);
  ThingSpeak.setField(5, light);
  int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
  if(x == 200)
  {
    Serial.println("Channel update successful.");
  }
  else
  {
    Serial.println("Problem updating channel. HTTP error code " + String(x));
  }
}

I feel like I'm missing something simple. The code isn't that complex.

Let me rephrase... it runs once, maybe twice. Then it doesn't anymore after that. I know this because I'm watching for data to post on ThingSpeak

The idea was to add components back one at at time, so you can work out what is using all the power... Looks like you've now got everything connected again?