Wattplot Build Guide: residential_60cell
STALE — auto-generated from the same template as
build_guide.md(which is itself stale). The panel-preset-specific geometry (Phase 0 lumber cut list, Phase 1 bed dimensions) is correct for the 60-cell residential preset; the electronics phases (Phase 7 onward) reference the v2.4 architecture that no longer exists. Seefirmware/README.mdanddocs/pinmap.htmlfor the current truth. Tracked in ROADMAP.md.
Step-by-step assembly of the entire apparatus. Follow the order below. Each step lists the time, tools, parts, and verification.
Total build time: ~7.9 hr over a weekend (with lumber pre-cut).
Specifications for this build:
- Panel: 65.0” × 39.0” × 1.6” (5.42 × 3.25 ft), 38.0 lb
- Wattage: 235 W (nameplate 250 W, derated after 12 yr, monofacial)
- Bed: 65.0” × 39.0” (5.42 × 3.25 ft), 12” deep walls, bottomless
Phase 0: Pre-build (Day 0, ~1.0 hr)
0.1 Lumber (from the cut list)
| Nominal | Qty | Length | Use |
|---|---|---|---|
| 2x12 | 2 | 65.0” (5.42 ft) | long bed wall (north/south) |
| 2x12 | 2 | 36.0” (3.00 ft) | short bed wall (west/east) |
| 2x6 | 2 | 65.0” (5.42 ft) | long frame rail |
| 2x6 | 2 | 36.0” (3.00 ft) | cross frame rail |
| 2x4 | 1 | 75.8” (6.32 ft) | diagonal brace |
| 4x4 | 2 | 65.0” (5.42 ft) | long skid |
Source from 8-ft stock: 4× 2x12, 2× 2x6, 1× 2x4, 2× 4x4
Tip: many yards will cut to length for free or a small fee. Have them cut each piece on the list above. None of the cuts are mitered (90° square cut only).
0.2 Hardware
- 2 × galvanized butt hinge, 4.0”×4.0” leaf, 0.5” pin, HDG
- 1 × ½” × 67.0” steel rod (continuous, through all hinges)
- 6 × aluminum mid-clamps, 35mm channel, M8 SS bolt + EPDM washer
- 8 × 3/8” × 4” carriage bolt HDG + washer + hex nut (bed corner joints)
- 8 × 5/16” × 3” lag bolt HDG (hinge leaf to bed wall)
- 18 × ¼” × 3” deck screw HDG Torx T-25
- 1 × 12V linear actuator, 4.0” stroke, IP65
0.3 Panel + electrical
- 1 × 250 W nameplate (235 W after derate) salvage panel (you provide)
- Verify under full sun: Voc within 5% of nameplate (multimeter)
- Glass intact, no cracks or delamination
- Aluminum frame straight, junction box sealed
- 1 × MPPT charge controller (sized to your panel, see
bring_your_own_panel.py) - 1 × 12V 100Ah LiFePO4 battery (LiTime or similar)
- 1 × Microinverter (Enphase IQ7+ or APsystems DS3)
- 1 × ESP32-WROOM-32E dev board (or use the PCB from
docs/pcb_design.md)
Phase 1: Bed (Day 1, ~1.9 hr)
1.1 Cut the wall half-lap notches
Each bed wall has a 3” wide × 0.75” deep notch at each end.
Tools: circular saw, chisel, mallet, square
Process:
- Mark the notch location on each wall (3” from each end, 0.75” deep).
- Make multiple passes with the circular saw at the notch depth.
- Clean out the waste with a chisel.
- Test-fit two walls at a corner.
Verification: the two walls meet at a 90° corner with no daylight.
1.2 Assemble the bed box
Tools: drill, ⅛” pilot bit, #6 × 1.5” wood screws, square
Process:
- Lay out the 4 walls on a flat surface. Long walls are 65.0” (5.42 ft). Short walls are 36.0” (3.00 ft).
- Bring the corners together. The half-lap notches interlock.
- Pre-drill 2 holes per corner (one near the top, one near the bottom).
- Drive #6 × 1.5” wood screws through the corners.
Verification: bed box is 65.0” × 39.0” outside, square (measure diagonally, both should be the same).
1.3 Attach the skids
Tools: drill, ⅛” pilot bit, #6 × 1.5” screws
Process:
- Flip the bed upside down.
- Place two 4x4×65.0” skids under the bed, aligned with the long walls.
- Pre-drill and screw through the skids into the bed walls.
- Use 2-3 screws per skid.
Verification: skids are flush with the bed ends, square, and the whole bed sits level on the ground.
Phase 2: Frame (Day 1, ~1.2 hr)
2.1 Assemble the frame rectangle
Tools: drill, ⅛” pilot bit, #6 × 1.5” wood screws, square
Process:
- Lay the 4 frame rails on a flat surface. Long rails are 65.0” (5.42 ft). Cross rails are 36.0” (3.00 ft).
- The cross rails fit between the long rails. Butt joints (no miter).
- Pre-drill 2 holes per corner. Drive #6 × 1.5” wood screws.
Verification: frame is 65.0” × 39.0” outside, square.
2.2 Add the diagonal brace
Tools: drill, ⅛” pilot bit, #6 × 1” screws, measuring tape
Process:
- The 2x4×75.8” diagonal brace runs corner to corner inside the frame.
- Position the brace so its ends butt into the inside faces of the long rails.
- Pre-drill 2 holes per end. Drive #6 × 1” screws (4 total).
Verification: brace is at the diagonal angle, both ends screwed.
Phase 3: Hinges (Day 1, ~20 min)
3.1 Install hinges on the bed’s south wall
Tools: drill, 5/64” bit, hinge screws (included with hinges), tape measure
Process:
- Lay the frame on top of the bed, with the frame’s south rail resting on the bed’s south wall.
- Position the 2 hinges evenly along the south rail. Spacing: 57.0” center-to-center, with 4” margin on each end.
- Mark the hinge positions on both the frame’s south rail and the bed’s south wall.
- Pre-drill 4 holes per hinge (2 per leaf), 5/64” bit.
- Attach the wall leaf to the bed’s south wall.
- Attach the frame leaf to the frame’s south rail.
Verification: frame hinges freely between 0° and ~90° tilt.
3.2 Insert the continuous hinge pin
Tools: mallet (rubber)
Process:
- Thread the ½” × 67.0” steel rod through all hinges, starting from one end.
- Tap gently with a rubber mallet to seat the pin fully.
- The pin should extend ~1” past the last hinge on each end.
Verification: pin is fully seated. Frame hinges smoothly with the pin in place.
Phase 4: Panel (Day 1, ~11 min)
4.1 Place the panel on the frame
Tools: hands (the panel weighs 38.0 lb).
Process:
- With the frame flat on the bed, place the panel on top of the frame, centered.
- The panel should rest on the wood rails with even margin on all four sides.
Verification: panel is centered, no overhang on the long rails.
4.2 Clamp the panel to the frame
Tools: drill, M8 hex driver, mid-clamps
Process:
- Place 4 mid-clamps on each long rail (8 total, evenly spaced along the panel frame).
- Place 2 mid-clamps on each cross rail.
- Tighten the M8 bolts to clamp the panel frame to the wood rails.
- Torque to ~3 Nm (snug, not crushing).
Verification: panel is firmly attached. Try to wiggle it: should not move.
Phase 5: Actuator Mount (Day 1, ~20 min)
5.1 Mount the bottom block on the bed’s north wall
Tools: drill, ⅛” pilot bit, #6 × 1.5” wood screws
Process:
- Cut a 3” length of 2x6 (offcut from any 2x6 scrap).
- Mount the block on the outer face of the bed’s north wall, at the bottom.
- Centered along the bed length.
- Pre-drill 2 holes and drive #6 × 1.5” screws.
5.2 Mount the top bracket on the panel’s underside
- Cut a 3” length of 2x6 (offcut).
- Mount on the underside of the panel, 2” north of the panel’s south edge.
- The bracket should sit just below the panel’s underside, flush with the panel’s south frame edge.
- Pre-drill and drive #6 × 1.5” wood screws through the bracket into the panel frame.
5.3 Connect the actuator
- Use ⅜” clevis pins to attach the actuator to both mount blocks.
- Test manually: the panel should now move from 0° to ~90° (or your actuator’s stroke limit).
Phase 6: Wire the panel to MPPT (Day 2, ~30 min)
6.1 MC4 connectors
Tools: MC4 crimper, wire stripper, multimeter
Process:
- Crimp MC4 connectors on the panel’s PV+ and PV- leads.
- Plug into the MPPT’s PV input (MC4 or SAE adapter, depending on the MPPT).
- Verify polarity: red → +PV, black → -PV. Reverse polarity kills MPPT.
6.2 MPPT to battery
- Connect MPPT battery output to the 12V LiFePO4 battery (via ring terminals or Anderson).
- Set the MPPT’s battery chemistry to LiFePO4 (MODE button on Sunapex).
- The MPPT status LED should turn on (green = charging or float).
Verification: under sun, panel Voc on multimeter matches nameplate ±5%. Battery voltage rises over the next hour.
Phase 7: Wire the controller (Day 2, ~1.0 hr)
7.1 ESP32 + sensors
Tools: soldering iron (or perfboard), wire stripper, multimeter
Pins (from firmware/wattplot.yaml):
| GPIO | Function |
|---|---|
| 4 | DS18B20 1-Wire data |
| 5 | Watering solenoid |
| 16, 17, 18 | H-bridge IN1, IN2, EN |
| 19 | Grow light relay |
| 21, 22 | I2C SDA, SCL |
| 25 | WS2812B status LED |
| 32 | Soil moisture ADC |
| 33 | Battery voltage ADC |
| 34, 35 | Limit switches (0° and 90°) |
7.2 Power
- Connect the DRV8871 H-bridge to the 12V battery (via a 5A fuse).
- Connect the ESP32’s VIN to a 5V buck converter on the 12V rail.
- Verify all grounds are common.
7.3 IMU + INA219 + DS18B20
- Mount the BMI160 on the panel (under the north rail). I2C address 0x68.
- Mount the INA219 in series with the actuator (high side). I2C address 0x40.
- Mount the DS18B20 in the bed soil.
- All sensors share the I2C bus: SDA (GPIO 21), SCL (GPIO 22), 3.3V, GND.
Verification: ESPHome logs show all sensors reporting values.
Phase 8: Flash ESPHome (Day 2, ~30 min)
8.1 First flash over USB
# Install ESPHome (if not already)
pip install esphome
# Flash the firmware
esphome run firmware/wattplot.yaml
8.2 WiFi + Home Assistant (optional)
- Set WiFi credentials in
firmware/secrets.yaml. - Re-flash. ESP32 connects to WiFi and exposes all entities to Home Assistant.
- Add the ESPHome integration in HA. Entities appear automatically.
Phase 9: Calibrate + test (Day 2, ~1.0 hr)
9.1 IMU zero-tilt offset
- With the panel flat (0°), read the BMI160’s pitch value via ESPHome log.
- That reading is your zero-tilt offset. Subtract it in the firmware.
- Re-flash.
9.2 Motor current calibration
- Manually drive the panel to 35°. Read the INA219 current (idle, no wind).
- Set that as the
target_current_Ainfirmware/wattplot.yaml. - Set
I_safe_Ajust above the stall current (typically 2.5A for DRV8871).
9.3 Limit switches
- Drive the panel to 0° (limit switch 0). Adjust switch position so it trips cleanly.
- Drive to 90° (limit switch 1). Same.
- Verify the firmware auto-stops at both limits.
9.4 End-to-end test
- Open Home Assistant. Verify all sensors reporting.
- Trigger a manual tilt from HA. Verify panel moves.
- Press the user-override button. Verify it overrides the decision stack.
- Leave it running for 24 hours. Check logs for any errors.
Total time: ~7.9 hr (with pre-cut lumber and a clean workspace).
Total cost: see python bring_your_own_panel.py for an itemized estimate.
Next: see docs/test_checklist.md for per-component and per-system tests.