Skip to the content
PCBKitNew board
2 layers24.4 × 112.5 mmSoil sensor, the printed circuit board in 3D

A BLE soil moisture + temperature sensor for houseplants: a custom fork-shaped PCB (CC2340R5MODA + resistive probe, CR2032 coin cell) plus an Android app that logs and charts the history.

Size
24.4 × 112.5 mm
Copper layers
2
Thickness
1.6 mm
Parts
24
Nets
24
Pads
78
Tracks, vias
100, 91
Pours
5
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
20 Jul 2026
Updated
29 Aug 2026

Overview

Soil sensor is an open-source printed circuit board by Guarecuco, from the Guarecuco/soil-sensor repository on GitHub. It is a 2-layer board of 24.4 × 112.5 mm with 24 parts on 24 nets, routed with 100 tracks and 91 vias.

It is built around the CC2340R5MODAN0MHAR, BSS84 and MMBT3904. Its parts include 8 capacitors, 5 resistors, 2 transistors, 1 IC and 1 connector. It belongs with the sensors and measurement boards of this library.

Main components

3

README

README.md

Soil Sensor

firmware

A BLE soil moisture + temperature sensor for houseplants: a custom fork-shaped PCB (CC2340R5MODA + resistive probe, CR2032 coin cell) plus an Android app that logs and charts the history.

text
soil-sensor/
├── firmware/   TI SimpleLink BLE5-Stack firmware (FreeRTOS, ticlang)
├── android/    Kotlin/Compose companion app
├── hardware/   KiCad project + JLCPCB fabrication/assembly output
└── docs/       screenshots, BLE protocol reference

PCB render, top layer PCB render, bottom layer

Fork-shaped PCB (top / bottom). Render by KiCad.

App screenshot

How it works

The board samples its resistive fork probe every 10 minutes and keeps a rolling 7-day buffer. The Android app connects, pulls only the samples it hasn't seen yet, and keeps its own unbounded local history.

The app can also push a signed firmware image to the sensor over BLE (on-chip OAD via MCUboot).

Hardware

KiCad project + JLCPCB fabrication/assembly output in hardware/.

  • MCU: CC2340R5MODA module (to simplify RF part)
  • Sensor: two exposed copper tines on the PCB itself act as a resistive soil probe (based on SparkFun SEN-13322), gated by a P-MOS switch so current only flows through the soil during a reading. Read via the CC2340's own ADC
  • Temperature: CC2340's on-die sensor
  • Battery: CR2032 coin cell; level estimated from VDDS via the CC2340's internal Battery Channel ADC (no fuel-gauge IC)
  • Debug: standard 10-pin Tag-Connect

Firmware

SDK basic_ble example, stripped to a peripheral-only role plus on-chip OAD:

  • app/app_soil_sensor.c - the glue: a 10-min Clock takes a sample (soil + battery), stores it, notifies subscribers, and reports its own version over Device Information at boot
  • app/soil_sensor.c - GPIO-gated ADC for the fork probe + die temperature
  • app/soil_history.c - RAM ring buffer (1008 samples ≈ 7 days) with a never-reset sequence number per sample so a client can resume a sync
  • app/battery_gauge.c - VDDS battery estimate via the internal Battery Channel ADC
  • app/Profiles/* - GATT services: custom soil sensor, Battery (0x180F + a custom mV characteristic), on-chip OAD glue

Building

Requires the SimpleLink Lowpower F3 SDK, SysConfig, and the ticlang compiler.

The makefile pulls SYSCONFIG_TOOL and TICLANG_ARMCOMPILER from the SDK's imports.mak ($SDK/imports.mak), which ships with placeholder /home/username/... paths. Edit those two ?= lines once to point at your real installs, e.g.:

make
SYSCONFIG_TOOL      ?= /home/you/ti/ccs2100/ccs/utils/sysconfig_1.28.0/sysconfig_cli.sh
TICLANG_ARMCOMPILER ?= /home/you/ti/ccs2100/ccs/tools/compiler/ti-cgt-armllvm_5.1.1.LTS

Then just:

sh
cd firmware/freertos/ticlang
gmake

Outputs:

  • soil_sensor.hex / soil_sensor.out - full-flash image for a debugger.
  • soil_sensor_ota.bin - the OAD image. Version is MAJOR.MINOR.<git commit count> (e.g. 1.0.6), stamped by tools/oad_version.sh. Build from a repo checkout; a CCS build copies the sources out of git and the commit count falls back to 1.0.0.
  • soil_sensor_v1.bin / _v2.bin - SDK fixed 1.0.0 / 2.0.0 placeholders, handy for OAD upgrade testing.

First flash (one-time, needs a debugger)

OAD updates a running device; the first flash needs three images at fixed addresses. Flash all three with UniFlash:

ImageWhere fromAddress
mcuboot_onchip_LP_EM_CC2340R53_nortos_ticlang.hex$SDK/examples/rtos/LP_EM_CC2340R53/ble/prebuilt_hexfiles/ (prebuilt)AUTO
basic_persistent_LP_EM_CC2340R53_freertos_ticlang.bin$SDK/examples/rtos/LP_EM_CC2340R53/ble/basic_persistent/ (build it)0x6000
soil_sensor_ota.binthis repo, built above0x34000

Use the prebuilt MCUboot hex. A self-built one defaults to a generic flash map that never boots the app slot.

Firmware updates over BLE (OAD)

Tap the update icon next to "Disconnect" in the app, pick soil_sensor_ota.bin, and confirm the version/size shown.

Tuning

  • Sample interval: SOIL_SAMPLE_PERIOD_MS in app/app_soil_sensor.c (currently 10 minutes).
  • Moisture thresholds: the raw ADC code from the resistive divider is ratiometric against VDDS (higher code = lower soil resistance = wetter) and depends on your probe geometry, resistor values, and soil/pot. Use the CSV export to work out real thresholds for your plant.

Android app

Location: android/. Kotlin + Jetpack Compose, Material 3 (dynamic color), Room, no third-party BLE or charting libraries.

Building

sh
cd android
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk

Requires local.properties pointing at an Android SDK (sdk.dir=...). It is not checked in, so create your own. minSdk 31 (Android 12), targetSdk/compileSdk 37.

BLE protocol

Services, characteristics, and record layout: docs/PROTOCOL.md.

Parts

24
QtyValueFootprintReferences
4100nFCapacitor_SMD:C_0603_1608MetricC2, C3, C4, C5
3FiducialFiducial:Fiducial_1mm_Mask2mmFID1, FID2, FID3
3MountingHoleMountingHole:ToolingHole_1.152mmH1, H2, H3
2100kResistor_SMD:R_0603_1608MetricR1, R4
10Resistor_SMD:R_0402_1005MetricR5
1100Resistor_SMD:R_0603_1608MetricR2
110kResistor_SMD:R_0603_1608MetricR3
110uFCapacitor_SMD:C_0805_2012MetricC1
115pFCapacitor_SMD:C_0402_1005MetricC6
11pFCapacitor_SMD:C_0402_1005MetricC7
1BSS84Package_TO_SOT_SMD:SOT-23Q2
1CC2340R5MODAN0MHARCC2340R5MODA:MHA0024A-MFGU1
1CR2032 3VBattery:BatteryHolder_Keystone_3034_1x20mmBT1
1Conn_02x05_Counter_ClockwiseConnector:Tag-Connect_TC2050-IDC-NL_2x05_P1.27mm_VerticalJ1
1DNMCapacitor_SMD:C_0402_1005MetricC8
1MMBT3904Package_TO_SOT_SMD:SOT-23Q1

Questions

How big is the Soil sensor PCB?

It measures 24.4 × 112.5 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Soil sensor use?

24 parts, built around the CC2340R5MODAN0MHAR, BSS84 and MMBT3904. 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.

Where can I download the Soil sensor KiCad files?

From the Guarecuco/soil-sensor repository on GitHub, at the commit this page was made from: the board is hardware/soil_sensor.kicad_pcb and its schematic hardware/soil_sensor.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Soil sensor design in my own project?

Its repository states no licence, so its author keeps all rights: ask Guarecuco before reusing the design.

Similar boards

  • 6 layers43.2 × 74.4 mmMonolith, the printed circuit board in 3D

    Monolith

    MidwestMotorBoy/Battery-Bank

    Monolith: an ultralight IP67 power bank for backpacking. 4S BAK 65E 21700 (91 Wh, under the 100 Wh airline limit), two bidirectional 100 W USB-C PD ports, Bluetooth LE (TI CC2340) with an iPhone app.

    289 parts
  • 6 layers150 × 100 mmNV Meter rev b, the printed circuit board in 3D

    NV Meter rev b

    curtisseizert/Nanovoltmeter

    A low noise nanovoltmeter design files and code

    552 parts44
  • 2 layers42.7 × 48.8 mmDuct turbo fan controller v4, the printed circuit board in 3D

    Duct turbo fan controller v4

    scattym/kicad-duct-turbo-fan-controller

    Fan controller projects for the duct turbo, terrabloom and ac infinity fans

    46 parts4GPL-3.0
  • 4 layers120 × 103.9 mmBALANCING CUBEV1.01, the printed circuit board in 3D

    BALANCING CUBEV1.01

    Evc-r/Balancing-Cube-STM32

    STM32F411CEU6 and ICM-20948 v2 self-balancing cube firmware port and integration plan.

    76 parts2
  • 4 layers227.8 × 132.5 mmPanel, the printed circuit board in 3D

    Panel

    YDrip/ydrip-pcb

    YDrip hardware files

    556 parts2CERN-OHL-W-2.0
  • 4 layers40.5 × 100 mmVcafd, the printed circuit board in 3D

    Vcafd

    GuavTek/ACID_VCA

    A eurorack VCA with a wavefolder and drive/clipping

    223 parts1CERN-OHL-W-2.0
  • 4 layers125 × 85 mmESP32 Educational Board, the printed circuit board in 3D

    ESP32 Educational Board

    nakul-biovaco/Embedsys-embedded-educational-board

    Industrial-grade ESP32-WROOM-32E educational development board (4-layer ENIG PCB, BQ24075 power-path, dual regulators, ST7789 IPS display & SHT40 sensor). 0 DRC certified.

    175 parts1
  • 2 layers74 × 60 mmDaughtercard, the printed circuit board in 3D

    Daughtercard

    TenOfNine/SmartKroneSplitFlap

    This repository contains the software and architecture for old Krone SplitFlap Displays. It works by using an ESP32 as a Master and then daisychains all modules using a daughter board for each element.

    53 parts1