Dark Moth R5 — electronics assembly

Build this guide around the corrected 94 × 60 mm through-hole power-latch PCB, an ESP32-C3 SuperMini, the separate five-channel LED driver, and one remote button connected by a removable two-wire plug. ESP32-S3 pin substitutions appear below. R5 changes the case and button arrangement; the copied board remains the earlier corrected copper design.

This is a source-checked assembly plan. It is not a physically assembled or load-tested electronics release. The checks below are necessary before enclosing a battery-powered prototype.

PCB placement diagram · Module wiring · LED driver wiring · Machine-readable manifest · Copied KiCad board

1. Identify the board before soldering

Use power_button_fixed.kicad_pcb, together with its project settings. It has four 2.7 mm mounting holes. The board outline is KiCad X = 4…98 mm, Y = 4…64 mm; nominal thickness is 1.6 mm.

The original v3-button/hardware/power_button.kicad_pcb is not the board to build: its GND track shorts to the Db cathode, its SENSE track shorts to an OUT+ switch pad, and another track violates clearance at Rgl. The corrected source reroutes these and adds the mounting holes. A new KiCad DRC report checks the copied source. DRC does not test component internals or circuit operation.

Leave the PCB switch footprint SW empty. The footprint repeats pad number 1 across its upper row and pad number 2 across its lower row, but the generator assigns different nets to the two X columns. A switch matching those contact groups could permanently connect OUT+ to BTN_N. A remote switch with independently verified normally-open contacts avoids that conflict. Do not treat an installed four-leg PCB switch as interchangeable with the remote arrangement.

The older inventory and SMD-board documents refer to J4/J6 and an EN_PWR logic-enable rail. Those are a different design. This PCB uses J1 and a real switched supply VSW; it carries the boost converter and ESP supply current.

2. Gather the parts

Measure the resistor values with a meter. The inventory confirms the listed families are on hand but does not establish the manufacturer, exact pinout, connector model or load capability of each physical part.

LocationReferenceQuantityPart / valueInstallation detail
Main PCBRb ↗ 3D1330 Ω, ¼ W, 1%No polarity; 10.16 mm lead pitch
Main PCBRbtn ↗ 3D11 kΩ, ¼ W, 1%Follow the corrected PCB; the older wiring guide's 10 kΩ is inconsistent
Main PCBRbe, Rgl, Rs1, Rs24100 kΩ, ¼ W, 1%No polarity; 10.16 mm lead pitch
Main PCBDb ↗ 3D11N4148 axial diodeStripe/cathode to pad 1, BTN_DIO
Main PCBQP ↗ 3D1SS8550 PNP, TO-92Pads 1/2/3 require E/B/C respectively
Main PCBQL ↗ 3D1BS170 N-MOSFET, TO-92Pads 1/2/3 require D/G/S respectively
Main PCBJ1 ↗ 3D11×6, 2.54 mm header plus mating six-way harnessOr insulated flying leads soldered to the same six holes
Main PCBSW0Existing SW_PUSH_6mm footprintUnpopulated; use two selected holes for remote leads
Remote buttonSW_REMOTE1Normally-open 6×6 mm tactile switchNominal 4.3 mm overall height above its small board; verify your switch
Remote buttonDaughterboard112×12×1.6 mm insulating perfboardMechanical allowance; verify switch legs and case carrier before cutting
Remote buttonBUTTON_PLUG1 pairMatched keyed two-pin inline plug/socket with two-wire pigtailsInline cable connector, not a new footprint on the main PCB
LED driverQ1–Q55BS170 N-MOSFETs, TO-92Five separate channel switches
LED driverRg1–Rg55100 Ω, ¼ W, 1%Series gate resistors
LED driverRp1–Rp5510 kΩ, ¼ W, 1%Gate-to-source pulldowns
LED driverDRV1Insulated hand-wired perfboardProposed 35×15 mm board; actual component packing is unverified
Floor modulesBATT11S 3.7 V LiPo, 4.2 V maximum chargeNominal 65×36 mm; 11 mm thickness allowance
Floor modulesCHG1USB-C TP4056 charger with protection circuitBAT+/BAT− and OUT+/OUT− must be identifiable
Floor modulesBOOST1MT3608 adjustable boost moduleSet output to 12.0 V before connecting the strip
Floor modulesESP1ESP32-C3 SuperMiniPrimary; S3 SuperMini is the alternate, not an additional module
Front lightLED1100 mm of 12 V common-anode Yuji RGBWW stripMatch actual labels; do not assume the physical pad order
Optional telemetryRd1, Rd20100 kΩ eachOmitted in recommended build; firmware disables battery readings

Total installed discrete parts: 6 BS170s, 1 SS8550, 1 diode, 16 resistors and 1 remote switch. Smallboard headers, wire, insulation, the button plug and case mounting hardware are additional. No capacitor is specified on the latch PCB; existing module capacitors remain part of their modules.

The R5 key stop allows 0.35 mm travel: 0.10 mm initial gap plus 0.25 mm nominal switch movement. The Omron B3F datasheet gives a nominal 0.25 mm pretravel for the 6×6×4.3 mm B3F-1000, with a 0.15–0.45 mm tolerance range. This is a dimensional reference, not proof of the unmarked switch on hand. Measure the actual switch stroke and adjust the stop/gap if necessary; the nominal geometry does not guarantee activation of every 6 mm tact.

No exact brand of button plug is established by the inventory. Choose and measure a matched keyed pair before fixing wire lengths; the CAD's 10×7×6 mm connector envelope is a routing allowance, not a verified part dimension. Do not substitute an unrelated connector solely because it has two contacts.

3. Populate the main PCB

PCB placement

Read the board from its component side, with J1 toward the upper-left. The following coordinates are board-local millimetres from the upper-left edge. Add 4 mm to X and Y to locate the same point in KiCad. pad 1 → pad 2 gives the two lead holes, not the resistor-body centre.

RefValuePad positions (X,Y)Required net / polarity
Rb ↗ 3D330 Ω1 (44,13) → 2 (54.16,13)PB → LDRV
Rbtn ↗ 3D1 kΩ1 (78,13) → 2 (88.16,13)GATE → BTN_DIO
Rbe ↗ 3D100 kΩ1 (28,29) → 2 (38.16,29)OUT+ → PB
Rgl ↗ 3D100 kΩ1 (70,36) → 2 (80.16,36)GATE → GND
Rs1 ↗ 3D100 kΩ1 (60,45) → 2 (70.16,45)BTN_N → SENSE
Rs2 ↗ 3D100 kΩ1 (78,40) → 2 (88.16,40)SENSE → GND
Db ↗ 3D1N41481 (62,29) → 2 (72.16,29)K/stripe → BTN_DIO, A → BTN_N
QP ↗ 3DSS85501 (28,13), 2 (29.27,13), 3 (30.54,13)E→OUT+, B→PB, C→VSW
QL ↗ 3DBS1701 (60,13), 2 (61.27,13), 3 (62.54,13)D→LDRV, G→GATE, S→GND
  1. Install the six resistors and Db first. Bend leads to the specified holes, seat without forcing the bodies, solder and trim the underside.
  2. Check Db's stripe against pad 1. Its orientation matters; the resistor orientation does not.
  3. Identify the actual manufacturer's transistor lead assignment before installing QP and QL. The board requires the roles listed above. A generic “flat face toward you” rule is insufficient for unidentified parts. If lead order differs, use insulated formed leads or a verified adapter; do not let crossed bare leads touch.
  4. Fit J1 and mark its pin-1 end. The footprint is rotated: its six holes run horizontally left to right, all at local Y=18 mm.
  5. Fit the two remote-switch leads in Section 4. Leave the other SW holes and the switch body position empty.
  6. Inspect both faces under magnification, then make the unpowered checks in Section 8.

The onsemi SS8550 datasheet identifies pins 1/2/3 as emitter/base/collector for its specified package. That supports this board's intended assignment, but does not identify a mixed-kit transistor by itself. Use the corresponding onsemi BS170 datasheet for the purchased BS170 package. The inventory's assertion that every middle leg is always Gate is not a substitute for identifying a part.

J1: the six actual PCB connections

PinLocal hole (X,Y)PCB netWire to
1(7,18)OUT+CHG.OUT+ protected positive supply
2(9.54,18)VSWBOOST.VIN+ and ESP.5V/VIN
3(12.08,18)GNDCHG.OUT− system return
4(14.62,18)GATEC3 GPIO3, or S3 GPIO9
5(17.16,18)SENSEC3 GPIO4, or S3 GPIO8
6(19.70,18)GNDESP.GND and the common load return harness

Pins 3 and 6 are connected on the PCB. Use a sound return junction for the boost, ESP and driver; do not route LED load current through the thin remote-button cable.

4. Make the detachable remote button

The remote button closes OUT+ to BTN_N. It does not connect to GND, SENSE or GATE directly. The steering diode and sense divider are already on the main PCB.

LeadExact existing PCB holeKiCad absoluteRemote end
OUT+SW upper-left hole at local (34.0,45.0)(38.0,49.0)Inline connector → one normally-open contact
BTN_NSW upper-right hole at local (40.5,45.0)(44.5,49.0)Other connector contact → other normally-open contact

Both selected holes are numbered 1 in the footprint. Coordinate, physical position and net identify them unambiguously. There is no J2 or “button socket” footprint on this PCB.

  1. On the loose four-leg tact switch, use continuity mode to find contacts that are open when released and close only while pressed. Do not choose two legs that are permanently common. Rotation and supplier drawings must be checked before soldering the small board.
  2. Mount that switch on its 12×12 mm daughterboard. Keep solder joints low and insulate any protruding ends. Test its release clearance in the R5 carrier before final assembly.
  3. Attach one wire from each selected contact to one half of a keyed two-pin connector. Attach the mating half to the two main-PCB holes above. Put the shrouded female contact half on the live PCB side when the chosen connector permits it.
  4. Label the harness ends OUT+ and BTN_N, insulate every joint and add strain relief to both boards. The contact itself has no polarity, but consistent labels prevent later mistakes.
  5. With the main PCB disconnected from power, verify the entire remote harness is open released and closed pressed. Unplugging it must leave the two PCB leads isolated.
  6. Route it along the case edge with enough slack to remove the carrier and unplug it. Keep wire away from the moving key, lid screws, diffuser slide path and hot boost components. The model shows an intended route; final length depends on the actual connector and installed parts.

5. Wire charger, supply and boost

Module wiring

FromToNotes
BATT.+CHG.BAT+Battery connection only
BATT.−CHG.BAT− onlyDo not connect this to system GND
CHG.OUT+J1.1Always-live protected supply
CHG.OUT−J1.3 and common system GNDLoad return is on the protection output side
J1.2BOOST.VIN+ and ESP.5V/VINSwitched battery rail; not regulated 5 V
BOOST.VIN− and VOUT−System GNDVerify actual module labels
ESP.GNDSystem GND / J1.6Common reference for all GPIOs
BOOST.VOUT+LED.+12VSet and measure 12.0 V first

Do not copy the old guide's common-ground list that joins BAT− and OUT−. In the protected DW01/dual-MOSFET topology, the MOSFETs interrupt the negative cell path. Bridging battery negative to load return defeats that switching. See the manufacturer's DW01A typical application circuit. Confirm your charger really has separate protected output pads; a basic TP4056 charger alone is not a protection circuit.

Measure the charger's programmed charge current and check it against the actual cell specification before charging. Do not infer cell capacity or allowable charge current from its outer dimensions. The TP4056 arrangement is not a documented load-sharing power supply; initial charging tests should be with the light off.

The ESP board's 5V pin is the input of its onboard regulator. Supplying it from VSW is the inherited design, and may fail at a low cell voltage because of the PNP voltage drop plus regulator dropout. Never connect the cell directly to 3V3. Identify the clone's regulator and measure its 3.3 V rail during boot, BLE and LED load changes. Disconnect the external power harness before flashing the ESP through USB; “button off” does not establish reverse-power isolation.

6. Assemble the separate LED driver

Five-channel wiring

These fifteen parts are on a separate hand-wired perfboard. They do not go into the 94×60 mm latch PCB. The source had no fabricated driver PCB. R5 supplies a proposed exact isolated-pad layout below and in driver-layout.json; it requires lead forming and upright resistors. Dry-fit the actual parts before soldering.

ChannelMOSFETSeries resistorPulldownC3 GPIOS3 GPIOStrip return pad
GreenQ1Rg1 = 100 ΩRp1 = 10 kΩ55G
RedQ2Rg2 = 100 ΩRp2 = 10 kΩ64R
BlueQ3Rg3 = 100 ΩRp3 = 10 kΩ76B
Warm whiteQ4Rg4 = 100 ΩRp4 = 10 kΩ1010WW
Cool whiteQ5Rg5 = 100 ΩRp5 = 10 kΩ2011CW, sometimes W

For each row, make these four connections; a and b here are assigned resistor-lead names, not pre-existing PCB pad markings:

  1. ESP GPIO → Rg.a. Rg.b → corresponding MOSFET Gate.
  2. That same Gate → Rp.a. Rp.b → MOSFET Source → system GND.
  3. MOSFET Drain → the specified strip channel return.
  4. Strip common +12V → BOOST.VOUT+. Do not connect a channel return directly to GND or it will remain on.

Label the driver harness G/R/B/WW/CW, plus GND, before installing it. All five channels share GND but have separate gate and drain nodes. For a diode-mode MOSFET check, discharge the gate to source first so stored gate charge cannot confuse the result; identify the package from its datasheet before applying power.

Do not infer that a BS170 is fully enhanced at 3.3 V from its threshold-voltage number: the datasheet's on-resistance specification uses a higher gate-drive voltage. Check each channel's current, drain voltage and temperature at the intended brightness. The existing design does not establish a guaranteed full-white current or a thermally validated enclosed duty cycle.

Proposed 35×15 mm perfboard hole layout

Perfboard placement

Use isolated-pad 2.54 mm perfboard, not connected stripboard. Trim to 35×15 mm only after confirming the actual parts fit. View the component side; rows A…E run top to bottom, columns 1…13 left to right. Hole A1 is 2.26 mm from the left edge and 2.42 mm from the top edge. All other holes follow the 2.54 mm pitch. No screw holes are reserved; the case bay retains the insulated board.

GroupD / G / S holes100 Ω Rg: body-side a / return b10 kΩ Rp: body-side a / return bPWM wireLED return wire
Q1 / GreenA2 / B2 / C2D2 / D3E3 / E2D2A2
Q2 / RedA4 / B4 / C4D4 / D5E5 / E4D4A4
Q3 / BlueA6 / B6 / C6D6 / D7E7 / E6D6A6
Q4 / WWA8 / B8 / C8D8 / D9E9 / E8D8A8
Q5 / CWA10 / B10 / C10D10 / D11E11 / E10D10A10

For each group at column c, form the transistor leads into A[c], B[c], C[c] by their D/G/S role. Mount both resistors upright: Rg body over D[c], other lead at D[c+1]; Rp body over E[c+1], other lead at E[c]. Insulate the long return lead beside each resistor body. Nominal maximum height is 7.6 mm above the board for upright resistors including the lead loop, or 9.2 mm including board thickness; measure your completed part.

Solder insulated underside jumpers B[c]→D[c+1]→E[c+1] for that gate, and C[c]→E[c] for its source. Daisy-chain C2, C4, C6, C8 and C10 to C13, then wire C13 to system GND. Use insulated wire between separated pads so intermediate PWM pads cannot be bridged. Attach the five GPIO wires to D2/D4/D6/D8/D10 and the five strip-return wires to A2/A4/A6/A8/A10. A crowded C13 pad may use an insulated off-board ground splice instead of stacking five wires into one hole.

Verify continuity for every channel against driver-layout.json, including isolation of each D-row PWM pad from GND and from its adjacent gate node through anything other than its 100 Ω resistor. This layout is source-derived and geometrically checked with nominal bodies; it has not been hand assembled.

7. Firmware required by this board

Download the R5 firmware ZIP, containing the sketch and required button_sense.h, with POWER_LATCH_DISCRETE=1. C3 is the primary target. The latch GPIO drives HIGH to hold power and LOW to release; long-press power-off occurs after the button is released. For a cold start, hold the button until the ESP has booted and asserted the latch; an arbitrarily brief click is not guaranteed to power it on. The initial power-on press is not treated as a normal light-toggle gesture.

The fitted Rs1/Rs2 pair divides the 3.0–4.2 V button node to about 1.5–2.1 V. This is not a guaranteed digital HIGH: the ESP32-C3 datasheet gives a minimum guaranteed HIGH input of 0.75×VDD. At VDD=3.3 V that is 2.475 V. R5 therefore reads the ADC with 1000 mV press / 500 mV release hysteresis, averages four conversions, and retains the existing 30 ms debounce. ADC attenuation is configured before boot confirmation or normal button reads. The module-style active-low switch path keeps its digital read.

The source defaults BATTERY_SENSE_ENABLED=0. Leave Rd1/Rd2 and GPIO1 unconnected. The battery BLE characteristic remains present with an empty value; no fictitious percentage is published. A fresh mobile app session displays the reading as unavailable. The current app ignores empty payloads rather than clearing earlier values, so restart the app after switching from telemetry-enabled firmware to avoid retaining an old reading. A raw-cell divider could feed current into an unpowered ESP input. Add telemetry only after designing and verifying its isolation and calibration; changing the input to VSW would measure the switched rail, not exact cell voltage.

Flash with the external supply harness disconnected. After extracting the firmware ZIP, run these commands from the directory containing dark_moth_ble_v3/. They compile; add the selected serial port for a separate upload:

arduino-cli compile --fqbn esp32:esp32:esp32c3:CDCOnBoot=cdc dark_moth_ble_v3
arduino-cli compile --fqbn esp32:esp32:esp32s3:USBMode=hwcdc,CDCOnBoot=cdc dark_moth_ble_v3

Only one board pin map is used in a build. Do not combine C3 GPIO3/4 button connections with the S3 LED map.

8. Bring up in stages before fitting the battery

  1. Unpowered: inspect transistor leads and diode stripe. Verify each J1 pin reaches its named component pads using pcb-pads.json. Verify no hard shorts between OUT+, VSW and GND. A transistor/diode circuit is not expected to show infinite resistance in every probe direction; compare with its net topology.
  2. Remote switch: independently check open released / closed pressed, then verify the same behavior through the plug. Confirm no bridge remains where the original PCB SW body would sit.
  3. Module preparation: power the boost separately from a current-limited bench supply and set 12.0 V unloaded. Keep it disconnected from the LED until measured. Configure the actual charger's charge current to suit the cell.
  4. Latch only: with battery disconnected, feed a current-limited 3.0–4.2 V bench source to J1.1 and J1.3. Use an initial modest current limit appropriate to the disconnected load. Check OUT+, VSW, QP base and QL gate while pressing the remote button. A press should raise VSW; with no MCU holding the gate, release should remove that drive.
  5. ESP only: attach its VSW/GND/latch/sense wires, leaving the boost and LEDs disconnected. Check actual 3.3 V rail stability, ADC readings at rest/press, boot-and-release latching, short tap and long-hold-release shutdown. Measure the latch GPIO during cold start and at full cell voltage: the OUT+ button path feeds that GPIO through Db/Rbtn before the ESP is fully powered. The 1 kΩ resistor limits current but is not isolation or a level shifter; verify the actual GPIO voltage/current against the ESP limits before approving this inherited circuit. Raise supply current limit only as necessary for known ESP boot demand; record peak current rather than assuming it.
  6. One LED channel: attach the boost, then test one channel at low brightness. Verify color, true off and MOSFET orientation. Repeat for all five. Check the strip's measured +12 V rather than its pad location.
  7. Intended load: increase brightness gradually while recording input current, VSW drop, regulator rail, QP temperature, driver temperatures and boost temperature. The SS8550 datasheet's high-current saturation test uses substantially more base current than the board's 330 Ω resistor supplies; maximum transistor current is not a promise of low loss here. Reject resets, unstable latching or excessive heating before enclosure assembly.
  8. Power-off and charging: measure off current with the button released, verify safe charger behavior with the chosen cell, and confirm the battery protection return has not been bypassed. No measured standby-current or thermal limit has yet been established by this project.
  9. Mechanical dry fit: use an insulating barrier under the main PCB, clear all trimmed leads from the cell, secure modules without pressing on the pouch, and check that the remote-button harness disconnects and the diffuser slides out freely. Close the case only after those checks pass.

Source provenance and reproducibility

The copied PCB/project bytes come from the original workspace's v3-button/case/pcb/, not from the flawed v3-button/hardware/ variant. The manifest records the PCB SHA-256. Pad coordinates are extracted from that copied source by extract_board.py. Board reference designators and nets are exact; commodity-module and component body dimensions remain nominal.

draw_guides.py redraws the circuit SVGs; draw_perfboard.py draws the proposed perfboard from the manifest. modules.json records the external BOM and uncertainty; interconnects.json records the two ESP pin maps and point-to-point topology. A 3D rendering communicates assembly intent; it does not establish lead clearance, connector fit, electrical operation or a fabricated perfboard layout.