Skip to content

Repository files navigation

MFM RS-485 Sensor Module

A MultiFlexMeter (MFM) sensor module. The hardware is a generic carrier: RS-485 + 1-Wire, with a software-selectable sensor supply rail (3.6 V / 5 V / 12 V). The firmware (RIOT-OS, STM32L010) is likewise mostly generic — it powers the rail, talks to the host over I2C, and runs a measurement FSM. The current application reads a LinkBlue dissolved-oxygen (DO) sensor over Modbus RTU.

The module is a slave to the MFM host: the host powers it, triggers a measurement over I2C, then reads back the result.

Hardware

Feature Notes
Sensor bus RS-485 (Modbus RTU) and 1-Wire
Sensor supply Boost rail, selectable 3.6 V / 5 V / 12 V (FB divider)
Host link I2C slave (MFM register protocol)
MCU STM32L010 (mfm-module board)

The rail voltage is a compile-time choice (boost_voltage in main.c), currently 12 V for the DO sensor. KiCad sources live in hardware/; fab outputs are generated separately and shipped as release assets.

Build

Prerequisites: the arm-none-eabi GCC toolchain, plus the RIOT submodule and an out-of-tree I2C-slave patch.

git submodule update --init --recursive
git apply --directory=RIOT 0001-i2c-slave.patch   # I2C slave mode, not yet upstream
make                                               # build
make flash                                         # build + flash via SWD

FW_VERSION is stamped from git describe --tags, so build from a tagged commit for a meaningful version string.

Build flags

Pass as make VAR=1. Defaults are production values.

Flag Default Effect
FAT 0 1 = factory-acceptance loop: power rails, init Modbus + DO, read forever. Bench bring-up only.
LOW_POWER 1 0 = block all PM modes so the CPU busy-waits in idle, keeping the SWD link and breakpoints reliable for debugging.
DEBUG_LED 0 1 = blink LED1 with the FSM state and LED2 with the last error code.

Firmware overview

The host drives the module through the MFM I2C register protocol — firmware version, init, measurement start/status/data, and error. Register map and semantics: see the MultiFlexMeter host protocol spec.

A measurement cycle: host writes MEAS_START → firmware powers the rail, validates VSensor, brings up Modbus, reads the DO sensor, publishes the payload → host reads MEAS_DATA. On a measurement failure the firmware returns to IDLE and exposes an app error code (also blinked on LED2) in the error register for the host to read. An invalid FSM state instead halts in ERROR; the host recovers by power-cycling.

stateDiagram-v2
    [*] --> SYSTEM_INIT: power on
    SYSTEM_INIT --> IDLE: GPIO, I2C, ADC up
    IDLE --> MFR_INIT: host: manufacturer init
    MFR_INIT --> IDLE
    IDLE --> MEASURING: host: measure
    MEASURING --> IDLE: done or failure
    ERROR --> ERROR: halt on invalid state (host power-cycles)

    state MEASURING {
        [*] --> SENSORS_INIT
        SENSORS_INIT --> DO_CONF: rail OK, sensor probed
        DO_CONF --> DO_READ: no-op (no DO config)
        DO_READ --> MEASURE_FINISH
        MEASURE_FINISH --> [*]
    }
Loading

FAT=1 replaces this flow with a standalone read loop (APP_STATE_FAT) that doesn't wait for an I2C command.

Power consumption

One measurement cycle, measured at the main board input

Measured at the MultiFlexMeter main board's supply, so the figures include the main board's own consumption, not just this module. Captured on a dev build (less power-efficient than production) with LoRa at SF7.

A measurement cycle's active phase lasts about 30 s and draws roughly 360 mC (11.7 mA average, 247 mA peak).

DO payload format

MEAS_DATA returns an 8-byte, packed, little-endian struct. Fields are copied verbatim from the sensor's Modbus input registers — the firmware does no scaling or validation, so each value is a raw fixed-point integer the consumer must scale (and range-check) itself.

Offset Field Type Range Scale Unit
0 DO value uint16 0–2000 ×0.01 mg/L
2 DO saturation uint16 0–200 ×0.1 %
4 Electrode signal uint16 0–1000 raw
6 Temperature int16 -100–1300 ×0.1 °C

Apply the scale to recover the physical value — e.g. a DO field of 742 is 7.42 mg/L.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages