Projects

LoRa Weather Station

Johann Wyss

Issue 21, April 2019

This article includes additional downloadable resources.
Please log in to access.

Log in

Build this long-range LoRa weather station with a proven range over 7km!

BUILD TIME: 8 hours (+ 3D printing time)
DIFFICULTY RATING: Intermediate

One of our readers, Cyril H, asked us if we could design a weather station with long range data transmission, using LoRa technology.

We've had a few LoRa projects in the pipeline for some time, and this certainly won't be the last. We're planning to increment through the complexities fo LoRa, as there are always a few challenges which need to be overcome.

LoRa has a few specific demands it makes of its microcontrollers, and unless you're going to write your own libraries for the LoRa, you need to ensure your approach is compliant with how it wants things to work.

As an example, we had to hunt down a serial-driven LCD rather than whatever LCD we first grabbed. We found LoRa would often interrupt our process of writing data to the screen when using many shield-based screens, or those using regular GPIO communication.

But more on this as these issues come up. Let's get going!

THE BROAD OVERVIEW

LoRa, short for long-range radio, is a low power, long distance, and low bandwidth wireless radio frequency modulation scheme. Its low bandwidth and data rate means data can be transmitted over long distances with lower power when compared to traditional RF schemes. This lower power also allows the LoRa hardware to be significantly less expensive, which opens the technology up to the home/hobbyist user.

In conjunction with an Arduino microcontroller and readily available sensors to read weather conditions, we are able to measure atmospheric conditions and transmit them over a long range to a receiver module.

These unassuming LoRa shields for Arduino, unlock a huge amount of potential for using the technology.

HOW IT WORKS

The LoRa module we are using comes pre-configured to use the specific frequency of 915MHz. This UHF frequency is part of the Industrial, Scientific and Medical band, often simply referred to as the ISM band. This is an open, licence-free band, which can be used for scientific and industrial applications, primarily for non-communication purposes. Whilst the band is effectively licence-free, there are very specific laws around the use of this band, the transmission power etc. You can find more information regarding the ISM band from the Australian Communications and Media Authority (ACMA) who are the regulators.

It’s worth mentioning that by default the LoRa protocol does not in any way attempt to encrypt the data that is being transmitted. Anyone operating on the same frequency can easily intercept and view your transmission. Therefore, if you’re sending sensitive data, you may want to encrypt or otherwise obfuscate the information to protect it from packet sniffing.

The temperature and humidity are detected using the DHT11 temperature and humidity sensor. This is a very low-cost digital sensor available at most hobby electronics retailers. It runs on 3.3 or 5V and has a maximum current of only 2.5mA, which makes it ideal for battery powered projects.

The sensor can detect temperatures between 0–50°C ± 2°C, and humidity range between 20–80% ± 5%. If you want a higher accuracy, you could source the DHT22, which has the same power requirements but has a much greater range and reports an accuracy of ± 0.5°C.

The sensor works on a single wire two-way communication serial interface. It uses a 40-bit data transfer; the decimal and integer values for the temperature and humidity being sent via 8 bits each, for a total of 32 bits, and a further 8 bits used for a checksum to verify the transmission.

The rain sensor appears to be little more than a PCB with tracks interlocking with a small spacing between them. When the PCB gets wet, the tracks allow current to flow, which is then amplified (relative to the amount of water present) using an LM358 operational amplifier.

Note: This very simple sensor has no way of differentiating between actual rain or if an insect has crawled over the sensor, so it should only be used as a rough guide and not for critical sensing. If you need a very accurate rain sensor you may need an optical rain sensor. Due to their cost and added complexity, we have not used one for this project.

Build 1:

The Prototype

Parts Required:Jaycar
2 × Arduino Compatible UNOXC4410
2 × LoRa ShieldXC4392
1 × DHT11 Temperature and Humidity SensorXC4520
1 × Rain Sensor ModuleXC4603
1 × Blue 5mm LED*ZD0185
1 x 1KΩ 1/4W Resistor*RR2774
1 × Mixed Jumper WiresWC6027

* Quantity required, may only be sold in packs. Breadboard and prototyping hardware is also required.

Note: LED and Resistor are not essential to prototype or build.

To prove the concept, develop the code and to test the sensors, we designed a prototype using a breadboard.

We sourced the components from local electronics retailers, and settled on an Arduino compatible UNO for the platform.

We have provided the parts list and fritzing diagram if you want to reproduce this yourself. We have kept it simple, and no soldering is required for the prototype.

ELECTRONICS

Wiring is quite straightforward. The LoRa shield plugs straight into the UNO and the sensors plug directly into the breadboard.

We added a 5mm LED in series with a 1kΩ resistor to the VCC pin of the DHT11 sensor to simply indicate that power was present. It isn’t required for the main build, and should be avoided if you are running from battery power and want to extend the battery life.

You may notice a MOSFET (not connected) in the photo above. This was originally intended to power the rain sensor, however, the sensor only draws 10mA when submerged in water, so the Arduino is able to provide enough power. i.e. The MOSFET isn’t required.

Considering that we plan to power our final build from a battery source, our goal was to power the sensors directly from the Arduino pins. This would allow us to remove power to the sensors when they were not being used, significantly reducing the current consumption of the device over time. Therefore, we needed to look at what current the device was consuming.

Note: Some DHT sensor outputs are different. Double check your module.

The Arduino UNO has an absolute maximum current output per digital pin of 40mA. Since we wanted to power the sensors directly from the digital pins, we needed to make sure their current draw was much lower than this value.

The datasheet for the DHT11 claims it draws a maximum current of 2.5mA whilst it is reading the sensor values. We tested this using a multimeter and discovered it was on average less than 1mA.

The LED we attached to this sensor was blue, and therefore had a forward voltage of about 3.3V. Since we are supplying 5V and using a 1kΩ resistor, the current draw from the LED we calculate to be 1.7mA.

I = (Vs - Vf) / R

I = 5 - 3.3 / 1000

I = 1.7mA

This means that while the sensor is active, the current supplied by the digital pin will be 4.2mA at max current, which is perfectly safe.

To wire up the circuit:

  • Digital pin 4 of the Arduino/LoRa shield goes to + of the DHT11.
  • Digital pin 5 of the Arduino/LoRa shield goes to + on the moisture sensor.
  • Analogue pin 0 of the Arduino/LoRa shield goes to S of the DHT11.
  • Analogue pin 1 of the Arduino/LoRa shield goes to AS on the moisture sensor.
  • Both sensors GND (–) go to GND on the Arduino/LoRa shield.

With the electronics assembled, we can prepare the software to upload to the UNO.

THE CODE

The code for the final unit can be downloaded from the Resources section on our website.

We will describe the transmit (TX) and receiver (RX) code separately below.

TX CODE

This project requires the use of the DHT11 library and the LoRa library.

The LoRa library was provided by Sandeep Mistry, and can be downloaded here: https://github.com/sandeepmistry/arduino-LoRa

Adafruit has shared the DHT11 library, which you can find here: https://github.com/adafruit/DHT-sensor-library

Install both libraries before attempting to compile the code.

We first wrote a basic pseudocode, outlining each step required to achieve the desired results. It was essentially:

  • Energise the temperature and humidity sensor
  • Read the temperature value
  • Read the humidity value
  • De-energise the temperature and humidity sensor
  • Energize the moisture sensor
  • Read the analogue value
  • De-energise the moisture sensor
  • Convert the results from the analogue read into sensible readings
  • Send the data via the LoRa module and/or serially

To do this, there were a few steps that first needed to be taken. For example, when we read the analogue sensor values from the moisture sensor, we will get a value between 0 and 1023, representing the maximum 10 bit value of the ADC. This figure is fairly useless in this format though, as what does a value of 700 mean without any unit designation to compare it to?

To counter this, we chose to convert the 10 bit ADC reading into a useable numerical representation by finding the two extremes of the sensor.

First, we took 1000 readings with 1 second intervals, with the sensor fully dry in the open air at room temperature. This resulted in an average reading of 702.

We then repeated the procedure with the sensor plate fully submerged in water, which provided an average result of 116.

We used these values as our distinction between the amount of moisture on the sensor. A value of 700 meant it was completely dry, and a value of 116 meant it was completely submerged.

It was then just a simple process to use the map() function to map these values to a value between 0 and 100, and treat them as a rudimentary percentage scale.

When you build this device, be sure to replace your results in the DRY and WET constants as there can be a significant difference based on the water hardness in your area, and discrepancies in the sensors themselves.

With that out of the way, it is time to start programming the sketch.

SETUP

#include <SPI.h>
#include <LoRa.h>
#include "DHT.h"
#define DHTPIN A0
#define DHTTYPE DHT11
const int DRY = 700;
const int WET = 120;
int count = 0;
int var = 0;
int DHTpin = 4;
int moistPin = 5;
int moist = 0;
DHT dht(DHTPIN, DHTTYPE);
void setup() {
  Serial.begin(9600);
  while (!Serial);
  pinMode(DHTpin, OUTPUT);
  pinMode(moistPin, OUTPUT);
  digitalWrite(DHTpin, LOW);
  digitalWrite(moistPin, LOW);
  if (!LoRa.begin(915E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
  dht.begin();
}

LOOP

For the prototype, we will just push the sensor data out using the serial print function. The data used by the LoRa library uses the same serial function, so converting it to LoRa is a very simple process. We will show in the final step.

 void loop() {
  // TEMP AND HUMIDITY SENSOR
  digitalWrite(DHTpin, HIGH);
  delay(300);
  float temp = dht.readTemperature();
  float humid = dht.readHumidity();
  digitalWrite(DHTpin, LOW);
  if (isnan(temp)){
    temp = 0;
  }
  if (isnan(humid)){
    humid = 0;
  }
  // MOISTURE SENSOR
  digitalWrite(moistPin, HIGH);
  delay(300);
  moist = analogRead(1);
  digitalWrite(moistPin, LOW);
  moist = map(moist, WET, DRY, 100, 0);
  // COUNTER
  count ++;
  if(count > 999){
    count = 0;
  }
  // DEBUG
  Serial.println("//////////Debug//////////");
  Serial.print("temp = ");
  Serial.print(temp);
  Serial.println("C");
  Serial.print("Humid = ");
  Serial.print(humid);
  Serial.println("% ");
  Serial.print("Moisture = ");
  Serial.print(moist);
  Serial.println("% ");
  Serial.print("counter = ");
  Serial.println(count);
  Serial.println("");
  delay(5000);
}

If you open the serial monitor, you will see something similar to the following image.

serial monitor

It shows the sensor readings, and a counter, which may be useful to verify that the device is receiving packets. More importantly, it shows you if the device is dropping when used on the RX module.

The next step is to program a second UNO and LoRa module to act as the receiver for the information.

For this, you need to either replace the debug section or just add the following code.

// LoRa packet TX
LoRa.beginPacket();
LoRa.print("Temp = " );
LoRa.print(temp);
LoRa.print(" C ");
LoRa.print("Humid= ");
LoRa.print(humid);
LoRa.print(" %");
LoRa.print("Moisture = ");
LoRa.print(moist);
LoRa.println("% ");
LoRa.endPacket();
delay(5000);

This will send the data out via the LoRa module rather than the Serial monitor. You can keep the debug code in if you like, however, just be sure to remove the delay, otherwise you will have twice the expected delay.

THE RX CODE

The RX prototype code is pretty much taken directly from the LoRa library example. It is simply a matter of receiving the incoming data stream and printing it serially using the serial monitor.

This will show you anything you’re sending via LoRa.print() function on the TX module, therefore proving that the two LoRa modules are communicating wirelessly.

SETUP

#include <SPI.h>
#include <LoRa.h>
void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.println("LoRa Receiver");
  if (!LoRa.begin(915E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

LOOP

void loop() {
  // TRY TO PARSE PACKET
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // READ PACKET
    while (LoRa.available()) {
      Serial.print((char)LoRa.read());
    }
    //PRINT RSSI OF PACKET
    Serial.print("’ with RSSI ");
    Serial.println(LoRa.packetRssi());
  }
}

TESTING THE PROTOTYPE

To test and power the device we connected the RX unit to a PC via USB. The TX unit was powered via a USB battery bank and was programmed to transmit via LoRa and not the serial output.

We tested the prototype at Johann's home, which is in a reasonably dense scrub area. There was only a limited range around the home to test the range with uninterpreted radio line of sight (LOS). The large trees would significantly reduce the range.

Testing was done by walking away from the house which had the transmitter inside and keeping an eye on the receiver's display.

A successful reading was attained at 130m away from the house, which is in a mostly open area but with large trees. However, moving several steps into the dense scrub, losing line of sight to the house, caused the signal to be significantly reduced, resulting in packet loss.

This testing helped determined that the transmitter needed to be lifted higher in the air to help keep in line of sight to the receiver.

POWER

Whilst the Arduino UNO can easily take a number of different voltages via the DC jack, it has linear voltage regulators for both the 5V and 3.3V rails. These regulators are very inefficient, and this inefficiency produces heat. This heat will then skew the readings from the temperature sensor. On top of that, with the device powered by a battery, this inefficiency will require a bigger storage capacity.

To test the current demands of the TX unit we used a fully charged 12V lead acid battery. With a fully charged voltage of 13.8V, there was a constant 50mA draw.

It is possible to reduce this current by switching from a linear 5 volt regulator to a switchmode regulator. These regulators are many times more efficient, which translates to a lower power consumption and less internal heating to skew the sensor readings.

When powered via a switchmode regulator producing 5V from the same 13.8V supply, the current draw on the lead acid battery was only 30mA. This is 40% less power wasted.

For this experiment, we used the XC4514 stepdown voltage regulator from Jaycar to step the voltage down to 5V. Note that when powering the device from 5V you should connect it to the USB input and not the DC jack.

Build 2:

LoRa Weather Station

Additional Parts Required:Jaycar
1 × Serial Enabled 20x4 LCD-
1 × 12V SLA 1.3Ah Battery or similarSB2480
1 × 2.1mm DC Bulkhead ConnectorPS0522
1 × 28 Pin or 40 Pin Male Header - StraightHM3211
1 × 40 Pin Female Header - StraightHM3230
1 × 2" Single Sided ProtoBoard-
4 × M3 × 10mm Bolts*HP0403
4 × M3 × Nuts*HP0425
4 × No.4 × 6mm Small Self-Tapping Screws*HP0550

* Quantity required, may only be sold in packs.

Hook-up wire, heatshrink, epoxy glue, cable ties and heatshrink may also required.

With a successful prototype built and tested, we now move on to design a final build for a permanent installation.

We will describe the electronics, 3D printed enclosures and how we tested our project to achieve a range greater than 7km.

We will also describe how you can add an LCD screen to the receiver so you don’t need to be tethered to a PC to read the data.

BUILDING THE CIRCUIT

The circuit is very similar to the prototype, however, the RX module has an LCD and the TX module has a PCB to secure the components for permanent operation.

Considering the simple circuit, we opted to use a standard prototyping perfboard instead of custom designing and manufacturing a PCB. The perfboard also has the footprint to connect to the LoRa shield using the included headers.

It is important to solder the headers to the track side of the perfboard, which is the opposite side to where the components will be facing. Insert the headers into the perfboard and raise them off the substrate to give you room to solder, as shown in the image here.

We recommend soldering only one or two of the pins on each strip first. This allows you to ensure they are positioned correctly to match the female headers on the LoRa module. If they are crooked or otherwise incorrectly placed it’s much easier to reposition with only one or two pins soldered.

The next task is to figure out where on the PCB you will place the temp and moisture sensors. We recommend having the DHT11 sensor high on the board so it will be closer to the ventilation holes in the enclosure, and less likely to suffer moisture ingress which will destroy the sensor.

To solder the components to the PCB, we needed to remove the header from the moisture sensor and replace it with a straight pin header. We soldered this from the other side so that the potentiometer was facing up, away from the PCB.

The same process was done with the DHT11 sensor so that it sat flat against the PCB, with the sensor facing out.

With the headers and sensors in place, it is then just a matter of making solder traces to connect each of the sensors to the correct pins as per the prototype diagram.

After soldering everything together you should find a large unused area of the PCB. We simply placed the PCB into a vise and scored the board on either side with a hobby knife so the board could easily be snapped separating the unused portion of the PCB from our newly created shield as shown above.

Once done you can simply slide the shield into the LoRa shield creating a sandwich of the 3 boards.

We then removed the moisture sensing PCB from the sensor module by de-soldering the two wires at the sensor module. We needed to extend this wire and add a connection so the LoRa shield, Arduino UNO and the sensor modules could be removed if needed.

To make this connection, we simply cut a male and female pin header strip so it had two connections each. To the sensor module side, we soldered the female header and to the sensing PCB we added a male. We tidied this connection with a little heatshrink, so it looked like the image above.

After creating this extension, it was just a matter of soldering either end to the sensor components.

The next step was to solder power wires to the underside of the Arduino DC jack, and again add a pin header connection.

Note: It is very important to solder the male pin header to the UNO side in this configuration because you don’t want the incoming power to be on an uninsulated connection. Doing so could allow the 12V to come into contact with exposed tracks or solder pads, which could destroy your project. we used a multimeter to verify which of the PCB pads were positive and which were ground, and simply soldered wires directly to these pads. The UNO should have reverse polarity protection here, but you should be extra careful to make sure you wire this correctly as if your device lacks this diode you can easily destroy your Arduino and the LoRa shield.

POWER

For the final build, we settled for powering the device directly from the 12V supply, however, if power demands are an issue for you, we thoroughly recommend you use the stepdown module to reduce the power consumption (due to increased regulator efficiency).

3D PRINTED ENCLOSURE

We printed the parts on a FlashForge Creator Pro using white FlashForge PLA with a 200-micron layer height. However, given the device is designed to be used outdoors, ABS may be more suitable for long term UV exposure. The components were sliced in Flashprint using tree supports where possible.

We designed the enclosure so that it can be mounted on a pole. This will allow the user to mount it high to avoid possible interference and hopefully provide line-of-sight for longer distances. We sized the hole diameter to match a commonly available wooden broom handle or doweling. Using wood helps to secure the sensor using just a self tapping screw. You can, of course, modify the base to suit your specific needs.

The enclosure consists of two components; the main base and the lid.

MAIN BASE

The main base has a raised area, sized to press fit the moisture sensor into. It has a small hole for the sensor wiring to come through, which will need to be sealed after the sensor is installed to prevent water ingress. We recommend using a little glue in the corners to secure the sensor PCB.

The main base takes about 8 hours to print at 200-micron layer height, and is designed to be printed in this orientation.

LID

The lid can easily be printed flat on the bed and takes about one hour to print. The lid is designed to be a very tight friction fit. It may be difficult to get on, depending on your printer's tolerances, etc. If you’re struggling to get it on, you can try just shaving a tiny bit of plastic off each corner.

RECEIVER

The receiver enclosure is printed flat on the bed as shown above. It should not need supports and takes about 8 hours to print at 200-micron layer height.

The receiver lid should be printed flat on the bed and at 200-micron layer height takes about an hour and a half to print.

Initial transmitter modelling
3D rendered transmitter
Built transmitter

THE CODE

The code for the final unit can be downloaded from the Resources section on our website.

THE TX CODE

In this code, we were originally transmitting the data every 3 seconds. There are 86,400 seconds per day, which means the device will send over 40,000 packets per day. This is fairly excessive for such a device, and may interfere with other LoRa users on the same frequency. Instead, we want to keep the total daily messages transmitted to under 500. To calculate the delay, we need to divide the number of seconds in a day by the number of messages we want to send daily.

delay = seconds in the day / no. of messages

delay = 86,400 seconds / 500

delay = 172.8 seconds

Therefore, we want a delay of 173 seconds to keep our transmissions below 500 to avoid congestion. This means the const DELAY should be 173,000.

SETUP & LOOP

#include <SPI.h>
#include <LoRa.h>
#include "DHT.h"
#define DHTPIN A0
#define DHTTYPE DHT11
const int DRY = 700;
const int WET = 120;
const int DELAY = 173000;//Delay in ms between tx
int count = 0;
int var = 0;
int DHTpin = 4;
int moistPin = 5;
int moist = 0;
DHT dht(DHTPIN, DHTTYPE);
void setup() {
  Serial.begin(9600);
  while (!Serial);
  pinMode(DHTpin, OUTPUT);
  pinMode(moistPin, OUTPUT);
  digitalWrite(DHTpin, LOW);
  digitalWrite(moistPin, LOW);
  if (!LoRa.begin(915E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
  dht.begin(); 
}
void loop() {
  // TEMP AND HUMIDITY SENSOR
  digitalWrite(DHTpin, HIGH);
  delay(300);
  float temp = dht.readTemperature();
  float humid = dht.readHumidity();
  digitalWrite(DHTpin, LOW);
  if (isnan(temp)){
    temp = 0;
  }
  if (isnan(humid)){
    humid = 0;
  }
  // MOISTURE SENSOR
  digitalWrite(moistPin, HIGH);
  delay(300);
  moist = analogRead(1);
  digitalWrite(moistPin, LOW);
  moist = map(moist, WET, DRY, 0, 100);
  // COUNTER
  count ++;
  if(count > 999){
    count = 0;
  }
  // LORA PACKET TX
  LoRa.beginPacket();
  LoRa.print("Temprature = " );
  LoRa.print(temp);
  LoRa.print("C");
  LoRa.print("Rel Humidity= ");
  LoRa.print(humid);
  LoRa.print("%");
  LoRa.print("Aprox Moisture= ");
  LoRa.print(moist);
  LoRa.print("%");
  LoRa.print("cnt=");
  LoRa.print(count);
  LoRa.endPacket();
  delay(DELAY);
}

THE RX CODE

The RX code is very simple, as all we need to do is print the information as it comes directly to a serial LCD. We originally attempted to separate the incoming data stream into separate floats and integers. Having the data stored in floats and integers would allow us to significantly reduce the length of the incoming data packet, and therefore seemingly decrease the chances for data corruption. However, cutting the array of incoming bits into their proper locations was difficult, without affecting the incoming data stream before we added the delays. For now, we send the data out to a serial LCD using the software serial library.

SETUP & LOOP

#include <SoftwareSerial.h>
#include <SPI.h>
#include <LoRa.h>
SoftwareSerial lcd(2, 3);
void setup() {
  Serial.begin(9600);
  lcd.begin(9600);
  while (!Serial);
  if (!LoRa.begin(915E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
  clearDisplay();
  setLCDCursorUnder();
}
void loop() {
  setLCDCursor(0);
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    while (LoRa.available()) {
      lcd.print((char)LoRa.read());
    }
    lcd.print(" RSSI=");
    lcd.print(LoRa.packetRssi());
    lcd.print(" ");
  }
}
void clearDisplay()
{
  lcd.write(0xFE);
  lcd.write(0x01);
}
void setLCDCursor(byte cursor_position)
{
  lcd.write(0xFE);
  lcd.write(0x80);
  lcd.write(cursor_position);
}
void setLCDCursorUnder()
{
  lcd.write(0xFE);
  lcd.write(0x0C);
}
void setLCDBlink()
{
  lcd.write(0xFE);
  lcd.write(0x0C);
}

THE RX ASSEMBLY

The receiver module is very simple to assemble. All you need to do is connect the serial LCD to the Arduino UNO and LoRa shield with the following connections:

  • Vdd on the LCD goes to 5V on the Arduino/LoRa shield.
  • Gnd on the LCD goes to gnd of the Arduino/LoRa shield.
  • RX on the LCD goes to digital pin 3 of the Arduino/LoRa shield.

We opted to use jumper wires to make these connections. You just cut one end of the jumper cable off leaving the other end with the male connection. Strip a small amount of insulation from the now cut end and tin the wires. You can then solder directly to the pads on the LCD PCB. Be careful though, as there is no strain relief on these wires so don’t pull on them.

With that done, connect the wires to the LoRa shield via the male jumper connector.

Next, secure the LCD to the enclosure using M3 x 10mm nuts and bolts.

Both the Arduino and LoRa shield are secured in place using hot glue. Do this after the antenna I-Pex connector has been pushed through the opening in the enclosure, and the antenna has been secured.

Now you simply close the device up and use some screws to secure the back panel.

WEATHERPROOFING

For this device to be useful as an outdoor device, we need to take some steps to protect it from the elements. The enclosure can’t possibly be sealed watertight as it requires air flow for the temperature and humidity sensors to work. That means a certain level of waterproofing needs to be done.

For example, we can significantly reduce water ingress by filling the hole in the roof where the moisture sensor wires protrude with a two-part epoxy resin. This resin should form a very tight bond with the plastic enclosure and wires preventing water from wicking between the surfaces via surface tension.

The two parts of the device should be glued together using hot glue so that the device can easily be removed from the enclosure at a later date. Similarly, this should also be done to the antenna port.

Doing this will minimise water getting into the enclosure, however, water can still get in via the vents under the awnings. Therefore, we highly recommend using a conformal coating to protect the electronics inside. This coating covers the contacts, tracks, and connectors of the PCB, and prevents corrosion.

You can use off-the-shelf specialty designed products like MG Chemicals 419C Acrylic Conformal Coating. Or you can even use a thick coat of acrylic paint or nail polish, etc. The idea is to protect the exposed metal contacts which will keep the electronics working fine, even after a little moisture ingress.

Be careful, however, not to coat the DHT11 sensor as it consists of an exposed sensor as shown here at 40x magnification. Covering this sensor with a conformal coating will almost certainly cause it to stop functioning correctly.

TESTING

To test the range of the device we needed to find a long stretch of open space, preferably with a high vantage point to house the transmitter.

Our testing was done in Queensland. After a few hours of intense staring at Google Maps the answer presented itself; The Gold Coast! Specifically chosen because of the stretch of coastline between Main Beach and Burleigh Waters. This stretch of coastline is over 17km long and offers the best possible conditions for line-of-sight as there is a lookout at the Burleigh heads side. However, this is also a very built up area and likely to be full of UHF signals and therefore interference.

To test the range capabilities, we made things as simple as possible by simply transmitting a counter. This way, the sketch uses a very minimum number of bytes for the transmission and, therefore, should be the best possible sketch to test the default range while excluding other unknown variables. The code for the range test is available on our website.

The transmitter was placed atop a 2.4m length of 19mm doweling to keep it above potential obstacles.

The small lead acid 12V battery and cable was also ziptied to this doweling to make the transmitter more portable. The receiver was simply powered via a USB battery bank and carried in hand.

Since we didn’t want to leave the transmitter unattended on a public beach, we had a colleague, Elliot, volunteer his time to help test the performance of the project. After a feed and plan of attack was discussed at the Burleigh heads surf lifesaving club, the testing procedure began.

Since we had no idea what range to expect, we initially started at a short distance. Elliot and the transmitter would take a position at John Laws Park on the southern end of the Burleigh Heads Rock Pool. After a short walk along the beach, stopping at each Life Saver Tower, where we would confirm that we were still successfully receiving a signal. This procedure repeated until reaching Mick Schamburg Park lookout 2km away, where we were still receiving 100% of the transmitted packets.

This initial result was very encouraging. It proved that the range was going to be significantly higher than the 2km as the signal was still very strong, reporting a received signal strength indicator (RSSI) of -102. The higher the number the better. i.e. the closer to zero the stronger the signal is. However, many other variables affect the quality of transmission such as noise, signal to noise ratio, interference, etc. Therefore, RSSI is only used as a guide.

We met back at the Burleigh Surf Lifesaving Club to discuss how to ramp up the test. We decided to test from the beach adjacent to the tallest building on the Gold Coast, Q1, which was about 10km from Elliot’s position at John Laws park.

Unfortunately, at that 10km distance there was a 100% packet loss with absolutely no communication. It was decided the best course of action now was to reposition Elliot from John Laws Park to the Mick Shamburg Park lookout, which would provide a range of 7.4km to the receiver.

10km range test was unsuccessful.

Amazingly, at this 7.4km distance, communications were possible. The signal strength was good with an RSSI of -120 to -130. Despite the decent signal strength, the device was not receiving every packet. We observed approximately one in every 7 or 8 sent packets did not make it to the receiver, meaning about 12.5% packet loss.

7.4km distance between Q1 beach and Mick Shamburg park lookout.

Initially, we put this down to the distance, however, on reflection, the strong RSSI suggests that interference may have been playing a bigger role than initially assumed.

This beach, in particular, is very close to the commercial centre of the Gold Coast and Cavill Ave. It’s very possible that this increased commercial and dense residential presence also increases the interference.

During the testing, we did notice what appeared to be an increase in data corruption and lost packets when we were in the vicinity of the lifeguard towers. This interference could possibly be from the Surf Lifesavers UHF communications, which may cause interference on some of the bands we were using. This could possibly be reduced by using the spectrum spreading functions in LoRa.

We suspect the corruption shown in the image above was an out of synchronous comms error where the receiver didn’t receive the final/end packet, and instead printed a garbled mess. These anomalies were rare, however.

Based on this testing, we can conclude that the practical range for the Jaycar LoRa module, when line-of-sight is maintained, seems to be about 7km using the default out of the box hardware. This is in conjunction with the default spreading factor and data rates.

7km we suspect is more than enough for most applications and is hugely impressive for such an inexpensive module. The range should extend much further with a better choice of antenna, better use of the spreading factor, and better management of interference.

WHERE TO FROM HERE?

To get a longer range, you could try to place the LoRa antenna a quarter wavelength in front of a metal plane (RF reflector) at least one wavelength square, so the antenna is toward the expected receiver, and do the same on the other end. However we're going to try this in a future LoRa project and measure the results.

You could swap the DHT11 temperature and humidity sensor for a DHT22 sensor, which has a higher resolution, greater accuracy, and a lower thermal mass. It can can easily be swapped into this project. All that would be required is to change the define from:

#define DHTTYPE DHT11

to:

#define DHTTYPE DHT22

Of course, you could look at other sensors to measure other atmospheric conditions.

Incorporating 2-way communication would also be an ideal modification for this project. We could easily attach buttons to the RX module which could be used to trigger real-world devices. For example, you could press a button on the RX module which could turn on a light, a fan or a solenoid valve etc. This could allow you to react to specific weather conditions without the need to leave your desk.

Adding more sensors and creating a WAN could help you get readings from different parts of your property.

This is only the beginning for our exploration of LoRa. Keep watch for future projects where we explore some of these suggestions further too!