Skip to content

NOTES

Overview

The online sensing module provides continuous sensor data acquisition and transmission functionality. It enables real-time monitoring of sensor data with configurable sampling frequency and multiple output channels (MQTT, serial, and optionally LCD).

Features

  • ✅ Configurable sampling frequency (default: 1.0 Hz, range: 0.1 - 300 Hz, practical limit: ~200 Hz)
  • ✅ MQTT transmission (enabled/disabled)
  • ✅ Serial output (enabled/disabled)
  • ✅ Optional LCD display (when TINY_MEASUREMENT_ENABLE_LCD is defined)
  • ✅ Fixed-rate data acquisition using ESP timer
  • ✅ Automatic data formatting
  • ✅ Thread-safe operation
  • ✅ Runtime configuration updates

Architecture

Timer-Based Sampling

The module uses ESP timer for precise periodic sampling:

  1. Timer Creation: Creates a periodic timer with period = 1 / sampling_frequency
  2. Timer Callback: Executes at each timer tick to read sensor data
  3. Data Output: Formats and outputs data to configured channels (MQTT, serial, LCD)

Data Flow

ESP Timer → Timer Callback → Sensor Read → Data Formatting → Output Channels
                                                                    ├─ MQTT
                                                                    ├─ Serial
                                                                    └─ LCD (optional)

Implementation Principles

Architecture Overview

The online sensing module implements a timer-driven, event-based architecture using ESP-IDF's high-precision timer system. The design prioritizes real-time data streaming with minimal latency.

Core Components

  1. ESP Timer (esp_timer)

    • High-precision hardware timer with microsecond accuracy
    • Periodic timer mode: triggers callback at fixed intervals
    • Timer period: period_us = 1,000,000 / sampling_frequency_hz
    • Timer callback executes in timer context (high priority, interrupt-like)
  2. Timer Callback Function

    • Executes synchronously at each timer tick
    • Performs sensor read operations (non-blocking SPI)
    • Formats data immediately (string formatting)
    • Publishes to output channels (MQTT, serial, LCD)
    • Minimal processing time to avoid missing timer ticks
  3. Output Channels

    • MQTT: Non-blocking publish via esp_mqtt_client_publish() (QoS 0)
    • Serial: Blocking printf() with immediate fflush()
    • LCD: Synchronous display update (may affect timing at high frequencies)

Programming Tools & APIs

  • ESP-IDF Timer API: esp_timer_create(), esp_timer_start_periodic()

  • ESP-IDF MQTT Client: esp_mqtt_client_publish() for network transmission

  • Standard C I/O: printf(), snprintf() for data formatting

  • FreeRTOS: State management and thread safety (no explicit tasks needed)

Execution Flow

  1. Initialization: Create periodic timer with calculated period
  2. Start: Execute immediate first sample, then start periodic timer
  3. Runtime: Timer callback fires at fixed intervals
    • Read sensor (SPI communication)
    • Format data (string conversion)
    • Output to enabled channels (non-blocking where possible)
  4. Stop: Delete timer, cleanup resources

Key Design Decisions

  • Immediate First Sample: Ensures data collection starts at t=0
  • Non-blocking MQTT: Prevents timer callback from blocking on network operations
  • Minimal Callback Processing: Keeps callback execution time short to maintain timing accuracy
  • State Flag Protection: Uses s_is_running flag to prevent callback execution after stop

Configuration

Default Configuration

Default values are defined in tiny_measurement_config.h:

#define TINY_MEASUREMENT_ONLINE_SENSING_DEFAULT_FREQ_HZ 1.0f
#define TINY_MEASUREMENT_ONLINE_SENSING_DEFAULT_ENABLE_MQTT true
#define TINY_MEASUREMENT_ONLINE_SENSING_DEFAULT_ENABLE_SERIAL true

Configuration Structure

typedef struct
{
    float sampling_frequency_hz;  // Sampling frequency in Hz
    bool enable_mqtt;              // Enable MQTT transmission
    bool enable_serial;            // Enable serial output
    bool enable_lcd;               // Enable LCD display (optional)
    const char *mqtt_topic;        // MQTT topic (NULL for default)
} online_sensing_config_t;

Data Format

MQTT Format

Compact format with 6 decimal places for full 20-bit precision:

x,y,z,temp

Example:

0.012345,-0.045678,0.987654,25.50

Serial Format

Same format as MQTT, with newline:

x,y,z,temp\n

LCD Format

One axis per line:

  • Line 1: X:0.012345

  • Line 2: Y:-0.045678

  • Line 3: Z:0.987654

  • Line 4: T:25.50C

Usage Workflow

  1. Initialize Sensor: Initialize ADXL355 sensor
  2. Set Sensor Handle: Call online_sensing_set_sensor_handle()
  3. Initialize Module: Call online_sensing_init() with configuration (or NULL for defaults)
  4. Start Sensing: Call online_sensing_start()
  5. Runtime Updates: Optionally update frequency or enable/disable channels
  6. Stop Sensing: Call online_sensing_stop() when done
  7. Deinitialize: Call online_sensing_deinit() to clean up

Performance Considerations

Sampling Frequency Limits

  • Minimum: 0.1 Hz (10 second period)
  • Maximum: 300 Hz (3333 microsecond period) - Code-level limit
  • Practical Maximum: ~200 Hz - Measured upper limit in actual hardware testing
  • Recommended: 1 - 200 Hz for most applications

Practical Limitation

While the code accepts frequencies up to 300 Hz, actual hardware testing shows that stable operation is limited to approximately 200 Hz. This limitation is primarily due to MQTT transmission constraints. At higher frequencies, MQTT publishing cannot keep up with the data generation rate, leading to buffer overflows, message queue saturation, and potential data loss. For reliable operation, especially when MQTT transmission is enabled, keep sampling frequency at or below 200 Hz.

Resource Usage

  • CPU: Timer callback executes at sampling frequency
  • Memory: Minimal stack usage in callback
  • Network: MQTT bandwidth depends on frequency and payload size. MQTT transmission is the primary bottleneck limiting the practical maximum sampling rate to ~200 Hz. At higher frequencies, MQTT publish operations cannot complete fast enough, causing message queue buildup and potential data loss.
  • Serial: High frequencies may cause serial buffer overflow

Improving Sampling Frequency

To achieve higher sampling frequencies, consider disabling unnecessary output channels:

  • Disable Serial Output: Serial printing (printf()) is blocking and can significantly slow down the timer callback, especially at high frequencies (>100 Hz)
  • Disable LCD Display: LCD updates are synchronous and relatively slow, making them unsuitable for frequencies above 10 Hz
  • Keep Only MQTT: If network transmission is required, keep only MQTT enabled and disable serial/LCD outputs

By disabling serial and LCD outputs, you can reduce the timer callback execution time and potentially achieve higher stable sampling rates.

Optimization Tips

  1. Disable Serial Output: For high frequencies (>100 Hz), disable serial output
  2. MQTT QoS: Use QoS 0 for high-frequency data (default)
  3. LCD Update: LCD updates are relatively slow, use only for low frequencies (<10 Hz)
  4. Stay Within Practical Limits: Keep sampling frequency at or below 200 Hz for stable operation, especially when MQTT is enabled. The 200 Hz limit is primarily due to MQTT transmission bandwidth constraints.
  5. Code-Level Limit: The code enforces a maximum of 300 Hz, but practical testing shows ~200 Hz is the reliable limit

Error Handling

Common Errors

  • ESP_ERR_INVALID_ARG: Invalid frequency (out of range: 0.1 - 300 Hz)
  • ESP_ERR_INVALID_STATE: Already running or not initialized
  • ESP_FAIL: Timer creation or start failed

Error Recovery

  • Check sensor handle is set before starting
  • Validate frequency range before initialization
  • Stop before restarting with new configuration

Thread Safety

  • Timer callback is executed in timer context (high priority)
  • Configuration changes require stopping and restarting
  • State checks prevent concurrent operations

Integration Notes

MQTT Integration

  • Requires MQTT client to be connected
  • Checks s_is_mqtt_connected before publishing
  • Uses default topic if mqtt_topic is NULL

Sensor Integration

  • Requires ADXL355 sensor handle
  • Must be initialized before setting handle
  • Sensor read operations are non-blocking

LCD Integration

  • Only available when TINY_MEASUREMENT_ENABLE_LCD is defined
  • LCD screen is cleared when starting
  • Updates are synchronous (may affect timing at high frequencies)