Skip to content

Commit a6697af

Browse files
author
Ravi Singh
committed
docs(hardware): wiring diagrams, INA219 variant, MPPT solar charging
Adds public/hardware/wiring.md as canonical pin/wiring reference for both RX targets (DevKit + C3 SuperMini) and TX with full solar power chain (CN3791 MPPT -> 18650 -> MT3608 boost -> 5V rail). Two TX power-monitoring variants documented: Variant A: voltage divider on ADC (legacy, simpler BOM) Variant B: INA219 over I2C (full charge/discharge/power telemetry) BOM.csv updated: replace TP4056 (linear) with CN3791 (MPPT) for solar use, add MT3608 boost, INA219, solar panel, protected 18650 holder. Two SKU totals: A and B. README.md hardware section now points to wiring.md prominently.
1 parent 6d735ae commit a6697af

3 files changed

Lines changed: 300 additions & 16 deletions

File tree

README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,19 @@ Long-range wireless water tank level monitoring using LoRa (RYLR998), ESP32, and
5858
| Receiver MCU | ESP32 DevKit v1 (or ESP32-C3 SuperMini) | $4-8 |
5959
| Transmitter MCU | ESP32-C3 SuperMini | $3 |
6060
| LoRa Module | REYAX RYLR998 (x2) | $8 each |
61-
| Ultrasonic Sensor | JSN-SR04T (waterproof) | $4 |
61+
| Ultrasonic Sensor | JSN-SR04T / AJ-SR04M (waterproof) | $4 |
6262
| Display | SH1106 1.3" OLED I2C | $3 |
63-
| Battery | 18650 LiPo + TP4056 charger | $3 |
63+
| Battery | 18650 LiPo + protected holder | $2.40 |
64+
| Solar charger | CN3791 MPPT (replaces TP4056 for solar TX) | $1.45 |
65+
| Boost converter | MT3608 3.7V → 5V | $0.60 |
66+
| Power monitor (optional) | INA219 over I2C | $1.45 |
6467

65-
**Total: ~$35-40 per setup**
68+
**Total: ~$46-63 per complete system** (entry vs premium SKU)
6669

67-
Full bill of materials: [hardware/BOM.csv](hardware/BOM.csv)
70+
📐 **[Detailed wiring diagrams, pin connections, and power chain →](hardware/wiring.md)**
71+
Includes block diagrams for both DevKit-RX and C3-RX, full TX power chain with solar charging, and both power-monitoring variants (voltage divider vs INA219 over I2C with auto-detect).
72+
73+
📋 **[Full BOM →](hardware/BOM.csv)**
6874

6975
## Quick Start
7076

hardware/BOM.csv

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
11
Component,Quantity (TX),Quantity (RX),Description,Approx Price (USD),Notes
2-
ESP32-C3 SuperMini,1,1,Main microcontroller with WiFi/BLE,$3.00,AliExpress/Amazon
2+
ESP32-C3 SuperMini,1,1,Main microcontroller with WiFi/BLE,$3.00,AliExpress/Amazon. RX can also use ESP32 DevKit v1.
33
RYLR998,1,1,LoRa module 868/915MHz,$10.00,Reyax official or AliExpress
4-
JSN-SR04T,1,0,Waterproof ultrasonic sensor,$5.00,20cm-450cm range
5-
WS2812B LED Strip,2 LEDs,3 LEDs,Addressable RGB LEDs,$1.00,Cut from strip
6-
100K Resistor,2,0,1/4W for voltage divider,$0.10,Any standard resistor
7-
3.7V Li-ion Battery,1,0,18650 or similar 1000mAh+,$5.00,Protected cell recommended
8-
TP4056 Module,1,0,Battery charging module,$0.50,Optional for charging
9-
USB Cable,0,1,Micro USB or USB-C for power,$2.00,Depends on ESP32 variant
10-
Waterproof Enclosure,1,0,IP65 or better,$5.00,For outdoor installation
4+
SH1106 OLED 1.3" 128x64,0,1,Display for RX,$3.00,I2C 0x3C
5+
JSN-SR04T / AJ-SR04M,1,0,Waterproof ultrasonic sensor,$5.00,20cm-450cm range
6+
WS2812B LED,2,2,Addressable RGB LEDs,$0.50,Cut from strip
7+
Tactile push button,1,0,Boot/config/pair button on TX,$0.20,Through-hole 6mm
8+
Solar panel 6V 180mA,1,0,Polycrystalline ~250x80mm,$1.80,For TX outdoor solar
9+
CN3791 MPPT Solar Charger,1,0,Buck-MPPT solar to Li-ion charger,$1.45,Replaces TP4056 for solar use; tracks Vmpp
10+
18650 Li-ion 3000mAh + protected holder,1,0,Single-cell with protection PCB,$2.40,Protection mandatory (CN3791 has no over-discharge cutoff)
11+
MT3608 DC-DC Boost 3.7V to 5V,1,0,Step-up converter for 5V loads,$0.60,EN pin to GPIO10 recommended for low-power
12+
100K Resistor 1%,2,0,Variant A only — voltage divider,$0.10,Skip if Variant B (INA219)
13+
INA219 Module 0.1Ohm shunt,1,0,Variant B only — power monitor over I2C,$1.45,Default I2C addr 0x40
14+
4.7K Resistor (I2C pull-ups),2,0,Variant B only,$0.10,Often included on INA219 module already
15+
USB Cable,0,1,USB-C for RX 5V wall power,$2.00,RX is wall-powered indoors
16+
USB-C 5V wall brick (>= 1.5A),0,1,Wall adapter for RX,$3.00,Standard phone charger works
17+
Waterproof Enclosure,1,0,IP65 or better,$5.00,For outdoor TX installation
1118
Jumper Wires,As needed,As needed,For connections,$2.00,22-26 AWG
1219
Pin Headers,As needed,As needed,2.54mm pitch,$1.00,Optional for modularity
13-
,,,,,"
14-
TOTAL TRANSMITTER,,,,$27.00 - $35.00,
15-
TOTAL RECEIVER,,,,$15.00 - $20.00,
16-
COMPLETE SYSTEM,,,,$42.00 - $55.00,
20+
,,,,,
21+
TOTAL TRANSMITTER (Variant A - voltage divider),,,,$28.00 - $36.00,Adds solar harvest + voltage-only SoC
22+
TOTAL TRANSMITTER (Variant B - INA219),,,,$30.00 - $38.00,Adds full charge/discharge/power telemetry
23+
TOTAL RECEIVER,,,,$18.00 - $25.00,Wall-powered indoor unit
24+
COMPLETE SYSTEM (TX-A + RX),,,,$46.00 - $61.00,Entry SKU
25+
COMPLETE SYSTEM (TX-B + RX),,,,$48.00 - $63.00,Premium SKU with power telemetry

hardware/wiring.md

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
# TankSync Hardware Wiring & Pin Connections
2+
3+
Authoritative wiring reference for the TankSync receiver (RX) and transmitter (TX) boards. Pin assignments here match `firmware/<target>/main/config.h` exactly; if the two ever disagree, the `config.h` file is the source of truth and this doc must be updated.
4+
5+
## Topology overview
6+
7+
| Device | Power source | Where it lives | Duty cycle |
8+
|---|---|---|---|
9+
| **RX** (receiver / display unit) | 5V USB-C wall brick (≥1.5A) → on-board 3.3V LDO | Indoors, near a power outlet, within WiFi range | Always-on; WiFi STA + LoRa RX listening continuously |
10+
| **TX** (transmitter / sensor unit) | 6V solar panel → CN3791 MPPT charger → 18650 Li-ion → MT3608 boost → 5V rail | Outdoors, mounted on or near the water tank, often far from the house | Deep-sleep cycle: wakes every 5 min, samples ultrasonic + LoRa burst (~3s awake), sleeps |
11+
12+
The TX is the energy-constrained device. The RX is intentionally indoor-and-plugged so its power budget (display + WiFi + LoRa-listen + LEDs) doesn't have to fit a small solar harvest.
13+
14+
---
15+
16+
## Receiver (RX) wiring
17+
18+
There are **two RX hardware variants** depending on the ESP32 chip on hand:
19+
- **DevKit ESP32 v1** (CP2102, 30-pin header) — full-size, more GPIOs, easier to breadboard
20+
- **ESP32-C3 SuperMini** — pocket-sized, fewer GPIOs
21+
22+
Both variants use the **same external modules** (RYLR998 LoRa, SH1106 OLED, WS2812B LEDs). Only the GPIO assignments differ. Power comes from a 5V USB-C wall brick into the dev-board's USB connector; the on-board AMS1117-3.3 LDO derives the 3.3V rail used by RYLR998.
23+
24+
### RX block diagram
25+
26+
```
27+
[5V USB-C wall brick, ≥1.5A]
28+
29+
30+
┌──────────────────────┐
31+
│ ESP32 (DevKit / C3) │
32+
│ USB connector │
33+
└─┬──────────────────┬─┘
34+
│ 5V rail │ 3.3V rail (from on-board LDO)
35+
▼ ▼
36+
┌────────────┐ ┌────────────┐ ┌──────────────────┐
37+
│ WS2812B ×2 │ │ RYLR998 │ │ SH1106 OLED │
38+
│ (status + │ │ LoRa │ │ 128×64, I²C 0x3C │
39+
│ water lvl)│ │ UART @ │ │ 3.3V or 5V │
40+
│ VDD = 5V │ │ 115200 │ │ tolerant module │
41+
│ DIN = GPIO │ │ VCC = 3.3V │ │ SDA, SCL pins │
42+
└────────────┘ └────────────┘ └──────────────────┘
43+
```
44+
45+
### Pin map — DevKit ESP32 RX
46+
47+
Source: `firmware/receiver/main/config.h`
48+
49+
| GPIO | Function | Connects to | Notes |
50+
|---|---|---|---|
51+
| 13 | WS2812B data | DIN of first LED in 2-LED chain | 3.3V data may need 74AHCT125 buffer if flicker observed |
52+
| 16 | UART2 RX | RYLR998 TXD | DevKit has UART2 free; C3 doesn't |
53+
| 17 | UART2 TX | RYLR998 RXD | |
54+
| 21 | I²C SDA | SH1106 SDA | Standard I²C bus |
55+
| 22 | I²C SCL | SH1106 SCL | |
56+
| 5V | Power | WS2812B VDD, OLED VCC (5V variant) | From USB |
57+
| 3.3V | Power | RYLR998 VCC, OLED VCC (3.3V variant) | From on-board LDO |
58+
| GND | Ground | All modules | Single common ground |
59+
60+
### Pin map — ESP32-C3 SuperMini RX
61+
62+
Source: `firmware/receiver-c3/main/config.h`
63+
64+
| GPIO | Function | Connects to | Notes |
65+
|---|---|---|---|
66+
| 2 | WS2812B data | DIN of first LED in chain | |
67+
| 9 | I²C SDA | SH1106 SDA | C3 GPIO matrix routes I²C anywhere |
68+
| 10 | I²C SCL | SH1106 SCL | |
69+
| 20 | UART1 RX | RYLR998 TXD | C3 only has UART0 (USB) and UART1 |
70+
| 21 | UART1 TX | RYLR998 RXD | |
71+
| 5V | Power | WS2812B VDD, OLED VCC (5V variant) | From USB |
72+
| 3.3V | Power | RYLR998 VCC, OLED VCC (3.3V variant) | From on-board LDO |
73+
| GND | Ground | All modules | Single common ground |
74+
75+
---
76+
77+
## Transmitter (TX) wiring — solar-powered, two power-monitoring variants
78+
79+
The TX is `firmware/transmitter/` (ESP32-C3 SuperMini). The board ships in two variants depending on the level of power-monitoring telemetry desired:
80+
81+
- **Variant A — Voltage divider only** (basic): battery percentage from ADC reading. Cheapest BOM. Used in the entry-level product SKU.
82+
- **Variant B — INA219 over I²C** (full): bidirectional current, accurate bus voltage, and computed power. Used in the premium SKU and required for any cloud-side energy analytics.
83+
84+
The firmware **auto-detects** which variant is installed by I²C-scanning at INA219's default address (`0x40`) at boot. Users can also force a mode via the web UI dropdown (Auto / Force INA219 / Force voltage divider / Disabled). The mode is saved to NVS.
85+
86+
### TX power chain
87+
88+
```
89+
┌──────────────────────┐
90+
│ Solar panel │ 6V open-circuit, 180mA short-circuit
91+
│ (6V / 180mA / ~1W) │ (Robu / generic crystalline)
92+
└──────────┬───────────┘
93+
│ Vin
94+
95+
┌──────────────────────┐
96+
│ CN3791 │ MPPT, tracks Vmpp ~4.5V on this panel
97+
│ MPPT Solar Charger │ ~85% efficiency under MPPT
98+
│ (Robu listing) │ R_PROG sets charge current (default ~500mA)
99+
└──────────┬───────────┘
100+
│ BAT± to cell
101+
102+
┌──────────────────────┐
103+
│ 18650 Li-ion │ 3000 mAh, with PCB protection circuit
104+
│ (3.0–4.2V) │ (mandatory — CN3791 has no over-discharge protection)
105+
└──────────┬───────────┘
106+
107+
├─► [Variant A: voltage divider 100k/100k → GPIO0 (ADC1_CH0)]
108+
109+
├─► [Variant B: INA219 in series with battery+ → I²C to ESP32]
110+
111+
112+
┌──────────────────────┐
113+
│ MT3608 Boost │ 3.7V → 5V regulated output
114+
│ 3.7V → 5V │ ~85% efficiency
115+
│ EN tied high (or to GPIO10 for low-power deep-sleep gating)
116+
└──────────┬───────────┘
117+
│ +5V rail
118+
119+
┌──────────┴────────────────────────────────────────────┐
120+
▼ ▼ ▼ ▼
121+
┌────────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
122+
│ ESP32-C3 │ │ WS2812B │ │ AJ-SR04M │ │ Common │
123+
│ SuperMini │ │ ×2 │ │ Sonar │ │ GND │
124+
│ VBUS = 5V │ │ VDD = 5V │ │ VCC = 5V │ │ │
125+
└─────┬──────┘ │ DIN = G7 │ │ TRIG = G4│ └──────────┘
126+
│ └──────────┘ │ ECHO = G5│
127+
│ └──────────┘
128+
│ on-board AMS1117-3.3 LDO
129+
130+
3.3V rail → RYLR998 LoRa (VCC, RXD = GPIO21, TXD = GPIO20)
131+
```
132+
133+
### TX pin map — Variant A (voltage divider only)
134+
135+
Source: `firmware/transmitter/main/config.h` (BAT_ADC_CHANNEL = 0)
136+
137+
| GPIO | Function | Connects to |
138+
|---|---|---|
139+
| 0 | ADC1_CH0 — battery voltage | Junction of 100kΩ / 100kΩ divider on Vbat (battery+ → 100k → GPIO0 → 100k → GND) |
140+
| 4 | Ultrasonic TRIG | AJ-SR04M TRIG |
141+
| 5 | Ultrasonic ECHO | AJ-SR04M ECHO |
142+
| 7 | WS2812B data | DIN of first WS2812B (2 LEDs in series) |
143+
| 8 | On-board LED | Built-in (no external) |
144+
| 9 | Button | Tactile switch to GND, internal pull-up |
145+
| 20 | UART1 RX | RYLR998 TXD |
146+
| 21 | UART1 TX | RYLR998 RXD |
147+
| 1, 2, 3, 6, 10 | **FREE** | Reserved for future expansion |
148+
149+
### TX pin map — Variant B (INA219 over I²C)
150+
151+
Adds I²C bus on GPIO1/2; voltage divider is **not installed** (INA219's bus-voltage register replaces it).
152+
153+
| GPIO | Function | Connects to |
154+
|---|---|---|
155+
| 0 | (unused — divider not installed in this variant) ||
156+
| 1 | I²C SDA | INA219 SDA (with 4.7kΩ pull-up to 3.3V) |
157+
| 2 | I²C SCL | INA219 SCL (with 4.7kΩ pull-up to 3.3V) |
158+
| 4 | Ultrasonic TRIG | AJ-SR04M TRIG |
159+
| 5 | Ultrasonic ECHO | AJ-SR04M ECHO |
160+
| 7 | WS2812B data | WS2812B DIN |
161+
| 8 | On-board LED | Built-in |
162+
| 9 | Button | Tactile switch |
163+
| 20 | UART1 RX | RYLR998 TXD |
164+
| 21 | UART1 TX | RYLR998 RXD |
165+
| 3, 6, 10 | **FREE** | Reserved |
166+
167+
### INA219 wiring detail (Variant B)
168+
169+
The INA219 is wired with its shunt resistor **in series with the battery's positive terminal**, so a single shunt sees both charge and discharge currents. INA219's signed shunt-voltage register distinguishes the direction automatically.
170+
171+
```
172+
[Battery+] ──[INA219 SHUNT (R_SH)]── [Common+ node] ─┬─ CN3791 BAT pin
173+
│ │ └─ MT3608 boost input
174+
V+ V-
175+
▲ ▲
176+
│ │
177+
INA219 V+ pin connects to battery side of shunt
178+
INA219 V- pin connects to common-node side of shunt
179+
180+
INA219 SDA → ESP32-C3 GPIO1
181+
INA219 SCL → ESP32-C3 GPIO2
182+
INA219 VS → ESP32-C3 3.3V output pin (powers the IC; ≠ load voltage)
183+
INA219 GND → common ground
184+
INA219 ADDR → 0x40 (default; A0/A1 jumpers left open)
185+
```
186+
187+
**Sign convention** (firmware-level interpretation):
188+
- Positive shunt current → battery is **discharging** (current leaving battery toward boost converter)
189+
- Negative shunt current → battery is **charging** (current flowing from CN3791 into battery)
190+
191+
Bus voltage register reads the V- side relative to GND, which is the battery voltage (post-shunt; the shunt drop is millivolts and negligible for SoC display).
192+
193+
### Sensor auto-detect & manual override
194+
195+
Firmware behavior at boot:
196+
197+
1. Initialize I²C bus on GPIO1 (SDA) / GPIO2 (SCL) at 100 kHz
198+
2. Probe address `0x40` with a single read
199+
3. If ACK → `power_mode = "ina219"`, save to NVS (overwrites manual setting only if `manual_override = "auto"`)
200+
4. If NACK → `power_mode = "voltage"`, fall back to ADC on GPIO0 with the existing `battery_monitor` divider logic
201+
5. NVS-stored `power_mode_override` field can force any mode: `"auto"`, `"ina219"`, `"voltage"`, `"disabled"`
202+
203+
Web UI exposes the override under TX Settings → Power Monitoring with a `<select>` dropdown showing the auto-detected value. PWA reads `/api/system → power_mode` and conditionally renders basic vs rich power telemetry.
204+
205+
---
206+
207+
## Bill of Materials (BOM additions)
208+
209+
For the canonical full BOM see `BOM.csv` in this directory. New entries added 2026-04-27 to support the solar-TX power chain:
210+
211+
| Component | Variant | Approx ₹ (Robu / generic) | Notes |
212+
|---|---|---|---|
213+
| Solar panel 6V / 180mA crystalline | A & B | ~150 | Polycrystalline, ~250×80 mm |
214+
| CN3791 MPPT solar charger module | A & B | ~120 | Buck-MPPT with R_PROG charge-current setting |
215+
| 18650 Li-ion 3000 mAh + protected holder | A & B | ~200 | Protection circuit mandatory (CN3791 lacks over-discharge cutoff) |
216+
| MT3608 DC-DC boost module 3.7V→5V | A & B | ~50 | EN pin recommended to GPIO10 for deep-sleep gating |
217+
| 100 kΩ resistor ×2 (voltage divider) | A only | ~5 | 1% tolerance recommended for accurate SoC |
218+
| INA219 module (Adafruit-style, 0.1Ω shunt) | B only | ~120 | Default I²C address 0x40 |
219+
| 4.7 kΩ resistor ×2 (I²C pull-ups) | B only | ~5 | Most INA219 modules already include these onboard |
220+
221+
**Variant A total adder:** ~₹525
222+
**Variant B total adder:** ~₹640
223+
224+
---
225+
226+
## Future expansion (reserved free GPIOs on TX)
227+
228+
| GPIO | Reserved for | Why |
229+
|---|---|---|
230+
| GPIO3 | CN3791 STAT pin (charging-LED output) | Direct read of charger state without inferring from current sign |
231+
| GPIO6 | Future PIR / motion sensor | Wake-on-motion to extend battery on long deep-sleep |
232+
| GPIO10 | MT3608 boost EN pin | Disable boost in deep-sleep to recover ~120 mAh/day quiescent loss |
233+
234+
---
235+
236+
## Firmware compatibility
237+
238+
The shared `battery_monitor` component (in both `public/firmware/transmitter/components/battery_monitor/` and `cloud/firmware/Transmitter-IDF/components/battery_monitor/`) currently provides voltage-divider support. INA219 + auto-detect support is added in **both trees** as a hardware-platform feature (not a cloud-roadmap feature) — see `project_firmware_strategy.md` rule #2 in project memory.
239+
240+
After the firmware update lands, the API surface becomes:
241+
242+
```c
243+
// power_monitor.h (was battery_monitor.h)
244+
245+
typedef enum {
246+
POWER_MODE_NONE,
247+
POWER_MODE_VOLTAGE,
248+
POWER_MODE_INA219,
249+
} power_mode_t;
250+
251+
typedef struct {
252+
power_mode_t mode;
253+
int pct; // 0–100 estimated SoC
254+
uint32_t vbat_mv; // battery voltage
255+
int32_t current_ma; // signed; +ve = discharging, -ve = charging (INA219 only; 0 in voltage mode)
256+
int32_t power_mw; // V × I (INA219 only; 0 in voltage mode)
257+
bool charging; // explicit flag (from current sign or voltage trend)
258+
} power_reading_t;
259+
260+
esp_err_t power_init(void); // auto-detect + NVS-stored override
261+
esp_err_t power_read(power_reading_t *out);
262+
esp_err_t power_set_override(const char *mode); // "auto" | "ina219" | "voltage" | "disabled"
263+
```
264+
265+
---
266+
267+
## License
268+
269+
Hardware design is open: BOM under CC BY-SA 4.0, schematics & wiring docs (this file) under MIT. Firmware in `public/firmware/` is MIT; firmware in `cloud/firmware/` is AGPL-3.0 (proprietary cloud variant).

0 commit comments

Comments
 (0)