Projects

Desktop Weather Station

with Arduino Nano 33 BLE Sense

Johann Wyss

Issue 39, October 2020

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

Log in

We take a look at the Nano 33 BLE Sense board from Arduino and use it to make a desktop weather station.

BUILD TIME: 2 HOURS (+ 3D PRINTING TIME)
DIFFICULTY RATING: Intermediate

It is an exciting time to be a maker. We now have access to a wide range of microcontrollers and development boards to suit different projects and applications. In this issue, we get hands-on with Arduino’s Nano 33 BLE Sense board and put some of its environmental sensors to good use in a desktop weather station project.

The Broad Overview

With its eight embedded sensors and Bluetooth support, the Arduino Nano 33 Sense board can be used in many applications without the need for external sensors and circuitry. It is compact too, measuring just 45 x 18mm.

We take a detailed look at this feature-rich Nano Sense board and use the temperature, humidity, and pressure sensors to make a simple desktop weather station.

Our project uses an 84 x 48 dot matrix LCD to display, which as you will read, presented us with some interesting challenges for its backlight.

Finally, we house the Nano Sense and LCD in a 3D printed enclosure and show you how to overcome some temperature fluctuations when using the onboard temperature sensor.

The Nano 33 BLE Sense

NANO FORM FACTOR

The Arduino Nano is usually our go-to board for prototyping applications so we were naturally very keen to play with the Nano Sense. The Nano Sense shares the same form factor and pinout as the Nano, which means in many cases, you can simply replace the OG Nano in your project with the new Nano Sense. However, there is one big limitation. The Nano Sense is not 5V tolerant and nor does it have a 5V regulator on board. This means, to replace the Nano in your existing projects, you would need a level shifter on the inputs and a way to power any devices you have attached to the 5V pin.

Microcontroller

Another significant point of difference between the Arduino Nano and the Nano Sense is the microcontroller itself. The traditional Nano uses the 8-bit ATmega328 running at 16MHz, which is identical to the microcontroller used on the Arduino Uno. The Nano Sense on the other hand uses the 32-bit nRF52840 ARM cortex M4 at 64MHz. This means, in theory, the Sense is much faster and more powerful than the previous. With that aside, it also has 1MB of flash storage as opposed to the traditional Nano’s 32KB, and 256KB or RAM vs 2KB on the previous Nano. You have significantly more room for programming.

Note: The Sense is powerful enough to run TensorFlow Lite for Edge Computing applications. This is beyond the scope of this article, however, we will look at this machine learning abilities in a future project.

SENSORS

As its name implies, the Arduino Nano 33 BLE Sense includes sensors integrated onboard, along with Bluetooth Low Energy (BLE) support. The eight built-in sensors are used to measure:

  • Temperature
  • Humidity
  • Pressure
  • Motion (9 axis accelerometer / magnetometer)
  • Gestures
  • Light colour & intensity
  • Proximity
  • Audio (Digital microphone)

For our project, we will be looking at the temperature, humidity, and pressure sensors. Whilst we won’t be using the other sensors, we figure that we should certainly make the project open enough so that, if desired, the project could easily be modified to include them. For example, you could control the LCD backlight by using the light sensor, only turning the backlight on if the room is dark. Or, you could use gestures to control which variable is displayed on the LCD perhaps. The added sensors give quite a bit of flexibility for those keen to tinker.

Temperature and humidity

The onboard ST HTS221 is responsible for reading temperature and humidity environmental data. This capacitive temp and humidity sensor has an accuracy of ± 0.5°C between 15°C and 40°C, and ± 3.5% relative humidity (RH) between 20% to 80%.

Barometric Pressure

The pressure readings are measured using the ST LPS22HB MEMS pressure sensor, which is purported to be the world’s smallest pressure sensor at just 2mm x 2mm. It has an accuracy of ±0.1 hectopascals (hPa).

Display

Since the sensors are built onto the same development board as the microcontroller, the only big decision we needed to make with this project was which LCD to use. For us, that decision was an incredibly simple one.

Given that the Nano Sense is a 3.3 volt board, for simplicity, we wanted to use a 3.3V LCD. This limits our choices to a handful of OLED displays, such as the SparkFun Micro OLED breakout that you can find at Core Electronics, or the much more common Nokia 5110 LCD. Bang for buck, this LCD punches well above its weight with a resolution of 84x48 pixels. The display produces crisp text too, despite the text being only 7 pixels tall.

Given its availability at most electronics retailers, and a large amount of data it can show at any one time, it’s a perfect screen for this project.

Backlight

The LCD we are using in this project has a backlight, which makes it great to see the weather data at night time. For our final build, we are using the LCD from Jaycar Electronics, which has 4 x 150Ω current limiting resistors soldered to the rear of the PCB as shown here.

These resistors mean we can power the LCD backlight direct from 3.3V without fear of damaging it. However, please note, the LCD we used for the prototype did not have these resistors, and as such, we added a current limiting resistor for the backlight. You will notice this resistor in the Fritzing diagram below.

If your LCD does have the four resistors, you can omit the resistor on the light pin.

Note: During the creation of this project, we encountered an odd discrepancy between the different display types. For the prototype, we used a Nokia 5110 LCD from our parts storage, which we suspect was a SparkFun model from Core Electronics. In the final build, we used a Nokia LCD from Jaycar. The LCD backlight on the prototype’s LCD was activated by a 3.3V supply to the Light pin and needed a current limiting resistor. However, the LCD from Jaycar in our main build required a ground potential added to the Light pin for it to illuminate. We have previously used this LCD from Jaycar, which we were confident had its backlight powered via 3.3V so there may be a change with recent stock. If you find that your LEDs are not illuminating on the Jaycar LCD replace the 3.3V connection to Light with a ground connection.

Backlight options

We mentioned previously the ability to control the backlight directly from a GPIO pin of the Arduino Nano Sense. However, we need to clarify that the circuit will need to be protected to ensure you don’t damage the pin on the development board.

When supplied with 3.3V, the Nokia 5110 LCD consumes less than 10mA and as much as 55mA when the backlight is illuminated. This high current is the result of each of the 4 LEDs being powered in parallel with a series resistor.

The maximum current output on any pin of the Nano Sense is only 15mA as opposed to the 40mA of the original Nano. If you wish to power the backlight via a digital pin on the Nano Sense board, you will need to ensure that the current does not exceed 15mA. This can be done by simply adding a current limiting resistor in series with the digital pin you use.

If your LCD does not have any current limiting resistors on the PCB you can calculate the resistor value using the following equation.

R1 = (Vin - Vf) / Imax

Where:

R1 is the resistor value.

Vin is the 3.3V input.

Vf is the forward voltage of the LED (In our case, 1.7V).

Imax is the maximum current of 15mA.

Whereas, if like us your LCD has the current limiting resistors, we need to consider the parallel resistance before putting a resistor in series. We know the resistor value on the PCB is 150Ω and we know there are four of them, all in parallel, as shown in this diagram.

Thus, if you wish to power the backlight via a pin you will need to add a series resistor to protect the microcontroller.

To calculate the combined resistance of resistors in parallel with more than two resistors, we use the following equation.

1/Rtotal = 1/R1 + 1/R2 + 1/R3 + 1/R4

Thus, for us the total resistance of the 4 resistors is:

1/Rtotal = 1/150 + 1/150 + 1/150 + 1/150 = 37.5Ω

Therefore, to calculate the resistor needed to keep the current below 15mA, the equation is.

R1 = ((Vin - Vf) / Imax) - Rtotal

Where:

R1 is the resistor we will need in parallel.

Vin is the 3.3V input voltage.

Vf is the forward voltage (In our case, 1.7V).

Imax is the maximum current the pin can deliver.

Rtotal is the total resistance of the resistors in parallel (In our case, 37.5Ω).

This returned a value of 69.16Ω. The next highest resistor in the E12 range is 82Ω. In this case, using an 82Ω resistor will draw about 13mA on the Nano Sense pin and provide about 3.2mA per LED.

This is, of course, only necessary if you wish to power the backlight from a pin of the Nano Sense. It can be ignored if you are powering the backlight from the 3.3V rail. For our project, we are happy to just keep the backlight powered constantly to keep it nice and simple.

Build 1:

The Prototype

Electronics

Parts Required:JaycarAltronicsCore Electronics
1 x Arduino Nano 33 BLE Sense--ABX00031
1 x 84x48 Dot Matrix LCD (Nokia 5110)XC4616Z6348LCD-10168
1 × 40 Pin Female Header - StraightHM3230P5390POLOLU-1014

Parts Required:

* A breadboard and prototyping hardware is also required

Out of the box, the Nano Sense does not have any headers soldered to the PCB. Thus, our first action is to solder the headers so we can plug it into a breadboard.

Note: Unlike other Arduino boards, the Nano Sense has its pinouts silkscreened to the bottom side of the board. This can make it challenging to prototype once it is in a breadboard, unless you refer to online or printed pinouts, such as the official one on the Arduino website. We tried soldering the header pins from the other side to see the labels as we prototyped, however, we quickly noticed this was not ideal because it meant the other sensors and the reset button were hindered.

Next, solder the male header pins to the LCD. We soldered the pins to the through-holes closest to the smallest bevel edge.

Follow the Fritzing diagram or the following table to connect the LCD to the Nano Sense.

*Pin 7 (LIGHT) on the LCD is connected to either a digital pin of your choice via the series resistor you calculated earlier or directly to 3.3V (if you have a module with the current limiting resistors pre-installed) on the Arduino Nano Sense.

The code

The code for this project can be downloaded from our website. The code is fairly straightforward, however, there are a couple of libraries that you will need to download.

The libraries

Your first port of call should be to download the libraries for the temperature, humidity, and pressure sensors built into the Sense board. To do this, simply use the built-in library manager.

Go to Sketch > Include Library > Manage Libraries (Control + Shift + I on Windows).

Search and install “PS22HB”. Installing this will allow you to use the pressure sensor built into the Arduino Nano BLE.

Follow the same procedure but search and install “HTS221”. Installing this will allow you to easily use the temperature and humidity sensor.

Whilst not immediately needed for this project, we recommend you also download the following libraries, which will allow you to control the remaining sensors on the Nano Sense.

Search for and install the following libraries if you’re wanting to tinker and explore the other sensors on the Arduino Nano Sense BLE.

  • LSM9DS1 for the accelerometer / magnetometer
  • PDM is the Adafruit library and may be compatible with the MP34DT05 microphone
  • Arduino Sound is the official library for the MP34DT05 microphone on the Nano Sense
  • APDS9960 is for the gesture sensor
  • Finally, search and install the Nokia 5110 library from Hossein Baghayi.

Note: We had some compatibility issues with other LCD libraries, including the one from Adafruit and our personal favourite from Rinky-Dink. In our case, neither would compile when using the Arduino Nano Sense as the board.

Setup

Setup is very simple for this project. The first three lines are simply adding the required libraries. The following five lines define which pin is connected to the LCD and is used within the Nokia 5110 library.

The constant variable offset is used to rectify any offset temperature on the sensor.

Due to its compact form factor, the Arduino Nano Sense can suffer from self-heating. This is when the heat from the processor and other circuitry causes the temperature of the board to rise, which affects the embedded temperature sensor.

To test the level of heating, we used two multimeters (The UNI-T UT804 and Digitech QM1571) along with two thermocouples to read the actual ambient temperature. In or testing, the Arduino Nano Sense was consistently reading 3.46°C above the ambient temperature reported from both multimeters.

Note: These tests were done after the device had been running for over an hour to ensure that the board was at the expected operating temperature.

We suspect there would be a number of ways to reduce self-heating. This could include reducing the load on the processor, which would reduce its overall power dissipation into the board, reduce the electrical load on the voltage regulator circuit, or better still, bypass the need for the regulator altogether by supplying the project directly with 3.3V.

Of course, another approach is to allow for this temperature difference in the software, which is the method we went with. This does not change the fact that the board is heating but rather accounts for the level of heating experienced.

Since this project is fairly simple and the current demands are constant, the amount of heating does not fluctuate. If you’re going to implement a control system for the LED backlight however, you may want to consider directly powering the entire circuit directly from a 3.3V supply. This will bypass the onboard voltage regulator and mean the heating will not fluctuate with load fluctuations. i.e. heat up more when the LED backlight is on.

Therefore, the value you enter into the offset memory location will be a difference in temperature. This number is then subtracted from the actual read. So, if you are running the same test and your sensor is showing 2.02°C more than offset, the value is 2.02.

The remaining code in the setup loop is to provide an error message and/or halt the program if there are any issues with communicating with serial or the sensors. If either sensor fails, the display will show an error message, explaining which of the sensors are not functioning correctly.

#include <Arduino_HTS221.h>
#include <Arduino_LPS22HB.h>
#include "Nokia_5110.h"
#define RST 2
#define CE 3
#define DC 4
#define DIN 5
#define CLK 6
const float offset = 3.45;
Nokia_5110 lcd = Nokia_5110(RST, CE, DC, DIN, 
CLK);
void setup() {
  Serial.begin(9600);
  if (!Serial){
    lcd.print("Serial failed");
    delay(1000);
  }
  if (!HTS.begin()) {
    lcd.print("HTS sensor");
    lcd.setCursor(0, 2);
    lcd.print("failed");
    while (1);
  }
  if (!BARO.begin()) {
    lcd.print("Temp sensor!");
    lcd.setCursor(0, 2);
    lcd.print("failed");
    while (1);
  }
lcd.clear();
}

Loop

The loop is equally as simple. We first take a reading using the function HTS.readTemperature(); This returns a float value and places it in the temperature variable. We then remove the offset value from the temperature variable to account for the self-heating.

The HTS.ReadHumidity(); and BARO.readPressure(); functions read and store the humidity and pressure from the sensors, and into their respective variables.

After that, it’s just a simple case of writing the values to the LCD display.

The function lcd.setCursor(x, y); is used to position the text on the display.

The LCD has a total of six horizontal banks from bank 0 to 5. Each bank has 84 columns of 8 pixels. The x variable positions the horizontal position between 0 and 83 while the y variable sets the bank between 0 and 5.

The LCD.print(); function writes the string, float, or integer to the LCD display, and the ln designator is a carriage return.

Finally, we have the line delay(1000); that refreshes the display once a second or every 1000 milliseconds. You can reduce the value if you want a faster refresh rate. We tested it with a 100ms delay and it worked as expected, however, the jittery least significant digit was distracting. Given the project is intended to sit on your desktop, a 1 second / 1 Hz refresh rate is more than sufficient.

void loop() {
  float temperature = HTS.readTemperature();
  temperature = (temperature - offset);
  float humidity    = HTS.readHumidity();
  float pressure = BARO.readPressure();
  lcd.setCursor(1, 0);
  lcd.print("Temperature = ");  
  lcd.setCursor(30, 1);
  lcd.print(temperature);
  lcd.println(" C");
  lcd.setCursor(0, 2);
  lcd.print("Humidity = ");  
  lcd.setCursor(30, 3);
  lcd.print(humidity);
  lcd.println(" %");
  
  lcd.setCursor(0, 4);
  lcd.print("Pressure = ");  
  lcd.setCursor(30, 5);
  lcd.print(pressure);
  lcd.println(" kpa");
  delay(1000);
}

Programming the Nano Sense

We would have thought that programming the Arduino Nano Sense would be as simple as programming any other Arduino device, however, it was now straightforward in our case. With the Arduino Nano Sense selected, and the correct port, we would constantly receive an error when trying to upload our program.

The error seemed to suggest that the port was busy. The only way we were able to upload a program to the Arduino Nano Sense was to press its reset button twice in rapid succession to force it into an upload mode.

Note: You can tell that the Nano Sense is in upload mode when the orange LED slowly fades on and off at a breathing-like pace.

We did notice, however, that this upload method would also change the port. You may want to double-check that the port is selected after double-tapping the reset button.

Testing

Apply power to your Nano Sense and the LCD should display the three environmental values.

This was the point where we discovered the self-heating issue and circled back to apply the offset in the code. We recommend that you compare the temperature displayed on the LCD against a high-accuracy thermometer you have available. You can then adjust the value of the offset constant to match your results.

Build 2:

The Main Build

Parts Required:JaycarAltronicsCore Electronics
1 x Arduino Nano 33 BLE Sense--ABX00031
1 x 84x48 Dot Matrix LCD (Nokia 5110)XC4616Z6348LCD-10168
1 × 40 Pin Female Header - StraightHM3230P5390POLOLU-1030
1 × Female Pin Header StripHM3230P5390PRT-00115

Parts Required:

* Hook-up wire is also required

The electronics in the final build are identical to the prototype. The only difference is that we power the Nano Sense from the Vin pin instead of its USB port. We have still made the USB port accessible if you want to tinker with the other sensors over time.

Wiring Harness

To connect the LCD and the Nano Sense together, we use a female header strip, which needs to be cut down to the correct number of pins. The LCD connector has a strip 8-pins long, and the Arduino side has a 6-pin long strip and a single pin that goes to the power connection on the Arduino.

We soldered the harness together with 7 x 50mm lengths of hook-up wire, and insulated them with liquid electrical tape (heatshrink is just as effective).

Our harness, as seen from the LCD, is wired as follows:

*Your LCD may require 3.3V or GND attached to the light pin.

Note: To connect the Light pin, we just created a solder bridge to connect light to either the VCC or GND pin.

We are powering the project with 5V to the Vin input pin using a similar female header system we used to connect the LCD to the Arduino. The power input pin can accept any voltage between 4.5V and 21V.

Note: It’s highly likely that a higher voltage on this pin will result in a change being needed to the offset as the voltage regulator could play a role in self-heating.

With the wiring harness made, we now need to assemble the electronics into the 3D printed enclosure.

3D printing

We wanted our weather station to sit proudly on our desk with the screen at a convenient angle to see the weather-related variables at a glance. This obviously meant getting the components off of our prototyping breadboard and into some type of enclosure.

We also wanted our design to not hinder the sensors of the Nano Sense, and still be flexible enough for us to access the other sensors should we want to tinker with them in the future.

Our case was designed in Fusion 360 and we will provide the working files on our website if you want to modify the project to suit your specific needs. The enclosure prints in two sections. The front holds the Arduino Nano Sense via a friction fit, and the LCD is secured in place using four #4 6mm screws. The stand is just a simple angled design that displays the screen at the perfect angle as we sit at our desk.

Front panel

The front was printed at 200-microns layer height on our Flashforge Creator Pro using Flashforge branded white PLA. It prints face down on the build surface and can be printed with or without supports. In this orientation and layer height, the front took about 1.5 hours to print.

STAND

The stand was printed in black 3DFillies PLA+ on our Flashforge Creator Pro at 200-microns. We printed it on its side, and it must be printed with supports enabled. In this orientation, and at this layer-height, the part took about 2 hours to print.

Assembly

To assemble our project, we first screwed the LCD to the four posts on the enclosure so that the larger bezel around the LCD was at the top (furthest from the Arduino Nano Sense mounting location.

The Arduino Nano Sense can then be inserted into its position from the front, pressing it tightly into its recess. If your Arduino is sitting loosely in the recess due to printer tolerances etc, you may need to secure it in place with a small dab of hot glue or other such adhesive that is easy to remove.

With the LCD and Arduino inserted into place, you can connect the wiring harness you created earlier. When you’re done your project should look like this.

We now simply need to glue the front panel holding the LCD and Arduino to the stand. For this, we just used a little hot glue, but you can use any adhesive you like.

Note: If using super glue, be very careful as the fumes cause white staining on the surrounding plastics.

Testing

With the project constructed, it is a good idea to test the accuracy of the readings once again and to adjust the temperature offset if necessary.

In our test, one DMM reported the temperature as 24.6°C and the other DMM reported 24.5°C. The Arduino Nano Sense was reading 25.4°C, 0.85°C higher than the meters, which is on top of the 3.45°C offset we had already accounted for in software. This meant, in total, the Arduino Nano Sense was reading 29.7°C.

Note: In our example, we are using a different Arduino Nano Sense to our prototype. This may explain the difference in the offset, however, it could also be based on powering the device from the Vin pin and not USB.

To calculate the offset value needed to adjust for the self-heating, we use the equation:

Offset = Ar - (( M1r + M2r ) / n )

Where:

Ar is the Arduino reading

M1 is meter 1 reading

M2 is meter 2 reading

n is the number of meter readings used

Offset = 29.7 - (( 24.4 + 24.5 ) / 2 )

Thus, the offset required to accommodate for the self-heating is 5.15. Changing the offset const in the software will correct for this error and will provide readings at least as accurate as the multimeters you used for calibration.

Where to from here?

This project was intended as just a starting point to get you familiar with the Arduino Nano Sense, and to show you how to easily connect an LCD to display all sorts of data from the various different on-board sensors.

With that said, there are many ways you could improve on this simple project.

As we suggested earlier, a backlight control would be a nice easy one to start with. You could use the light sensor to activate the backlight when the room becomes dark.

You could even use the gesture sensor to alternate between which variable is being displayed at any specific time.

If you find it hard to understand the pressure readings in kilopascals (kPa), you could change that to display the weather conditions based on the pressure readings over time. For example, a low-pressure trend could indicate inclement weather approaching. eg. rain and wind.

We found a great tutorial and chart from the University of British Columbia to help explain weather expectations based on the pressure that may help: https://www.eoas.ubc.ca/courses/atsc113/sailing/met_concepts/11-met-marine-weather/11c-forecasting/

Johann Wyss

Johann Wyss

DIYODE Staff Technical Writer