Arduino-style motor and servo control using Firmata — a combined MegaWrapper library
Project description
MegaWrapper
Control DC motors and servos on an Arduino over Firmata — with optional VL53L0X time-of-flight distance sensors.
from megawrapper import Board
board = Board("/dev/ttyUSB0")
motor = board.attach_motor(2, 4, 11)
motor.forward(100)
board.close()
Installation
From PyPI (recommended):
pip install megawrapper # core (pyfirmata2)
pip install 'megawrapper[pyserial]' # + built-in Firmata backend
pip install 'megawrapper[sensor]' # + VL53L0X ToF sensor
pip install 'megawrapper[pyserial,sensor]' # all extras
From source (editable):
git clone https://github.com/vihaanvp/MegaWrapper.git
cd MegaWrapper/repo
pip install -e .
Requirements: Python 3.8+, Arduino running StandardFirmata.
Dependencies:
| Dep | Type | For |
|---|---|---|
pyfirmata2 |
hard | Default Firmata backend |
pyserial |
optional ([pyserial]) |
Alternative built-in Firmata client |
adafruit-circuitpython-vl53l0x |
optional ([sensor]) |
VL53L0X ToF sensor (Raspberry Pi / Blinka) |
Quick Start
1. Upload StandardFirmata to your Arduino
Arduino IDE → File → Examples → Firmata → StandardFirmata → Upload.
2. Find the serial port
| OS | Typical port |
|---|---|
| Linux | /dev/ttyUSB0, /dev/ttyACM0 |
| macOS | /dev/tty.usbserial-* |
| Windows | COM3, COM4 |
3. Run a motor
import time
from megawrapper import Board
board = Board("/dev/ttyUSB0")
motor = board.attach_motor(2, 4, 11) # d1, d2, pwm pins
motor.forward(75)
time.sleep(2)
motor.stop()
board.close()
API Reference
Board — Arduino connection
from megawrapper import Board
# Connect
board = Board(port="/dev/ttyUSB0", stby=None)
# Attach motors
motor = board.attach_motor(d1=2, d2=4, pwm=11, name=None) # → Motor
# Control
board.stop_all() # coast all motors
board.wake() # STBY → HIGH (requires stby pin)
board.sleep() # STBY → LOW (requires stby pin)
# Lifecycle
board.close() # clean teardown
with Board(...) as b: # context manager — auto-close
# Singleton access
Board.get_active_board() # → Board | raises RuntimeError
Board.has_active_board() # → bool
__repr__: Board(port='COM3', motors=2) (pyserial mode) or Board(motors=2) (pyfirmata2).
Backend mode (optional kwarg on Board):
board = Board("/dev/ttyUSB0", backend="pyserial") # built-in Firmata via pyserial
board = Board("/dev/ttyUSB0") # pyfirmata2 (default)
Motor — DC motor via H-bridge
Drives a motor through 2 direction pins + 1 PWM pin (L298N, TB6612FNG, L293D, MX1508).
motor.forward(speed=100) # 0–100, default full
motor.backward(speed=100) # 0–100, default full
motor.stop() # coast (both direction pins LOW)
motor.brake() # short terminals (both HIGH)
motor.set_speed(50) # change speed, keep direction
motor.speed # current speed (0–100), settable
motor.direction # "forward" | "backward" | "stopped" | "braked"
motor.name # optional label from attach_motor()
Raises InvalidSpeedError if speed is not a number or outside 0–100.
Servo — standard servo on PWM pin
from megawrapper import Servo
servo = Servo()
servo.attach(pin=9) # requires a Board to exist first
servo.write(90) # 0–180 (clamped)
servo.read() # last commanded angle
servo.move_smooth(180, 15) # step 1° at a time
servo.sweep(0, 180, 1, 15) # continuous sweep
servo.detach() # release pin
servo.pin # attached pin or None
servo.current_angle # last angle or None
Raises:
RuntimeErrorif no Board exists or servo not attachedValueErrorif angle is not a number orstep ≤ 0
VL53L0X — Time-of-Flight Distance Sensor
I²C-based, independent of Board/Firmata. Runs on the host (Raspberry Pi / Blinka).
from megawrapper.sensor import VL53L0X # or: from megawrapper import VL53L0X
# Single sensor
sensor = VL53L0X() # auto I²C, address 0x29
print(sensor.distance) # centimetres
# Multiple sensors on one bus
sensors = VL53L0X.auto_address([17, 27, 22]) # GPIO pins for XSHUT
for s in sensors:
print(s.distance)
| Method / Property | Description |
|---|---|
VL53L0X(i2c=None, address=0x29) |
Constructor. Auto-creates I²C bus if omitted. |
.distance |
Measured distance in cm (raw mm ÷ 10). |
VL53L0X.auto_address(xshut_pins, i2c=None) |
Wake up to 16 sensors, assign addresses 0x30–0x3F. |
Requires: pip install 'megawrapper[sensor]' and Blinka-compatible hardware.
Utilities
from megawrapper import delay, millis
delay(1000) # pause 1 second
now = millis() # epoch milliseconds
Exceptions
MegaWrapperError # base (catch-all)
├── InvalidSpeedError # speed not a number or outside 0–100
├── BoardConnectionError # cannot reach Arduino
└── StandbyNotConfiguredError # wake()/sleep() without STBY pin
Examples
8 ready-to-run scripts in examples/:
| File | Shows |
|---|---|
single_motor.py |
Basic forward / stop |
dual_motor.py |
Two motors with names |
keyboard_control.py |
Interactive CLI motor control |
endless_sweep.py |
Servo sweep loop |
move_smooth.py |
Smooth servo movement |
pyserial_control.py |
Built-in pyserial Firmata backend |
vl53l0x_sensor.py |
Single VL53L0X distance readout |
vl53l0x_multi_sensor.py |
Multi-sensor auto-addressing |
python examples/single_motor.py
Motor/servo examples need an Arduino; sensor examples need a Raspberry Pi (or Blinka board) with VL53L0X.
Testing
python -m pytest tests/ -v
91 tests (90 passing, 1 pre-existing env-related skip), all mock the Arduino — no hardware required.
Project Wiki
Full documentation lives on the GitHub Wiki:
License
MIT © Vihaan Parlikar
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file megawrapper-0.2.2.tar.gz.
File metadata
- Download URL: megawrapper-0.2.2.tar.gz
- Upload date:
- Size: 15.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b306f1df270fe80077929fcd80ddd8ca0c3bb6a2d2dd7902c6a74f66a0be1a3
|
|
| MD5 |
e4e7bf741aa1b551ceff648e140b948d
|
|
| BLAKE2b-256 |
76fbb5fae257716ff09768f4de8323fe9f96ca4c24108de3b7db713ac4041d14
|
Provenance
The following attestation bundles were made for megawrapper-0.2.2.tar.gz:
Publisher:
publish.yml on vihaanvp/MegaWrapper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
megawrapper-0.2.2.tar.gz -
Subject digest:
5b306f1df270fe80077929fcd80ddd8ca0c3bb6a2d2dd7902c6a74f66a0be1a3 - Sigstore transparency entry: 2067133215
- Sigstore integration time:
-
Permalink:
vihaanvp/MegaWrapper@bfae7fc78eb5c9a4b047daf0b31528dc14983255 -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/vihaanvp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@bfae7fc78eb5c9a4b047daf0b31528dc14983255 -
Trigger Event:
release
-
Statement type:
File details
Details for the file megawrapper-0.2.2-py3-none-any.whl.
File metadata
- Download URL: megawrapper-0.2.2-py3-none-any.whl
- Upload date:
- Size: 9.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4919acdd0f969d8acb5b98520f1175a461edd7f5f91a1095c69c6461e891160
|
|
| MD5 |
ea4e749b4b1d846294ef76531d60338c
|
|
| BLAKE2b-256 |
952be1a68db512fca5d6daed901036c8b2b0076eaf51a72ad54cc44f83912e3a
|
Provenance
The following attestation bundles were made for megawrapper-0.2.2-py3-none-any.whl:
Publisher:
publish.yml on vihaanvp/MegaWrapper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
megawrapper-0.2.2-py3-none-any.whl -
Subject digest:
c4919acdd0f969d8acb5b98520f1175a461edd7f5f91a1095c69c6461e891160 - Sigstore transparency entry: 2067133318
- Sigstore integration time:
-
Permalink:
vihaanvp/MegaWrapper@bfae7fc78eb5c9a4b047daf0b31528dc14983255 -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/vihaanvp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@bfae7fc78eb5c9a4b047daf0b31528dc14983255 -
Trigger Event:
release
-
Statement type: