batterie-nb.ino
Voltage sag during radio transmission reveals battery health: this sketch measures VBAT before and after each publish, computing slope and transaction duration. A wear indicator far more honest than remaining percentage alone.
Hardware
An Arduino MKR NB 1500 (SAMD21 microcontroller, u-blox LTE-M/NB-IoT modem, external antenna, LiPo power on J6 or USB). LiPo on the battery connector, data SIM, reachable test server.
Wiring
No wiring; VBAT sensing is internal to the SAMD21 (hardware divider).
How it works
analogRead(VBAT) samples voltage through the 1.5x divider; the before/after difference across the NB-IoT transaction correlates remaining capacity with cell age.
Running it
Install the Arduino SAMD Boards package and the MKRNB library, select the board, upload. Plan for an activated IoT SIM (LTE-M or NB1) and good reception: attaching to the network can take several minutes.
Variants
Log the slope over several days to predict the recharge date, or skip transmissions when the slope crosses an alert threshold.
batterie-nb.ino
// Estimation d'autonomie : VBAT + moyenne glissante de consommation.
// Releve la tension batterie avant/pendant/apres une emission radio.
#include <MKRNB.h>
const char PIN_SIM[] = "0000";
const char APN[] = "iot.1nce.net";
NB nb;
NBClient client;
float lireVbat() {
return 3.3 * analogRead(VBAT) / 1023.0 * 1.5;
}
void setup() {
Serial.begin(9600);
if (nb.begin(PIN_SIM) != NB_READY) while (true);
while (nb.getStatus() != NETWORK_JOINED) delay(2000);
nb.attachGPRS(APN);
}
void loop() {
float avant = lireVbat();
unsigned long t0 = millis();
bool ok = false;
if (client.connect("192.0.2.10", 1883)) {
client.print("station/01/bat\n");
client.println(avant, 2);
client.stop();
ok = true;
}
unsigned long duree = millis() - t0;
float apres = lireVbat();
Serial.print("avant="); Serial.print(avant, 3);
Serial.print(" apres="); Serial.print(apres, 3);
Serial.print(" dT="); Serial.print(duree);
Serial.println(ok ? " mV/s OK" : " mV/s ECHEC");
delay(60000);
}