Embedded SystemsDistinguishedlegendary

Time-Series Classification: 1D CNN on Sensor Data

Design and size a 1D CNN for sensor time-series classification on Cortex-M: convolution math, MAC/memory budget, quantization, and windowing pitfalls.

7 min readAhmet Zahid ArıcanUpdated 12 Sept 2026
Contents & prerequisites

Time-series classification is the workhorse task behind activity recognition, fall detection, predictive maintenance (bearing/vibration fault classes), gesture recognition, and ECG/PPG arrhythmia flagging — all running on Cortex-M class MCUs with a few hundred kB of RAM. A 1D CNN is usually the right architecture for this: it exploits local temporal correlation the way a 2D CNN exploits spatial correlation in images, it is cheap in MACs compared to LSTMs/GRUs, and it maps directly onto CMSIS-NN/TFLite Micro kernels that are already optimized for Cortex-M SIMD and NPUs like Ethos-U. This article covers the math of 1D convolution over sensor windows, how to size a network for an MCU budget, and a worked example classifying IMU windows into activity classes.

Why 1D CNN Over RNN/LSTM for Embedded Time Series

Property1D CNNLSTM/GRU
Compute per inferenceO(kernel·channels·length), fully parallelSequential, O(4·hidden²) per step, recurrent
Latency on MCUDeterministic, vectorizable (CMSIS-NN arm_convolve)Poor SIMD utilization, gate nonlinearities per step
MemoryWeights only; no persistent hidden state across long sequencesHidden/cell state must persist; harder to quantize well
Receptive fieldGrows with depth/dilation — must be engineeredNaturally unbounded (in theory)
Typical accuracy on fixed-length windows (HAR, KWS-like)Matches or beats RNNs when window ≤ a few secondsBetter for variable-length / long-range dependencies

For fixed-length sensor windows (e.g., 1–4 s of accelerometer/gyro data, or a vibration FFT frame), a 1D CNN is almost always the better MCU choice: it quantizes cleanly to INT8, runs on CMSIS-NN or an NPU accelerator, and has no sequential data dependency that stalls a pipeline.

The 1D Convolution Operation

Given an input sequence x[n] with C_in channels (e.g., 6 channels for a 3-axis accel + 3-axis gyro), a 1D conv layer with kernel size K, C_out filters, stride S, applies:

y[c_out, n] = Σ_{c_in=0}^{C_in-1} Σ_{k=0}^{K-1} w[c_out, c_in, k] · x[c_in, n·S + k]  +  b[c_out]

This differs from a 2D image conv only in that the sliding window moves along one axis (time) instead of two (height/width). Each filter learns a temporal pattern — e.g., the shape of a single footstep acceleration spike, or a fault-induced vibration transient — and slides it across the whole window, producing a feature map whose length is:

L_out = floor((L_in − K) / S) + 1        (no padding)
L_out = floor((L_in + 2·P − K) / S) + 1  (with padding P)

MAC count per conv layer:

MACs = C_in · C_out · K · L_out

This is the number you multiply against your MCU's MACs/cycle (e.g., 1 for plain Cortex-M4 DSP extension, 4–16 for Cortex-M55 + Ethos-U55 offload) to estimate layer latency.

Typical Architecture for Sensor Windows

A practical MCU-sized 1D CNN for activity/vibration classification:

Input:  [C_in=6, L=128]           (e.g., 6-axis IMU, 128 samples @ 64 Hz ≈ 2 s)
Conv1D: 16 filters, K=5, stride=1, ReLU     -> [16, 124]
MaxPool1D: pool=2                            -> [16, 62]
Conv1D: 32 filters, K=5, stride=1, ReLU     -> [32, 58]
MaxPool1D: pool=2                            -> [32, 29]
Conv1D: 32 filters, K=3, stride=1, ReLU     -> [32, 27]
GlobalAveragePool1D                          -> [32]
Dense: 32 -> num_classes, Softmax

Design choices that matter for embedded deployment:

  • Global average pooling instead of Flatten+Dense on the last feature map — removes a large, position-sensitive dense layer and makes the network robust to small time shifts in the window (the sensor event doesn't always start at sample 0).
  • Stride/pooling instead of deep stacks — MCU SRAM is the binding constraint, not depth; two or three conv layers with pooling usually saturate accuracy for windowed sensor classification.
  • Small kernels (K=3–7) — sensor transients (footsteps, gear mesh impacts) are short; large receptive fields are better built by stacking layers or using dilation than by using huge kernels.
  • Depthwise-separable variants (depthwise conv along time + pointwise 1×1 across channels) cut MACs substantially when C_in is large (e.g., 8+ sensor channels), at a small accuracy cost — same trick as MobileNet, applied along the time axis.

Sizing the Network to an MCU Budget

Worked example: STM32-class Cortex-M4 @ 80 MHz, 128 kB RAM budget for tensors/scratch, no NPU offload, running INT8 CMSIS-NN kernels at roughly 1 MAC/cycle after DSP extension utilization.

Using the architecture above, C_in=6, L=128:

Layer 1: MACs = 6 · 16 · 5 · 124 = 59,520 Layer 2: MACs = 16 · 32 · 5 · 58 = 148,480 Layer 3: MACs = 32 · 32 · 3 · 27 = 82,944 Dense: MACs = 32 · num_classes (say 6 classes) = 192

Total ≈ 291,136 MACs/inference

At ~1 MAC/cycle: 291,136 cycles ÷ 80 MHz ≈ 3.6 ms per inference. For a classifier running once per 2 s window, that's <0.2% CPU duty cycle — comfortably real-time with large headroom for the rest of the application (sensor fusion, BLE stack, etc.).

Memory check:

  • Weights: (6·16·5) + (16·32·5) + (32·32·3) + (32·6) ≈ 480 + 2560 + 3072 + 192 = 6,304 params → ~6.3 kB at INT8, negligible.
  • Largest activation buffer: layer-1 output [16, 124] at INT8 = 1,984 bytes; input buffer [6,128] = 768 bytes. Peak scratch, including double-buffering for in-place-friendly ops, stays under ~8 kB.

Both compute and memory fit comfortably inside a 128 kB RAM / 80 MHz M4 budget — this workload is dominated by conv layer 2, so if a further speed cut is needed, reducing filters there (32→24) or switching to depthwise-separable convs there gives the biggest return.

Windowing and Labeling — the Part That Breaks in Practice

The CNN math is straightforward; most real-world accuracy loss comes from windowing choices upstream:

  • Window length vs. class dynamics: must be long enough to contain at least one full cycle of the pattern (e.g., one gait cycle ≈ 1–1.2 s at typical walking cadence) but short enough to bound latency and keep the class boundary crisp during transitions.
  • Overlap (sliding window with 50% overlap is typical): increases training data and smooths decision boundaries across window edges, at the cost of ~2× inference rate.
  • Normalization stats computed on-device: if per-window mean/std normalization is used at inference, it must match exactly what training used (same axis reduction, same epsilon), or accuracy silently degrades — this is a common silent bug in TFLite Micro deployment pipelines.
  • Sensor sampling jitter: MCU ADC/IMU sampling isn't perfectly periodic; training data collected on a PC-tethered logger with different jitter characteristics than the final firmware's DMA-driven sampling can create a train/deploy distribution shift that no amount of model tuning fixes.

Quantization and Deployment Path

The standard pipeline (see the TFLite Micro Workflow and Post-Training Quantization articles for depth) applies directly:

  1. Train in float32, verify accuracy on held-out windows.
  2. Post-training INT8 quantization (or QAT if the float→INT8 accuracy drop exceeds ~1–2 points, which is more common in time-series nets than vision nets because activation dynamic range per channel can vary sharply between quiet and event windows).
  3. Convert to a .tflite flatbuffer, deploy via TFLite Micro or compile straight to CMSIS-NN calls.
  4. Validate that the interpreter's chosen kernel (e.g., arm_convolve_s8) matches the expected MACs/cycle assumption used in the sizing above — im2col-based fallbacks on unsupported shapes can be 2–4× slower than the optimized direct-conv path.

Key Takeaways

  • 1D CNNs slide a temporal kernel across sensor channels; MACs per layer = C_in · C_out · K · L_out, and this number drives both latency and memory sizing before any code is written.
  • They beat LSTM/GRU on MCUs for fixed-length windows because they're fully parallel, SIMD/NPU-friendly, and quantize cleanly to INT8.
  • Global average pooling before the final dense layer improves shift-robustness and shrinks parameter count versus Flatten+Dense.
  • A 3-layer, ~6k-parameter network classifying 2 s / 6-channel IMU windows fits comfortably in ~3.6 ms at 80 MHz and ~8 kB scratch RAM on a plain Cortex-M4 — no NPU required for this class of problem.
  • Most accuracy loss in deployed systems comes from windowing/normalization mismatches between training and firmware, not from the CNN architecture itself — verify these first when accuracy drops after deployment.

Learning

Sign in to track your progress.

Evidence

Public projects engineers linked to Time-Series Classification: 1D CNN on Sensor Data.

Add evidence

No engineer has linked a project to this topic yet. Built something that proves it? Add the project and tag it with embedded-systems-time-series-classification-1d-cnn-on-sensor-data — it then shows here and on your public profile.