Hi
I've been testing some scenarios and I can conclude the Connector Carrier accepts happily the 12VDC I provide through its input screw pins, converts it into a healthy 5.09VDC to feed into the VIN pin, and that it also extends the board's 5V pin (with only 4.66VDC) and VCC (with just 3,28VDC) pin to the screws too. Those two last coming from the MKR board itself, not the connector carrier buck.
According to https://docs.arduino.cc/learn/electronics/power-pins, when VIN is used, the 5VDC and VCC pins become output only. So doing this https://forum.arduino.cc/t/mkr-connector-carrier-low-connector-voltage-when-using-vin-non-usb-power/703989/5 won't help the way I need.
My issue is that if I feed 12VDC from my 20W power supply into the connector carrier, the SMS are never sent. Usually that means lack of power from the power source, which in this case it is not the reason. If I connect the USB port to my computer or a power adaptor, all SMS are sent. But it should not be that way, because USB in power is disabled when VIN is used according to the documentation.
I also tried simply connecting the USB cord with the charger still attached but unplugged from the socket, and the SMS are sent too. If the issue was that my code needed an USB host to work, the unplugged charger wouldn't be enough.
There is something weird going on here. Feels like the ghost of electronics (not software). But I cannot tell why since the SMS are not coming and the USB console is unavailable at the time of the issue.
Any piece of advice?
Thanks
#undef DEBUG // If defined it enables debug messages to serial usb. Comment or undef to deactivate DEBUG to console and the console itself.
#include "arduino_secrets.h"
#include <MKRGSM.h>
#include <ArduinoLowPower.h>
#include <RTCZero.h>
#include <Arduino_PMIC.h> // Toolbox for the chip dealing with power and battery
//#include <Modem.h> // SARA-U201 GSM modem chip
// Self awareness
const int DEBUG_LEVEL = 2; // 0 = no debug, 1 = some debug, 2 = deep debug (if not defined the DEBUG tag, this has no effect)
const int sketchUpdateWindow = 10000; // Tine window to allow sketch updates after boot
bool watchdogFlag = false; // If the board gets frozen, lets try to prevent bricking and auto-recover failure when possible
// Duty cycle
const int shortLoopPeriod = 600000; // Sleep for 600000 miliseconds (10 minutes)
const int longLoopPeriod = 3600000; // Sleep for 3600000 miliseconds (60 minutes)
int loopPeriod = shortLoopPeriod; // Work period of the board = 600000 miliseconds (10 minutes) by default
// GSM network data
const char SIM_APN[] = SECRET_SIM_APN;
const char SIM_PIN[] = SECRET_OPTIONAL_SIM_PIN;
const char SIM_APN_USERNAME[] = SECRET_OPTIONAL_SIM_APN_USERNAME;
const char SIM_APN_PASSWORD[] = SECRET_OPTIONAL_SIM_APN_PASSWORD;
const char controlPhoneNumber[] = SECRET_CONTROL_PHONE_NUMBER;
const int connectWaitingTimeForGSM = 10000; // GSM network connect proved slow in Spain, so lets wait 10 seconds instead of 1.
const int maximumLengthSMS = 140; // How many char do we want to allow into an SMS or chain of SMSs.
// Incoming water valve pressure sensor pin and attributes
const int incomingPressureSensorPin = A4; // Analog PIN connector of the board to plug the sensor to
const float incomingPressureSensorMinPressure = 0.0; // Minimum pressure callibrated with external manometer that can be read by ADC
const float incomingPressureSensorMaxPressure = 5.0; // Maximum pressure callibrated with external manometer that can be read by ADC
const int incomingPressureSensorMinReading = 102; // ADC reading of minimum voltage for minimum pressure of the sensor (500mVDC at 0 bar)
const int incomingPressureSensorMaxReading = 921; // ADC reading of maximum voltage for maximum pressure of the sensor (4500mVDC at 5 bar)
// Power management
volatile unsigned long time_last_battery_interrupt = millis();
// Set up the GSM module
GSM gsmAccess;
GSM_SMS sms;
void setup() {
//////////////////////////
// Sketch update window //
//////////////////////////
/*
It seems the board won't be accepting upload of new scketches if in low power mode.
So lets wait ten seconds upon board start so there is a chance.
*/
delay(sketchUpdateWindow);
//////////////////////////////////////////
// USB serial port to use for debugging //
//////////////////////////////////////////
#ifdef DEBUG
// Initialize the serial communication for debugging
Serial.begin(9600);
while (!Serial) {
; // Wait for serial port to connect
}
#endif
//////////////////////////////////////
// Power Management Integrated Chip //
//////////////////////////////////////
/*
#ifdef DEBUG
Serial.println("PMIC initialization about to start.");
#endif
// Available only for MKRGSM1400 and MKRNB1500
#if defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500)
// Attach the PMIC IRQ pin
attachInterrupt(digitalPinToInterrupt(PMIC_IRQ_PIN), batteryInterrupt, FALLING);
#endif
// Initialize the power management integrated cirtuit that charges and uses the battery
if (!PMIC.begin()) {
#ifdef DEBUG
Serial.println("Failed to initialize PMIC!");
#endif
// while (1); QUESTION TO FUTURE ME: why did the original author of PMIC eample lock the board in an endless loop if failed PMIC?
}
// Set the input current limit to 2 A
if (!PMIC.setInputCurrentLimit(2.0)) {
#ifdef DEBUG
Serial.println("Error in set input current limit");
#endif
}
// Set the overload input voltage to 3.88 V
if (!PMIC.setInputVoltageLimit(3.88)) {
#ifdef DEBUG
Serial.println("Error in set input voltage limit");
#endif
}
// set the minimum voltage used to feeding the module embed on Board
if (!PMIC.setMinimumSystemVoltage(3.5)) {
#ifdef DEBUG
Serial.println("Error in set minimum system volage");
#endif
}
// Set the desired charge voltage to 4.11 V
if (!PMIC.setChargeVoltage(4.2)) {
#ifdef DEBUG
Serial.println("Error in set charge volage");
#endif
}
// Set the charge current 500 mA
if (!PMIC.setChargeCurrent(0.500)) {
#ifdef DEBUG
Serial.println("Error in set charge current");
#endif
}
// Enable the Charger
if (!PMIC.enableCharge()) {
#ifdef DEBUG
Serial.println("Error enabling Charge mode");
#endif
}
#ifdef DEBUG
Serial.println("PMIC initialization done!");
#endif
*/
/////////////////
// GSM Module //
/////////////////
/*
SIM has PIN disabled due to undefined incompatibilities.
We use the constructor without PIN.
*/
// Start GSM connection
#ifdef DEBUG
if (DEBUG_LEVEL > 0) { Serial.println("Starting GSM..."); }
#endif
if (gsmAccess.begin() != GSM_READY) {
#ifdef DEBUG
if (DEBUG_LEVEL > 1) { Serial.println("Not connected on first attempt!"); }
#endif
do {
#ifdef DEBUG
if (DEBUG_LEVEL > 1) { Serial.println("Not connected yet!"); }
#endif
delay(connectWaitingTimeForGSM);
} while (gsmAccess.begin() != GSM_READY);
#ifdef DEBUG
if (DEBUG_LEVEL > 1) { Serial.println("Finally connected!"); }
#endif
}
#ifdef DEBUG
if (DEBUG_LEVEL > 0) { Serial.println("GSM initialized."); }
#endif
///////////
// Clock //
///////////
/*
Now that we have GSM, we can read the time and set it.
*/
}
void loop() {
int incomingPressureSensorValue;
float incomingPressure;
// Check for watchdog flag
if (watchdogFlag) {
// Perform recovery or error handling here
#ifdef DEBUG
if (DEBUG_LEVEL > 0) { Serial.println("Watchdog triggered! Performing recovery..."); }
#endif
// Restart the Arduino board
restartBoard();
}
//////////////////////////////////////
// Power Management Integrated Chip //
//////////////////////////////////////
/*
// Deal with battery management
if (millis() - time_last_battery_interrupt > loopPeriod) {
// Enable the Charger
if (!PMIC.enableCharge()) {
#ifdef DEBUG
Serial.println("Error enabling Charge mode");
#endif
}
// canRunOnBattery() returns true if the battery voltage is < the minimum
// systems voltage
if (PMIC.canRunOnBattery()) {
// loop until charge is done
if (PMIC.chargeStatus() != CHARGE_TERMINATION_DONE) {
delay(1000);
} else {
// Disable the charger
Serial.println("Disable Charge mode");
if (!PMIC.disableCharge()) {
Serial.println("Error disabling Charge mode");
}
// if you really want to detach the battery call
// PMIC.disableBATFET();
//isbatteryconnected = false;
}
}
}
*/
////////////////////
// Real work here //
////////////////////
// Read pressure sensor value and convert to actual pressure
incomingPressureSensorValue = analogRead(incomingPressureSensorPin);
incomingPressure = map(incomingPressureSensorValue,
incomingPressureSensorMinReading,
incomingPressureSensorMaxReading,
incomingPressureSensorMinPressure,
incomingPressureSensorMaxPressure);
// Send SMS and check if it was successful
if (!sendPressureSMS(incomingPressure)) {
// Perform a retry here
if (!sendPressureSMS(incomingPressure)) {
// Perform recovery here
#ifdef DEBUG
if (DEBUG_LEVEL > 1) { Serial.println("Failed to send SMS twice in a row! Performing recovery after waiting for something to change."); }
#endif
// Sleep a short loop period just in case it can be solved before reset and forget
LowPower.deepSleep(shortLoopPeriod);
// Try to report the failure and abort restart if it can be sent
if (!sendStringSMS("Last SMS report could not be sent and this SMS just prevented a board restart")) {
// Restart the Arduino board
restartBoard();
#ifdef DEBUG
} else {
if (DEBUG_LEVEL > 1) { Serial.println("SMS report failed to be sent twice, but a third SMS after " + String(shortLoopPeriod) + " seconds ago was successfull. Let's continue."); }
#endif
}
}
#ifdef DEBUG
else {
if (DEBUG_LEVEL > 1) { Serial.println("Sent SMS on the second try."); }
}
} else {
if (DEBUG_LEVEL > 1) { Serial.println("Sent SMS on the first try."); }
#endif
}
// Reset the watchdog flag
resetWatchdog();
//////////////////////////////////////
// Power Management Integrated Chip //
//////////////////////////////////////
/*
To-Do:
- Check if running on battery when we find out how in order to:
· tell when the board lost its main power source
· report back the situation at least once
· minimize consumption radically
- Set the GSM chip into low power before deep sleeping the rest of the board
· this probably means we should reconnect at the beginning of the loop.
*/
// Put the board into sleep mode
LowPower.deepSleep(loopPeriod);
}
void batteryInterrupt() {
time_last_battery_interrupt = millis();
}
void resetWatchdog() {
// Reset the watchdog timer
watchdogFlag = false;
}
void restartBoard() {
// Restart the Arduino board
NVIC_SystemReset();
}
bool sendPressureSMS(float data) {
String message = "Pressure reading CCdC: " + String(data, 2) + " bar";
return sendStringSMS(message);
}
bool sendStringSMS(String message) {
// Check if the length is lower than the maximumLengthSMS const defined
if (message.length() > maximumLengthSMS) {
#ifdef DEBUG
if (DEBUG_LEVEL > 0) { Serial.println("SMS not sent because it was over the defined limits: " + message); }
#endif
return false;
}
// Declare and populate the char array that the sendSMS function needs
char messageArray[maximumLengthSMS];
message.toCharArray(messageArray, maximumLengthSMS);
// Actually send the SMS
if (sms.beginSMS(controlPhoneNumber)) {
sms.print(messageArray);
if (sms.endSMS()) {
#ifdef DEBUG
if (DEBUG_LEVEL > 0) { Serial.println("SMS sent"); }
#endif
return true; // SMS sent successfully
} else {
#ifdef DEBUG
if (DEBUG_LEVEL > 0) { Serial.println("Error while sending the SMS"); }
#endif
return false; // Failed to send SMS
}
} else {
#ifdef DEBUG
if (DEBUG_LEVEL > 0) { Serial.println("Error starting to send the SMS"); }
#endif
return false; // Failed to start SMS
}
}
////////////////////
// GSM chip tools //
////////////////////
String doATcommandChipGSM(const char* s) {
String doATresponse;
doATresponse.reserve(15);
MODEM.send(s);
MODEM.waitForResponse(500, &doATresponse);
return doATresponse;
}
void resetChipGSM() {
pinMode(GSM_RESETN, OUTPUT);
digitalWrite(GSM_RESETN, HIGH);
delay(100);
digitalWrite(GSM_RESETN, LOW);
return;
}