This project provides a robust, API-driven system to automate a fume hood sash. It is designed to run on a Raspberry Pi as a set of managed services.
The project is organized into two main components within the src/hood_sash_automation directory:
actuator/: Contains the complete logic for controlling the motorized fume hood sash. It uses multiple Hall effect sensors for precise positioning, a relay for motor control, a current sensor for collision detection, an LCD for status display, and physical buttons for manual control. It exposes an HTTP API for remote commands.sensor/: Contains the logic for a simple, single-point sash position sensor. It exposes an HTTP API to report the current status.
This package is designed to be installed on a Raspberry Pi from a clone of this repository.
- Python 3.7+
- I2C enabled on the Raspberry Pi (
sudo raspi-config) - GPIO and I2C tools installed from Raspberry Pi OS:
sudo apt update sudo apt install -y python3-rpi.gpio i2c-tools
-
Clone the repository to your Raspberry Pi:
git clone https://github.com/AccelerationConsortium/fume-hood-sash-automation.git cd fume-hood-sash-automation -
Create a Python virtual environment and activate it. Use system site packages so the venv can use the OS-provided GPIO library.
python3 -m venv venv --system-site-packages source venv/bin/activate -
Install the project and its dependencies. On an actuator Pi, install the actuator extra. On a sensor Pi, install the sensor extra.
pip install --upgrade pip pip install -e ".[actuator]" # or, for a sensor-only Pi: pip install -e ".[sensor]"
After installation, here's how to get the API service running:
-
Start the API service:
# Make sure you're in the project directory with venv activated hood_sash_automation_actuator -
Test the API (in another terminal):
# Check if the service is running curl http://localhost:5000/status # Move to position 2 curl -X POST http://localhost:5000/move -H "Content-Type: application/json" -d '{"position": 2}'
-
Use the remote control example:
python examples/remote_control_example.py
- Config files live in
src/hood_sash_automation/config. - Use
actuator_config.yamlfor the actuator Pi andsensor_config.yamlfor the sensor Pi. - Review GPIO pins, I2C addresses, movement timeouts, and safety thresholds before deployment.
- The actuator equipment status auto-detects Wi-Fi/LAN IP from
wlan0and Tailscale IP fromtailscale0; config values can override them if needed. - Keep
home_on_startup: falsewhile commissioning so the sash does not move when the service starts. - To use a config outside the package, set
HOOD_SASH_ACTUATOR_CONFIGorHOOD_SASH_SENSOR_CONFIGto the YAML file path.
For the services to run automatically on boot, they should be managed by systemd.
The service files in the systemd/ directory are templates. You must edit them to set the correct User and ensure the WorkingDirectory points to the absolute path of your project directory on the Pi. The services load their default config files from src/hood_sash_automation/config.
Copy the configured service files to the systemd directory and set the correct permissions:
sudo cp systemd/*.service /etc/systemd/system/
sudo chmod 644 /etc/systemd/system/actuator.service
sudo chmod 644 /etc/systemd/system/sensor.serviceReload the systemd daemon to recognize the new files, then enable the services to start on boot:
sudo systemctl daemon-reload
sudo systemctl enable actuator.service
sudo systemctl enable sensor.serviceYou can now either reboot your Pi or start the services manually:
sudo systemctl start actuator.service
sudo systemctl start sensor.serviceVerify the actuator service is enabled, running, and serving the API:
systemctl is-enabled actuator.service
sudo systemctl status actuator.service
curl http://localhost:5000/statusAfter a reboot, run the same checks. From a Tailscale-connected machine, use the Pi's Tailscale IP:
curl http://<pi-tailscale-ip>:5000/statusRun the services through systemd for normal deployment:
sudo systemctl start actuator.service
sudo systemctl start sensor.service
sudo systemctl status actuator.service
sudo systemctl status sensor.serviceUse the Pi's Wi-Fi/LAN IP or Tailscale IP to call the APIs:
- Actuator service:
http://<actuator-pi-ip>:5000 - Sensor service:
http://<sensor-pi-ip>:5005 - Full endpoint reference: API Guide
Quick actuator health check:
curl http://<actuator-pi-ip>:5000/healthThe examples/ directory contains remote_control_example.py, which demonstrates how to control the sash from any computer on the same network.
The API service must be running on your Raspberry Pi first (see Usage above).
- Install Dependencies: The script requires the
requestslibrary.pip install requests
- Configure Host: Open
examples/remote_control_example.pyand change thePI_HOSTvariable to the Wi-Fi/LAN IP or Tailscale IP of your Raspberry Pi. - Run the Script:
python examples/remote_control_example.py
The script will:
- Check if the API service is running
- Move the sash to home position (1)
- Cycle through all positions (2, 3, 4, 5)
- Return to home position
- Display real-time status updates
Successfully connected to the actuator service at http://100.x.y.z:5000
>>> Sending command to move to position 1...
API Response: Moving sash to position 1
[Polling] Current Position: 1, Is Moving: false
Movement finished. Final position: 1
>>> Sending command to move to position 2...
API Response: Moving sash to position 2
[Polling] Current Position: 1, Is Moving: true
[Polling] Current Position: 2, Is Moving: false
Movement finished. Final position: 2
Sequence complete.
Use Docker tests for local logic checks and device tests on the Raspberry Pi before moving hardware.
- Docker testing guide: tests/docker-test/Docker_Test.md
- Device testing guide: tests/device-test/Device_Test.md
Common commands:
# Local mocked tests
./tests/docker-test/scripts/setup_local_only.sh
./tests/docker-test/scripts/test_local.sh integration
# Pi smoke/API tests
cd ~/fume-hood-sash-automation
source venv/bin/activate
sudo systemctl stop actuator.service
python tests/device-test/smoke_tests.py --component actuator
sudo systemctl start actuator.service
python tests/device-test/api_service_test.py --service actuator- Raspberry Pi (Zero 2W, 3B+, 4, etc.)
- Digital Hall Effect Sensors
- DC Motor Linear Actuator (for actuator)
- 2-Channel Relay Board (for actuator)
- INA219 Current Sensor (for actuator)
- DFR0997 LCD Display (for actuator, optional)
- Physical Push Buttons (for actuator, optional)
- GPIO pin numbers use the BCM numbering scheme.
- The
actuatorandsensorcomponents are generally designed for separate devices but can be run on the same Raspberry Pi if needed.