Skip to content

Data Analysis for PicoBot

This tutorial explains how to collect and analyze sensor data from the PicoBot for calibration, debugging, and machine learning.

What You'll Learn

In this tutorial, you'll understand:

  • Why separating collection from analysis improves development workflow
  • How IMU sensors (accelerometer, gyroscope) provide motion data
  • The difference between time-domain (bump detection) and frequency-domain (FFT) analysis
  • How machine learning can classify motion types from sensor data
  • The importance of data formats and proper I2C configuration

After completing this tutorial, you'll be able to:

  • ✅ Set up the data collection pipeline (robot → UDP → PC)
  • ✅ Record sensor data during robot operation
  • ✅ Run analysis tools (bump detector, FFT, vibration analyzer)
  • ✅ Interpret analysis results for calibration and debugging
  • ✅ Train and evaluate a motion classifier

Overview

The data analysis workflow separates collection (on robot) from analysis (on PC):

Robot (Pico W)              Host (PC)
┌──────────────┐           ┌──────────────────┐
│ Read sensors │──UDP───▶  │ Receive & store  │
│ Send packets │           │ data/record.csv  │
└──────────────┘           └────────┬─────────┘
                           ┌──────────────────┐
                           │ Analyze offline  │
                           │ - bump_detector  │
                           │ - fft_analyzer   │
                           │ - motion_classifier
                           └──────────────────┘
Why separate collection from analysis?
  • Robot code stays simple and reliable
  • Can experiment with analysis algorithms on PC
  • Can replay recorded data without robot
  • Easier debugging with full PC tools

Hardware Configuration

PicoCar Pin Mapping

Component Pin I2C Bus
IMU SDA GP14 I2C1
IMU SCL GP15 I2C1
Ultrasonic TRIG GP0 -
Ultrasonic ECHO GP1 -
Motor Left FWD GP13 -
Motor Left BWD GP12 -
Motor Right FWD GP10 -
Motor Right BWD GP11 -
I2C Bus Selection

The Pico has two I2C buses. GP14/GP15 are on I2C1, not I2C0:

# Correct:
i2c = I2C(1, sda=Pin(14), scl=Pin(15), freq=400000)

# Wrong (will error):
i2c = I2C(0, sda=Pin(14), scl=Pin(15), freq=400000)

BMI160 IMU Sensor

Parameter Value Notes
I2C Address 0x68 0x69 if SDO=VCC
Chip ID 0xD1 Verify on init
Accel Range ±2g 16384 LSB/g
Gyro Range ±250°/s 131.2 LSB/°/s
ODR 800 Hz Configurable
Byte Order Little-endian Unlike MPU6050!

Quick Start

Step 1: Upload Robot Code

ampy --port /dev/ttyACM0 put src/robot/pico_collector.py main.py

Step 2: Run Host Collector

cd src/host
python host_collector.py

Step 3: Collect Data

  1. Drive robot with WASD keys
  2. Press R to start recording
  3. Drive a measured distance (e.g., toward wall)
  4. Press R to stop recording
  5. Press E to export CSV

Step 4: Analyze

python analyzers/bump_detector.py data/recording_*.csv
python analyzers/fft_analyzer.py data/recording_*.csv --plot

Analysis Methods

Bump Detection (Time Domain)

Counts wheel bumps using threshold crossing:

Signal: ~~~∿∿∿~~~∿∿∿~~~∿∿∿~~~
             ↓ high-pass filter
Filtered: ---↑↓↑---↑↓↑---↑↓↑---
             ↓ threshold crossing
Bumps:       1     2     3

Algorithm: 1. Calculate acceleration magnitude: mag = sqrt(ax² + ay² + az²) 2. Apply high-pass filter to remove DC/drift 3. Count threshold crossings (rising edges)

Output: B/cm (bumps per centimeter) for distance estimation

python analyzers/bump_detector.py data/recording.csv

FFT Analysis (Frequency Domain)

Reveals what frequencies are present in the signal:

Time Domain:          Frequency Domain:
∿∿∿∿∿∿∿∿∿∿∿∿   FFT   [0][1][2][▌][4][5]...
                →              ↑
                         Peak at 25 Hz

Use cases: - Find wheel bump frequency - Detect motor vibration - Design filters

python analyzers/fft_analyzer.py data/recording.csv --channel ax --plot
Interpreting FFT Results
  • Peak at 20-50 Hz: Likely wheel bumps
  • Peak at 100+ Hz: Motor vibration or electrical noise
  • Multiple peaks: Multiple vibration sources

Vibration Analysis

Estimates speed from vibration intensity:

Fast motion → More shaking → Higher variance
Slow motion → Less shaking → Lower variance
Stopped     → Sensor noise → Very low variance

Algorithm: 1. Calculate acceleration magnitude per sample 2. Compute variance over sliding window 3. Map variance to speed (needs calibration)

python analyzers/vibration_analyzer.py data/recording.csv

Motion Classification (ML)

Classifies motion type using machine learning:

Labels: - STOPPED - FORWARD - BACKWARD - TURN_LEFT - TURN_RIGHT

Workflow: 1. Collect labeled data (host app auto-labels from keyboard) 2. Train classifier 3. Evaluate accuracy 4. Deploy model

# Train
python analyzers/motion_classifier.py train data/ai_dataset.csv

# Evaluate
python analyzers/motion_classifier.py evaluate data/ai_dataset.csv

Comparison: Bump vs FFT

Aspect Bump Detector FFT Analyzer
Domain Time Frequency
Method Threshold crossing Fourier transform
Output Bump count Frequency spectrum
Real-time Yes (simple) Needs window
Accuracy Good More precise
Use case Distance estimation Analysis, debugging

When to use which: - Bump detector: Real-time on robot, simple calibration - FFT: Post-analysis, finding exact frequencies, filter design

Data Formats

Sensor Packet (UDP)

Header (2 bytes):
  [type:1][count:1]

Per sample (36 bytes):
  [timestamp:8][ax:4][ay:4][az:4][gx:4][gy:4][gz:4][us:4]

Recording CSV

time_s,ts_us,ax,ay,az,gx,gy,gz,us,motor_l,motor_r,bumps,vib
0.000000,123456789,0.02,-0.01,0.98,0.5,0.3,0.1,45.2,0,0,0,1.2

AI Dataset CSV

label,ax,ay,az,gx,gy,gz,us,motor_l,motor_r,bumps,vib
FORWARD,0.12,0.03,0.98,1.2,0.5,0.3,45.2,70,70,150,12.5

Troubleshooting

"bad SCL pin" Error

Use I2C1 for GP14/GP15:

i2c = I2C(1, sda=Pin(14), scl=Pin(15), freq=400000)

"BMI160 not found" Error

Check: - I2C address (0x68 or 0x69) - Wiring connections - 3.3V power (not 5V)

No Data Received

Check: - Robot WiFi connected (shown on boot) - Host on port 5005 - Firewall allows UDP

Theory Background

  • [[Reference/extras/signal-processing/basics|Signal Processing Basics]] - Math foundations (FFT, filters, variance)
  • [[Reference/extras/signal-processing/robot-data-pipeline|Robot Data Pipeline]] - How data flows from sensor to analysis

Reference

  • [[Reference/07-data-analysis/analyzers-reference|Analyzers Reference]] - CLI tool reference
  • [[Reference/extras/hardware/picocar-pinout|PicoCar Pinout]] - Complete hardware pinout

Self-Assessment

Quick Check – Did You Get It?

🔹 Why do we collect data on the robot but analyze it on the PC? 🔹 What is the difference between time-domain and frequency-domain analysis? 🔹 How does the bump detector convert accelerometer data into distance? 🔹 Why is I2C bus selection (I2C0 vs I2C1) important for the BMI160 sensor? 🔹 What does a peak in the FFT spectrum tell you about the robot's motion?

Research Tasks

  1. Sampling rate investigation: What happens to your analysis if you change the IMU sampling rate from 500 Hz to 100 Hz? How does this affect FFT resolution?

  2. Noise characterization: Record data while the robot is stationary. What does the FFT show? How can you use this to design better filters?

  3. Classifier comparison: Train models using different algorithms (tree, forest, knn). Which performs best on your data? Why might that be?


Next Steps

  • [[Reference/07-data-analysis/distance-measurement|Distance Measurement]] - Detailed distance estimation methods
  • [[Reference/07-data-analysis/analyzers-reference|Analyzers Reference]] - CLI tool reference
  • Return to Course Overview