High-Level Embedded Python Library for declarative hardware programming
Project description
BitBound – High-Level Embedded Python Library
Hardware abstraction for MicroPython that makes embedded development as simple as working with modern web APIs.
🎯 Vision
MicroPython is excellent, but complex hardware interactions often require deep knowledge of bus protocols and register configurations. BitBound abstracts hardware components (sensors, motors, displays) with a modern, declarative API—similar to how web frameworks abstract HTTP.
from bitbound import Hardware
# Create hardware manager
hardware = Hardware()
# Attach devices with simple, declarative syntax
sensor = hardware.attach("I2C", type="BME280")
fan = hardware.attach("GPIO", type="Relay", pin=5)
# Use threshold-based events instead of polling loops
sensor.on_threshold("temperature > 25°C", lambda e: fan.on())
sensor.on_threshold("temperature < 23°C", lambda e: fan.off())
# Read values naturally
print(f"Temperature: {sensor.temperature}°C")
print(f"Humidity: {sensor.humidity}%")
print(f"Pressure: {sensor.pressure} hPa")
# Run the event loop
hardware.run()
✨ Features
- Declarative Hardware Attachment: No more manual register configuration
- Natural Unit Expressions:
"temperature > 25°C","pressure < 1000hPa" - Event-Driven Programming: Threshold callbacks, change detection, interval events
- Simulation Mode: Develop and test without physical hardware
- Wide Device Support: Sensors, actuators, displays
- Cross-Platform: Works on MicroPython, CircuitPython, and standard Python
📦 Installation
Standard Python (for development/simulation)
pip install bitbound
MicroPython
Copy the bitbound folder to your device's filesystem:
mpremote cp -r bitbound :
🚀 Quick Start
Basic Sensor Reading
from bitbound import Hardware
hw = Hardware()
# BME280 temperature/humidity/pressure sensor
sensor = hw.attach("I2C", type="BME280")
# Read all values
data = sensor.read_all()
print(f"Temperature: {data['temperature']}°C")
print(f"Humidity: {data['humidity']}%")
print(f"Pressure: {data['pressure']} hPa")
print(f"Altitude: {data['altitude']} m")
LED Control
from bitbound import Hardware
hw = Hardware()
# Simple LED
led = hw.attach("GPIO", type="LED", pin=2)
led.on()
led.off()
led.blink(times=5)
# RGB LED
rgb = hw.attach("GPIO", type="RGB", pins={"r": 12, "g": 13, "b": 14})
rgb.color = (255, 0, 0) # Red
rgb.color = "#00FF00" # Green (hex)
rgb.color = "blue" # Named color
Motor Control
from bitbound import Hardware
hw = Hardware()
# DC Motor with H-Bridge
motor = hw.attach("GPIO", type="DCMotor",
enable_pin=5, in1_pin=6, in2_pin=7)
motor.forward(speed=75) # 75% speed
motor.backward(speed=50)
motor.stop()
# Servo Motor
servo = hw.attach("GPIO", type="Servo", pin=15)
servo.angle = 90 # Move to 90 degrees
servo.sweep(0, 180) # Sweep from 0 to 180
Display Output
from bitbound import Hardware
hw = Hardware()
# Character LCD
lcd = hw.attach("I2C", type="LCD1602")
lcd.write("Hello World!")
lcd.write("Line 2", y=1)
# OLED Display
oled = hw.attach("I2C", type="SSD1306")
oled.text("BitBound", 0, 0)
oled.line(0, 10, 127, 10)
oled.show()
Event-Driven Programming
from bitbound import Hardware
hw = Hardware()
sensor = hw.attach("I2C", type="BME280")
fan = hw.attach("GPIO", type="Relay", pin=5)
led = hw.attach("GPIO", type="LED", pin=2)
buzzer = hw.attach("GPIO", type="Buzzer", pin=15)
# Temperature thresholds
sensor.on_threshold("temperature > 30°C", lambda e: (
fan.on(),
buzzer.beep()
))
sensor.on_threshold("temperature < 25°C", lambda e: fan.off())
# Humidity alert
sensor.on_threshold("humidity > 80%", lambda e: led.blink(3))
# Value change detection
sensor.on_change("temperature", lambda e:
print(f"Temp changed: {e.old_value} -> {e.new_value}")
)
# Run event loop
hw.run()
Complex Expressions
# Compound conditions
sensor.on_threshold(
"temperature > 25°C AND humidity < 40%",
lambda e: humidifier.on()
)
# Range check
sensor.on_threshold(
"temperature BETWEEN 20°C AND 25°C",
lambda e: print("Optimal temperature!")
)
# Pressure monitoring
sensor.on_threshold(
"pressure < 1000hPa OR pressure > 1030hPa",
lambda e: alert()
)
📖 Supported Devices
Sensors
| Device | Bus | Properties |
|---|---|---|
| BME280/BMP280 | I2C | temperature, humidity, pressure, altitude |
| DHT11/DHT22 | GPIO | temperature, humidity |
| DS18B20 | OneWire | temperature |
| BH1750 | I2C | lux |
| MPU6050 | I2C | acceleration, gyroscope, temperature |
| PIR | GPIO | motion |
| Analog | ADC | value, voltage, percent |
Actuators
| Device | Bus | Methods |
|---|---|---|
| Relay | GPIO | on(), off(), toggle() |
| LED | GPIO | on(), off(), blink() |
| RGB LED | GPIO | color property |
| NeoPixel | GPIO | fill(), pixel[], rainbow() |
| DC Motor | GPIO | forward(), backward(), stop() |
| Servo | GPIO | angle property, sweep() |
| Stepper | GPIO | step(), rotate() |
| Buzzer | GPIO | beep(), tone(), melody() |
Displays
| Device | Bus | Methods |
|---|---|---|
| LCD1602/LCD2004 | I2C | write(), clear(), backlight |
| SSD1306 OLED | I2C | text(), line(), rect(), pixel() |
| 7-Segment | GPIO | digit(), number() |
🔧 Configuration
Custom Pin Configuration
hw = Hardware()
# I2C with custom pins
sensor = hw.attach("I2C", type="BME280", scl=22, sda=21, freq=400000)
# SPI with all pins specified
device = hw.attach("SPI", type="...", sck=18, mosi=23, miso=19, cs=5)
# UART with custom settings
gps = hw.attach("UART", type="...", tx=17, rx=16, baudrate=9600)
Device Discovery
hw = Hardware()
# Scan I2C bus
addresses = hw.scan("I2C")
print(f"Found devices at: {[hex(a) for a in addresses]}")
# Auto-discover devices
discovered = hw.discover()
for category, devices in discovered.items():
print(f"{category}: {devices}")
🧪 Simulation Mode
BitBound automatically runs in simulation mode when no hardware is detected. This allows development and testing on any computer:
from bitbound import Hardware
# Simulation mode is automatic on desktop
hw = Hardware()
# All devices work in simulation
sensor = hw.attach("I2C", type="BME280")
print(sensor.temperature) # Returns simulated value: 23.5
led = hw.attach("GPIO", type="LED", pin=2)
led.on() # Works without hardware
🔌 Unit System
BitBound understands physical units:
from bitbound.units import parse_value, convert
# Parse values with units
value, unit = parse_value("25°C")
print(unit.to_si()) # 298.15 (Kelvin)
# Convert between units
celsius = convert(77, "°F", "°C") # 25.0
Supported units:
- Temperature: °C, °F, K
- Pressure: Pa, hPa, kPa, bar, mbar, psi, atm
- Humidity: %, RH, %RH
- Length: mm, cm, m, km, in, ft
- Time: ms, s, min, h
- Electrical: V, mV, A, mA, µA, W, Ω, kΩ, MΩ
- Light: lux, lx
- Frequency: Hz, kHz, MHz
📁 Project Structure
bitbound/
├── __init__.py # Main exports
├── hardware.py # Hardware manager
├── device.py # Device base classes
├── event.py # Event system
├── expression.py # Expression parser
├── units.py # Unit handling
├── buses/
│ ├── base.py # Bus abstraction
│ ├── i2c.py # I2C implementation
│ ├── spi.py # SPI implementation
│ ├── gpio.py # GPIO implementation
│ ├── uart.py # UART implementation
│ └── onewire.py # OneWire implementation
└── devices/
├── sensors/ # Sensor implementations
├── actuators/ # Actuator implementations
└── displays/ # Display implementations
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
MIT License - see LICENSE for details.
🙏 Acknowledgments
- Inspired by modern web frameworks and their declarative approaches
- Built on top of the excellent MicroPython/CircuitPython ecosystems
- Thanks to all the open-source hardware driver contributors
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 bitbound-0.1.0.tar.gz.
File metadata
- Download URL: bitbound-0.1.0.tar.gz
- Upload date:
- Size: 52.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b85daab67412b4ad0497e105fac570e13d3216e89fc4838b00e6f191e315a503
|
|
| MD5 |
913e885b9a193aba3f2db1f0e1db67a8
|
|
| BLAKE2b-256 |
5a71d66b3e8ef1e163e0c76e375eb7bf671773e5b4d95d1a99ff6d0b466204ad
|
File details
Details for the file bitbound-0.1.0-py3-none-any.whl.
File metadata
- Download URL: bitbound-0.1.0-py3-none-any.whl
- Upload date:
- Size: 59.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ca1a92271da5b93b1a1661874a19a9ec996bf276524af7e1ff1b798ded1bd63c
|
|
| MD5 |
8b97f001273dc6bb004edb22edbcf3bd
|
|
| BLAKE2b-256 |
1bcff0ca9704b961b37b332657f1bca4f674d947e34e935b7d2e3b72cedd07d4
|