Celebration of the Shadows

So, tomorrow I’m off to the Lakeside Country Club, Frimley Green in Surrey for the Celebration of the Shadows which this year features five “Shadows” bands from Norway, Sweden, Finland and the UK.

Maybe I’ll meet up with some of my cyber buddies there? If you recognize my ugly mug please do say hello! I’ll probably be wearing my ‘usual’ shirt like the last time in 2015 😉

You might find me in the Rose and Thistle sampling a few of their excellent craft beers and maybe having a fish and chip on the Green, weather permitting, which it will, of course!

DSC01010

 

Advertisements

Why Didn’t You Tell Me it Was Raining?

“Why Didn’t You Tell Me it Was Raining?” is the question that prompted my latest project and it’s one that my wife usually asks me as she rushes out to bring in the washing after she realizes it has been raining for five minutes. My reply “Sorry love, I didn’t notice” was not really having the calming effect I hoped for and when she said “Can you not invent something” it set me to thinking.

Sensing the Rain

A quick search online turned up this little module on Amazon for £3.99:71WaLsViYrL._SL1500_

The module works with a supply voltage Vcc of 3.3V or 5V (I used the latter for compatibility with the 5V Arduino Pro Mini I will be using) and has a comparator IC and an analog output pin A0 and a digital output D0. When some rain drops bridge the gap between the tracks on the ‘sensor’ the analog output, normally a high voltage near Vcc, will fall to a lower value.

After connecting the module to the Pro Mini and running a simple sketch to read the rain module signals I decided to use the analog output which showed a reading of 1023 when dry falling to 500 or so when the sensor got wet. I probably could have simply connected an LED or buzzer to the digital pin, placed the sensor board outside and ran a couple of long wires in to the house but that would have been too simple! Besides, I had a stash of cheap Arduino Pro Mini clones that I had bought from China on Aliexpress so I might as well use one. They are also readily available now from UK sellers for less than £3 on ebay, for example, this one.

If using the Pro Mini you will need a USB-Serial adaptor to allow you to upload the Arduino sketch to the board. This is usually called an FTDI USB-Serial adaptor or something similar. I used a Sparkfun FTDI Basic adaptor but there are plenty of cheaper ones available. Just make sure that you fit the correct gender of connector to the short side of the Pro Mini.

The cheap adaptors usually use the CH340 USB-Serial adaptor chip and you may need to download the driver for this chip if it’s not already installed on your computer. The more expensive adaptors use the FTDI chip which is supported natively by Windows and Mac OS.

The Sparkfun adaptor comes with a female header already fitted so you need to fit a male six pin header to the Pro Mini. Other adaptors usually come with both male and female headers that you can choose to solder either type to suit.

You can re-use the USB-Serial adaptor for other projects as it’s only used while uploading the Arduino sketch to the board and can be disconnected afterwards.

Why not go Wireless?

By this time my brain was coming up with more and more ideas so that the project began to develop into something more ambitious than what it had started out as. Why bother with having to run wires from the back yard, through the house, to the living room where ‘er indoors would be waiting while the washing dried?

I found a 433MHz wireless transmitter and receiver on Amazon but after several attempts I really couldn’t get it to work reliably, probably due to interference or lack of range, despite fitting an aerial wire to try to extend this.

51C58+4Qw1L
This transmitter/receiver set just wouldn’t work consistently.

A bit of further research on the internet turned up a lot of information on the RF24L01+ 2.4GHz Wireless Transceiver IC and there are a number of modules using this chip with a built-in antenna on the PCB. Having both transmit and receive functions in one module, I hoped that two of these would do the job.71s1DTkuhuL._SL1200_
These modules require a supply voltage of 3.3V but they have 5V tolerant logic inputs so they can be used with a 5V Arduino.

From the information I read on the Internet, it seems that these modules are very fussy about having a good clean 3.3V power supply. They also have their pins ‘on the bottom’ of the module in two rows of four so this makes it a little awkward to connect. Both problems can be solved by using the following adaptor boards (available from Amazon). They bring out the connectors to a single row on top of the board and they have a built-in 3.3V regulator and filtering capacitors to ensure a good clean supply to the RF module.

516HKNa8TTL

The RF module plugs in to the 2×4 way female header and the Vcc and GND connectors go to the 5V and GND on the Arduino. The logic connections to the Arduino are then made via the six male header pins on the adaptor board. (Only five of the connections are actually required).

The RF module costs just over £1 each and the adaptor boards are only about 90p each – I don’t think I could even buy the parts for that, never mind getting the PCB and putting them together!

The RF24L01+ module is very well supported on the Internet and there are a number of Arduino Libraries available. The one I used can be added to the Arduino IDE using the Arduino Library Manager.

2017-09-18

Documentation for the RF24 Library is available here.

I adapted one of the RF24 library example sketches, turning one into the ‘sender’ and one into the ‘receiver’ side of the system. The sketch can send and receive a data packet or payload that can contain whatever data you decide to send. In my case the data packet contains a time stamp, the rain sensor analog reading, a temperature reading and a humidity reading. The latter two were to be measured by a DHT11 Arduino compatible module but currently, while I have got it working reliably on an Arduino Uno board, I haven’t succeeded in getting it to work properly on the Pro Mini for some reason.

The transmitter is programmed to send a data packet once a second though this can easily be changed by altering a value in the sketch:

#define interval 1

sets the interval to 1 second. If this was changed, for example,  to

#define interval 5

then the readings would be sent every five seconds.

How to Charge the Batteries?

The receiver part of the system stays indoors so I decided to use an Arduino Nano clone which has a built-in USB connector and to power this via a left-over mobile phone charger (the type with a USB A connector and a lead terminating in a USB Mini B connector to  suit the Nano). For (re)programming the Nano, the USB lead can be unplugged from the charger and plugged in to a USB port on the computer.dsc06125.jpg

The transmitter would obviously need to be battery operated and as I was browsing the web for some parts I came across some small and relatively cheap solar panels and it occurred to me that, since  this box was going to be outside on a ‘good drying day’, there ought to be enough solar power to trickle charge the NiMH battery pack I was planning to use.

These panels cost just £3.99 each from Hobby Components and are rated at 5V 0.8W so potentially could supply a current of up to 160mA. I am using six NiMH cells in a pack which supplies about 7.2V (~1.2V per cell). The solar panels are connected in series (giving ~10V max) and the ground side goes to the negative terminal of the battery pack. The positive output of the solar panel connects via an 1N5819 Schottky diode to the positive side of the battery pack. This diode is essential to prevent the battery from feeding a current back into the solar panels when the solar cells are not illuminated. Feeding back a current into the solar cells can damage them.

When I tested the setup on a reasonably sunny day in August I was measuring a charging current of around 70-80 mA which should be sufficient to keep the battery topped up.

It’s Gotta be Waterproof!

Well, the transmitter unit has to sit outside with the potential of being rained on so it needed to go in a waterproof box but the rain sensor board and the solar cells have to be externally mounted for obvious reasons. To enable the solar panels and the rain sensor to fit on top of the box, I ordered one which measures 200x120x75 mm from ebay. Although the supplier is located in China it was dispatched the same day and arrived very quickly.

Box

I mounted the solar cells by squeezing an acrylic-based sealant (the sort of stuff you use to seal around your shower or bath) around the edges of the panels and pressing them onto the top of the enclosure. I then added a fillet of sealer around the edges of the panels and this seems to have worked well.

The same technique was not so successful for mounting the rain sensor board as I couldn’t get a good seal around the edges of the pcb and, besides, being acrylic based, the sealant uses, I think, water as the solvent so this was setting off the sensor before it fully cured. I think I might have got it to work but I was concerned that any water that did get under the rain sensor would  be difficult to remove and could take a long time to dry out after it had got rained on.

I have ended up with the rain sensor board mounted a few millimeters about the top of the enclosure with the air gap hopefully allowing it to dry naturally in a few minutes once the rain has stopped. It can easily be unplugged and dried manually if required. The hole for the sensor leads was sealed using a copious amount of the acrylic sealant.dsc06122.jpg

For the On/Off Charge switch I found a toggle switch in my parts bin and I also had a rubber sealing ‘boot’ that fitted it. Both were, as far as I can recall, bought from RS Components many years ago but the boot is no longer stocked but this one is similar, just make sure the thread fits the toggle switch you plan to use.

F7118439-01

When the switch is in the OFF/CHG position the battery pack is disconnected from the circuit but the solar panels remain connected to the battery pack to ensure it is trickle charged as long as there is sufficient light hitting the panels.

Some Gut Shots

The Receiver

It’s about time to reveal the innards of the two boxes. The receiver was built in a small ABS box and, because it fitted neatly in this box, I decided to just keep the circuit on the small breadboard I had used when testing the ideas.

The LED flashes each time a data packet is received from the transmitter so you can be sure the system is working and, when the ‘rain’ signal drops below the threshold I have set in the code, the LED will flash and the beeper will beep out a message in Morse Code. My message says “It’s Raining” but you can amend the sketch to send any message you want.  I shamelessly stole the Morse code routines from this page.

DSC06141

The RF24 radio module is on the left wall of the box, the Arduino Nano, the beeper (black circular object) and the LED and resistor are mounted on the small breadboard. The radio module is connected to the Arduino using female-male Dupont cables. I cut a slot in the end wall of the box to allow the USB Mini B cable to connect to the on-board USB socket on the Arduino.

A hole is drilled for the LED in the lid of the box.DSC06124

The beeper is a ‘5V Active Buzzer’ which makes a loud beep (frequency 2500 +/- 500Hz) when the + pin is taken to 5V (the – pin is connected to GND). I bought it from Hobby Components for £0.98.

When the receiver is powered up it first flashes the LED and beeps five times to confirm that it’s on. After that the LED will only flash when a data packet is received. It is possible to have it beep as well but ‘er indoors found that very annoying so I disabled the beep 😉

The Transmitter

You might think that the size of the enclosure is a bit of overkill but this was, as mentioned above, determined by the amont of space required on the lid to mount the two solar panels and the rain sensor. It does mean there is plenty of room inside and I could probably manage to fit in a larger Arduino such as the Uno but this one seems to work ok.

DSC06132

The red and black leads are the solar panel connections and the yellow and orange leads are coming from the rain sensor. The Arduino Pro Mini, the rain sensor module and other circuitry is mounted on a prototyping PCB I got free with an order for some PCBs from a Chinese manufacturer. I found that I could mount the PCB using two screws into two of the mounting pillars moulded into the bottom of the box.

The RF24 radio module on it’s adaptor is mounted with a double-sided foam sticky pad to the base of the box. The 6-cell battery holder is also mounted to the bottom with double-sided sticky foam tape.

DSC06135

DSC06133

The rain sensor module (with the blue preset resistor) is plugged into a 4-way female header on the PCB. The Arduino Pro Mini programming pins, to which the USB-Serial adaptor is connected, are visible to the left of the multi-coloured ribbon cable.

Source Code for the Arduino Sketches

Transmitter

/*
 * Author: Philip Hawthorne
 * Date: 24/08/2017
 *
 * This started life as a rain detector so my wife could be warned when her washing is in danger of getting wet!
 *
 * This code is for the transmitter (sensor) side
 *
 * Based on the Getting Started example sketch for nRF24L01+ radios
 * This is a very basic example of how to send data from one node to another
 * Updated: Dec 2014 by TMRh20
*/

#include <SPI.h>
#include "RF24.h"

/* Include the DHT11 library available at http://arduino.cc/playground/Main/DHT11Lib */
#include <dht11.h>

/****************** User Config ***************************/
/*** Set this radio as radio number 0 or 1 ***/
bool radioNumber = 0;

/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */
RF24 radio(7, 8);
/**********************************************************/

byte addresses[][6] = {"1Node", "2Node"};

#define RainSensorPin 14

// Define the time interval (seconds) between data sends
#define interval 1

dht11 DHT11;

/* Define the DIO pin that will be used to communicate with the sensor */
#define DHT11_DIO 9

struct dataStruct {
 unsigned long _micros;
 int rain;
 float temperature;
 float humidity;
} myData;

void setup() {
 pinMode(RainSensorPin, INPUT);
 Serial.begin(115200);

radio.begin();
 radio.setDataRate(RF24_250KBPS );
 
 // You can set the PA Level low (RF24_PA_LOW) to prevent power supply related issues when testing
 // and the likelihood of close proximity of the devices. RF24_PA_MAX is default.
 // Comment out the line you're not using
 
 // radio.setPALevel(RF24_PA_LOW);
 radio.setPALevel(RF24_PA_MAX);

// Open a writing and reading pipe on each radio, with opposite addresses
 if (radioNumber) {
 radio.openWritingPipe(addresses[1]);
 radio.openReadingPipe(1, addresses[0]);
 } else {
 radio.openWritingPipe(addresses[0]);
 radio.openReadingPipe(1, addresses[1]);
 }

// Start the radio listening for data
 radio.startListening();
}

void loop() {

int RainSensorReading = 0;

/****************** Ping Out Role ***************************/

radio.stopListening(); // First, stop listening so we can talk.

RainSensorReading = analogRead(RainSensorPin);
 myData.rain = RainSensorReading;

if (DHT11.read(DHT11_DIO) == DHTLIB_OK)
   {
 myData.temperature = DHT11.temperature;
 myData.humidity = DHT11.humidity;
 }
 Serial.println(F("Now sending"));

unsigned long start_time = micros(); // Take the time, and send it. This will block until complete
 if (!radio.write( &myData, sizeof(myData) )) {
 Serial.println(F("failed"));
 }
#ifdef DEBUG
 radio.startListening(); // Now, continue listening

unsigned long started_waiting_at = micros(); // Set up a timeout period, get the current microseconds
 boolean timeout = false; // Set up a variable to indicate if a response was received or not

while ( ! radio.available() ) { // While nothing is received
 if (micros() - started_waiting_at > 200000 ) { // If waited longer than 200ms, indicate timeout and exit while loop
 timeout = true;
 break;
 }
 }

if ( timeout ) { // Describe the results
 Serial.println(F("Failed, response timed out."));
 } else {
 unsigned long got_time; // Grab the response, compare, and send to debugging spew
 radio.read( &myData, sizeof(myData) );
 unsigned long end_time = micros();

// Spew it
 Serial.print(F("Rain temp humi sensor readings, Sent: "));
 Serial.print(RainSensorReading);
 Serial.print(" ");
 Serial.print(DHT11.temperature);
 Serial.print(" ");
 Serial.print(DHT11.humidity);
 Serial.print(F(", Got response "));
 Serial.print(myData.rain);
 Serial.print(" ");
 Serial.print(myData.temperature);
 Serial.print(" ");
 Serial.println(myData.humidity);
 Serial.println(F(", Round-trip delay "));
 Serial.print(end_time - start_time);
 Serial.println(F(" microseconds"));
 }
#endif
 // Try again 1s later
 delay(interval*1000);
} // Loop

Receiver

/*
 * Author: Philip Hawthorne
 * Date: 24/08/2017
 *
 * This started life as a rain detector so my wife could be warned when her washing is in danger of getting wet!
 *
 * This code is for the receiver side
 *
 * Getting Started example sketch for nRF24L01+ radios
 * This is a very basic example of how to send data from one node to another
 * Updated: Dec 2014 by TMRh20
*/

#include <SPI.h>
#include "RF24.h"

/****************** User Config ***************************/
/*** Set this radio as radio number 0 or 1 ***/
bool radioNumber = 1;

/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */
RF24 radio(7, 8);
/**********************************************************/

byte addresses[][6] = {"1Node", "2Node"};

#define buzzerPin 3
#define ledPin 2

const int rain_threshold = 800;

const int maxRepeats = 2;

unsigned long count = 0;
int alarmRepeats = 0;
unsigned long startTime = millis();
unsigned long timeNow;

struct dataStruct {
 unsigned long _micros;
 int rain;
 float temperature;
 float humidity;
} myData;

//For letters
char* letters[] = {
 ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", // A-I
 ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", // J-R
 "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.." // S-Z
};

//For Numbers
char* numbers[] = {
 "-----", ".----", "..---", "...--", "....-", ".....",
 "-....", "--...", "---..", "----."
};
int dotDelay = 100;

String msg = "It's Raining";

void setup() {
 Serial.begin(115200);
 radio.begin();
 radio.setDataRate(RF24_250KBPS );

// Set the PA Level low to prevent power supply related issues since this is a
 // getting_started sketch, and the likelihood of close proximity of the devices. RF24_PA_MAX is default.
 radio.setPALevel(RF24_PA_MAX);

// Open a writing and reading pipe on each radio, with opposite addresses
 if (radioNumber) {
 radio.openWritingPipe(addresses[1]);
 radio.openReadingPipe(1, addresses[0]);
 } else {
 radio.openWritingPipe(addresses[0]);
 radio.openReadingPipe(1, addresses[1]);
 }

// Start the radio listening for data
 radio.startListening();

pinMode(buzzerPin, OUTPUT);
 pinMode(ledPin, OUTPUT);
 alarm(5, 200, true, true); // Beep and flash the LED so user knows it's on
}

void loop() {

bool alarm_on = false;

/****************** Pong Back Role ***************************/

unsigned long got_time;

if ( radio.available()) {
 // Variable for the received timestamp
 while (radio.available()) { // While there is data ready
 count++;
 radio.read( &myData, sizeof(myData) );
 alarm(1, 100, false, true); // Flash LED as visual confirmation that an RF signal is being received.
 timeNow = millis();
 Serial.print("Received signal after ");
 Serial.print((timeNow - startTime) / 1000);
 Serial.println(" seconds");

// Show the values being received on the Serial Monitor

Serial.print("Data received: Rain = ");
 Serial.print(myData.rain);
 Serial.print(", Humidity = ");
 Serial.print(myData.humidity);
 Serial.print(", Temperature = ");
 Serial.println(myData.temperature);
 Serial.println("---------------------------");
 if (myData.rain < rain_threshold) {
 alarm_on = true;
 alarmRepeats ++;
 if (alarmRepeats > maxRepeats) {
 alarm_on = false;
 alarmRepeats = 0;
 }
 }// Get the payload
 }
 // if (alarm_on) alarm(5, 200, true, true); // Flash LED and sound the Beeper
 if (alarm_on) soundMorse(msg);
#ifdef DEBUG
 radio.stopListening(); // First, stop listening so we can talk
 radio.write( &myData, sizeof(myData) ); // Send the final one back.
 radio.startListening(); // Now, resume listening so we catch the next packets.
 Serial.print(F("Sent response "));
 Serial.print(count);
 Serial.print(", rain = ");
 Serial.print(myData.rain);
 Serial.print(", Humidity = ");
 Serial.print(myData.humidity);
 Serial.print(", Temperature = ");
 Serial.println(myData.temperature);
#endif
 }
} // Loop

void soundMorse(String msg)
{
 char ch;

for (int i = 0; i < msg.length(); i++) {

ch = msg[i];
 if (ch >= 'a' && ch <= 'z')
 {
 flashSequence(letters[ch - 'a']);
 }
 else if (ch >= 'A' && ch <= 'Z') {
 flashSequence(letters[ch - 'A']);
 }
 else if (ch >= '0' && ch <= '9') {
 flashSequence(numbers[ch - '0']);
 }
 else if (ch == ' ') {
 delay(dotDelay * 4);
 }
 }
}

void alarm(byte beeps, int msecs, bool beep, bool flash) {

for (int i = 0; i < beeps; i++) {
 if (flash) digitalWrite(ledPin, HIGH);
 if (beep) digitalWrite(buzzerPin, HIGH);
 delay(msecs);
 digitalWrite(ledPin, LOW);
 digitalWrite(buzzerPin, LOW);
 delay(msecs);
 }
}

void flashSequence(char* sequence) {
 int i = 0;
 while (sequence[i] != NULL) {
 flashDotOrDash(sequence[i]);
 i++;
 }
 delay(dotDelay * 3);
}




void flashDotOrDash(char dotOrDash) {
 digitalWrite(ledPin, HIGH);
 digitalWrite(buzzerPin, HIGH);
 if (dotOrDash == '.')
 {
 delay(dotDelay);
 }
 else // must be a -
 {
 delay(dotDelay * 3);
 }
 digitalWrite(ledPin, LOW);
 digitalWrite(buzzerPin, LOW);
 delay(dotDelay);
}

Arduino on YouTube

Here’s a few YouTube channels that I’ve found particularly helpful for how-to articles on using the Arduino platform.

Ralph S Bacon provides very good, clear explanations of how to do stuff on the Arduino. He takes his time to explain not only what to do, but why that works.

Jeremy Blum has a series of excellent Arduino tutorials on his YouTube channel, plus a lot of other good stuff.

Julian Ilett’s YouTube channel’s motto is “Electronics on the cheap” so he’s got loads of ideas for projects on a budget.