Skip to main content

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:

  • RuntimeError if no Board exists or servo not attached
  • ValueError if angle is not a number or step ≤ 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 0x300x3F.

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

megawrapper-0.2.2.tar.gz (15.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

megawrapper-0.2.2-py3-none-any.whl (9.9 kB view details)

Uploaded Python 3

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

Hashes for megawrapper-0.2.2.tar.gz
Algorithm Hash digest
SHA256 5b306f1df270fe80077929fcd80ddd8ca0c3bb6a2d2dd7902c6a74f66a0be1a3
MD5 e4e7bf741aa1b551ceff648e140b948d
BLAKE2b-256 76fbb5fae257716ff09768f4de8323fe9f96ca4c24108de3b7db713ac4041d14

See more details on using hashes here.

Provenance

The following attestation bundles were made for megawrapper-0.2.2.tar.gz:

Publisher: publish.yml on vihaanvp/MegaWrapper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for megawrapper-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c4919acdd0f969d8acb5b98520f1175a461edd7f5f91a1095c69c6461e891160
MD5 ea4e749b4b1d846294ef76531d60338c
BLAKE2b-256 952be1a68db512fca5d6daed901036c8b2b0076eaf51a72ad54cc44f83912e3a

See more details on using hashes here.

Provenance

The following attestation bundles were made for megawrapper-0.2.2-py3-none-any.whl:

Publisher: publish.yml on vihaanvp/MegaWrapper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page