This project is a significant upgrade to my previously posted project: Arduino Dual BME280 IoT Recording HygroThermoGraph posted in 2016.
Background: I grow ~1500 tomato plants every spring for the Maplewood Garden Club in Maplewood, NJ. About 250 of these plants are grafted. The critical step in grafting tomato plants is the the 'healing process' where the plants have to be subjected to a high humidity environment in a week long healing and weaning process. We repeat this process up to three times during the spring enabling us to achieve the quantities required for the sale. Since the greenhouse is a few miles from my home it is useful to remotely monitor the temperature and relative humidity in the healing chamber as well as the greenhouse during this process. Should the conditions get outside of the desired ranges we can address them.
The 2016 version was based on an Arduino Mega, with ethernet and real time clock shields. It also required a hacked router configured as a client-bridge to provide internet access via a wireless cellular router. It is a complicated set-up with a lot of connectors and wires. Over time the warm humid conditions in the greenhouse have caused corrosion on many of the connections.
I decided to redesign the electronics to simplify and eliminate as many parts as possible. The revised device requirements are to read the BME280's, get the time from a reliable internet site, move data to Thingspeak, and get weather forecasts. It is useful to have access to weather forecasts in the greenhouse to guide us in shading the plants during the critical healing process. Too much sun can be detrimental to the healing plants. An Esp8266 appeared to have the capacity to manage all of these things in a tiny footprint.
Getting a weather forecast - I decided to use Bodmer's library to pull down Dark Sky's weather forecasts. Dark Sky will provide minute by minute forecast data for free as long as the api calls don't exceed 1000/day. Since Bodmer has done the hard work of creating a library to interpret the Dark Sky forecast as well as a JSON parser to decode the stream it was an easy choice for me. Both of these library's need to be downloaded and installed in the Arduino library. Simply follow his excellent installation instructions on github. You will need to create a DarkSky API account and enter your key in the first tab of the sketch.
Multipletab structure: The sketch is organized into a multiple tab structure. The multiple tab feature is a significant help with organizing, editing and debugging.
Scrolling data on a 4 line lcd - In my earlier project I showed how to scroll text on the first line of a 16 x 2 LCD. The challenge here is to adapt that code to a 20 x 4 I2C LCD. Both the previous and new versions adapt the clever code shared by whizzzkid. The LCD layout scrolls the first line with the date, time, temperature and RH data from one BME 280. The second line is non-scrolling data from the second BME280. The third line scrolls current Dark Sky forecast information. The fourth row scrolls a three day Dark Sky forecast. The third row can have up to 85 characters and the fourth row up to 200 characters. I was concerned that using String(s) as opposed to string(s) or character arrays could cause problems with the ESP8266 Heap memory. Majenko gives an excellent explanation of the problem here. It's a worthwhile read. I decided to follow his advice and construct the scrolling lines as character arrays. I must admit this was a big coding challenge for me as there are a lot of character array components, for loops, pointers and character counts to keep track of.
There are three scrolling line functions in the sketch, one for each scrolling line. The structure of the functions are the same. Each function is called every ~410ms which sets the speed at which the scroll appears to move. The character array's for scrolling rows three and four are constructed in void getDarkSky(). They are passed as pointers to void moveDarkSkyR2( ) and void moveDarkSkyR3( ).
The scrolling functions merely create an illusion of motion similar to a motion picture. The sketch creates snap shots that are displayed on the lcd at an Interval of ~410ms between frames. Each frame is different from the preceding frame by changing the first and last character displayed.
There are four components to scrolling a line of more than 20 characters. The first component is displaying the initial 20 characters of the array. It starts by placing the cursor at position 20 and decrementing the cursor position with each pass until it gets to position 1. With each pass an array is displayed where the length of the segment displayed is incremented by one on each pass. The second component is displaying the next 20 character segments. With these segments the first and last character array counter is incremented by one giving the illusion of scrolling movement when displayed. The third component is finishing the line. The length of the array is determined each time the forecast is updated. The number of characters in the array is compared with the moving letter function counters. When the function counters detect that the end of line is in the line being displayed it fills open positions with blanks or null characters until the end of line moves to position one. The counters are then reset and the process starts over. Simply said nothing is really moving except the cursor in the first 20 positions. The illusion of movement or scrolling is achieved by printing arrays of characters that are different by one character at the beginning and end with each pass through the function. I have commented the sketch in an attempt to make this clear.
I2C 20 X 4 LCD: A few considerations -
- Brightness Control - There is a contrast control built into the PCF85741 I2C backpack of the LCD. It does not have a brightness control. Harilaos shows a circuit for dimming the LCD backlight. The circuit diagram is here -
- The sketch uses duinoWitchery's Extensible hd44780 LCD library. It has some line wrapping features that were interesting to me when I was developing the sketch. Other I2C LCD library's should work as well but this one has some great features built in.
Internet Time: I relied on the code from Instructables and Simple Circuits to get the time from an NTC time server. Again, the time information is contained in character arrays to minimize the impact on the heap. The time function is named void getNTC_Time() in the sketch.
Reading the BME-280's: The Adafruit library is used to communicate with the BME280's over I2C. The sketch function void takeReadingBME280 reads the sensors every 3000ms accumulating and averaging 20 temperature, RH and barometric pressure readings every minute. This function also composes the array that scrolls on row 1. The array is passed as a pointer to void moveLetters( ). The function void writeThingSpeak() uploads the data to Thingspeak roughly every minute. This function also governs the calling of void getDarkSky() for an updated weather forecast every fifth Thingspeak update or every five minutes. This keeps the Dark Sky API accesses under the 1000/day limit. You will need to enter your Thingspeak key in the first tab of the sketch.
Booting the Wemos: There are a number of things that have to be handled in void Setup() including the initializing the BME280's and checking their connections, establishing the wifi connection and getting the time. These setup items are handled in the function void bme280RecorderBoot(). This function makes sure the BME280's and wifi are operational before moving on to void loop().
Protecting the BME280's: To keep the reliability of the device up it is important to protect 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 is harsh particularly with dust, heat, humidity and in the healing chamber, water vapor. 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 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 50 micron Polishing Filter media. Contact cement is used (two coats were required) to create a seam in the sleeve.1 / 8 • Sensor protection made with 50 micron aquarium filter cloth glued with contact cement
Thingspeak & Google Charts:
While ThingSpeak provides an extremely reliable and easy to use service (and it’s priced right too-it's FREE!) I was not satisfied with the graphical capability provided. My data on ThingSpeak is displayed here and 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.
In conclusion: This project is built on the shoulders of many enthusiasts who have been kind enough to share their wisdom, code and advice. I thank them profusely. They include:
- Bodmer (https://github.com/Bodmer, JSON Decoder, Dark Sky Weather)
- Adafruit Industries (http://www.adafruit.com/products/2652)
- whizzzkid (Single line scroll from Nishant Arora-https://goo.gl/qPGpWB)
- Majenko (https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/)
- MichaelB247 (https://www.instructables.com/id/Simplest-ESP8266-Local-Time-Internet-Clock-With-OL/)
- Simple Projects (https://simple-circuit.com/esp8266-esp-01-internet-clock-wifi/)
- Thingspeak (www.thingspeak.com)
- Mike Teachman (Google Charts Gadget)