RG-15 Rain Sensor¶
The Hydreon RG-15 is an optical rain sensor used in SQMeter to flag sky quality readings taken during active rainfall. Rain causes light scattering that makes SQM values unreliable, so the RG-15 lets the firmware mark affected readings accordingly. It is an optional peripheral.
Initialised means the ESP32 opened the UART. Online means the firmware received and parsed a valid RG-15 response.
Specifications¶
| Spec | Value |
|---|---|
| Supply voltage | 5 V or 12 V |
| Interface | UART (serial) |
| Default baud rate | 9600 |
| Output | ASCII polled or event-driven |
| Rain rate range | 0–999 mm/hr |
| Operating temp | −40 °C to +60 °C |
Wiring¶
The connector on the RG-15 PCB is labelled J2. Pin 1 is closest to the housing edge marked with a triangle.
| J2 Pin | Label | Connect to |
|---|---|---|
| 1 | GND | ESP32 GND |
| 2 | V+ | 5 V supply |
| 3 | OUT (open-collector) | Not required — leave unconnected |
| 4 | Serial OUT (TX from sensor) | ESP32 RX GPIO (default: GPIO 18) |
| 5 | Serial IN (RX into sensor) | ESP32 TX GPIO (default: GPIO 19) |
Pin direction
J2 pin 4 is the sensor's TX line — connect it to the ESP32 RX pin. J2 pin 5 is the sensor's RX line — connect it to the ESP32 TX pin.
Voltage levels
The RG-15 serial lines operate at 5 V. Most ESP32 GPIO inputs are 5 V-tolerant, but verify your specific board before connecting without a level shifter.
Serial protocol¶
The firmware communicates with the RG-15 over UART at 9600 baud, 8N1 by default.
If you enable rain.debugUart, the firmware logs the UART command/response flow to the serial console. This is safe to use in the field and does not expose WiFi, MQTT, or OTA secrets.
Poll command¶
In polling mode the firmware sends R\n to request a reading. The sensor responds with one ASCII line:
| Field | Description |
|---|---|
Acc |
Accumulation since the last poll (mm or in) |
EventAcc |
Accumulation since the start of the current rain event |
TotalAcc |
Cumulative total since the sensor last powered on |
RInt |
Current rain intensity (mm/h or in/h) |
Optional flag characters may appear after the unit suffix:
| Character | Meaning |
|---|---|
i |
Hardware / lens fault |
o |
Emitter saturation |
Configuration commands¶
The firmware sends these commands on startup to apply the configured mode:
| Command | Effect |
|---|---|
M |
Set metric output (mm) |
I |
Set imperial output (inches) |
H |
Set high resolution (0.01 mm / 0.001 in) |
L |
Set low resolution (0.2 mm / 0.01 in) |
DIP switches vs serial configuration¶
The RG-15 has DIP switches on the PCB that set defaults for units and resolution. On every power cycle the sensor reads the DIP switches and resets to those defaults.
SQMeter re-applies the configured units and resolution over serial each time the firmware starts or the sensor is reconfigured. This ensures the sensor operates in the mode you specified regardless of the DIP switch positions.
If you set units or resolution to "switch", the firmware does not send the corresponding command and the DIP switch setting is used instead.
Configuration¶
Set it up in Settings → Sensors → Rain sensor, or add the rain block via POST /api/config:
"rain": {
"enabled": true,
"rxPin": 18,
"txPin": 19,
"baudRate": 9600,
"debugUart": false,
"mode": "polling",
"resolution": "high",
"units": "metric",
"pollIntervalMs": 5000,
"rainClearDelayMs": 900000,
"dailyResetEnabled": true,
"dailyResetHour": 0,
"dailyResetMinute": 0
}
| Field | Type | Default | Description |
|---|---|---|---|
enabled |
boolean | false |
Enable the RG-15 sensor |
rxPin |
integer | 18 |
ESP32 GPIO connected to sensor Serial OUT |
txPin |
integer | 19 |
ESP32 GPIO connected to sensor Serial IN |
baudRate |
integer | 9600 |
Serial baud rate (2400, 4800, 9600, 19200) |
debugUart |
boolean | false |
Log RG-15 UART command/response traffic |
mode |
string | "polling" |
Compatibility field; RG-15 communication is polling-only |
resolution |
string | "high" |
"high", "low", or "switch" |
units |
string | "metric" |
"metric", "imperial", or "switch" |
pollIntervalMs |
integer | 5000 |
Polling-mode interval between R read commands |
rainClearDelayMs |
integer | 900000 |
Local delay before SQMeter clears its raining latch after intensity returns to zero |
dailyResetEnabled |
boolean | false |
Send the RG-15 O command once per day to reset TotalAcc |
dailyResetHour |
integer | 0 |
Local-hour reset schedule for TotalAcc |
dailyResetMinute |
integer | 0 |
Local-minute reset schedule for TotalAcc |
Communication¶
SQMeter uses polling-only RG-15 communication. The firmware sends R on the configured pollIntervalMs cadence and reads the response. This proves the UART command/response path on every poll.
EventAcc is maintained by the RG-15 for the current rain event and resets about 60 minutes after the last detected drop. SQMeter also exposes a local raining boolean that stays true for rainClearDelayMs after the last non-zero intensity reading, so you can treat an event as over after 10, 15, 45, or another configured number of minutes.
TotalAcc persists until the RG-15 O reset command is sent or the counter rolls over. SQMeter can send O manually from the System page or on a daily schedule, commonly at 00:00, so the value can be treated as a resettable daily total instead of a lifetime total.
REST API¶
GET /api/sensors (and /ws/sensors, MQTT <base>/state) includes a rain group while the rain sensor is enabled. Values are always metric - an RG-15 set to inches is converted:
{
"rain": {
"status": "ok",
"ageMs": 40,
"raining": false,
"rainingNow": false,
"intensity": 0.0,
"eventAccumulation": 0.0,
"sensorEventAccumulation": 2.4,
"totalAccumulation": 12.34,
"lensFault": false,
"emitterSaturated": false
}
}
| Field | Description |
|---|---|
status |
ok, missing (not responding), error or stale. Other fields only appear when ok |
ageMs |
Age of the last valid reading |
raining |
Rain, held for rainClearDelayMs after the last drop |
rainingNow |
The RG-15 reports rain right now |
intensity |
Rain intensity, mm/h |
eventAccumulation |
SQMeter's event total, cleared by rainClearDelayMs |
sensorEventAccumulation |
The RG-15's own EventAcc (cleared by its own ~60 min timer) |
totalAccumulation |
Resettable total (TotalAcc), mm |
lensFault |
The sensor reported a hardware / lens fault |
emitterSaturated |
The sensor reported emitter saturation |
GET /api/status has the sensor's health under sensors.rain and UART diagnostics under diagnostics.rain:
{
"sensors": { "rain": { "status": "ok", "ageMs": 40 } },
"diagnostics": {
"rain": {
"state": "online", "uartOpened": true, "rxPin": 18, "txPin": 19, "baudRate": 9600, "uartPort": 1,
"lastCommand": "R", "lastAck": "R", "lastResponse": "Acc 0.00 mm, EventAcc 0.00 mm, TotalAcc 1.24 mm, RInt 0.00 mmph",
"timeouts": 0, "parseErrors": 0, "successfulReads": 42,
"lastPollAgeMs": 40, "lastResponseAgeMs": 40, "lastSuccessfulReadAgeMs": 40,
"lastRainDetectedAgeMs": 1260000, "lastTotalResetAgeMs": 3600000,
"softwareVersion": "1.000", "softwareBuildDate": "Sep 23 2020", "resetReason": "PwrUp", "powerOnDays": 13, "emitterTotal": 19
}
}
}
| Field | Description |
|---|---|
state |
Connection state: disabled, configured, uart_opened, configuring, command_sent, awaiting_response, acknowledged, reading_received, online, stale, timeout or parse_error |
uartOpened, rxPin, txPin, baudRate, uartPort |
The serial port in use |
lastCommand, lastAck, lastResponse |
The last command sent, its acknowledgement and the last line received |
lastError |
The last communication or parse error, if any |
timeouts, parseErrors, successfulReads |
Counters since the device started |
lastPollAgeMs, lastResponseAgeMs, lastSuccessfulReadAgeMs |
Time since the last R poll, any reply, and the last reading that parsed |
lastRainDetectedAgeMs |
Time since rain was last seen (drives raining) |
lastTotalResetAgeMs, lastRebootAgeMs |
Time since the last O (total reset) and K (reboot) |
softwareVersion, softwareBuildDate, resetReason, powerOnDays, emitterTotal |
What the RG-15 reported in its start-up banner |
Ages, lastError and the banner fields only appear once there's something to report. With the rain sensor disabled, neither sensors.rain nor diagnostics.rain appears.
Communication test¶
Use POST /api/sensors/rg15/test to trigger a manual RG-15 read and inspect the raw response details:
The response includes the command sent, bytes written, raw response, acknowledgement status, parse status, elapsed time, and a troubleshooting hint if the read times out.
Use these endpoints from the System page or directly when bringing up hardware:
curl -X POST http://sqmeter.local/api/sensors/rg15/reset-total
curl -X POST http://sqmeter.local/api/sensors/rg15/reboot
reset-total sends O and expects the o acknowledgement. reboot sends the RG-15 restart command K; after reboot, the sensor is marked offline until fresh UART traffic is received and parsed.
MQTT¶
The rain group above is published in <base>/state (when Rain is on under Settings → Network → MQTT → Publish), and the UART diagnostics in <base>/diagnostics when Diagnostics is on. See MQTT.
Sensor placement¶
- Mount outdoors with an unobstructed view of the sky.
- Keep away from roof overhang drip zones — drips from overhangs trigger false positives.
- Mount on a level surface so water drains correctly.
- Avoid locations where debris or bird activity is likely.
Freezing climates
Hydreon offers the RG-15H heated variant for installations where icing is a concern. It is a drop-in replacement — the interface and wiring are identical.
Troubleshooting¶
| Symptom | Likely cause | Fix |
|---|---|---|
initialized: true but online: false |
UART opened but no valid RG-15 response yet | Check wiring, baud rate, and sensor power |
status: 2 (read error / invalid data) |
Wiring fault or malformed response | Verify J2 pin 4 → ESP32 RX, J2 pin 5 → ESP32 TX |
status: 3 (timeout) |
Sensor not sending data | Check power, baud rate, mode setting, and the debug UART logs |
| Values always zero | Sensor in DIP switch units that differ from config | Set resolution/units to match, or use "switch" mode |
lensBad: true |
Lens fouled or hardware fault | Clean the lens; replace sensor if fault persists |
emSat: true |
Very intense light source near sensor | Check for direct sunlight hitting the emitter |
What successful debug logs look like:
[RG15] UART begin rx=16 tx=17 baud=9600
[RG15] forcing metric units: TX "M"
[RG15] RX ack "m" after 42ms
[RG15] forcing high resolution: TX "H"
[RG15] RX ack "h" after 39ms
[RG15] poll TX "R"
[RG15] RX raw: "Acc 0.00 mm, EventAcc 0.00 mm, TotalAcc 1.24 mm, RInt 0.00 mm/h"
[RG15] parsed acc=0.00 event=0.00 total=1.24 intensity=0.00 unit=mm
[RG15] online=true age=0ms
What timeout logs look like:
[RG15] UART begin rx=16 tx=17 baud=9600
[RG15] forcing metric units: TX "M"
[RG15] timeout waiting for ack "m" after 500ms
[RG15] sensor remains offline: no UART response received
If you still get no response:
- Swap RX/TX if the wiring is reversed
- Check that the RG-15 and ESP32 share a common ground
- Verify the configured GPIO pins are correct and not shared with another peripheral
- Confirm the baud rate matches the sensor
- Confirm the sensor has power and the serial level is compatible
- Use a USB-UART adapter or logic analyser if you need to confirm the line activity directly