super simple PIC-based wireless sensor platform
  • MATLAB 57.9%
  • Python 19.4%
  • C 16.1%
  • Shell 6.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
daru 2059a0c100 fix(sim): full-rate port dumps, gate 3D viewer, drop stale script
- 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
2026-11-05 12:05:31 -06:00
firmware chore: fix project name casing to PICsense in prose references 2026-09-29 23:49:56 -05:00
kicad refactor: move simulation/ to repo root 2026-09-29 23:20:35 -05:00
references rename an1333 file 2026-07-26 22:19:26 -05:00
resources docs: add v0.1 board photo to README 2026-09-29 23:39:08 -05:00
simulation fix(sim): full-rate port dumps, gate 3D viewer, drop stale script 2026-11-05 12:05:31 -06:00
tx_emulator chore: prep for public release 2026-09-29 22:37:53 -05:00
.env.example chore: fix project name casing to PICsense in prose references 2026-09-29 23:49:56 -05:00
.gitignore fix(sim): full-rate port dumps, gate 3D viewer, drop stale script 2026-11-05 12:05:31 -06:00
decode_pickle.sh chore: prep for public release 2026-09-29 22:37:53 -05:00
decode_pickle_soapy.sh refactor: move simulation/ to repo root 2026-09-29 23:20:35 -05:00
decode_pickle_tcp.sh refactor: move simulation/ to repo root 2026-09-29 23:20:35 -05:00
LICENSE chore: prep for public release 2026-09-29 22:37:53 -05:00
README.md Update README.md 2026-10-07 03:02:01 +00:00

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.

PICsense v0.1

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).