I needed a way of remotely monitoring the temperature and relative humidity in a greenhouse used by my local garden club. We grow and graft tomato plants for our annual plant sale. Careful control of the T and RH is helpful to insuring the success of the grafting process. Given the large T and RH changes that a greenhouse can experience we wanted to measure the conditions 24 hours a day, seven days a week. After exploring commercial recording hygro-thermographs and determining the cost to be prohibitive I decided to build my own.
The basic design specs for this device were:
Have the ability to:
1. Measure T and RH with two separate sensors
2. Record the date, time, T and RH on an on-board memory card
3. Dump the contents of the memory card via web connection to the device
4. Upload real-time measurements to an IoT website
5. View the data graphically as a function of time
When I started the project a year ago I was an Arduino/IoT/C++ NOOB. The closest I had come to building something like this was replicating MightyOhm’s WiFi Radio based on a hacked ASUS WL-520GU router. As this project evolved the WiFi radio experience turned out to be very helpful. As you might imagine the project described in this Instructable is the result of countless iterations along a very interesting learning journey. This most recent iteration uses BME280 temperature, relative humidity and barometric pressure sensors. My previous version used DHT22 sensors. My thanks to everyone who has shared their learning, wisdom and code on the internet. I would not have been able to write the code for this without all of the functions and code snippets that I borrowed from everyone who shared. I have tried to note and thank these authors at the top of my sketch and throughout this Instructable.
Step 1: Tools, Hardware, Software
Soldering Iron and solder
Needle nose pliers
Thin kerf saw to cut the proto-board (bandsaw, hacksaw, coping saw)
1- Arduino Mega 2560
2- I2C/SPI Breakout Temperature Humidity Barometric Pressure BME280 Digital Sensor (ME-BME280) Ebay
1- Micro SD Card
1- DS3231 AT24C32 IIC Real Time Clock Module for Arduino
1 pkg – male header pins
1 pkg – female header pins
1 pkg – right angle male header pins
1 pkg.- Jumper Wires (you will need male-male and male-female)
1 roll, four conductor (phone) wire or equivalent (to connect sensors to Arduino)
1- Hackable router- DD-WRT capable (I use Asus WL-520GU and TP-Link N300)
24 or 26 gauge solid insulated wire (phone wire or Ethernet-SD cable wire works fine)
1 foot of 1” PVC Pipe
4- 1” PVC Pipe Caps
3- 8-24 x 1” nylon screws and nuts
Note that the BME280 sensor is available in many slightly different packages from Adafruit, Sparkfun, Amazon, etc. The Adafruit version has the logic level convertor onboard eliminating the need for the Sparkfun device on the list above.
-Arduino sketch- BME280_Recorder_C_Ethernet-GitHub.ino and make sure all of the libraries found on each #include line in the sketch are in your local Arduino IDE library.
-Clock Setting sketch such as this one. This sketch will enable you to set the time on your Real-Time Clock Module using the Arduino Mega and the LCD Keypad Shield.
-Cactus IO BME280 I2C Library- https://goo.gl/yWBL5G (This library is required for dual BME280 sensor setups!)
Step 2: Set the Date/Time on the Real-Time Clock Module
-Attach the pushbutton LCD shield to the Arduino Mega. With jumper wires connect the 5V and GND on the RTC module to 5V and GND on the Arduino. Connect SDA, SCL on the RTC module to Arduino pins 20 and 21.
-Connect the Arduino to your computer via USB. Upload the time setting sketch. Follow the directions on the LCD and set the date and time.
-Disconnect everything and set the parts aside.
Step 3: Prepare the Proto-board
A proto-board is incorporated in this project because the Arduino Ethernet-SD shield and the Push Button LCD Display shield do not play nice together. They both use pin 10 and pin 4. Fortunately, this conflict can be handled in the sketch and on the proto-board.
The first thing you need to do is plug the proto-board into the Ethernet-SD shield. You may note that the Ethernet receptacle prevents you from plugging in the proto-board completely. If so, simply cut a slot in the proto-board to avoid the interference. I used a bandsaw to cut mine.
Remap pins D10 to D3 and pin D4 to D2 as follows. Bend pins D10 and D4 on the proto-board so that they no longer plug into the Ethernet-SD shield. (Or, just cut them off.) Using some insulated wire, solder a jumper from pin D10 to pin D3 and another jumper from pin D4 to pin D2. These pins are remapped in the sketch in line #63- LiquidCrystal lcd(8, 9, 2, 5, 6, 7); and the line #750- analogWrite(3,100);. The latter line sets the lcd backlight pwm dimming on pin D3. Cano64 published this solution at https://goo.gl/2eJZe9.
The proto-board can also be used to mount and connect the Sparkfun bi-directional logic level convertor. This device is required for use with the BME280 as they operate at 3.3V. It is not entirely clear whether it is required in the I2C mode but it isrequired for SPI. Since I opted to use I2C and I fried two sensors with 5v instead of 3v in an early attempt (it pays to read spec sheets!), I opted to use the logic level converter to be safe. Wire it per diagram the diagram above. In my set-up I soldered header pins to the Logic Converter and then soldered it to the proto-board. If you want to set-up your sensors and logic level controller up on a breadboard before soldering- DO NOT SOLDER the logic level controller to the protoboard yet.
I also used PCB mount screw terminal blocks to connect the sensor wires to the proto-board. I used a right angle male header block for connecting SDA and SCL pins from the Arduino to the proto-board.
At this point you can assemble the shield stack- Ethernet-SD shield on the Arduino, proto-board on the Ethernet-SD shield, Pushbutton LCD on the proto-board.
Step 4: Format a Micro-SD Card:
Simply follow the directions that came with your card to format it as a FAT 16 or 32.
The sketch needs a text file named HC_Data.txt to write the data to. Create this text file on your computer and save it on the SD card.
Insert the SD card into the Ethernet-SD card slot.
Step 5: Testing Your Rig on a Breadboard
If you are tempted to fire the device up at this point, upload the sketch and try it. This is a good way to determine which libraries may need to be added. (to add libraries, in the Arduino IDE, Sketch>Include Library) This is a good time to download and add the libraries noted in Step 1- Software.
The sketch is written to go through a boot-up process (see the video above) where it initializes things and checks for the presence of others. It displays some of the steps on the LCD display and detailed steps on the serial monitor. Unfortunately, the sketch will stop very early in this process when it can’t find the BME280’s. (If I was following this recipe, I’d fire it up anyway to see what happens—so go ahead if you want)
At this point you will have to think ahead and imagine how you want to deploy your BME280’s and decide whether you want to hardwire them to a four-wire cable or you want to plug them into a female header or use screw connectors. This Instructable uses screw connectors on the proto-board and female header plug-in on the sensor end.
Solder male header pins onto the BME280 boards.
Plug the BME280’s and logic converter into the breadboard.
Wire the BME280’s with breadboard jumper wires as per the diagram above. Depending on the particular version of BME280 you purchased you may need to read the documentation and figure out how to connect them as shown in the diagram. The sketch works with these sensors through I2C communication requiring the sensors to have separate addresses (0x76 and 0x77). This happens by connecting Chip Select (CSB) to Vcc on both and SDO to GND on one and SDO to Vcc on the other. (Note: there are four connector BME280's available where the sensor address is changed by unsoldering a joint on the board -- just make sure that your seller supplies documentation)
Step 6: Create a ThingSpeak Account:
Go to ThingSpeak.com. Open an account and a channel. The sketch writes data to seven ‘Fields’— (1)Time, (2)Date, (3)BME1 Temperature, (4)BME1 Relative Humidity, (5)BME2 Temperature, (6)BME2 Relative Humidity, (7)BME1 Barometric Pressure. Set these fields up in ThingSpeak
Copy and paste your Channel ID (found under the Channel Settings tab) and your Write API Key (found under the API Keys Tab) on lines 108 and 109 of the sketch.
Pick an IP address for your device to communicate to the ‘client-bridge’ router that will be configured in later steps It should be something like 192.168.1.XXX where xxx is a number such as 55 (It needs to be an unused address on your LAN). Enter that IP address on line 152 of the sketch. A MAC address is also set for the Ethernet communication on your network. It is set on line 139 and is currently BA:BA:BE:EF:BA:BA. You can set this to anything that will be unique on your network.
If you haven’t uploaded the sketch at this point -- do it now.
With a little luck it will start running!
Bring up the Serial Monitor on your computer so that you can see what the device is doing.
Hopefully the sketch compiles and uploads. Since the client-bridge is not configured at this point it will not upload data to ThingSpeak.
Step 7: Overview of the Sketch:
The sketch performs numerous functions:
1- As it begins execution in voidSetup() the sketch:
a. Initializes and displays a greeting on the serial monitor (void greeting(), line 938 and initializes the LCD and displays a greeting
b. Dims the LCD backlight with PWM (see line 741)
c. Accesses the date and time from the RTC and displays it on the serial monitor and LCD. If unsuccessful a warning is displayed. (from: Andrew Basterfield, AlarmClock, https://goo.gl/Heigw1 and Sparkeys Widgets, https://goo.gl/BUaKya)
d. Checks the BME 280 sensors to ensure they are connected and displays their state on the LCD and serial monitor. If unsuccessful the sketch halts.
e. Obtains and displays the local IP address of the client-bridge
f. Initializes the SD card, and warns if it is not present. It opens and determines the sd card type, volume type, volume size and will display all the files in the volume by uncommenting lines 909-920.
3- It reads BME280-1 every 2.6 seconds (24 readings/average ~60 seconds) and BME280-2 every 3.1 seconds 20 readings/average ~60 seconds) and computes an average of the T, RH and BP about every minute
4- It writes these averages from both sensors with the time and date to the SD card (from: toptechboy.com)
5- It uploads the averages from both sensors with the time and date to ThingSpeak every 63 seconds
6- It has a web server that listens for remote requests. When receiving a request it will dump the contents of the SD card to the requester (From: javacasm for WebServerDataLogger)
I employed Simon Monk’s Timer.h library to take care of the time sequencing of events. You may be curious about the odd timing of the sensor readings. Since the Arduino cannot read these sensors at the same time the readings have to be spaced out. 2.6 and 3.1 seconds minimizes the possibility of attempting simultaneous reading and data transfer in later cycles from the sensors to a great extent. I’m sure there are more elegant ways to accomplish this—but this is what I was able to make work! You may notice that the scrolling digits on the LCD will occasionally stall for an instant. This results when the controller is trying to do two things at once. It is very noticeable when the web server responds to a request for data and dumps the contents of the SD card.
Step 8: Configuring the Client Bridge:
When I started experimenting with this device I was reluctant to use an Arduino wi-fi shield due to the cost, potential coding challenges and possibe power requirements. Since I had some experience hacking routers with DD-WRT and Open-wrt I opted to go this way although the wi-fi route in hindsight is likely much cleaner (but, I've never tried it). Configuring the router to client bridge mode was the most frustrating part of this project. Note that there are numerous DD-WRT versions each designed for specific routers and the interface is slightly different for each one.
(for the unfamiliar- you will be flashing the firmware memory in your compatible router with DD-WRT in the same way you would install a firmware update. DD-WRT replaces the stock OS with a new OS and a completely different router interface.)
2- Get a hackable router (Craigslist maybe?).
3- Install the appropriate version of DD-WRT
4- Configure the router in Client bridge mode. The instructions are here-https://goo.gl/uWVG16 (follow them exactly!) When you have it configured correctly and connected to your computer it should give you a wireless ethernet connection to your LAN and WAN
5- Connect it to the Arduino and restart the sketch.
6- Check ThingSpeak to determine if your data is uploading
7- Type the web address of your router into a web browser. It should begin to download the data on the SD card.
Step 9: Protecting the BME280’s:
I was unable to find any information outlining best practices for protecting the BME280’s from the environment. I know from my experience with DHT-22’s in earlier iterations of this device that the greenhouse environment where they operate is harsh particularly with dust (and stray water). I designed and built simple protective covers for the sensors from 1” PVC Pipe and pipe caps. I used Double Side Prototype PCB Universal Printed Circuit Board as a platform to connect the sensor wires from the Arduino as well as to create a plug-in mount for the sensor with a female header. I have another version that uses the 2P 5mm Pitch PCB Mount Screw Terminal Blocks to connect the four-wire sensor cable from the Arduino. I drilled four 3/8 in holes around the periphery of ~ 4 inch section of pvc pipe to allow airflow around the sensor. The board is held in place inside the tube with a nylon screw and nut. Protective sleeves were made from the 50 micron Polishing Filter media. Contact cement is used (two coats were required) to create a seam in the sleeve.
Step 10: Visualizing the Data
While ThingSpeak provides an extremely reliable and easy to use service (and it’s priced right too-FREE!) I was dissatisfied with the graphical capability it provides. My data on ThingSpeak is displayed here . I invested a significant amount of time looking for a better graphing capabilities on other IoT sites. I explored every free IoT service that I could find and found most to be difficult or impossible to get running. None of them yielded better graphing capabilities. The journey led me to FatCat Labs in NYC one night for Arduino Tuesday. One of the participants suggested that I was “going about this the wrong way” and that I should “create a website and use Google Charts” to display the data. In the moment I was frustrated with his advice as the last thing I wanted to do was to create a website. But, on the train ride home I came to grips with his advice and decided to go for it. I started messing around with Google Charts and didn’t get very far until I discovered a brilliant solution shared by Mike Teachman. His code and instructions for using it are on GitHub (use the one labeled as 'new version'). You can see my graphs using his code here and here. It is possible to use Google Graphs to display the data on gauges. I modified the gauge code on ThingSpeak’s private channel to make these gauge gadgets. The code for the Barometric Pressure gauge is here. You will have to add your channel number and read API key. If you want to experiment with the code parameters you can run it on JSFIDDLE. Just copy the code into the HTML section enter your ThingSpeak channel number and API read code and click RUN. It will display your gauge in the right hand panel.
Barometric Pressure Readings: Unless you live at sea-level the barometric pressure readings will be different than what is reported by your favorite local weather station. All reported barometric pressure readings are corrected to sea level. Thus, knowing the sea level BP and your device BP you can calculate your altitude. Or, if you know your altitude you can calculate a correction factor. You can find a detailed explanation here.
Step 11: Deploying It in the Greenhouse:
I have two of these devices. One I keep at home for development and experimenting with tomato grafting. The other is deployed in the greenhouse where we use a verizon hotspot for the internet connection. In the photos above you can see how I protect it from dust, water and curious hands. The plastic box is from Home Depot (shoe box ~$3). The Arduino is held in place with nylon screws and nuts through holes in the bottom of the box. The client-bridge router is held in place with Velcro tape. I don't use a proto-board in this version. Instead the remapping of D10 and D4 is done with the ribbon cables. The logic level converter is mounted on a small board wired as per the diagram and uses screw connectors to connect the sensors. I used a few coats of Liquid Electrical Tape on the back side of this board to protect the wiring from shorting. The logic level converter board and the Real-time Clock plug into female headers on another board to keep them out of the way. The power and sensor wires pass through holes with grommets on the sides of the box.