Off-The-Shelf Hacker: Portable Atmospheric Readings with a Sparkfun Breakout Board
The postman delivered a BME280 atmospheric breakout board, last week from Sparkfun. It measures local barometric pressure, humidity, altitude and temperature. This kind of sensor might measure outdoor weather conditions, help troubleshoot indoor environments or even act as a navigational sensor on an unmanned aerial vehicle (UAV). The board costs around $20.
I thought I’d team the BME280 board with a NodeMCU microcontroller and send the data to my “chest-top computer,” also known as the steampunk conference badge. Being battery operated with a couple of USB ports the badge makes it a quick and easy platform for temporary and portable measurement jobs. We’ve covered an external high-temperature sensor a while back.
Why Use a NodeMCU?
The NodeMCU is pretty much my go-to Arduino clone now. It is about the same length and a quarter wider than an Arduino Nano and has built-in Wi-Fi plus about 1MB of program space. It functions pretty much the same as a regular Arduino and can be easily programmed with the standard Arduino interactive development environment (IDE). I buy them in a three-pack of NodeMCU boards from Banggood for $14. Likewise, I pick up a three-pack of Arduino Nano clones for about $11 for projects that don’t need Wi-Fi. I’ve used Nano clones for lots of projects and they send data just fine over USB or the serial line.
You can use the Lua programming language on the NodeMCU boards, right out of the box. My preference is to use the Arduino IDE and libraries for projects. Be sure to set the board type to NodeMCU 1.0 (ESP-12E Module). The default baud rate is 9600. I usually run 115200 on all my projects.
Since I’m just getting the basic functionality of the sensor working with the conference badge, I’ll leave the Wi-Fi part for another time. Developing projects is easier by going in phases. It’s sensible to get one phase working solidly, then add new functionality and features in later versions.
Connecting The BME280 To The NodeMCU Board
The BME280 has two different interfaces, I2C and SPI. SPI needs six wires. The I2C setup only needed four wires. I went with I2C.
Instead of soldering a four or six pin header on the board any more, I opt to strip the insulation off of some 22-gauge solid-core wire and use that for breadboard pins. The technique is simple and it gives the option of removing the “pins” and soldering connecting wires right to the board as the project takes on a more permanent prototype or demo status. Push about 1/2 inch of bare wire through the hole in the board and down into the breadboard. Solder the wire on the top side of the BME 280 at the board level. Then clip off the little bit of excess wire. Do that for all four pins. It is much more difficult to remove regular connected headers when you move the board off of the breadboard.
The connections between the two boards were uncomplicated. I just ran 22-gauge solid core (insulated this time) between the NodeMCU board and the BME 280. You could also use standard six-inch pin-type proto jumper wires, although that won’t be as neat an installation.
You can get the code for the BME 280 to run on an Arduino from a number of places. I downloaded the Sparkfun BME 280 library from GitHub. This library had a number of examples including one for basic atmospheric data and one for local pressure. The basic data example is great for checking to see if the sensor works. I used the local pressure code to calibrate the sensor for local conditions. Both examples ran without issues on the NodeMCU board.
Adjust the local Reference Pressure
Nathan Seidle @ SparkFun Electronics
March 23, 2018
Feel like supporting our work? Buy a board from SparkFun!
https://www.sparkfun.com/products/14348 - Qwiic Combo Board
https://www.sparkfun.com/products/13676 - BME280 Breakout Board
'Sea level' pressure changes with high and low pressure weather movement.
This sketch demonstrates how to change sea level 101325Pa to a different value.
See Issue 1: https://github.com/sparkfun/SparkFun_BME280_Arduino_Library/issues/1
Google 'sea level pressure map' for more information:
29.92 inHg = 1.0 atm = 101325 Pa = 1013.25 mb
Serial.println("Example showing alternate I2C addresses");
Wire.setClock(400000); //Increase to fast I2C speed!
mySensor.setReferencePressure(101710); //Adjust the sea level pressure used for altitude calculations
Serial.print(" Pressure: ");
Serial.print(" Locally Adjusted Altitude: ");
Serial.print(" Temp: ");
The code is straightforward. It sets up the device using the library, then just calls the various data values and prints the results. I like to use English units of measure and commented out the metric value lines. We also need to adjust the setReferencePressure value to local conditions. We’ll discuss that shortly, in the next section.
Once the compiled code is uploaded to the NodeMCU board, you can reset the board and read the values using the serial terminal in the Arduino IDE or a regular terminal on a Linux desktop. Use our standard stty and cat commands.
linux-notebook% stty -raw -icrnl -F /dev/ttyUSB0 115200
linux-notebook% cat /dev/ttyUSB0
Using the NodeMCU-BME280 device combination on the Raspberry Pi conference badge is easy. Boot the badge, plug the NodeMCU USB cord into the Pi and run the stty/cat command combo in a terminal window. The data will scroll up the screen. Use CTRL-C to stop reading data.
Calibration Is Tricky
Finding the correct setReferencePressure is still a “black art” to me. Obviously, we want to have accurate barometric and altitude readings for our projects. I live near Orlando International Airport (OIA), so I figured their local atmospheric data could be used to calibrate my sensor. The airport altitude is listed as 96 feet above sea level. My local town also shows the same altitude on Wikipedia. I’m in between the two, not on a hill or depression, so the number seems reasonable for my use.
Suppose the local OIA sea level pressure is 1015.8 and the altitude is 96 feet according to their current measurements.
If I use a setReferencePressure of 1013800, I get a BME280 measurement of 101380 (divide by 100 to be consistent with the OIA reading) and 0.0 feet elevation.
If, on the other hand, we use a setReferencePressure of 101710, I get a BME280 measurement of 101377 and an elevation of 90.7 feet. This elevation is close to the actual altitude of OIA. That 1015.8 air pressure (local at OIA) is a bit off of the measured 1013.77 of the BME280.
At the same time the barometric pressure and altitude using GPS Essentials on my Galaxy 8+ phone. It gave readings of 101490 (1014.90) and 35.6 feet altitude.
What is the correct setReferencePressure number for my location? Does it matter that the sensor is inside, with an air-conditioned temperature of about 81 degrees F. while the outside temperature is 84 degrees F?
Putting it all together, there is considerable variance between the readings. Which one is correct? Right now I don’t know and this illustrates one of the difficulties of building a physical computing device. You always have to ask yourself if your data “seems” right. When it doesn’t we clearly need a deeper understanding. That takes time and effort to learn.
I didn’t know very much about the relationship between actual and measured barometric pressure, humidity, temperature and so on before fiddling around with the BME280. What is clear is that calibration of the sensor to actual local conditions is important and needs to be well understood and verified before implementing the technology into everyday gadgets and projects.
The basic operation of the BME 280 and the Raspberry Pi conference badge “chest-top” computer worked. It is now a matter of calibrating and gaining confidence in the data through testing and adjustment to make the setup useful.