Skip to content

NOTES

Overview

The offline sensing module provides high-frequency batch sensor data acquisition and storage functionality. It is designed for scenarios requiring precise, time-stamped data collection with configurable sampling parameters and multiple storage options.

Features

  • ✅ High-frequency sampling (default: 100 Hz, range: 1 - 4000 Hz)
  • ✅ Configurable sampling duration (default: 10 seconds, range: 0.1 - 3600 seconds)
  • ✅ Memory buffer storage (enabled/disabled)
  • ✅ SD card storage (enabled/disabled)
  • ✅ MQTT report after sampling completion (enabled/disabled)
  • ✅ High-precision timer-based sampling (ESP timer)
  • ✅ Automatic file naming with timestamps and parameters
  • ✅ Thread-safe operation
  • ✅ Support for delayed and scheduled start

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 and store sensor data
  3. Data Storage: Stores data in memory buffer and/or SD card
  4. Completion Report: Generates report and optionally sends via MQTT

Data Flow

ESP Timer → Timer Callback → Sensor Read → Memory Buffer → SD Card Storage
                                                            MQTT Report

Configuration

Default Configuration

Default values are defined in tiny_measurement_config.h:

#define TINY_MEASUREMENT_OFFLINE_SENSING_DEFAULT_FREQ_HZ 100.0f
#define TINY_MEASUREMENT_OFFLINE_SENSING_DEFAULT_DURATION_SEC 10.0f
#define TINY_MEASUREMENT_OFFLINE_SENSING_DEFAULT_ENABLE_MEMORY true
#define TINY_MEASUREMENT_OFFLINE_SENSING_DEFAULT_ENABLE_SD true
#define TINY_MEASUREMENT_OFFLINE_SENSING_DEFAULT_ENABLE_MQTT_REPORT true

Configuration Structure

typedef struct
{
    float sampling_frequency_hz;      // Sampling frequency in Hz
    float sampling_duration_sec;       // Sampling duration in seconds
    bool enable_memory;                // Enable memory buffer storage
    bool enable_sd;                    // Enable SD card storage
    bool enable_mqtt_report;          // Enable MQTT report after sampling
    const char *sd_file_path;          // SD card file path (NULL for auto-generated)
    const char *mqtt_report_topic;     // MQTT topic for report (NULL for default)
} offline_sensing_config_t;

Data Storage

Memory Buffer

  • Stores samples in RAM during sampling
  • Thread-safe access using mutex
  • Can be retrieved after sampling completion
  • Automatically allocated based on sampling parameters

SD Card Storage

  • Saves data as CSV file
  • Automatic filename generation with timestamp and parameters
  • Format: YYYYMMDDHHMMSS_FXXXX_DXXXX.csv or BootXXXXX_FXXXX_DXXXX.csv
  • CSV format: timestamp_us,x,y,z,temp

File Naming

With System Time:

20250116120000_F0100_D0010.csv
- 20250116120000: Date and time (YYYYMMDDHHMMSS) - F0100: Frequency (4 digits, zero-padded) - D0010: Duration (4 digits, zero-padded)

Without System Time (Boot Time):

Boot12345_F0100_D0010.csv
- Boot12345: Boot time in seconds (last 5 digits) - F0100: Frequency (4 digits, zero-padded) - D0010: Duration (4 digits, zero-padded)

Data Format

CSV Format

timestamp_us,x,y,z,temp
1234567890,0.012345,-0.045678,0.987654,25.50
1234567891,0.012346,-0.045679,0.987655,25.51
...
  • timestamp_us: Timestamp in microseconds since boot
  • x, y, z: Acceleration values in g (6 decimal places)
  • temp: Temperature in °C (2 decimal places)

MQTT Report Format

{
  "samples": 1000,
  "freq_hz": 100.00,
  "duration_sec": 10.00,
  "memory_ok": true,
  "sd_ok": true,
  "sd_path": "/sdcard/20250116120000_F0100_D0010.csv",
  "start_us": 1234567890,
  "end_us": 1334567890
}

Usage Workflow

  1. Initialize Sensor: Initialize ADXL355 sensor
  2. Set Sensor Handle: Call offline_sensing_set_sensor_handle()
  3. Initialize Module: Call offline_sensing_init() with configuration
  4. Start Sensing: Call offline_sensing_start() (blocks until complete)
  5. Get Report: Call offline_sensing_get_report() for results
  6. Get Data (optional): Call offline_sensing_get_memory_data() to retrieve samples
  7. Deinitialize: Call offline_sensing_deinit() to clean up

Performance Considerations

Sampling Frequency Limits

  • Minimum: 1 Hz
  • Maximum: 4000 Hz
  • Recommended: 10 - 1000 Hz for most applications

Memory Requirements

Memory buffer size = sampling_frequency × sampling_duration × sizeof(offline_sensing_sample_t)

Example: 100 Hz × 10 sec × 32 bytes = 32 KB

Resource Usage

  • CPU: Timer callback executes at sampling frequency
  • Memory: Buffer allocated based on sampling parameters
  • Storage: SD card write speed limits maximum frequency
  • Blocking: offline_sensing_start() blocks until sampling completes

Error Handling

Common Errors

  • ESP_ERR_INVALID_ARG: Invalid frequency or duration (out of range)
  • ESP_ERR_INVALID_STATE: Already running or not initialized
  • ESP_ERR_NO_MEM: Memory allocation failed
  • ESP_FAIL: SD card write failed

Error Recovery

  • Check sensor handle is set before starting
  • Validate frequency and duration ranges before initialization
  • Ensure SD card is mounted and writable
  • Check available memory before starting long-duration sampling

Thread Safety

  • Timer callback is executed in timer context (high priority)
  • Memory buffer access is protected by mutex
  • State checks prevent concurrent operations
  • offline_sensing_start() is blocking (runs in calling task context)

Integration Notes

SD Card Integration

  • Requires SD card to be mounted
  • Uses MOUNT_POINT constant for file paths
  • File operations use standard C file I/O
  • Errors are logged but don't stop sampling

MQTT Integration

  • Requires MQTT client to be connected
  • Checks s_is_mqtt_connected before publishing
  • Report is sent after sampling completion
  • Uses default topic if mqtt_report_topic is NULL

Sensor Integration

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

Delayed and Scheduled Start

The module supports delayed and scheduled start through the command handler:

  • Delayed Start: DL=<seconds> - Start after specified delay
  • Scheduled Start: TIME=<YYMMDDHHMMSS> - Start at specified time

These features are implemented in the command handler wrapper task, not in the core offline sensing module.