- MATLAB 57.9%
- Python 19.4%
- C 16.1%
- Shell 6.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
- InitFDTD OverSampling=1 in _auto/_dirac: default (4) decimates port dumps to 4x Nyquist (~78 samples) -> ~162 MHz S11 bins, aliased curves - nearest-bin S11@915 print (old +/-1 MHz window matched no grid point) - show_3d=0 switch: CSXGeomPlot blocks the run until the VTK window closes - remove stale simulate_picsense.m (hand-placed L5/C7 collide with auto-import; superseded by simulate_picsense_auto.m) - gitignore tmp_snapshot*/ baselines |
||
| firmware | ||
| kicad | ||
| references | ||
| resources | ||
| simulation | ||
| tx_emulator | ||
| .env.example | ||
| .gitignore | ||
| decode_pickle.sh | ||
| decode_pickle_soapy.sh | ||
| decode_pickle_tcp.sh | ||
| LICENSE | ||
| README.md | ||
PICsense
PICsense is a small ecosystem of extremely inexpensive, simple wireless sensors for home automation and similar low-criticality uses. The first member of the ecosystem is the PIC[k]LE — a low-cost transmitter board powered by a single CR2032. Depending on the configured sample rate, the target battery lifetime is at least one year of deployment.
Over time, PICsense is intended to grow into a plug-and-play ecosystem of supported sensor boards and add-ons, with an interface control document (ICD) defining the targetted sensor classes and the protocol between them and the transmitter.
The current firmware implements no wireless security. Future releases are expected to make spoofing and decoding significantly harder for listeners — this likely requires a full rtl_433 decoder (see issue #10) — to make the platform more generally useful. The design is not aimed at resistance to physical tampering: if someone has physical access to the sensor, they can figure out how to decode or spoof it. Do not rely on this hardware for critical applications — it's for things like soil moisture, a fish tank water level, or whether a window is open.
Built-in sensors
- temperature (built into the PIC MCU)
- battery (onboard sampling circuit)
External sensor support
External sensors are powered directly from the unregulated battery voltage. Supported (or planned) classes:
- resistive
- capacitive
- active sensor*
- must support unregulated 3V battery input (powered by CR2032)
- should draw less than 10 mA and stabilize output in under 25 µs
Ideas: capacitive water level sensor, active hall effect switch, active IR closure beam.
Radio
- 433/915 MHz ISM bands (current firmware transmits at 922.875 MHz)
- OOK, Manchester encoded, 2 kbps (4 kbps half-bit rate)
- 15-byte packets:
field bits notes preamble 16 0xCEBC device ID 8 packet count 24 temperature raw 16 10-bit ADC, left-padded FVR raw 16 10-bit ADC, left-padded analog raw 16 10-bit ADC, left-padded TX status 16 bit 15 = FVR error flag CRC 8
Receiving is done with rtl_433 using a
flex decoder spec (see decode_pickle.sh), with output forwarded to MQTT.
The decoder emits raw ADC values; the Home Assistant config below does the
math from them.
Repository layout
| directory | contents |
|---|---|
firmware/ |
PIC16L1509 firmware (MPLAB/XC8, CMake) — see firmware/PIC[k]LE/README.md |
kicad/ |
KiCad schematic, PCB, and footprints |
simulation/ |
openEMS FDTD antenna simulation scripts |
tx_emulator/ |
GNU Radio/HackRF TX emulator for testing without hardware |
references/ |
datasheets and application notes |
Firmware
Build and flash instructions are in firmware/PIC[k]LE/README.md.
Requires the MPLAB VS Code extension (XC8 v3.10), CMake ≥ 3.24, and Ninja.
Receiving data
decode_pickle.sh runs rtl_433 with the flex decoder and publishes decoded
packets to MQTT. It reads its configuration from a .env file in the repo
root — copy .env.example to .env and fill in your broker details
(MQTT_HOST, MQTT_PORT, MQTT_USER, MQTT_PASSWORD, topics). .env is
gitignored; never commit real credentials.
Sample Home Assistant MQTT sensor config
sensor:
# pickle v0.1
- name: "PIC[k]LE Voltage"
state_topic: &pickle_event_topic "pickle/events"
value_template: "{{ (2.048 * 1023.0 / value_json.fvr_raw) | round(3) }}"
unit_of_measurement: "V"
availability_topic: "pickle/availability"
state_class: "measurement"
- name: "PIC[k]LE Temperature"
state_topic: *pickle_event_topic
value_template: "{{ ((0.659 - (2.048 / value_json.fvr_raw * 1023.0) / 2 * ( 1 - (value_json.temp_raw / ( 1023 )))) / 0.00132 - 40 + 50) | round(2) }}"
unit_of_measurement: "°C"
availability_topic: "pickle/availability"
state_class: "measurement"
- name: "PIC[k]LE ADC Voltage"
state_topic: *pickle_event_topic
value_template: "{{ (2.048 / value_json.fvr_raw * value_json.adc_raw) | round(3) }}"
unit_of_measurement: "V"
availability_topic: "pickle/availability"
state_class: "measurement"
TX emulator
tx_emulator/ contains a GNU Radio flowgraph that mimics the sensor over the
air using a HackRF, so the receive path can be tested without hardware. See
tx_emulator/README.md for setup.
Simulation
simulation/ holds openEMS FDTD scripts that model the on-board
antenna (S11, current distribution). The scripts read the openEMS install
location from OPENEMS_HOME (default /opt/openEMS).
Note: the simulation work is currently in development — the models and results are not yet validated, and generated plots are not committed.
Hardware revisions
- v0.1 — concept proof; the board as currently documented here.
- v0.2 — planned; more capable with a cleaner design.
Common debug/programming issues
- rtl_433 doesn't sense any packets
- power-cycle the pickle; it may have put the transmitter into a bad state and can't recover
- cannot program the device, "not in low voltage programming mode"
- check the project settings — it's not possible to accidentally put the device in HVP mode
License
Hardware design: CERN-OHL-S v2 (strongly reciprocal).
