MCU Integration
Overview
VBatPower accepts telemetry data from any device that can make HTTP POST requests. The data format is intentionally simple — a flat CSV that can be generated with printf on any 8-bit MCU.
The typical flow:
- Create a project in the VBatPower app
- Generate an API key in Settings > API
- Send telemetry from your MCU to
POST /api/v1/telemetry - View graphs and analysis in the app
Arduino / ESP32
Using the WiFi HTTP client to send telemetry data:
// Global state
uint32_t nonce = 0;
uint32_t runid = 1;
// Read sensors and send data
void sendTelemetry() {
float batteryV = analogRead(VBAT_PIN) * 3.3 / 4095.0 * 2.0;
float currentMA = readINA219();
uint32_t elapsed = millis();
nonce++;
String json = "{\"records\":[";
// Battery voltage (type: v = value measurement)
json += "{\"id\":\"0\",\"type\":\"v\",\"value\":";
json += String(batteryV, 3);
json += ",\"unit\":\"V\",\"nonce\":";
json += String(nonce);
json += ",\"runid\":";
json += String(runid);
json += "},";
// State execution duration (type: t = telemetry timing)
json += "{\"id\":\"0.0.0\",\"type\":\"t\",\"value\":";
json += String(500); // execution duration in ms
json += ",\"unit\":\"ms\",\"nonce\":";
json += String(nonce);
json += ",\"runid\":";
json += String(runid);
json += "},";
// Current draw (type: v = value measurement)
json += "{\"id\":\"0.0.0\",\"type\":\"v\",\"value\":";
json += String(currentMA, 2);
json += ",\"unit\":\"mA\",\"nonce\":";
json += String(nonce);
json += ",\"runid\":";
json += String(runid);
json += "},";
// Elapsed time from boot (type: n = nonce timing)
json += "{\"id\":\"0.0.0\",\"type\":\"n\",\"value\":";
json += String(elapsed);
json += ",\"unit\":\"ms\",\"nonce\":";
json += String(nonce);
json += ",\"runid\":";
json += String(runid);
json += "}]}";
HTTPClient http;
http.begin("https://api.vbatpower.com/api/v1/telemetry");
http.addHeader("Content-Type", "application/json");
http.addHeader("Authorization", "Bearer " + String(API_KEY));
int code = http.POST(json);
http.end();
} STM32 (bare metal / HAL)
For STM32 with a UART-to-WiFi module (ESP8266 AT commands) or Ethernet, format the JSON payload with snprintf:
char buf[512];
int len = snprintf(buf, sizeof(buf),
"{\"records\":["
"{\"id\":\"0.0.0\",\"type\":\"t\","
"\"value\":%lu,\"unit\":\"ms\","
"\"nonce\":%lu,\"runid\":%lu},"
"{\"id\":\"0.0.0\",\"type\":\"v\","
"\"value\":%.2f,\"unit\":\"mA\","
"\"nonce\":%lu,\"runid\":%lu},"
"{\"id\":\"0.0.0\",\"type\":\"n\","
"\"value\":%lu,\"unit\":\"ms\","
"\"nonce\":%lu,\"runid\":%lu}"
"]}",
exec_duration_ms, nonce, runid,
current_ma, nonce, runid,
HAL_GetTick(), nonce, runid
); Send buf as the HTTP POST body to /api/v1/telemetry with headers Content-Type: application/json and Authorization: Bearer your-key.
Offline Collection
If your MCU lacks network connectivity, log data to SD card or serial in CSV format:
// Print CSV to Serial or SD file
void logSample(uint32_t nonce, uint32_t runid) {
float vbat = readBattery();
float current = readCurrent();
uint32_t elapsed = millis();
Serial.printf("0,v,%.3f,V,%lu,%lu\n", vbat, nonce, runid);
Serial.printf("0.0.0,t,500,ms,%lu,%lu\n", nonce, runid);
Serial.printf("0.0.0,v,%.2f,mA,%lu,%lu\n", current, nonce, runid);
Serial.printf("0.0.0,n,%lu,ms,%lu,%lu\n", elapsed, nonce, runid);
} Capture the serial output to a .csv file and import it in the Data page.
Nonce Strategy
The nonce is a monotonically increasing counter that groups measurements taken at the same point in time. Rules:
- Increment once per measurement cycle (not per record)
- All records in one cycle share the same nonce
- Never reset within a run — use
runidto separate experiments - Use a 32-bit unsigned integer — at 1 sample/second, this overflows after 136 years
Tips
- Batch uploads — buffer multiple nonces and send them in a single POST to reduce WiFi wake-ups and save power.
- 8-bit MCUs — the CSV format requires no JSON parsing on the device side. Use
printfto format rows and upload as a file later. - Multiple states — measure different operating modes (sleep, active, TX) by assigning each to a different state ID (e.g.
0.0.0for sleep,0.0.1for active). - Battery monitoring — include a voltage measurement at depth 1 (e.g.
0,v,3.28,V,...) to track discharge over time.