Hello,
I'm trying to make my MKR1500 with a GPS6MV2 GPS module, connect to the mobile network when powered on and send positional data. Then when the power to the USB is turned off the board continues to send positional data for a given amount of time before eventually going to sleep, until the USB receives power again.
However, i can't get the sleep functionality to work how i need.
Can someone please help ?
What i know so far.
The GPS module works.
The MQTT connection to the mobile network and dash board works.
The wakeup interrupt detects when the board is plugged in.
Currently the board will, Setup correctly and send data whilst the USB is plugged in. It then sends data as expected for 1 min before sleeping. Unfortunately when i plug the USB back in the board wakes up and seems to continue in the main loop() before going to setup(), here it either freezes or when i then unplug the USB it goes straight to sleep and seems to now skip the 1 min sending data section.
I have tried printing the variables which control this functionality and they seem to be correct. I can't understand why the boards functionality falls apart after it's been sent to sleep and woken back up.
Here is the Code that i've been using.
#include "main.h"
#include <MKRNB.h>
#include <ArduinoMqttClient.h>
#include <Arduino_MKRGPS.h>
#include <TimeLib.h>
#include <TinyGPSPlus.h>
#include "wiring_private.h"
#include "ArduinoLowPower.h"
// Please enter your sensitive data in the Secret tab or arduino_secrets.h
// PIN Number
const char PINNUMBER[] = SECRET_PINNUMBER;
// #define serialGPS Serial1
Uart serialGPS (&sercom3, 1, 0, SERCOM_RX_PAD_1, UART_TX_PAD_0); // Create the new UART instance assigning it to pin 1 and 0
// initialize the library instance
NBClient client;
MqttClient mqttClient(client);
GPRS gprs;
NB nbAccess;
NBModem modem;
TinyGPSPlus gps;
// Publishing Frequency Variables
unsigned long interval = 1 * 60 * 1000; // n Minutes
unsigned long previousMillis = 0;
// Sending Data Length Variables
unsigned long sendingDataCounter;
unsigned long dataSendingDuration = 2;
float latitude;
float longitude;
volatile bool hasBeenWoken = false;
const int powerDetectionPin = 5;
// I want the board to wake up when reciving power form the USB port.
// Once awake i want it to send it's positional data to the dashboard.
// when the power is turned off, i want it to continue to send data,
// for a given amount of time (3 hours), before eventually going to sleep.
void charging() {
hasBeenWoken = true;
}
void connectToNetwork(){
// connection state
boolean connected = false;
Serial.print("Modem Initialization ...");
// After starting the modem with NB.begin()
// attach to the GPRS network with the APN, login and password
while (!connected)
{
if ((nbAccess.begin(PINNUMBER) == NB_READY) &&
(gprs.attachGPRS() == GPRS_READY))
{
connected = true;
}
else
{
Serial.println("Not connected");
delay(1000);
}
}
//prints the modems IMEI number cut and paste into Adafruit cloud
Serial.println(modem.getIMEI());
mqttClient.setId(modem.getIMEI());
mqttClient.setUsernamePassword(AIO_USERNAME, AIO_KEY);
Serial.print("MQTT Initialization ...");
if (!mqttClient.connect(AIO_SERVER, AIO_SERVERPORT))
{
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
while (1)
;
}
}
void getGpsPostion(){
// - - - GPS Section - - -
while (serialGPS.available()) {
if(gps.encode(serialGPS.read()))
{
if (gps.location.isValid())
{
latitude = gps.location.lat();
longitude = gps.location.lng();
}
}
}
}
void setup()
{
for (int i = 0; i < 20; i++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
}
// initialize serial communications.
Serial.begin(9600);
serialGPS.begin(9600);
Serial.println("In Setup...");
// GPS Input and Output Pins.
pinPeripheral(1, PIO_SERCOM); //Assign RX function to pin 1
pinPeripheral(0, PIO_SERCOM); //Assign TX function to pin 0
pinMode(LED_BUILTIN, OUTPUT);
// setting Pin for detecting 5v USB power spike.
pinMode(powerDetectionPin, INPUT_PULLUP);
LowPower.attachInterruptWakeup(powerDetectionPin, charging, RISING);
connectToNetwork();
delay(3000);
}
// - - - - - MAIN LOOP Section - - - - - -
void loop()
{
mqttClient.poll();
unsigned long currentMillis = millis();
getGpsPostion();
// - - - Sending Data Section - - -
if(currentMillis - previousMillis >= interval)
{
// save the last time a message was sent
previousMillis = currentMillis;
Serial.println("Publishing Data");
// Updating the dashboard Logs
mqttClient.beginMessage(AIO_FEED_LOGS);
mqttClient.println(" - Modem IMEI number: " + String(modem.getIMEI()));
mqttClient.println(" - GPS Coordinates: " + String(latitude) + " latitude, " + String(longitude) + " longitude");
mqttClient.endMessage();
}
// - - - - - Sleep control section - - - - - -
// Counts miniutes when not plugged in.
if(digitalRead(5)){
sendingDataCounter = 0;
} else {
sendingDataCounter = minute();
hasBeenWoken = false;
}
// Check used to recal setup after sleep.
if(hasBeenWoken){
Serial.println("Running Setup Function");
hasBeenWoken = false;
setup();
}
// Final check before sending board to sleep.
if(!digitalRead(5) && (sendingDataCounter >= dataSendingDuration)){
hasBeenWoken = false;
sendingDataCounter = 0;
LowPower.sleep();
}
// Makes LED flash to show loop is turning.
for (int i = 0; i < 5; i++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
Serial.print(".");
delay(2000);
}
void SERCOM3_Handler()
{
serialGPS.IrqHandler();
}
Here's a pic of the hardware i'm using.