Skip to content

Architecture Overview

The Multiflexmeter (MFM) is an IoT sensor platform built around the ATmega1284P microcontroller. It uses LoRaWAN for long-range communication to The Things Network (TTN).

┌─────────────────────┐ I2C/SMBus ┌─────────────────────┐
│ Sensor Module │◄──────────────────►│ ATmega1284P MCU │
│ (Address 0x36) │ │ │
└─────────────────────┘ │ ┌───────────────┐ │
│ │ LMIC Stack │ │
│ └───────┬───────┘ │
└──────────┼──────────┘
│ SPI
┌──────────────────────┐
│ RFM95 LoRa Radio │
│ (868 MHz) │
└──────────┬───────────┘
│ RF
┌──────────────────────┐
│ LoRaWAN Gateway │
└──────────┬───────────┘
│ IP
┌──────────────────────┐
│ The Things Network │
└──────────────────────┘

ATmega1284P MCU

The main microcontroller running the firmware. Features 128KB Flash, 16KB SRAM, and 4KB EEPROM.

RFM95 Radio

LoRa transceiver module operating at 868 MHz (EU868) using the SX1276 chipset.

Sensor Module

External I2C/SMBus sensor module at address 0x36 providing measurement data.

LMIC Stack

IBM LoRaWAN-in-C library handling LoRaWAN protocol, join procedures, and TX/RX scheduling.

The firmware uses a cooperative job scheduling model provided by the LMIC library. There are no interrupts for application logic; all operations are scheduled as jobs.

setup()
├─ Board initialization
├─ Sensor I2C init
├─ LMIC stack setup
├─ EEPROM config load
└─ LMIC_startJoining() → EV_JOINING event
loop()
└─ os_runloop_once() ← Processes scheduled jobs
EV_JOINING
EV_JOINED
├─► job_pingVersion()
│ └─ Sends HW/FW version on FPort 2
└─► (45s delay)
job_performMeasurements()
└─ Triggers sensor via I2C CMD 0x10
└─► (10s delay)
job_fetchAndSend()
├─ Reads sensor via I2C CMD 0x11
├─ Transmits data on FPort 1
└─ scheduleNextMeasurement()
└─► (interval delay) → job_performMeasurements()
ModuleFilePurpose
Mainsrc/main.cppLMIC event handling, job scheduling, downlink processing
Sensorssrc/sensors.cppSensor module interface wrapper
SMBussrc/smbus.cppLow-level I2C/TWI protocol (80 kHz)
Configsrc/rom_conf.cppEEPROM configuration storage
RPMsrc/rpm_calculation.cppPulse count to RPM conversion
Boardsrc/boards/mfm_v3_m1284p.cppBoard-specific initialization
Watchdogsrc/wdt.cppMCU reset mechanism

The firmware operates as a passthrough system:

  • Raw sensor data is transmitted without firmware-level interpretation
  • The sensor module at address 0x36 encodes data in its own format
  • Data decoding happens in the application layer (TTN decoder + backend)

This design minimizes firmware complexity and allows flexible sensor integration.

All operations use LMIC’s job scheduler:

  • No blocking code in the main loop
  • Jobs are scheduled with delays using os_setTimedCallback()
  • The watchdog ensures recovery from hangs

All runtime configuration is stored in EEPROM:

  • LoRaWAN credentials (AppEUI, DevEUI, AppKey)
  • Measurement interval
  • Sensor-specific settings (wheel teeth count)
  • Configuration can be modified via OTA downlinks