For obvious reasons it’s important for an automated observatory to detect when it’s raining and do an emergency close of the roof or close the slit for a dome. While there are a few cheap rain detectors from China available for a few dollars, they tend to be relatively insensitive and corrode rapidly.
A good inexpensive alternative with excellent sensitivity is the RG-11 Rain Gauge from Hydreon Corporation1. For $ 59 USD, this device will detect a single raindrop and close a relay that allows a computer to take action to avoid damage to equipment. Communicating with an Arduino allows us to connect to a host PC via a USB connection so the host can regularly query the rain gauge's status. We will use an Arduino Nano to watch the rain gauge.
You see below a simple circuit where a relay on the rain gauge closes when it detects rain. The Common terminal is connected to GND on the Arduino and the Normally Open terminal is tied to the D2 pin. The D2 pin has a pullup resister between the pin and +5v so the input doesn’t float when there’s a HIGH condition. When the rain gauge detects rain, it closes a circuit between COM and NO which drives the signal of the D2 pin LOW, signalling an unsafe condition. The Rain Gauge is connected to 12v power. DIP switches on the RG-11 board allow you to select sensitivity. In our case we turn on switch 5 which sets the device to very sensitive, turn off when rain not detected, and no dark mode (turns on when dark).
The Arduino sketch supporting this circuit is similarly reasonably simple. After initializing a pinState variable and then defining that safeState is a HIGH reading on the pin, the setup() function sets pin 2 (Digital pin 2) for the connection to the RG-11 and also sets up Pin 13 as an output. Pin 13 controls the onboard LED on the Nano so it’s convenient when debugging to have it mirror the state of pin 2.
The Nano USB port is initialized at 9600 baud, and the initial state is sent as notsafe#. The loop() function then reads the D2 pin state, toggles the onboard LED on pin 13 depending on the result, and then, if there has been a request to provide the pin state, sends either safe# or not safe # to the serial port.
bool pinState = LOW;
bool safeState = HIGH ; // Rain the pin goes high
void setup() {
pinMode(2, INPUT_PULLUP);
pinMode(13, OUTPUT); // Onboard LED
Serial.begin(9600); // initialize serial
Serial.flush(); // flush the port
Serial.print("notsafe#"); // send notsafe# as first state
}
void loop() {
String cmd;
pinState = digitalRead(2);
if (pinState == safeState) {
digitalWrite(13,HIGH);
}
if (pinState != safeState) {
digitalWrite(13,LOW);
}
if (Serial.available() > 0) {
cmd = Serial.readStringUntil('#');
if (cmd.substring(0,1) == "S") {
if (pinState == safeState) {
Serial.print("safe#");
digitalWrite(13,HIGH);
}
if (pinState != safeState) {
Serial.print("notsafe#");
digitalWrite(13,LOW);
}
}
}
}
The Python code that runs on the host server to talk to the Arduino makes use of the pyserial library, so you will need to load that library with pip:
python -m pip install pyserial
After that the Python code is fairly simple to send a request for status to the Arduino and interpret the response every 5 secs:
import serial
import time
ser = serial.Serial('/dev/ttyUSB0',9600, timeout=1)
if (ser.is_open):
print("Connected to: ",ser.name)
else:
print ("Error opening port exiting ...")
exit(-1)
while (True):
# Send status request
ser.write(b'S#')
line = ser.readline()
if (line == b"safe#"):
rainDetected=False
print("No rain...\n")
elif (line == b"notsafe#"):
rainDetected=True
print("Rain detected...\n")
else:
rainDetected=True
print("No reading...\n")
time.sleep(5)
ser.close()
The Arduino on my Linux test system comes up as /dev/ttyUSB0, but your system may differ – use sudo dmesg
on Linux to see what port is added when you plug it in, or in Windows, check the Device Manager. Of course, this is not overly useful code, but is illustrative of how to interact with a serial device like an Arduino. For my micro-observatory, the results of the query is used to initiate a telescope park (since my roof can’t close unless the telescope is in the park position) and then a roof close. I have a fairly sizable script that looks at several sources for weather information (including my Machine Learning base cloud detection system) to pass along whether the roof should be open or not to the INDI Server.
Many thanks to Mike (tosjduenfs) for posting the circuit and sketch on Cloudy Nights2. His ASCOM driver for this circuit can be downloaded from Google Drive3. In an INDI environment, this script would feed information to the Weather Proxy, or in my case, to the Weather Watcher task.
https://rainsensors.com/products/rg-11/
https://www.cloudynights.com/topic/792701-arduino-based-rg-11-safety-monitor-for-nina-64bit/
https://drive.google.com/file/d/15yfj12i-uRQiIlVdWfWqn1OPZCDWl5NA/view?usp=sharing