L.I.P.S. is an open-source assistive device that lets people with limited hand or arm mobility control a computer using sip and puff breath pressure combined with a mini analog joystick. It plugs in over USB and presents itself as a standard keyboard and mouse — no drivers, no software installation, works on any operating system.
USB VID/PID notice: The Vendor ID and Product ID used in this project are temporary placeholders pending official registration with pid.codes.
L.I.P.S. was designed for people who cannot use a conventional keyboard or mouse. The device reads breath pressure through a silicone mouthpiece, maps each sip and puff gesture to a configurable action (key press, mouse click, or scroll), and maps joystick movement to the mouse cursor.
Everything is configurable without re-flashing. A web app connects to the device over USB serial and lets you change what each sensor does — no code editing required.
Key properties:
- Plug-and-play USB — enumerates as HID Keyboard + HID Mouse + CDC Serial
- 1 or 2 breath pressure sensors depending on variant
- Analog joystick for cursor control with automatic calibration
- Mouse sensitivity, scroll speed, and joystick calibration saved to EEPROM
- Fully open-source hardware and firmware (CC BY-NC-SA 4.0)
- Input — Breath
- 1 or 2 MPXV7002DP differential pressure sensors
- Each sensor connected to the mouthpiece via silicone tubing
- Analog voltage output read directly by the CH552 ADC
- Input — Joystick
- 2-axis analog joystick
- Output wipers read by CH552 ADC
- Center position calibrated automatically on first boot
- Control Core
- CH552G microcontroller (8051 core, native USB engine)
- Firmware in Arduino (CH55xDuino framework)
-
Output
- USB HID Keyboard — key presses, modifier combos
- USB HID Mouse — left/right/middle click, cursor movement, scroll
- USB CDC Serial — configuration protocol for the web configurator
-
Non-Volatile Storage
- CH552 internal EEPROM — mouse speed, scroll speed, joystick calibration ranges
| Parameter | Value |
|---|---|
| Core | 8051, 24 MHz |
| Package | SOP-16 |
| Supply | 3.3 V (internal LDO from 5 V USB) |
| USB | Native full-speed USB engine |
| ADC | 6 channels, 8-bit |
| Non-volatile | 128-byte EEPROM |
The CH552G was chosen for its native USB hardware (no external USB chip needed) and good Arduino ecosystem support via the CH55xDuino framework.
Each breath input uses an MPXV7002DP differential pressure sensor:
- Differential range: −2 to +2 kPa
- Output at rest: ~2.5 V (equal pressure on both ports)
- Puff (pressure into port A): output rises above 2.5 V
- Sip (suction at port A): output falls below 2.5 V
- The firmware auto-baselines on every boot — no manual zero needed
Each sensor is decoupled with a 100 nF capacitor on the supply pin. Port B is left open to atmosphere.
A 2-axis hall effect joystick with center detent:
- Powered from the CH552's 3.3 V rail — the hall effect output range is referenced to its supply, which matches the CH552 ADC reference (also 3.3 V)
- Axis outputs connected directly to CH552 ADC pins
- Calibration is automatic: on first boot the firmware measures the center position over ~1.5 seconds. Calibration is saved to EEPROM and survives power cycles.
- To recalibrate: hold both sensors active simultaneously for 3 seconds, or send command
Rover the serial protocol
Pin layout (viewed from the front, stem pointing up): each potentiometer has three legs — GND, SIG, VCC.
| Parameter | Value |
|---|---|
| Connector | USB-C (16-pin SMD) |
| ESD protection | USBLC6-2SC6 |
| VID | 0x1209 (temporary — see notice at top) |
| PID (Single) | 0xC55B (temporary) |
| PID (Dual) | 0xC55C (temporary) |
| PID (Plus) | 0xC55D (temporary) |
| USB class | Composite: HID Keyboard + HID Mouse + CDC Serial |
USB-C CC pins use 5.1 kΩ pull-down resistors — no power-delivery negotiation needed, works with any standard USB-C cable.
The PCB was designed in KiCad. There are several revisions in this repo:
- V3.x — uses accessible, easy-to-source components. All V3 revisions share the same circuit; they differ only in layout and which variant they target. These are the recommended versions for building.
A standard 2-layer PCB ordered as-is from any fab house is all that's needed to run the device — no special stackup, no impedance control, no additional components. The board is powered entirely over USB; no external power supply or charger is required.
The current V3.x revisions include Castellated holes, which make soldering easier but increase the PCB fabrication cost slightly. They can be removed from the design without affecting functionality if you want to reduce cost.
Each PCB revision includes an interactive BOM (bom/ibom.html) inside its folder — open it in a browser to see component placement and reference designators before ordering or assembling.
Production files (gerbers, BOM, pick-and-place positions, and IPC netlist) are ready to upload directly to your fab house:
| Revision | Gerbers | BOM | Positions | Netlist |
|---|---|---|---|---|
| V3 | gerber.zip | BOM.csv | positions.csv | netlist.ipc |
| V3.1 | gerber.zip | BOM.csv | positions.csv | netlist.ipc |
| V3.2 | gerber.zip | BOM.csv | positions.csv | netlist.ipc |
Three firmware variants exist. Choose the one that matches your PCB revision:
| Variant | Sensors | Sketch | USB PID |
|---|---|---|---|
| SINGLE | 1 | code/1sensor/1sensor.ino |
0xC55B |
| DUAL | 2 | code/dualVariant/dualVariant.ino |
0xC55C |
| PLUS | 2 | code/plusVariant/plusVariant.ino |
0xC55D |
SINGLE and DUAL/PLUS differ in which CH552 pins are used for sensors. DUAL and PLUS have identical behavior but a rotated pin layout to match different PCB orientations.
- The CH552 enumerates over USB as a composite HID Keyboard + HID Mouse + CDC Serial device.
- On every boot the firmware reads the pressure sensors for ~1 second to establish a baseline. Keep the mouthpiece unpressurized during this time.
- Joystick ADC values are mapped to mouse cursor movement using the stored calibration range.
- Each pressure reading is compared against a threshold above/below baseline to detect a puff or sip. The action triggered is loaded from EEPROM.
- The CDC serial channel runs a small command protocol (
docs/PROTOCOL.md) that the web configurator uses to read and write settings without re-flashing.
The following are stored in the CH552's internal EEPROM and survive power cycles and firmware re-flashes:
- Mouse cursor speed
- Scroll speed
- Joystick calibration (center point, axis ranges)
Sensor action assignments (what each sip/puff does) are configured via the web tool and stored as well. On a blank device defaults are: puff → left click, sip → right click.
The enclosure is 3D printed and split into three parts: a head (holds the mouthpiece), a top lid, and a bottom lid. STL files are organised per variant:
| Variant | Folder |
|---|---|
| SINGLE | enclosure/1sensor/ |
| DUAL | enclosure/dualVariant/ |
| PLUS | enclosure/plusVariant/ |
Material: Both PLA and RESIGN have been tested and work. Use whatever you have available.
Print settings: The values below are examples — infill percentage, wall count, and similar settings have no meaningful impact on function since this is a shell with no structural loads.
| Setting | Example value |
|---|---|
| Layer height | 0.2 mm |
| Walls | 3 perimeters |
| Infill | 15–25% |
| Supports | Only where needed |
The mouthpiece channel may need to be cleared with a 3 mm drill bit if your printer leaves sag in the bridge.
For hand-soldering the PCB from bare board, see
docs/PCB_SOLDERING.mdfirst. The steps below assume the PCB is already fully assembled.
Cut wires at least 3–5 cm long and strip the ends. Solder the wires to the joystick first, then position it inside the case and route the wires to the PCB pads — adjusting length and orientation as you go before committing to the PCB solder joint. The final wire run from joystick to PCB should end up no more than ~1.5 cm once everything is seated. VCC and GND must be connected correctly. The signal lines (X and Y axes) can be swapped in software, so wire them however is most convenient given your layout.
The joystick has two axes, so there are two GND pins and two VCC pins — but they are the same net. Bridge the two GND legs together and the two VCC legs together at the joystick, so only one GND wire and one VCC wire need to run to the PCB.
Do not put the case on yet. Flash the firmware (see Section 8) and verify that:
- The device enumerates over USB
- The joystick moves the cursor
- Sip and puff are detected
Fix any issues now while the board is still accessible.
Take the silicone tube and push it through the sensor hole in the case from the outside, pushing it further in than it needs to go — leave extra length inside.
Insert the PCB into the case by leading with the USB-C connector end. Once the connector is aligned with its cutout, connect the silicone tube to the pressure sensor port.
While pulling the silicone tube back out from the outside of the case (to take up the slack), simultaneously press the PCB toward the case from the inside. Continue until you hear and feel a snap — this is the PCB seating flush against the case walls.
Move the joystick module into its position in the case. Check that it fits — depending on how the case was printed there may be a small amount of material to trim or sand. Once confirmed, apply super glue (cyanoacrylate) to secure it in place and hold for a few seconds until set.
Apply glue to the contact points shown in the image below, align the lid, and hold it in place for a few seconds.
| Component | Notes | Link |
|---|---|---|
| CH552G (SOP-16) | Main microcontroller | |
| MPXV7002DP | Differential pressure sensor | |
| USB-C connector (16-pin SMD) | ||
| 5.1 kΩ resistor × 2 | USB-C CC pull-downs | |
| USBLC6-2SC6 | USB ESD protection | |
| 100 nF capacitor (0603) | Sensor decoupling, one per sensor | |
| Analog joystick module | 2-axis with center detent | |
| Silicone food-grade tubing, 3 mm ID | At least 13 cm per sensor input — cut to fit during assembly | |
| Mouthpiece tip | Food-grade silicone, replaceable | |
| M2 × 6 mm screws × 4 | Enclosure fasteners |
See the interactive BOM in each PCB revision's bom/ibom.html for exact reference designators.
The L.I.P.S. web tool lets you select your device variant, automatically puts the device into bootloader mode, and flashes the correct firmware. It also has a settings page for configuring sensor actions.
Website Here : https://projectlips.me/
One-time setup:
- Install Arduino IDE 2.x: arduino.cc/en/software
- Add the CH55xDuino board package URL under File → Preferences → Additional Boards Manager URLs:
https://raw.githubusercontent.com/DeqingSun/ch55xduino/ch55xduino/package_ch55xduino_mcs51_index.json - Open Tools → Board → Boards Manager, search CH55x, install CH55xDuino.
Board settings:
| Setting | Value |
|---|---|
| Board | CH55x Boards → CH552 |
| USB Settings | USER CODE w/ 266B USB ram |
Entering bootloader mode:
You almost never need to do this manually. A board fresh from the manufacturer enters bootloader mode automatically on its very first plug-in. After that, the configurator's Enter Bootloader button sends a serial command to reset into bootloader without touching the hardware.
- From the configurator (normal method): click Enter Bootloader — the device resets into bootloader automatically over serial.
- Boot pads (debug / emergency only): There is no physical boot button. Instead, the PCB has two exposed pads. To use them: unplug the device, short the two pads together with tweezers or a wire bridge, plug in USB while keeping them shorted, then release. This method is only needed if the firmware has been modified in a way that removes the serial bootloader command.
Uploading: click Upload (→) in Arduino IDE. The port is detected automatically.
For full details see docs/ARDUINO_SETUP.md.
| Path | Contents |
|---|---|
code/ |
Firmware — one Arduino sketch per variant, each with its USB library |
pcb/ |
KiCad schematics, PCB files, iBOM, and production files for each revision |
enclosure/ |
STL files per variant for 3D printing |
configurator.html |
Web tool to enter bootloader mode (Chrome/Edge) |
docs/PCB_SOLDERING.md |
Hand-soldering the PCB |
docs/ARDUINO_SETUP.md |
Compiling and flashing from Arduino source |
docs/PROTOCOL.md |
USB serial protocol spec |
docs/PIN_MAP.md |
CH552 pin assignments and PCB compatibility matrix |
docs/WIRING.md |
Block diagrams and wiring tables |
docs/SCS_ID.md |
How to customize the USB device name |
scripts/ |
Release packaging scripts (bash + PowerShell) |
.github/workflows/ |
CI — compiles firmware and creates release packages |
- Check the USB cable — many USB-C cables are charge-only and carry no data.
- Verify VBUS → 3.3 V with a multimeter. Should read ~3.3 V.
- Inspect USB connector solder joints under magnification.
- Try a different USB port (some hubs are picky).
- Use the configurator's Enter Bootloader button first — this is the normal method and works without touching the hardware.
- If the firmware has been modified and the serial bootloader command no longer works, use the boot pads: unplug, short the two pads on the PCB with tweezers while plugging in, then release.
- Try a different USB cable.
- Confirm the board and USB settings in the IDE match Section 8.
- Trigger a recalibration: hold both sensors simultaneously for 3 seconds, or send
Rover serial. - Check for cold solder joints on the joystick GND legs.
- If drift persists, try increasing the deadzone — raise
#define DEADZONEin the firmware (try8or10).
- Open the serial monitor and check that the raw sensor value actually changes when you breathe.
- Adjust thresholds in firmware:
#define THRESH_PUFF/THRESH_SIP. If the sensor is noisy, raise the absolute values. - Check the silicone tubing for kinks or pinholes — either will dampen the pressure signal.
- Web Serial only works in Chrome or Edge — Firefox and Safari are not supported.
- Make sure no other app (Arduino Serial Monitor, PuTTY, etc.) has the port open.
- Check that the USB VID/PID in the configurator matches the variant you flashed.
Quick index of everything in docs/:
| File | What it's for |
|---|---|
PCB_SOLDERING.md |
Step-by-step hand-soldering guide for the bare PCB |
ARDUINO_SETUP.md |
One-time Arduino IDE setup and manual flashing instructions |
WIRING.md |
Block diagrams and wiring tables for all connections |
PIN_MAP.md |
CH552 pin assignments and which PCB revision uses which pins |
PROTOCOL.md |
USB serial command protocol used by the web configurator |
SCS_ID.md |
How to change the USB device name that appears on your computer |
This project is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0).
You are free to share and adapt the material for non-commercial purposes, provided you give appropriate credit and distribute any adaptations under the same license.