Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions PCB/accelerometer.kicad_sch
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,39 @@
)
)
)
(property "MF" "Samsung Electro-Mechanics"
(at 0 0 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Manufacturer_Part_Number" "CL05B103KB5NNNC"
(at 0 0 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "LCSC" "C15195"
(at 0 0 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects
(font
(size 1.27 1.27)
)
)
)
(pin "1"
(uuid "4956d8c4-1d8d-4074-b8d5-533c8f877953")
)
Expand Down Expand Up @@ -966,6 +999,39 @@
)
)
)
(property "MF" "QST"
(at 0 0 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Manufacturer_Part_Number" "QMA6100P"
(at 0 0 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "LCSC" "C2887190"
(at 0 0 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects
(font
(size 1.27 1.27)
)
)
)
(pin "1"
(uuid "9b3725f0-38d8-4bee-9996-89e125552bda")
)
Expand Down Expand Up @@ -1081,6 +1147,39 @@
)
)
)
(property "MF" "FH (Guangdong Fenghua Advanced Tech)"
(at 0 0 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Manufacturer_Part_Number" "0402CG101J500NT"
(at 0 0 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "LCSC" "C1546"
(at 0 0 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects
(font
(size 1.27 1.27)
)
)
)
(pin "1"
(uuid "0656c962-e0ad-4e0b-a6a7-5b34482a07c7")
)
Expand Down Expand Up @@ -1166,6 +1265,39 @@
)
)
)
(property "MF" "Samsung Electro-Mechanics"
(at 0 0 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Manufacturer_Part_Number" "CL05B222KB5NNNC"
(at 0 0 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "LCSC" "C84703"
(at 0 0 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects
(font
(size 1.27 1.27)
)
)
)
(pin "1"
(uuid "e023ab51-a3c3-4e80-8d55-95a22c72db3e")
)
Expand Down
52 changes: 39 additions & 13 deletions PCB/diagrams/power_control_layout.html

Large diffs are not rendered by default.

20 changes: 12 additions & 8 deletions PCB/diagrams/power_control_layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@

Q_PWR1 carries the entire board's current — every milliamp the ESP32, XBee, OLED, and everything else draws passes through one SOT-23 PMOS. But the layout-driving constraint here isn't electrical at all: SW_PWR1 is a physical button that has to land under a hole in your enclosure.

**Source:** `PCB/power_control.kicad_sch`  ·  **Nets:** VSYS → PWR_EN  ·  **Package:** SOT-23 ×3, SOD-123 ×2
**Source:** `PCB/power_control.kicad_sch`  ·  **Nets:** VSYS → PWR_EN  ·  **Package:** SOT-23 ×3, SOD-123 ×3

## What's on this sheet

A press-to-start, software-held latch: the button turns the board on, the MCU has to grab the hold line before the button is released, and either side of a diode-OR can keep power on. A small transistor inverter (R_INV_BASE1 / Q_INV1 / R_INV_PU1) sits between the button and that diode-OR — see callout F for why it can't just tap the button's sense line directly.
A press-to-start, software-held latch: the button turns the board on, the MCU has to grab the hold line before the button is released, and either side of a diode-OR can keep power on. A small transistor inverter (R_INV_BASE1 / Q_INV1 / R_INV_PU1) sits between the button and that diode-OR — see callout F for why it can't just tap the button's sense line directly, and callout D for why `R_LATCH_G1` is 1MΩ rather than 10kΩ.

| Ref | Value | Footprint | Role |
|---|---|---|---|
| Q_PWR1 | DMG2305UX | SOT-23 | Main power switch — VSYS to PWR_EN, carries full system current |
| R_PWR_EN_PD1 | 100kΩ | 0402 | `PWR_EN` pull-down to GND — the buck's EN pin has no internal bias and must not be left floating (callout G) |
| Q_LATCH1 | 2N7002 | SOT-23 | Pulls Q_PWR1's gate low to turn it on |
| D_OR1 / D_OR2 | 1N4148W | SOD-123 | Diode-OR: `PWR_BTN_TRIGGER` (actual button press, via the inverter) or MCU hold, either one latches power on |
| R_GATE1 | 100kΩ | 0402 | Q_PWR1 gate pull-up — off by default |
| R_LATCH_G1 | 10kΩ | 0402 | Q_LATCH1 gate pull-down — off by default |
| R_LATCH_G1 | 1MΩ | 0402 | Q_LATCH1 gate pull-down — off by default; sized to not starve the diode-OR's drive (callout D) |
| R_BTN_PU1 | 100kΩ | 0402 | Button sense pull-up — MCU reads pressed (0V) vs idle (VSYS) |
| R_INV_BASE1 | 10kΩ | 0402 | Inverter base resistor, from `PWR_BTN_SENSE` |
| R_INV_BASE1 | 100kΩ | 0402 | Dedicated VSYS pull-up for Q_INV1's base — decoupled from `PWR_BTN_SENSE` (callout F) |
| D_INV_ISO1 | BAT54W | SOD-123 | Schottky isolator: lets a press pull Q_INV1's base low without loading `PWR_BTN_SENSE` |
| Q_INV1 | MMBT3904 | SOT-23 | Inverter: idle (button up) holds `PWR_BTN_TRIGGER` low; pressed lets `R_INV_PU1` pull it high |
| R_INV_PU1 | 100kΩ | 0402 | `PWR_BTN_TRIGGER` pull-up to VSYS — the inverter's collector load |
| C_DBNC1 | 100nF | 0402 | Button debounce, right at the switch |
Expand All @@ -43,9 +45,10 @@ Top copper layer. The VSYS→PWR_EN path runs straight across the top as one thi
| **A** | **Q_PWR1 is the one part on this sheet that isn't low-current.** Every downstream milliamp — MCU, XBee, OLED, everything — flows through its source-drain path. DMG2305UX's RDS(on) (~35–50mΩ) keeps drop and heat trivial at this board's current budget, but a SOT-23 has no separate thermal pad — the source/drain copper itself is the heatsink, so give those pads real copper, not just a skinny trace. |
| **B** | **SW_PWR1's position isn't yours to optimize electrically.** It has to land under a hole in whatever enclosure this board sits in — mechanical placement drives this part, and the rest of the latch logic has to route to wherever that ends up, not the other way around. |
| **C** | **C_DBNC1 sits right on the switch's own pins.** Same principle as the charger's pushbutton guidance in its own datasheet: the debounce cap does its job by being close to the contact bounce it's filtering, not by being close to anything else. |
| **D** | **The diode-OR and its pull-down are one compact decision node.** D_OR1, D_OR2, R_LATCH_G1, and Q_LATCH1's gate all meet at PWR_LATCH_G — keeping that cluster tight matters less for noise than for just keeping the logic legible on the board. |
| **D** | **The diode-OR and its pull-down are one compact decision node — and R_LATCH_G1's value is load-bearing, not incidental.** D_OR1, D_OR2, R_LATCH_G1, and Q_LATCH1's gate all meet at PWR_LATCH_G. A press only drives this node through `R_INV_PU1` (100kΩ) and a diode drop — with the original 10kΩ pull-down, that divider left barely 0.3V at Q_LATCH1's gate, nowhere near enough to turn it on. Raised to 1MΩ, the same divider delivers ~2.4–3.1V across the battery's usable range, without adding any idle current (that's set by `R_INV_PU1`, untouched). Keeping this cluster tight matters less for noise than for just keeping the logic legible on the board. |
| **E** | **PWR_HOLD arriving late is a hard failure, not a glitch.** Per this project's own GPIO notes, pin 36 (PWR_HOLD) must go high as the MCU's very first instruction — release the button before that happens and R_LATCH_G1's pull-down turns everything back off. Not a layout fix, but it's the reason D_OR2's path exists at all. |
| **F** | **D_OR1 can't read `PWR_BTN_SENSE` directly — found the hard way, on real hardware.** The original design had `R_BTN_PU1` (to VSYS) and a since-removed `R_PWR_SENSE1` (to GND) both on that node, dividing it to roughly half VSYS at idle — comfortably above a diode's ~0.6V forward threshold, so `D_OR1` was forward-biased (and the board powered on) the instant a battery was plugged in, button or no button. The inverter fixes this properly instead of just retuning the divider: idle, `Q_INV1` is on and holds `PWR_BTN_TRIGGER` at GND; pressed, it turns off and `R_INV_PU1` pulls `PWR_BTN_TRIGGER` to VSYS. Only a real press can forward-bias `D_OR1` now. Keep this block close to `D_OR1` — it's three parts serving one signal, not worth spreading out. |
| **F** | **D_OR1 can't read `PWR_BTN_SENSE` directly — found the hard way, on real hardware.** The original design had `R_BTN_PU1` (to VSYS) and a since-removed `R_PWR_SENSE1` (to GND) both on that node, dividing it to roughly half VSYS at idle — comfortably above a diode's ~0.6V forward threshold, so `D_OR1` was forward-biased (and the board powered on) the instant a battery was plugged in, button or no button. The inverter fixes this properly instead of just retuning the divider: idle, `Q_INV1` is on and holds `PWR_BTN_TRIGGER` at GND; pressed, it turns off and `R_INV_PU1` pulls `PWR_BTN_TRIGGER` to VSYS. Only a real press can forward-bias `D_OR1` now. Keep this block close to `D_OR1` — it's parts serving one signal, not worth spreading out.<br><br>**Second-order bug, found the same way:** the inverter's own base resistor originally tapped `PWR_BTN_SENSE` directly, in series with `R_BTN_PU1` — stealing enough idle base current to sag the MCU's own button-read node to ~1V instead of near-VSYS. `R_INV_BASE1` is now its own dedicated 100kΩ pull-up straight to VSYS (not sharing current with `R_BTN_PU1`), and `D_INV_ISO1` (a Schottky, chosen specifically for its lower forward drop than Q_INV1's own base-emitter junction) lets a press still pull the base low without ever loading `PWR_BTN_SENSE`. |
| **G** | **`PWR_EN` had no defined rest state — TI's own datasheet says not to do this.** `Q_PWR1`'s drain feeds the buck's EN pin directly, with nothing else on that node. TLV62569's EN pin is a bare comparator input with no internal pull ("Do not leave floating" per its datasheet) — with `Q_PWR1` off, EN was held by MOSFET/input leakage alone, no guaranteed logic level. `R_PWR_EN_PD1` (100kΩ to GND) fixes it: negligible loading when `Q_PWR1`'s tens-of-mΩ RDS(on) is driving EN high, solid GND the instant it's off. |

## Routing priority

Expand All @@ -55,10 +58,11 @@ The button's position is fixed by the enclosure before you start — everything
2. Put C_DBNC1 directly on SW_PWR1's sense pin before routing anything else nearby.
3. Route the VSYS→Q_PWR1→PWR_EN lane as one straight, generously-wide path across the board.
4. Cluster Q_LATCH1, R_GATE1, R_LATCH_G1, D_OR1, and D_OR2 into one compact low-current block under the main lane.
5. Keep R_INV_BASE1, Q_INV1, and R_INV_PU1 together as their own small block, close to D_OR1 — they're a single-purpose inverter, not independent parts.
5. Keep R_INV_BASE1, D_INV_ISO1, Q_INV1, and R_INV_PU1 together as their own small block, close to D_OR1 — they're a single-purpose inverter, not independent parts.
6. Bring PWR_BTN_SENSE and PWR_HOLD in from wherever the MCU sheet actually sits — these are off-sheet nets, not local components.
7. Drop `R_PWR_EN_PD1` right at Q_PWR1's drain, on the way to `PWR_EN` leaving the sheet — it's a bias resistor for that pin, not an independent part.

> **Checked, not just assumed:** DMG2305UX is rated for ~4A continuous with 35–50mΩ RDS(on) in this SOT-23 package — comfortably oversized for a handheld controller's sub-2A system budget, so this isn't a thermal risk the way the charger's WSON is. MMBT3904 is a general-purpose small-signal part switching microamps here (just enough to bias a diode) — nowhere near its ratings, no thermal consideration needed. Nothing on this sheet needed correcting beyond the divider/inverter fix in callout F.
> **Checked, not just assumed:** DMG2305UX is rated for ~4A continuous with 35–50mΩ RDS(on) in this SOT-23 package — comfortably oversized for a handheld controller's sub-2A system budget, so this isn't a thermal risk the way the charger's WSON is. MMBT3904 is a general-purpose small-signal part switching microamps here (just enough to bias a diode) — nowhere near its ratings, no thermal consideration needed. BAT54W's job is purely to isolate two nodes at sub-1V forward drop, also nowhere near its ratings. Connectivity alone (ERC, netlist, DRC) doesn't catch bad DC bias points — the `R_LATCH_G1`/`PWR_BTN_SENSE` loading bugs in callouts D and F, and the floating `PWR_EN` in callout G, all passed every connectivity check and were only found by actually working through the bias/divider math or reading the driven IC's own datasheet, so don't treat a clean ERC/DRC as proof a gate-drive, sense, or enable network will behave.

---
*Generated from `PCB/power_control.kicad_sch` — a placement reference, not a manufacturing drawing. Model your actual footprints and DRC against your fab's rules. A richer standalone version with the full interactive design lives in [power_control_layout.html](power_control_layout.html).*
32 changes: 27 additions & 5 deletions PCB/diagrams/power_control_layout.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading