Siddhant Kumar
Project 099 · Retail

Smart Vending Telemetry.

Puts every vending machine online — reporting stock, sales and faults in real time so you restock the right machines, never miss a sale, and fix breakdowns fast.

Intermediate 12–18 hours 27 min read TelemetryRetailCloud
Jump to source Bill of materials
Smart Vending Telemetry — reference build illustration MCU VCC · GND · SIG · NC
Difficulty
Intermediate
Build time
12–18 hours
Indicative cost
₹2,800 – ₹5,000 per machine
Platform
ESP32 DevKit V1 (ESP-WROOM-32)
Category
Retail
Last updated
28 July 2026
Contents — 26 sections

Project Overview

Puts every vending machine online — reporting stock, sales and faults in real time so you restock the right machines, never miss a sale, and fix breakdowns fast.

A vending machine is a shop that runs itself in a location no one visits — which is exactly why it is so often failing quietly: sold out of its best line for a week, jammed and taking money for nothing, or being restocked on a fixed schedule that wastes trips to full machines and misses empty ones. The reason is that the operator is blind between visits. This project fixes that by putting the machine online: a telemetry unit reports stock, sales and faults in real time, so the operator always knows the true state of every machine and can act on it.

The unit monitors what matters commercially and operationally. It tracks stock levels per slot (from vend events, and optionally sensors) so the operator knows what is running low where; it records sales (what sold, when, for how much) for revenue visibility and demand insight; and it detects faults — a jam, a payment failure, a temperature problem in a chilled machine, a door left open — and alerts immediately. All of this streams over cellular (vending machines rarely have Wi-Fi) to a central platform.

The value is turning a fleet of blind machines into a managed, data-driven operation: route restocking to the machines that actually need it (and skip the ones that don't), never miss sales to unnoticed sell-outs, fix breakdowns fast instead of after a customer complains, and understand demand to stock each machine to its location. It is honest that integrating with real vending hardware (via MDB/DEX or sensors) varies by machine, and that payment/cash handling is a regulated, security-sensitive domain to be treated carefully. But as a real-time stock/sales/fault telemetry unit, it gives vending operators the one thing an unattended machine never has: continuous visibility.

Stocked shelves in a supermarket aisle
Smart vending telemetry puts every machine online — reporting stock, sales and faults in real time. Photograph sourced from Wikimedia Commons — Supermarket shelves.jpg. Reused under the licence stated on that page; please check it before republishing.

What this project does

  • Reports per-slot stock levels in real time
  • Records sales (item, time, price) for revenue/demand insight
  • Detects and alerts faults (jam, payment, temperature, door)
  • Streams telemetry over cellular to a central platform
  • Routes restocking to the machines that need it
  • Catches sell-outs and breakdowns immediately
  • Turns a blind fleet into a managed operation

Real-World Applications

SettingHow it is used
Vending fleet managementLive stock, sales and faults across many machines.
Route optimisationRestocking only machines that need it, cutting wasted trips.
Revenue visibilityReal-time sales and demand per machine/location.
Uptime / serviceFast fault response instead of customer complaints.

Deployment contexts where a build of this kind earns its keep.

Features & Capabilities

  • Per-slot stock tracking (vend events / sensors)
  • Sales recording and demand analytics
  • Fault detection + immediate alerts
  • Cellular telemetry to a fleet platform
  • Restock-routing and sell-out prevention
  • Machine health (temperature, door, payment)
  • Honest about vending-hardware integration and payment security

Difficulty, Time & Required Skills

AttributeValue
Difficulty levelIntermediate
Estimated completion time12–18 hours
Indicative build cost₹2,800 – ₹5,000 per machine
Primary disciplineRetail
Reference platformESP32 DevKit V1 (ESP-WROOM-32)

Skills you should have (or will pick up)

  • Vending integration (MDB/DEX or sensor-based) for vend/sale events
  • Per-slot stock and sales tracking
  • Fault detection (jam/payment/temperature/door)
  • Cellular telemetry to a platform
  • Fleet analytics: restock routing, demand

Bill of Materials

Every part below is commonly available from Indian and international hobby-electronics suppliers. Prices are indicative 2026 retail figures in Indian rupees and will drift — treat them as a budgeting guide, not a quotation.

ComponentKey specificationQtyApprox. cost
ESP32 DevKit V1 (ESP-WROOM-32)
Wi-Fi transmit bursts peak near 500 mA — size the regulator accordingly.
Dual-core Xtensa LX6 @ 240 MHz, 520 KB SRAM, 4 MB flash, Wi-Fi 802.11 b/g/n + BLE 4.2, 34 GPIO, 18× 12-bit ADC, 2× 8-bit DAC1₹450
SIM800L GSM/GPRS module
Transmit bursts hit 2 A — needs a 4.0 V supply and a 1000 µF bulk capacitor.
Quad-band 850/900/1800/1900 MHz, GPRS class 12, SMS + TCP/IP1₹550
DS18B20 waterproof temperature probe
Dozens can share one GPIO — you address them by ROM code.
−55 to +125 °C, ±0.5 °C from −10 to +85 °C, 9–12-bit resolution, unique 64-bit ROM ID1₹160
Reed switch + magnet pair (door contact)
Wire it normally-closed so a cut cable reads the same as an open door — fail-safe by construction.
NO contact, 10–15 mm operating gap, 100 V / 0.5 A, > 10⁷ operations1₹55
0.96″ SSD1306 OLED display
Static images burn in — invert or scroll the screen periodically.
128 × 64 monochrome, 1.3–3.3 V logic, 100 kHz–400 kHz I²C1₹250
18650 Li-ion cell 3400 mAh + holder
Never charge below 0 °C; always use a protected cell or a BMS.
3.7 V nominal, 4.2 V full, 3400 mAh, ~12.6 Wh, 2 C discharge1₹450
Vending interface
Integration varies by machine
MDB/DEX tap or vend-event sensors for sales/stock1₹700
Cellular modem + SIMTelemetry uplink (no Wi-Fi at most sites)1₹900
Health sensorsTemperature (chilled), door (reed), jam/payment status1₹300
Enclosure + powerIn-machine mount, powered from the machine1₹300

Estimated total: ₹4,115, excluding tools, shipping and consumables.

Tools and consumables

  • Soldering iron (temperature controlled, 350 °C) with 0.8 mm 60/40 or lead-free solder
  • Digital multimeter — continuity, DC volts and current ranges
  • Wire strippers, flush cutters and a small set of precision screwdrivers
  • Heat-shrink tubing and a heat gun (or a lighter, carefully)
  • A laptop with a USB port and the toolchain listed above

Hardware Specifications

PartSpecificationSupplyInterfaceReference
ESP32 DevKit V1 (ESP-WROOM-32)Dual-core Xtensa LX6 @ 240 MHz, 520 KB SRAM, 4 MB flash, Wi-Fi 802.11 b/g/n + BLE 4.2, 34 GPIO, 18× 12-bit ADC, 2× 8-bit DAC3.3 V logic / 5 V USBUART, SPI, I²C, I²S, CAN, PWMDatasheet
SIM800L GSM/GPRS moduleQuad-band 850/900/1800/1900 MHz, GPRS class 12, SMS + TCP/IP3.4–4.4 V (NOT 5 V)UART AT commandsDatasheet
DS18B20 waterproof temperature probe−55 to +125 °C, ±0.5 °C from −10 to +85 °C, 9–12-bit resolution, unique 64-bit ROM ID3.0–5.5 V1-Wire (multi-drop)Datasheet
Reed switch + magnet pair (door contact)NO contact, 10–15 mm operating gap, 100 V / 0.5 A, > 10⁷ operationspassiveDigital with pull-upDatasheet
0.96″ SSD1306 OLED display128 × 64 monochrome, 1.3–3.3 V logic, 100 kHz–400 kHz I²C3.3–5 VI²C (0x3C)Datasheet
18650 Li-ion cell 3400 mAh + holder3.7 V nominal, 4.2 V full, 3400 mAh, ~12.6 Wh, 2 C discharge3.0–4.2 VHolder / spot-welded tabsDatasheet

Consolidated electrical and interface specifications for every active part in the build.

Power Budget & Supply Sizing

Add up the typical active current of every part, then size the supply with at least 50 % headroom so transmit bursts and motor inrush never brown out the controller.

LoadSupply railTypical current (mA)Notes
ESP32 DevKit V1 (ESP-WROOM-32)3.3 V logic / 5 V USB160Wi-Fi transmit bursts peak near 500 mA — size the regulator accordingly.
SIM800L GSM/GPRS module3.4–4.4 V (NOT 5 V)2000Transmit bursts hit 2 A — needs a 4.0 V supply and a 1000 µF bulk capacitor.
DS18B20 waterproof temperature probe3.0–5.5 V1.5Dozens can share one GPIO — you address them by ROM code.
0.96″ SSD1306 OLED display3.3–5 V20Static images burn in — invert or scroll the screen periodically.

Summed typical draw is 2181.5 mA. With a 1.5× design margin the supply should deliver at least 3300 mA continuously at the stated rail voltage.

Software Requirements & Development Environment

Reference toolchain: Arduino IDE 2.3.x with the ESP32 board package 3.x (or PlatformIO on VS Code). Anything newer normally works; anything older may lack the board definitions used here.

  • Install the Arduino IDE 2.3.x (or PlatformIO if you prefer a real editor and dependency locking).
  • Add https://espressif.github.io/arduino-esp32/package_esp32_index.json under File → Preferences → Additional Board Manager URLs, then install esp32 from the Boards Manager.
  • Set the correct port under Tools → Port. On Linux add yourself to the dialout group: sudo usermod -aG dialout $USER and log out and back in.
  • Open the Serial Monitor at 115200 baud — every sketch here logs its state there.
  • Keep File → Preferences → Show verbose output during: compilation switched on while you are debugging build errors.

Required libraries

LibraryWhy it is neededInstall
WiFi (ESP32 core) bundledStation/AP connection management for the ESP32.Bundled with the ESP32 Arduino core
PubSubClient 2.8Lightweight MQTT 3.1.1 client for constrained devices.Library Manager → "PubSubClient" by Nick O'Leary
OneWire + DallasTemperature 2.3.x / 3.9.xBus enumeration and conversion commands for DS18B20 probes.Library Manager → "DallasTemperature" (pulls OneWire)
ArduinoJson 7.xZero-allocation JSON serialisation and parsing.Library Manager → "ArduinoJson" by Benoit Blanchon
NTPClient / configTime bundledWall-clock time from an NTP server for timestamping.Bundled (`configTime()` on ESP32)

Block Diagram

The block diagram shows the functional decomposition of the system — what senses, what decides, what acts, and where the data ends up.

Smart Vending Telemetry — system block diagramFunctional block diagram of the Smart Vending Telemetry system. MonitorVend/saleeventsStockper slotHealthtemp/door/jamDetectLow stocksell-out riskFaultjam/pay/tempStreamCellularto platformActRoute restockwho needs itFix fastfault alertrightrightnone
Smart Vending Telemetry — system block diagram

Circuit Diagram & Wiring

Every signal line in the build is shown below, followed by a pin-by-pin connection table you can work through with a multimeter in hand.

Smart Vending Telemetry — wiring schematicConnection schematic showing which controller pin drives each peripheral. Sensors / InputsControllerActuators / OutputsESP32 DevKit V1(ESP-WROOM-32)3.3 V logic / 5 V USBVending interfaceGPIO 16/17Vend/sale eventsTemp sensorGPIO 4Chilled-machine tempDoor reedGPIO 34Door openCellular modemGPIO 27/14Telemetry uplinkOLEDGPIO 21/22Local statusMachine powerregPowerStatus LEDGPIO 2Health
Smart Vending Telemetry — wiring schematic
PeripheralPeripheral pinController pinSignal
Vending interfaceMDB/DEX/UARTGPIO 16/17Vend/sale events
Temp sensorDATAGPIO 4Chilled-machine temp
Door reedINGPIO 34Door open
Cellular modemUARTGPIO 27/14Telemetry uplink
OLEDSDA/SCLGPIO 21/22Local status
Machine power12/24VregPower
Status LEDINGPIO 2Health

Wire one row at a time and tick it off — most "it does not work" reports trace back to a single swapped pair.

Wiring explanation

  • Interface the machine for vend/sale events (MDB/DEX where available, or vend-detect sensors) — integration varies by machine.
  • Add health sensors: temperature for chilled machines, a door reed, and jam/payment status where accessible.
  • Stream telemetry over cellular; vending sites rarely have Wi-Fi.
  • Power from the machine via a regulator; keep the unit isolated from payment/cash systems.
  • Do not interfere with payment/cash handling — monitor, and treat that domain as security-sensitive.
An ESP32 development board with the ESP-WROOM-32 module and USB connector
Vend events drive per-slot stock tracking so restocking is routed only to machines that need it. Photograph sourced from Wikimedia Commons — ESP32 Espressif ESP-WROOM-32 Dev Board.jpg. Reused under the licence stated on that page; please check it before republishing.

System Architecture

Read the stack from the bottom up: physical hardware, the firmware that drives it, the transport that moves data off the device, and the software a human actually looks at.

Smart Vending Telemetry — architecture stackLayered architecture from hardware to user interface. Hardware layerESP32 DevKit V1 (ESP-WROOM-32) · DS18B20 waterproof temperature probeDriver layerwifi · pubsub · onewire · arduinojsonApplication logicsampling loop · filtering · thresholds · state machineTransport layerCellular → vending fleet platform · TLS · retry and backoffPresentation layerdashboard · mobile notifications · historical charts
Smart Vending Telemetry — architecture stack

Working Principle

A vending machine's whole business model is being unattended — a shop in a place no one staffs — and that is precisely what makes it fail expensively. Between an operator's visits the machine can sell out of its best product and keep taking custom for lines nobody wants, jam and refuse to vend while still accepting payment, or (if chilled) drift out of safe temperature — and the operator learns none of it until the next scheduled visit, which itself may be a wasted trip to a machine that is still full. Every one of these losses is a visibility problem, and telemetry solves it by making the unattended machine continuously report its own state.

The telemetry tracks the three things that actually determine a vending operation's success. Stock per slot tells the operator what is running low and in which machine, so a sell-out is anticipated rather than discovered — tracked from vend events (each vend decrements a slot) and optionally sensors. Sales — what sold, when, at what price — give real-time revenue visibility and, aggregated, reveal demand: which products move at which locations, so each machine can be stocked to its site instead of a generic planogram. Faults — a jam, a payment failure, an over-temperature in a chiller, a door left open — are detected and alerted immediately, because a broken machine earns nothing and annoys customers for every hour it stays broken unknown.

The transport reality shapes the design: vending machines sit in lobbies, corridors and streets that rarely offer Wi-Fi, so telemetry streams over cellular to a central platform. There the individual machines become a managed fleet. The operational payoffs are direct and measurable: restocking is routed to the machines that need it (and full machines are skipped), turning fixed, wasteful schedules into demand-driven routes; sell-outs are prevented, so the machine is always selling its best lines; breakdowns are fixed fast, maximising uptime and revenue; and demand data informs what to stock where. This is the same shift every telemetry system delivers — from reacting late to acting on live data — applied to a fleet whose defining feature is that no one is watching it.

The design is honest about two real constraints. First, integration varies: some machines expose sales/stock through standard interfaces (MDB between the controller and peripherals, DEX for audit data), while others need vend-detection sensors retrofitted — so the telemetry unit meets the machine where it is. Second, and importantly, payment and cash handling is a regulated, security-sensitive domain: the telemetry unit is a monitor, and it must not interfere with payment/cash systems or handle payment data casually — anything touching payments carries compliance and security obligations that must be respected. Within those honest bounds, the unit delivers exactly what an unattended machine has always lacked and most needs: continuous, real-time visibility of its stock, its sales and its faults, so the operator can run a fleet on data instead of guesswork.

The maths behind it

Stock tracking from vends

plainStock tracking from vends
Each slot starts at capacity; every vend decrements it:

  stock[slot] -= 1   on a vend event
  low if stock[slot] ≤ SLOT_MIN → restock this slot/machine

Optionally corrected by sensors / restock re-tare.

Fault detection

plainFault detection
jam       : vend commanded but not dispensed
payment   : repeated payment failures
temp      : chiller temp > T_max for > t
door      : open beyond a service window

→ immediate alert (a broken machine earns nothing).

Fleet value

plainFleet value
route restock → only machines with low stock (skip full)
prevent sell-outs → always selling best lines
fix faults fast → maximise uptime × revenue
demand → stock each machine to its location.

Program Flowchart

The firmware is a single cooperative loop. Nothing blocks for long, so networking, sensing and the user interface all stay responsive.

Smart Vending Telemetry — firmware flowchartControl flow through the main program loop. Monitor vends, stock, healthVend event?Record sale; decrement slot stockCheck faultsRecord sale; decrement slotstockCheck faultsFault or low stock?Alert (fault / restock)Report telemetryAlert (fault / restock)Report telemetryStream to platform
Smart Vending Telemetry — firmware flowchart

Assembly Instructions

Build on a breadboard first and only commit to solder once the whole system has run for an hour without a fault.

  1. Interface the machine for vend/sale events

    Tap vend/sale events via MDB/DEX where available, or fit vend-detection sensors, and add health sensors (temperature, door, jam/payment status).

  2. Track stock/sales and detect faults

    Decrement slot stock on vends, record sales, and detect jams, payment failures, temperature and door faults.

  3. Stream over cellular and manage the fleet

    Stream telemetry to a platform over cellular, alert on faults/low stock, and drive restock routing and demand analytics.

Step-by-Step Implementation Guide

Work through these in order. Each step ends in something you can observe, so a failure is always localised to the step you just finished.

  1. Record sales, track stock and flag faults

    On each vend, record the sale and decrement the slot; independently check for faults (jam, payment, temperature, door) and flag low stock.

    cppvending.ino
    int stock[SLOTS];                 // per-slot remaining
    const int SLOT_MIN = 2;
    const float T_MAX = 8.0;          // chiller degC
    
    // A completed vend: record the sale and decrement the slot.
    void onVend(int slot, int price_cents){
      if (stock[slot] > 0) stock[slot]--;
      recordSale(slot, price_cents, now());          // revenue + demand
      if (stock[slot] <= SLOT_MIN)
        alert("low_stock", slot);                    // restock THIS slot/machine
    }
    
    // Independent health/fault checks.
    const char* checkFaults(bool vendFailed, int payFails, float temp, bool doorOpen){
      if (vendFailed)          return "jam";          // commanded, not dispensed
      if (payFails >= 3)       return "payment_fault";
      if (temp > T_MAX)        return "over_temperature";
      if (doorOpen)            return "door_open";
      return nullptr;
    }
    if (stock[slot] > 0) stock[slot]--;Each vend decrements that slot's stock, so the operator always knows what is running low and where.
    recordSale(slot, price_cents, now()); // revenue + demandSales are recorded with time and price for real-time revenue visibility and demand analysis.
    if (stock[slot] <= SLOT_MIN) alert("low_stock", slot); // restock THIS slot/machineA low slot flags for restock before it sells out, and names the exact slot and machine for routing.
    if (vendFailed) return "jam"; // commanded, not dispensedA jam is inferred when a vend is commanded but nothing dispenses — a fault that otherwise takes money for nothing until noticed.
  2. Stream telemetry and alert immediately

    Stream stock/sales/health to the platform over cellular, and alert immediately on faults and low stock so machines are fixed and restocked fast.

Complete Source Code

The listing below is complete and compiles as written — there are no elided sections. Read the annotations under each block before you upload it.

cppvending_telemetry.ino
/* ═══════════════════════════════════════════════════════════════
   Smart Vending Telemetry — ESP32 + cellular

   Reports per-slot STOCK, SALES and FAULTS in real time to a fleet
   platform over cellular, so operators route restocking, prevent
   sell-outs, and fix breakdowns fast. Monitors only — never interferes
   with payment/cash (a regulated, security-sensitive domain).
   ══════════════════════════════════════════════════════════════════ */

#include <ArduinoJson.h>

#define SLOTS 24
int   stock[SLOTS];
const int   SLOT_MIN = 2;
const float T_MAX = 8.0;
const char* MACHINE = "VM-207";

void stream(const char* topic, JsonDocument& d){
  char buf[256]; serializeJson(d, buf);
  cellularPublish(topic, buf);                   // over cellular
}

void onVend(int slot, int price){                // completed sale
  if (stock[slot] > 0) stock[slot]--;
  StaticJsonDocument<128> s;
  s["machine"]=MACHINE; s["slot"]=slot; s["price"]=price; s["stock"]=stock[slot];
  stream("vending/sale", s);                     // sales + demand
  if (stock[slot] <= SLOT_MIN){
    StaticJsonDocument<96> a;
    a["machine"]=MACHINE; a["slot"]=slot; a["alert"]="low_stock";
    stream("vending/alert", a);                  // route restock here
  }
}

void reportHealth(bool vendFailed, int payFails, float temp, bool door){
  const char* fault = nullptr;
  if (vendFailed) fault="jam";
  else if (payFails>=3) fault="payment_fault";
  else if (temp>T_MAX) fault="over_temperature";
  else if (door) fault="door_open";

  StaticJsonDocument<160> h;
  h["machine"]=MACHINE; h["temp"]=temp; h["door"]=door;
  h["fault"]=fault?fault:"none";
  stream("vending/health", h);
  if (fault) stream("vending/fault", h);         // immediate fault alert
}

void setup(){ cellularInit(); loadStock(stock); }

void loop(){
  int slot, price;
  if (pollVendEvent(&slot, &price)) onVend(slot, price);   // MDB/DEX/sensor
  reportHealth(vendFailed(), paymentFailures(), chillerTemp(), doorOpen());
  delay(5000);
}
if (stock[slot] > 0) stock[slot]--;Slot stock is decremented on each vend so per-slot levels stay current for restock routing.
stream("vending/sale", s); // sales + demandEvery sale streams to the platform for real-time revenue visibility and demand analytics.
stream("vending/alert", a); // route restock hereA low slot alerts with the machine and slot, so restocking goes only to machines that need it.
if (fault) stream("vending/fault", h); // immediate fault alertFaults raise an immediate alert, because a broken machine loses money every hour it sits unknown.
if (pollVendEvent(&slot, &price)) onVend(slot, price); // MDB/DEX/sensorVend events come from the machine's interface (MDB/DEX) or sensors — integration meets the machine where it is.

Configuration & Calibration

Configuration steps

  • Configure the vending interface (MDB/DEX or sensors) and per-slot capacities.
  • Configure low-stock thresholds, fault checks and chiller temperature limit.
  • Configure cellular telemetry and the fleet platform link.
  • Configure isolation from payment/cash systems (monitor only).

Calibration procedure

An uncalibrated sensor produces confident, precise, wrong numbers. Do this once per physical unit and record the constants.

  1. Vend/stock accuracy

    Verify vends decrement the right slot and that stock matches a manual count; re-set on restock.

  2. Fault detection

    Confirm jams, payment failures, over-temperature and door-open are detected and alerted.

  3. Connectivity

    Verify cellular telemetry across the machine's locations.

Network Architecture & Connectivity

Smart Vending Telemetry — network topologyPath taken by telemetry from field node to end user. Edge nodesGatewayCloudClientsMachine unitESP32Vending fleetall machinesCellularCarrierto platformMQTT/HTTPSVending platformstock/sales/faultsOperatorrestock/routeServicefault alerts
Smart Vending Telemetry — network topology

Communication protocol

Machines stream stock, sales and health/faults; the platform turns them into restock routes, revenue views and service alerts.

Topic / endpointDirectionPayload
vending/salemachine → platformmachine, slot, price, stock
vending/alertmachine → operatorlow-stock (machine, slot)
vending/faultmachine → servicejam / payment / temp / door

Message contract between the device and the broker.

Cloud platform configuration

A fleet platform provides live stock/sales/health, restock routing, revenue/demand analytics, and fault dispatch.

Dashboard setup

A fleet view of each machine's stock, sales, health and faults, with a prioritised restock route.

Mobile app integration

Fault alerts and low-stock alerts with the machine/slot to service.

Security considerations

  • Authenticate machines; secure telemetry.
  • Monitor only — never interfere with payment/cash; treat payments as regulated/secure.
  • Isolate the telemetry unit from payment systems.

Testing Procedure & Expected Output

Test from the bottom up. Confirm power, then each sensor in isolation, then the integrated loop — the first failing step tells you exactly where to look.

TestWhat you should see
Make a vendSale recorded; slot stock decrements
Draw a slot to thresholdLow-stock alert naming machine + slot
Simulate a jamImmediate jam fault alert
Raise chiller temperatureOver-temperature alert
Leave the door openDoor-open alert
Query the platformLive stock/sales/health across the fleet

Bench-test checklist. If a row fails, stop and fix it before moving on.

Expected output

Real-time stock, sales and fault telemetry per machine, driving restock routing and fast fault response.

jsonvending-telemetry.json
{
  "machine": "VM-207",
  "slot": 6,
  "sale_price": 150,
  "stock": 2,
  "temp": 5.4,
  "fault": "none",
  "alert": "low_stock"
}

Machine VM-207 just sold slot 6 down to 2 units and flagged low stock — restock is routed to this machine and slot specifically, while a full machine nearby is skipped.

A Grafana time-series dashboard
A fleet platform turns live telemetry into restock routes, revenue analytics and fast fault response. Photograph sourced from Wikimedia Commons — Grafana dashboard.png. Reused under the licence stated on that page; please check it before republishing.

Troubleshooting: Common Errors & Fixes

Stock count drifts

Likely cause. Missed vends / no restock reset

Fix. Reliable vend detection; reset stock on restock

No sales/vend events

Likely cause. Interface mismatch

Fix. Match MDB/DEX or fit vend sensors per machine

Jams not caught

Likely cause. No vend-fail detection

Fix. Detect commanded-but-not-dispensed vends

No telemetry at a site

Likely cause. Cellular coverage

Fix. Check signal/antenna; buffer and retry

Payment concerns

Likely cause. Touching payment systems

Fix. Monitor only; isolate; treat payment as regulated/secure

Restocking still wasteful

Likely cause. Not using telemetry for routing

Fix. Route to low-stock machines; skip full ones

The sketch will not upload — "Failed to connect" or "avrdude: stk500_recv()"

Likely cause. The bootloader is not being reached: wrong port, wrong board, a serial monitor holding the port open, or a USB cable that only carries power.

Fix. Close every serial monitor, confirm Tools → Board and Port, and swap to a known data-capable USB cable. On an ESP32 hold BOOT while the IDE prints "Connecting…", then release. If a peripheral is wired to the UART pins (GPIO 1/3 on ESP32, D0/D1 on Uno) unplug it — it fights the programmer.

The board resets in a loop, or the serial monitor prints "Brownout detector was triggered"

Likely cause. The supply cannot deliver peak current. Wi-Fi transmit bursts, relay coils and servos all pull far more than their average draw.

Fix. Power peripherals from a separate regulated supply with a common ground rather than from the board 5 V pin. Add a 470–1000 µF electrolytic capacitor across the supply near the load, and use a real power adapter rather than a laptop USB port.

Serial monitor shows garbage characters

Likely cause. Baud rate mismatch between Serial.begin() and the monitor, or a floating/shared UART line.

Fix. Set the monitor to 115200 to match the sketch. If it still garbles, the crystal or the USB bridge is being confused by noise — shorten the cable and keep motor wiring away from the USB lead.

An I²C device is not detected

Likely cause. Wrong address, missing pull-ups, swapped SDA/SCL, or a bus too long for the pull-up value.

Fix. Run an I²C scanner sketch first — it should print the device address. Most breakout boards include 4.7 kΩ pull-ups, but if you have chained four of them the parallel resistance is too low; remove the pull-ups from all but one board. Keep the bus under 30 cm at 100 kHz.

Wi-Fi connects but MQTT never does (state -2)

Likely cause. Wrong broker address or port, a firewall in the way, or the broker requiring credentials the sketch is not sending.

Fix. Test from a laptop on the same network first: mosquitto_sub -h <broker> -t "#" -v. If that works, the problem is on the device — check the IP literal, port 1883 (or 8883 for TLS), and that client.setServer() runs before connect(). PubSubClient state codes are documented in its header.

Readings arrive for a while and then stop

Likely cause. The Wi-Fi or MQTT session dropped and the sketch never reconnects, or the broker dropped the client on keep-alive timeout.

Fix. Never assume the link stays up. Check WiFi.status() and client.connected() at the top of every loop and reconnect with exponential backoff. Add a watchdog so a wedged network stack reboots the device instead of going silent.

Performance Optimisation

  • Track stock per slot from reliable vend detection; reset on restock.
  • Alert on faults immediately — fault latency is lost revenue.
  • Stream over cellular; buffer/retry where coverage is patchy.
  • Drive restock routing and demand stocking from the data.
  • Replace every delay() with a millis() comparison — blocking delays are the single most common cause of dropped readings.
  • Sample sensors on a fixed cadence and publish on a slower one; you almost never need to transmit at the sampling rate.
  • Move networking into its own FreeRTOS task so a slow DNS lookup cannot stall the control loop.
  • Use uint8_t / uint16_t where the range allows; on an 8-bit AVR a 32-bit add costs four times as much.
  • Batch several samples into one MQTT publish. Radio time, not CPU time, dominates the energy budget.
  • Set the MQTT keep-alive to a value that matches your reporting interval so the broker does not churn reconnections.
  • For battery builds use deep sleep between samples: an ESP32 drops from ~160 mA awake to about 10 µA asleep, which is the difference between days and months of runtime.

Safety Precautions

  • Monitor only — never interfere with payment/cash handling, a regulated and security-sensitive domain.
  • Isolate the telemetry unit from payment systems; handle any payment-adjacent data securely.
  • For chilled machines, treat over-temperature as a food-safety alert.
  • Install safely inside the machine, powered via a proper regulator.
  • Lithium cells vent and burn when abused. Only use protected cells or a proper BMS, never charge below 0 °C, and never leave a charging pack unattended on a wooden desk.
  • Never power an RF module without its antenna fitted — the reflected power destroys the output stage. Check your local licence-free band and duty-cycle limits before transmitting.
  • Wear eye protection when soldering or cutting, and solder in a ventilated space — rosin flux fumes are a respiratory irritant.
  • Power the circuit through a bench supply with a current limit while you are testing. A 300 mA limit turns a wiring mistake into a beep instead of a dead board.
  • Disconnect power before changing any wiring. Hot-plugging a sensor onto a live bus is the fastest way to lose a controller.

Maintenance

  • Reset slot stock on each restock; verify vend detection accuracy.
  • Check fault detection (jam/payment/temp/door) periodically.
  • Verify cellular coverage and telemetry delivery.
  • Review demand data to keep each machine stocked to its location.
  • Re-check every screw terminal and header after the first week — thermal cycling loosens connections that felt tight on day one.
  • Log pack voltage. When resting voltage after a full charge drops below about 4.0 V, the cell is near end of life — replace it.
  • Keep the broker and dashboard containers patched, and rotate device credentials at least once a year.
  • Recalibrate at the interval given in the calibration section, and keep the constants in a text file next to the firmware — not only in flash.
  • Keep a short logbook of firmware versions and what changed. Six months later you will not remember why that constant is 1.083.

Future Improvements & Upgrades

A working v1 is a platform, not a finish line. These are the upgrades that add the most capability for the least rework.

  • Add predictive restock (from sale-rate trends).
  • Add cashless/telemetry integration where compliant and secure.
  • Add dynamic pricing/promotions from demand.
  • Add energy monitoring and remote diagnostics.
  • Design a proper PCB. Once the breadboard version has run for a month, moving to a two-layer board removes the intermittent-contact failures that dominate prototype faults.
  • Add over-the-air firmware updates so you never have to physically reach a deployed node again.
  • Add persistent local storage (microSD or the on-chip flash) so a network outage does not create a hole in your data.
  • Move configuration out of the source: a captive-portal setup page or a JSON config file makes the build reusable without a recompile.
  • Add a battery and solar option so the unit survives a power cut and can be sited away from a socket.
  • Write a small test harness that feeds synthetic sensor values through the decision logic, so you can validate thresholds without physically triggering the event.

Frequently Asked Questions

Why do vending machines need telemetry?

Because they are unattended, the operator is blind between visits — machines sell out, jam while still taking money, or drift out of temperature, all unnoticed. Real-time stock, sales and fault reporting restores visibility so the operator can act.

How does it track stock?

Primarily from vend events — each vend decrements the slot — reset on restock, and optionally corrected by sensors. That tells the operator exactly what is low and in which machine.

Why cellular rather than Wi-Fi?

Vending machines sit in lobbies, corridors and streets that rarely offer Wi-Fi, so telemetry streams over cellular to reach a central platform reliably.

How does it save money?

By routing restocking only to machines that need it (skipping full ones), preventing sell-outs so the machine is always selling its best lines, fixing faults fast to maximise uptime, and using demand data to stock each machine to its location.

Does it handle payments?

No — it monitors only. Payment and cash handling is a regulated, security-sensitive domain, so the unit does not interfere with payment systems and treats any payment-adjacent data with care.

References & Learning Resources

These are the primary sources worth reading in full. Manufacturer datasheets always outrank forum posts when the two disagree.

  1. Vending machineReference
  2. Vending telemetry / MDBReference
  3. DEX (data exchange)Reference
  4. TelemetryReference
  5. Fleet / route optimisationReference