Skip to content

alonso28md/RAMCOD

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RAMCOD — Myoelectric Control Training System

RAMCOD Logo

Python MATLAB Arduino Wokwi Platform License

RAMCOD is a real-time myoelectric control training platform for mechano-electric prosthetics.
It captures EMG signals from surface electrodes, filters them through a clinical-grade MATLAB pipeline, and drives a servo motor on voluntary muscle contraction — replicating the closed-loop control of a real prosthetic limb.

Full simulation available — run the complete system without any hardware using Wokwi + VS Code.


Table of Contents


System Architecture

┌───────────────────────────────────────────────────────────────────────┐
│  PHYSICAL  (Mode A)                                                    │
│  [AD8232 sensors] → [Arduino UNO] ──── USB UART 230400 ────────────── │
│  or                                                                    │
│  SIMULATION  (Mode B)                                                  │
│  [Wokwi potentiometers] → [Virtual Arduino] ── RFC2217 TCP:4000 ────── │
│                                    │                                   │
├───────────────────────────────────────────────────────────────────────┤
│  PYTHON HOST  (src/python/)                                            │
│  serial_comm.py  →  auto-detects hardware OR rfc2217://localhost:4000  │
│  matlab_bridge.py → MATLAB Engine  OR  SciPy fallback                 │
│  activation.py   → refractory period + alternating S1↔S2 logic        │
│  gui_*.py        → PyQt5 GUI + pyqtgraph real-time plots               │
├───────────────────────────────────────────────────────────────────────┤
│  MATLAB  (src/matlab/functions/)                                       │
│  emg_filter.m  emg_rms.m  emg_calibrate.m  emg_activate.m             │
└───────────────────────────────────────────────────────────────────────┘

Hybrid Design Philosophy

Layer Tool Rationale
Signal processing MATLAB Signal Processing Toolbox; validated butter/filtfilt; industry-standard in clinical labs
Application & GUI Python Modern GUI (PyQt5); modular architecture; deployable without MATLAB licence
Embedded firmware Arduino C++ Low-cost open hardware; real closed-loop for demonstrations
Circuit simulation Wokwi Full hardware simulation; RFC2217 bridge connects to real Python GUI

The Python host calls MATLAB functions via the MATLAB Engine API. If MATLAB is unavailable, a numerically identical SciPy fallback runs transparently. A badge in the header shows the active backend.


Hardware Requirements

Component Specification
Arduino UNO (or compatible) ATmega328P, 5V
AD8232 EMG sensor modules 1 or 2 (system validated with 2)
Surface EMG electrodes Standard ECG/EMG snap-on electrodes
PWM servo motor Any 5V standard servo (SG90, MG996R…)
USB-A to USB-B cable Arduino connection

Pin connections

Sensor Signal LO+ LO−
Sensor 1 A0 D8 D9
Sensor 2 A1 D10 D11
Sensor 3 A2 D12 D13
Sensor 4 A3 D2 D4
Servo PWM D7

Sensors 3 & 4 mirror S1/S2 in the current 2-sensor hardware build. Full 4-sensor support is preserved in the code.


Software Requirements

Python

Python    >= 3.10
PyQt5     >= 5.15.0
pyqtgraph >= 0.13.0
pyserial  >= 3.5
numpy     >= 1.24.0
scipy     >= 1.11.0

MATLAB Engine API (optional — enables MATLAB backend)

  • MATLAB R2022a or newer + Signal Processing Toolbox
cd <MATLAB_ROOT>/extern/engines/python
python setup.py install

Wokwi simulation (optional — enables hardware-free demo)

Arduino firmware (hardware mode)

  • Arduino IDE 1.8+ or Arduino CLI
  • Library: Servo (bundled with Arduino IDE)

Repository Structure

RAMCOD/
├── src/
│   ├── arduino/
│   │   └── RAMCOD_firmware.ino          Production firmware (230400 baud)
│   │
│   ├── matlab/
│   │   ├── functions/
│   │   │   ├── emg_filter.m
│   │   │   ├── emg_rms.m
│   │   │   ├── emg_calibrate.m
│   │   │   └── emg_activate.m
│   │   ├── RMC_GUI_Comun.mlapp          Standalone MATLAB GUI
│   │   └── RAMCOD_tests.m               17 unit tests
│   │
│   ├── python/
│   │   ├── main.py                      Entry point
│   │   ├── requirements.txt
│   │   └── ramcod/
│   │       ├── serial_comm.py           Hardware + RFC2217 auto-detection
│   │       ├── matlab_bridge.py         MATLAB Engine + SciPy fallback
│   │       ├── activation.py            Servo activation controller
│   │       ├── profiles.py              JSON profile persistence
│   │       ├── worker.py                QThread acquisition
│   │       ├── gui_constants.py         Theme, widgets, constants
│   │       ├── gui_setup.py             Setup panels
│   │       └── gui_training.py          Real-time training view
│   │
│   └── wokwi/
│       ├── RAMCOD_wokwi.ino             Simulation firmware (115200 baud)
│       ├── diagram.json                 Circuit: Arduino + pots + servo + LED
│       └── wokwi.toml                   VS Code config + rfc2217ServerPort=4000
│
├── profiles/                            Saved user calibration profiles
├── docs/
│   └── RAMCOD_Technical_Documentation.docx
├── demo/
│   └── logo.png
└── README.md

Installation

Python dependencies

cd src/python
pip install -r requirements.txt

Arduino CLI (needed for Wokwi VS Code mode)

# Install Arduino CLI: https://arduino.github.io/arduino-cli/
arduino-cli core install arduino:avr

Wokwi VS Code extension

  1. Open VS Code → Extensions → search Wokwi
  2. Install Wokwi for VS Code
  3. Press F1Wokwi: Request a new License → follow browser prompt (free)

Running the Application

Mode A — Hardware (real Arduino)

# 1. Flash firmware
arduino-cli compile --fqbn arduino:avr:uno src/arduino/RAMCOD_firmware.ino
arduino-cli upload  --fqbn arduino:avr:uno --port /dev/ttyUSB0 src/arduino/RAMCOD_firmware.ino

# 2. Run GUI — auto-detects the board on COM/ttyUSB ports
cd src/python
python main.py

The header badge shows ● COM3 (or equivalent). Connection LED is green.


Mode B — Full simulation (Wokwi + VS Code)

This is the most impressive demo mode: the real Python GUI connects to a virtual Arduino running in Wokwi. No physical hardware needed.

Step 1 — Compile the simulation firmware

arduino-cli compile \
  --fqbn arduino:avr:uno \
  --output-dir src/wokwi/build \
  src/wokwi/RAMCOD_wokwi.ino

Step 2 — Start the Wokwi simulator

Open VS Code in the project root, then:

F1 → Wokwi: Start Simulator

The Wokwi panel opens — you see the Arduino UNO, two potentiometers, and the servo. Leave this panel visible (Wokwi pauses when hidden).

Step 3 — Run the Python GUI

cd src/python
python main.py

Step 4 — Connect

Click Search Board in the GUI.

  • The app first scans hardware COM ports (finds none)
  • Then tries rfc2217://localhost:4000 — finds the Wokwi simulation
  • Header badge changes to ● Wokwi Simulation in cyan
  • Connection LED turns blue

Step 5 — Use it

  • Check Electrodes → returns 1,1,1,1 (LO pins wired to GND in simulation)
  • Calibrate → captures 10 s baseline from the potentiometers at rest (leave them at 0)
  • Start Training → real-time EMG plots appear
  • Turn pot1 clockwise past 70% → servo in Wokwi moves to 0° + activation flash in GUI
  • Turn pot2 clockwise past 70% → servo moves to 90° + flash

Mode C — Wokwi web editor (no Python GUI)

Use this to quickly show the circuit to someone without installing anything.

  1. Go to wokwi.com/projects/new/arduino-uno
  2. Paste src/wokwi/RAMCOD_wokwi.ino → sketch.ino tab
  3. Paste src/wokwi/diagram.json → diagram.json tab
  4. Press ▶ Play
  5. Open Serial Monitor → send commands:
Command Response
C RAMCOD — handshake confirmed
A 1,1,1,1 — all sensors OK
1 Starts 10 s binary stream. Turn pots to activate servo.
S Sine wave test stream. Send any key to stop.

How RFC2217 Connects Python to Wokwi

┌──────────────────────────────────────────────────────────────────┐
│  Wokwi VS Code extension                                          │
│  ┌─────────────────────────┐                                      │
│  │ Virtual Arduino UNO     │                                      │
│  │  pot1 → A0 (EMG S1)     │                                      │
│  │  pot2 → A1 (EMG S2)     │  UART at 115200 baud (simulated)    │
│  │  servo ← D7             │        │                             │
│  └─────────────────────────┘        │                             │
│               ↕ wokwi.toml: rfc2217ServerPort = 4000             │
│  ┌─────────────────────────┐        │                             │
│  │ RFC2217 TCP server      │◄───────┘                             │
│  │ localhost : 4000        │                                      │
│  └─────────────────────────┘                                      │
└─────────────────┬────────────────────────────────────────────────┘
                  │  TCP (RFC2217 — serial-over-TCP standard)
┌─────────────────▼────────────────────────────────────────────────┐
│  Python  —  serial_comm.py                                        │
│  serial.serial_for_url("rfc2217://localhost:4000", baud=115200)  │
│                                                                    │
│  find_board() search order:                                        │
│    1. Scan hardware COM/ttyUSB ports  →  not found                │
│    2. Try rfc2217://localhost:4000    →  RAMCOD handshake OK ✔    │
│                                                                    │
│  After connection — identical API regardless of mode:              │
│    .check_sensors()  .start_stream()  .read_sample()              │
│    .send_servo()     .start_sine()    .close()                    │
└──────────────────────────────────────────────────────────────────┘

RFC2217 is an IETF standard (RFC 2217) for tunnelling serial port data over TCP. PySerial supports it natively via serial_for_url() — no extra libraries needed. The virtual serial port behaves identically to a real COM port from the application's perspective.


Usage Walkthrough

Step Action Result
① Connect Search Board Auto-detects hardware or Wokwi simulation
② Sensors Check Electrodes Green LED = contact OK (or always OK in simulation)
③ Calibrate Run Calibration Wizard 10 s rest capture → baseline RMS per sensor
④ Profile Save Persist calibration — skip next session
⑤ Train Start Training Real-time raw + filtered EMG plots
⑥ Activate Contract muscle / turn pot Servo moves + activation flash in GUI
⑦ Tune Sensitivity sliders Adjust threshold without recalibrating

Signal Processing Pipeline

Raw ADC [0–1023]
    │
    ▼  emg_filter.m / scipy.signal.butter + filtfilt
Butterworth bandpass 10–200 Hz, order 2, zero-phase
    │
    ▼  emg_rms.m / numpy
RMS envelope per 50 ms window  →  4 values (one per sensor)
    │
    ▼  emg_activate.m / activation.py
RMS > sensitivity × RMS_baseline  ?
    │  Yes → servo command byte → Arduino
    │         + 1 s refractory period
    │         + S1↔S2 alternation
    ▼
Servo moves

MATLAB Functions Reference

Function Signature Returns
emg_filter (raw_data, fs, 'LowHz', 10, 'HighHz', 200, 'Order', 2) filtered N×4
emg_rms (filtered_window) rms_vals 1×4, rectified N×4
emg_calibrate (filtered_data, active_sensors) noise_profile struct
emg_activate (rms_vals, noise_profile, sensitivity, next_cmd) cmd uint8, sensor int

Run unit tests from MATLAB:

cd src/matlab
run('RAMCOD_tests.m')   % 17 assertions, 4 suites

Arduino Protocol Reference

Direction Byte Meaning
PC → Board 'C' Handshake → "RAMCOD\r\n"
PC → Board 'A' Sensor check → "1,0,1,0\r\n"
PC → Board '1''6' Stream N×10000 samples
PC → Board 'S' Sine test stream
Board → PC uint16 ×4 One sample, 8 bytes, LSB first: S1 S2 S3 S4
PC → Board uint8 2–4 Servo → Position A
PC → Board uint8 6–9 Servo → Position B

Baud rate: 230400 (hardware) / 115200 (Wokwi simulation).


Configuration Reference

Parameter File Default Notes
BAUD_HARDWARE serial_comm.py 230400 Real Arduino
RFC2217_URL serial_comm.py rfc2217://localhost:4000 Wokwi endpoint
rfc2217ServerPort wokwi.toml 4000 Must match above
SAMPLE_RATE gui_constants.py 1000 Hz Hardware nominal
WINDOW_MS gui_constants.py 50 ms RMS window
SCROLL_SEC gui_constants.py 10 s Plot time window
CALIB_SECS gui_constants.py 10 s Calibration duration
SERVO_POS_A/B firmware 0° / 90° Servo target angles
EMG_THRESHOLD RAMCOD_wokwi.ino 700/1023 Wokwi standalone threshold

Developed by Alonso Martín Díez · Biomedical Engineering · UEM 2026

About

Myoelectric control training system for prosthetic hand activation · MATLAB + Arduino + Python

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors