
Windmeter modbus interface
pe1mew/windmeters-modbus-interface
Universal interface for cup-anemo- and wind-directon- sensor to modbus

A modbus interface for a resistor wire encoder and a WCH CH32V003J4M6
Wire encoder modbus interface is an open-source printed circuit board by pe1mew, from the pe1mew/wire-encoder-modbus-interface repository on GitHub. It is a 2-layer board of 80 × 80 mm with 36 parts on 27 nets, routed with 302 tracks and 86 vias.
It is built around the CH32V003J4M6, MAX3485ED and BZX84-C3V3, with the DB207 and PESD5V0S1BA among its other parts. Its parts include 10 resistors, 7 connectors, 6 capacitors, 3 diodes and 2 ICs. It belongs with the interfaces and adapters boards and the RISC-V boards of this library.
A CH32V003-based interface board that measures how far a window is open and publishes it on Modbus RTU over RS-485, powered by 24 V passive PoE and designed for daisy-chained field buses.
The measurement comes from a draw-wire encoder: a spring-loaded drum pays out a steel wire attached to the moving window frame, and the drum turns a 10 kΩ potentiometer. The wiper voltage is therefore an absolute measure of the opening — valid the instant power returns, with no homing move and no count to lose.
Two end-of-travel switches report that the window has reached a mechanical stop, read as a supervised resistor ladder that also monitors its own cable.
One firmware build, addressed by a PC1 solder jumper:
| Jumper open | Jumper bridged |
|---|---|
| 40 | 45 |
The 40/45 pair is deliberately clear of the sibling
windmeters-modbus-interface
family (30–37), so both can share one RS-485 segment.
| Area | State |
|---|---|
| Requirements | design/TDS.md v0.7 — 79 requirements (28 FR-MB, 20 FR-S, 23 FR-E, 8 NFR), every one traced to a test row and gate-enforced by software/hil/acceptance/test_traceability.py |
| Drivers | Modbus RTU + debug UART carried over HIL-verified; the encoder driver (software/drivers/wire_encoder/) is written, verified and integrated |
| Product firmware | Complete. Integration stages A–F done (design/integrationPlan.md) — measurement, averaging, persistence and sensing health. 6 364 B flash (44 %), 1 108 B RAM (62 %). A healthy device reports status 0x0000 |
| Hardware/HIL | Schematic and PCB layout in hardware/KiCad/; the build under test is still a breadboard, so every Group A result carries that caveat. HIL rig complete: ADALM2000 RS-485 master, Saleae Logic16, and a built window emulator |
| Testing | 3 host suites (scale, avg, health), 27 HIL scripts, 11 acceptance tests. Results in software/hil/testReport.md |
| Blocked | Four items, all on instruments, not code: adjustable PSU (±15 % supply margin, TP-A03/TP-B23 — the tightest unmeasured number), a PCB (TP-B36), a precision resistance box (FR-E03), a 5 ms bounce injector (FR-E15) |
| Release | No firmware version tagged yet; fw-v1 is a candidate pending the above (software/firmware/RELEASES.md) |
The board reuses the sibling project's design wholesale apart from the sensor front-end:
design/softwareArchitecture.md).The pin budget is the binding constraint. The SOP-8 package bonds
several GPIO onto shared pins (pin 1 is PD6 and PA1; pin 8 is PD1, PD4
and PD5), leaving six physical I/O pins — and every one is committed:
Modbus data, the wiper, DE/RE, the address jumper, the end-switch ladder,
SWIO. Note PC1 and PC4 are assigned the reverse of the obvious way: PC4
carries an ADC channel and PC1 does not, so the analog pin goes to the
switch loop and the boot-time address jumper takes the digital pin. Any
front-end idea that needs another pin does not fit. See
design/TDS.md §4.2.
12 input registers (FC04) and 6 holding registers (FC03/06/16). Inputs:
instantaneous and averaged opening, the minimum/maximum of the current
averaging window, the raw ADC code, status bits (including end-of-travel
reached and switch-loop fault), identification (build + firmware version),
uptime, CRC/served counters, seconds-since-last-valid-reading, and movement
rate. Holdings: zero offset,
measurement window, averaging window, full travel, and the two-point raw
calibration (raw code closed / raw code fully open) — so one image serves
any window, calibrated in the field over Modbus. All persisted in flash
across reset/power-loss; the defaults apply only on first boot / erased
store. The authoritative map with ranges, defaults and requirement IDs is
design/TDS.md §2.7/§2.8.
| Path | Contents |
|---|---|
design/ | The design-document chain (index in design/README.md): scratchBook → description → TDS → softwareArchitecture (+ UML diagrams in design/diagrams/) → driverDevelopment → integrationPlan |
hardware/KiCad/ | Schematic + PCB (KiCad); symbol libraries as git submodules |
hardware/Documentation/ | Component datasheets (HLK-K78xx, DB20x, MAX3483/85, Kradex enclosure) |
software/firmware/ | Product firmware (PlatformIO + ch32v003fun): one release build, plus a bench-only test build |
software/drivers/ | Standalone driver projects with HIL test shells (the verified libraries the product references in place) |
software/hil/ | Scripted hardware-in-the-loop harness: Saleae Logic 2 (MCP) + ADALM2000 (libm2k) + acceptance/ pytest suite |
Doxyfile | Doxygen config — builds a single site (design docs + API reference) with this README as the landing page |
documentation/ | Chip pinout, programmer manual, and sensor reference material |
Clone with submodules:
git clone --recurse-submodules https://github.com/pe1mew/wire-encoder-modbus-interface.gitRequires PlatformIO and a WCH-LinkE on SWIO.
cd software/firmware
pio run # the release build
pio run -t upload # flash via WCH-LinkEencoder_test adds bench-only hooks — never release that binary. Resource
ceilings (14 336 B flash / 1 792 B RAM, NFR-RES01) are enforced as hard
build gates.
The firmware version byte lives in src/version.h; the release process is
documented in RELEASES.md.
Acceptance suite (bench: Saleae Logic 2 with its MCP server, ADALM2000, WCH-LinkE, TTL Modbus rig):
cd software/hil/acceptance
..\.venv-m2k\Scripts\python.exe -m pytest .Only the build-gate rows are populated so far; the protocol and
measurement rows arrive with the driver work. See
software/hil/README.md for instrument setup,
wiring, and the bench-quirk catalogue.
What the device does — design/description.md
is the functional description in prose: sensing principle, what it
reports, commissioning, fault behaviour, and the boundary of what it does
not do. Start there.
Design record — design/README.md indexes the
document chain (requirements → architecture → drivers → integration) and
the UML diagrams.
API + design site — the firmware headers/sources carry full Doxygen,
and Doxyfile folds the design docs in as pages with this
README as the landing page. Build the browsable HTML with:
doxygen Doxyfile # output in documentation/doxygen/html/index.htmlpe1mew/windmeters-modbus-interface —
the sibling project this repository is derived from: same MCU, same
RS-485 front-end, same zero-ISR architecture, and the same potentiometer
reading topology. Its Modbus RTU driver, board/persistence modules and
HIL harness are carried over here, and its design/ chain is the
reference for anything not yet written down.pe1mew/windmeters-modbus-interface-tester —
the Modbus RTU master bench tool (M5Stack AtomS3 + RS-485) used to
exercise devices in this family.Software is provided under a Source-Available Non-Commercial License; documentation and images under CC BY-NC-ND 4.0. See LICENSE and license.md. Third-party datasheets and KiCad library submodules remain under their owners' terms.
Remko Welling (PE1MEW)
| Qty | Value | Footprint | References |
|---|---|---|---|
| 4 | 10k | Resistor_SMD:R_1206_3216Metric_Pad1.30x1.75mm_HandSolder | R4, R6, R7, R11 |
| 4 | ~ | Jumper:SolderJumper-3_P1.3mm_Bridged12_Pad1.0x1.5mm_NumberLabels | JP2, JP3, JP4, JP5 |
| 3 | 100n | Capacitor_SMD:C_1206_3216Metric_Pad1.33x1.80mm_HandSolder | C1, C2, C5 |
| 2 | 20k | Resistor_SMD:R_1206_3216Metric_Pad1.30x1.75mm_HandSolder | R2, R3 |
| 2 | 68k | Resistor_SMD:R_1206_3216Metric_Pad1.30x1.75mm_HandSolder | R8, R9 |
| 1 | 100u | Capacitor_THT:CP_Radial_D8.0mm_P5.00mm | C3 |
| 1 | 120 | Resistor_SMD:R_1206_3216Metric_Pad1.30x1.75mm_HandSolder | R1 |
| 1 | 1n | Capacitor_SMD:C_1206_3216Metric_Pad1.33x1.80mm_HandSolder | C6 |
| 1 | 4k7 | Resistor_SMD:R_1206_3216Metric_Pad1.30x1.75mm_HandSolder | R5 |
| 1 | 4u7 | Capacitor_THT:CP_Radial_D5.0mm_P2.50mm | C4 |
| 1 | Address select | Jumper:SolderJumper-2_P1.3mm_Open_Pad1.0x1.5mm | JP6 |
| 1 | BZX84-C3V3 | Package_TO_SOT_SMD:SOT-23 | D2 |
| 1 | CH32V003J4M6 | Package_SO:JEITA_SOIC-8_3.9x4.9mm_P1.27mm | U1 |
| 1 | DB207 | my-KiCad-library:DB207-DIP-4 | B1 |
| 1 | Draw-wire | Connector_JST:JST_NV_B03P-NV_1x03_P5.00mm_Vertical | J4 |
| 1 | End switch close | Connector_JST:JST_NV_B03P-NV_1x03_P5.00mm_Vertical | J6 |
| 1 | End switch open | Connector_JST:JST_NV_B03P-NV_1x03_P5.00mm_Vertical | J5 |
| 1 | LOGO_LogoRFSee_37x8mm | my-KiCad-library:LOGO_LogoRFSee_37x8mm | G*** |
| 1 | MAX3485 | Package_SO:SOIC-8_3.9x4.9mm_P1.27mm | U2 |
| 1 | MODBUS-P1 | my-KiCad-library:CONN_215877-1 | J1 |
| 1 | MODBUS-P2 | my-KiCad-library:CONN_215877-1 | J3 |
| 1 | PESD5V0S1BA | Diode_SMD:D_SOD-323_HandSoldering | D3 |
| 1 | Programming | Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical | J2 |
| 1 | SM712_SOT23 | Package_TO_SOT_SMD:SOT-23 | D1 |
| 1 | enable term. | Jumper:SolderJumper-2_P1.3mm_Open_Pad1.0x1.5mm | JP1 |
| 1 | ~ | my-KiCad-library:HLK-K7803-500R3 | P1 |
It measures 80 × 80 mm and has 2 copper layers, 1.6 mm thick.
36 parts, built around the CH32V003J4M6, MAX3485ED, BZX84-C3V3 and DB207. 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 pe1mew/wire-encoder-modbus-interface repository on GitHub, at the commit this page was made from: the board is hardware/KiCad/wire-encoder-modbus-interface.kicad_pcb and its schematic hardware/KiCad/wire-encoder-modbus-interface.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 pe1mew before reusing the design.

pe1mew/windmeters-modbus-interface
Universal interface for cup-anemo- and wind-directon- sensor to modbus



do2mad/messsystem-1mhz
Ein kleines Messgerät für den Reparaturplatz: Es überwacht sechs Gleichspannungen (0–30 V) und eine Wechselspannung (9 V) gleichzeitig und zeigt sie auf einem 20×4-LCD an.

74th/stickpoint-firmware
Pointer module with joystick (PIM447 Compatible)

KaiPereira/Alchemical-Cosmological-Badges
These are alchemical-cosmological PCB hackathon badges I designed in a day for the Fallout hackathon in Shenzhen, China.


tvecera/ch32-projects
A collection of example projects and experiments for CH32-series microcontrollers from WCH (Nanjing Qinheng Microelectronics).