
Lcd dsi
Novin3dp/7inch-hdmi-screen
این برد دولایه (۶۸×۴۲ میلیمتر) همان پنل ۷ اینچ AT070TN92 و تاچ GT915 را این بار از پورت DSI رزبریپای راه میاندازد. نسخهی HDMI در پوشهی hardware/ دستنخورده باقی مانده است.

Full-Stack Embedded System Wearable
Pulsepatch is an open-source printed circuit board by suhaant, from the suhaant/Amethyst repository on GitHub. It is a 4-layer board of 30 × 40 mm with 90 parts on 65 nets, routed with 873 tracks and 155 vias.
It is built around the MDBT42Q-512KV2, AD8603AUJ and DRV8837DSG, with the TPS61040DBV, TPS61165DBV and 74LVC1G08Z among its other parts. Its parts include 26 capacitors, 20 resistors, 12 ICs, 9 diodes and 3 inductors. It belongs with the wearables boards and the nRF52 and nRF5x boards of this library.
A wearable patch that senses infection before you can see it, scores the risk with an ML model, has an AI agent check the evidence, and treats with low-frequency ultrasound and 405 nm violet light.
Watch the 40-second film · How it works · Quick start · The math · Safety
60% of diabetic foot ulcers become infected, and 15–20% of diabetic foot infections end in amputation. Nerve damage removes pain, the body's warning sign, so infection often goes unnoticed until it's visible, and by then it's serious.
The early signs are measurable long before that. Infected wounds turn alkaline (healthy wounds sit at pH 4–6; infected ones at 7.5–9), get warmer and wetter, and bacteria use up the glucose in wound fluid. Amethyst watches for exactly those changes.
Sources: Diabetes Care; Nussbaum et al., Value in Health 2018. More in hardware/research/.
flowchart LR
P["Amethyst patch<br/>pH · moisture · 3× temp"] -->|"BLE, every 30 min"| S
C["CGM<br/>blood glucose"] --> S
S["FastAPI server<br/>POST /api/readings"] --> A{{"Gemini agent"}}
A -->|tool| M["XGBoost model<br/>risk = likelihood × severity"]
A -->|tool| D["Dosing engine<br/>tiers + safety caps"]
A --> F["Notes, fact-checked<br/>in code"]
S --> App["Expo app<br/>alert · therapy · trends"]
S --> DB[("Databricks<br/>care record + dashboard")]
D -->|"therapy command"| PValidated leave-one-person-out (16 folds): every person is scored by a model that never saw their data.
| Random forest | XGBoost (shipped) | |
|---|---|---|
| AUC | 0.976 | 0.978 |
| Brier skill score | 0.834 | 0.845 |
| Infected wounds detected | 100% | 100% |
| Median hours from onset to alarm | 30.3 | 27.2 |
| False alarms, clean wounds | 0.3% | 2.1% |
| Model size | 11.9 MB | 3.1 MB |
| Time per prediction | 12.4 ms | 0.14 ms |
We shipped XGBoost: it alarms 3.1 h earlier and is 3.8× smaller and 89× faster, which matters on a wearable. The extra false alarms are absorbed by risk smoothing and the agent's review.
Which sensors matter most (AUC of each sensor on its own): moisture 0.952 · temperature 0.933 · pH 0.917 · wound glucose 0.886 · blood glucose 0.650 · pH + temp + moisture together 0.976.
All results are on simulated data (see limits). The full method is in
docs/ml-pipeline.md.
Training data. No public dataset of continuous wound-sensor readings with infection labels exists, so we simulated one from 30+ published studies and real Dexcom glucose traces from 16 people (PhysioNet):
$$600 \text{ wounds} \times 14 \text{ days} \times 48 \text{ readings/day} = 403{,}200 \text{ labelled readings}$$
Features. 5 signals × (6 h median, change vs. day-1 baseline, 6 h change, 24 h change, 24 h std) + 2 time-of-day terms = 27 features.
Risk = likelihood × severity. Trained on cleanly separated data, the classifier is near-certain for any sustained shift. So we scale its probability by how far the signs have actually moved toward a full infection:
$$p = P(\text{warning}) + P(\text{infection})$$
$$s = \text{mean of the 3 largest of } \left\lbrace \frac{\Delta \text{pH}}{0.65},\ \ \frac{\Delta T}{1.6^{\circ}\text{C}},\ \ \frac{-\Delta \ln Z}{-\ln 0.65},\ \ \frac{-\Delta g / g_0}{0.40}\right\rbrace$$
Each Δ is a 2 h median minus the patient's day-1 baseline. The denominators are a full infection's average effect in the simulator: pH +0.65, temperature +1.6 °C, impedance −35%, wound glucose −40%. Each term is clipped to [0, 1.25] and s to [0, 1]. Using the top 3 of 4 means a wound whose pH doesn't rise, which happens in real infections, still scores. The score is then smoothed so one noisy reading can't trigger treatment (τ = 3 h, Δt = 0.5 h):
$$R_t = R_{t-1} + \alpha(100 p_t s_t - R_{t-1}), \qquad \alpha = \frac{0.5}{3 + 0.5} \approx 0.143$$
Tiers use 10-point hysteresis: each is entered at its threshold and left only 10 points below it, so the device doesn't flicker.
| Tier | Enter at | Therapy each 8 h session (3/day) |
|---|---|---|
| 0 · Monitor | — | 1.5 MHz healing ultrasound, 6.7 min (20 min/day ÷ 3) |
| 1 · Watch | 30 | Healing ultrasound + closer monitoring |
| 2 · Treat | 55 | Ultrasound to break biofilm → 405 nm light |
| 3 · Intensive | 80 | Same, scaled up toward the caps |
Light dose (treat tier and above) at 10 mW/cm², with the 36 J/cm² daily cap split over 3 sessions:
$$x = \text{clip}\left(\frac{R - 30}{60}, 0, 1\right), \qquad E = 12x \ \text{J/cm}^2, \qquad t = \frac{E}{0.010 \ \text{W/cm}^2}$$
Ultrasound (treat tier and above), run before the light:
$$y = \text{clip}\left(\frac{R - 55}{35}, 0, 1\right), \qquad t_{\text{US}} = \max(4,\ 10y) \ \text{min}, \qquad I = 0.1 + 0.4y \ \text{W/cm}^2$$
| Risk R | Light | Ultrasound |
|---|---|---|
| 55 (enters treat) | 5 J/cm² → 8.3 min | 4 min at 0.10 W/cm² |
| 72.5 | 8.5 J/cm² → 14.2 min | 5 min at 0.30 W/cm² |
| 100 | 12 J/cm² → 20 min (3 × 12 = 36 J/cm²/day cap) | 10 min at 0.50 W/cm² |
wound_agent/ wraps the model and dosing in three tools: get_sensor_history → predict_infection → plan_treatment. The LLM writes structured notes: summary, trend, reasoning, data_quality_flags, conflicting_signals, recommend_clinician_review and confidence.
GEMINI_MODEL=gemini-3.1-pro-preview with GEMINI_THINKING=high gives maximum care. OpenRouter and Claude Opus also work (AGENT_PROVIDER=gemini|openrouter|claude).

A reusable 30 × 40 mm, 4-layer pod that clips onto a disposable hydrogel pad. Full spec →
| Block | Parts |
|---|---|
| Radio + MCU | Raytac MDBT42Q (nRF52832), Bluetooth LE |
| Temperature | 3× TMP117: wound edge, reference skin, ambient |
| Moisture | 1 kHz square wave through a 47 kΩ reference into the pad electrodes, read as impedance (no dedicated chip) |
| pH | AD8603 buffer on the working electrode |
| Light | 6× 405 nm LEDs, TPS61165 constant-current boost, PWM dimming |
| Ultrasound | 15 mm 30 kHz piezo disc, TPS61040 boost (5–10 V) + DRV8837 H-bridge + 4.7 mH resonant inductor |
| Power | Single LiPo, MCP73831 charger, AP2112K 3.3 V regulator |
| Extras | Pad-ID resistor, button for a daily pain/odour check-in, SWD debug pads |
Generated, not drawn. One Python file (design.py) generates the schematic, places every part, autoroutes all 178 connections and runs KiCad's electrical and design-rule checks in one command.
Power and heat budget (details):
| Layer | What it enforces |
|---|---|
1 · Software (risk_to_dose.py) | Dose caps, tier hysteresis, no therapy when impedance > 150 kΩ (patch lifted) |
2 · Firmware (firmware/) | The same caps again, whatever the phone asks: 10 mW/cm², 36 J/cm²/day, 10 min of pulsed ultrasound (500 ms on / off), stop at 41 °C, and no session without a pad attached and on the skin, a working wound sensor, and battery > 3.5 V |
| 3 · Hardware | Every TMP117 alert pin feeds AND gates on the light and ultrasound enables. At 42 °C, therapy cuts out even if the firmware has crashed |
Python 3.12+ (Adam's pinned numpy 2.5 and xgboost 3.4 need it).
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env # add GEMINI_API_KEY (or OPENROUTER_ / ANTHROPIC_API_KEY)Run the agent on a simulated wound:
python main.py -v --scenario infected # healthy | early_infection | infected | sensor_fault | patch_lifted
python main.py --history sample_data/simulated_wound_history.csv
python main.py --offline # model + dosing only, no LLMLive demo + hardware API (then open http://localhost:8000):
python demo_ui/server.py
python demo_ui/send_reading.py --scenario infection --count 8 --every 3 # pretend to be the patch| Endpoint | What |
|---|---|
POST /api/readings | One patch reading in → risk, tier and therapy plan out |
GET /api/state | Latest assessment (the app polls this) |
GET /api/events | Server-sent events for every pipeline step |
POST /api/reset | New patient with a fresh 24 h baseline |
GET /docs | Interactive API docs |
Phone app (Expo Go):
cd app && npm install && npx expo start # add --tunnel on campus Wi-FiFirmware tests (simulated board) and board build (KiCad 10):
cd firmware && make test && make arm-check
cd hardware/kicad && ./build.sh # about 6 min with autorouting; --no-route for secondsDatabricks care record (landing from the databricks branch; design in docs/superpowers/specs/):
python main.py --databricks # readings + assessments to Databricks, care-team dashboardFilm:
cd remotion && npm install && npm run devTests:
python -m pytest| Path | What |
|---|---|
wound_agent/ · main.py | AI agent: tools, prompts, providers, fact check, CLI |
predict.py · risk_to_dose.py · model/ | Trained XGBoost model, risk score, dosing engine |
generate_data.py · train_*.py · compare_models.py | Simulator, training, RF vs. XGBoost, validation (write-up) |
research/ · hardware/research/ | Literature values for every simulator parameter, signal and dose, with sources |
demo_ui/ | FastAPI server, hardware API, animated live demo |
app/ | Expo companion app: Pair, Home, Alert, Therapy, Trends |
hardware/ · firmware/ | KiCad board generator + board, C firmware with Zephyr port |
remotion/ | Demo film and brand assets |
tests/ | Pipeline tests: scenarios, tiers, dose caps, interlock |
Built at WolfHacks 2026 by:
Glucose data: BIG IDEAs Lab Glycemic Variability and Wearable Device Data v1.1.3, PhysioNet, ODC-By 1.0.
| Qty | Value | Footprint | References |
|---|---|---|---|
| 10 | 100n | Capacitor_SMD:C_0402_1005Metric | C5, C7, C8, C9, C10, C12, C15, C16, C17, C26 |
| 6 | 100k | Resistor_SMD:R_0402_1005Metric | R9, R10, R12, R13, R17, R20 |
| 6 | 405nm | LED_SMD:LED_Cree-XP | D2, D3, D4, D5, D6, D7 |
| 5 | 1u | Capacitor_SMD:C_0402_1005Metric | C3, C4, C11, C14, C24 |
| 4 | 4.7u | Capacitor_SMD:C_0603_1608Metric | C1, C2, C18, C21 |
| 3 | 10k | Resistor_SMD:R_0402_1005Metric | R6, R8, R11 |
| 3 | 1M | Resistor_SMD:R_0402_1005Metric | R2, R3, R15 |
| 3 | 4.7k | Resistor_SMD:R_0402_1005Metric | R1, R4, R5 |
| 3 | GND | TestPoint:TestPoint_Pad_1.5x1.5mm | TP2, TP4, TP11 |
| 3 | TMP117 | Package_SON:WSON-6-1EP_2x2mm_P0.65mm_EP1x1.6mm | U4, U5, U6 |
| 2 | 10u | Inductor_SMD:L_Taiyo-Yuden_NR-30xx | L1, L2 |
| 2 | 74LVC1G08 | Package_TO_SOT_SMD:SOT-23-5 | U8, U9 |
| 2 | GND | TestPoint:TestPoint_Pad_2.0x2.0mm | TP16, TP19 |
| 2 | MBR0540 | Diode_SMD:D_SOD-123 | D1, D8 |
| 1 | +3V3 | TestPoint:TestPoint_Pad_1.5x1.5mm | TP10 |
| 1 | +3V3 | TestPoint:TestPoint_Pad_2.0x2.0mm | TP18 |
| 1 | 100n 25V | Capacitor_SMD:C_0402_1005Metric | C25 |
| 1 | 100p | Capacitor_SMD:C_0402_1005Metric | C13 |
| 1 | 10R | Resistor_SMD:R_0402_1005Metric | R14 |
| 1 | 10u | Capacitor_SMD:C_0603_1608Metric | C6 |
| 1 | 180k | Resistor_SMD:R_0402_1005Metric | R16 |
| 1 | 1k | Resistor_SMD:R_0402_1005Metric | R19 |
| 1 | 1u 50V | Capacitor_SMD:C_0805_2012Metric | C19 |
| 1 | 220n | Capacitor_SMD:C_0402_1005Metric | C20 |
| 1 | 22p | Capacitor_SMD:C_0402_1005Metric | C23 |
| 1 | 4.7m | Inductor_SMD:L_6.3x6.3_H3 | L3 |
| 1 | 4.7u 25V | Capacitor_SMD:C_0805_2012Metric | C22 |
| 1 | 47k 1% | Resistor_SMD:R_0402_1005Metric | R7 |
| 1 | 560k | Resistor_SMD:R_0402_1005Metric | R18 |
| 1 | AD8603 | Package_TO_SOT_SMD:TSOT-23-5 | U7 |
| 1 | AP2112K-3.3 | Package_TO_SOT_SMD:SOT-23-5 | U2 |
| 1 | DRV8837 | Package_SON:WSON-8-1EP_2x2mm_P0.5mm_EP0.9x1.6mm | U12 |
| 1 | MCP73831 | Package_TO_SOT_SMD:SOT-23-5 | U1 |
| 1 | MDBT42Q-512K | RF_Module:Raytac_MDBT42Q | U3 |
| 1 | MOIST_1 | TestPoint:TestPoint_Pad_2.0x2.0mm | TP14 |
| 1 | PAD_AUX | TestPoint:TestPoint_Pad_2.0x2.0mm | TP15 |
| 1 | PAD_ID | TestPoint:TestPoint_Pad_2.0x2.0mm | TP17 |
| 1 | PH_REF | TestPoint:TestPoint_Pad_2.0x2.0mm | TP13 |
| 1 | PH_WE | TestPoint:TestPoint_Pad_2.0x2.0mm | TP12 |
| 1 | PIEZO_A | TestPoint:TestPoint_Pad_1.5x1.5mm | TP5 |
| 1 | PTS810 | Button_Switch_SMD:SW_SPST_PTS810 | SW1 |
| 1 | RESET_N | TestPoint:TestPoint_Pad_1.5x1.5mm | TP9 |
| 1 | SWDCLK | TestPoint:TestPoint_Pad_1.5x1.5mm | TP8 |
| 1 | SWDIO | TestPoint:TestPoint_Pad_1.5x1.5mm | TP7 |
| 1 | TPS61040 | Package_TO_SOT_SMD:SOT-23-5 | U11 |
| 1 | TPS61165 | Package_SON:WSON-6-1EP_2x2mm_P0.65mm_EP1x1.6mm | U10 |
| 1 | US_OUT2 | TestPoint:TestPoint_Pad_1.5x1.5mm | TP6 |
| 1 | VBAT | TestPoint:TestPoint_Pad_1.5x1.5mm | TP3 |
| 1 | VCHG | TestPoint:TestPoint_Pad_1.5x1.5mm | TP1 |
| 1 | status | LED_SMD:LED_0603_1608Metric | D9 |
It measures 30 × 40 mm and has 4 copper layers, 0.8 mm thick.
90 parts, built around the MDBT42Q-512KV2, AD8603AUJ, DRV8837DSG and TPS61040DBV. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the suhaant/Amethyst repository on GitHub, at the commit this page was made from: the board is hardware/kicad/pulsepatch/pulsepatch.kicad_pcb and its schematic hardware/kicad/pulsepatch/pulsepatch.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask suhaant before reusing the design.

Novin3dp/7inch-hdmi-screen
این برد دولایه (۶۸×۴۲ میلیمتر) همان پنل ۷ اینچ AT070TN92 و تاچ GT915 را این بار از پورت DSI رزبریپای راه میاندازد. نسخهی HDMI در پوشهی hardware/ دستنخورده باقی مانده است.






