ESP32 Greenhouse Monitor

Collect temp/humidity, soil moisture, sunlight data to be stored on local web server

Similar projects worth following
My own version of what others have done... This project will be built around an ESP32 and a BME280, using a soil moisture probe and a common photoresistor.

The goal is to use solar power and deep-sleep mode to create a self-sufficient sensor cluster and monitor conditions in my greenhouse as Winter draws near. The collected data will be sent over WiFi to a web server and stored in a mySQL database. Using PHP libraries I hope to render graphical web pages showing the historical data.

Due to requiring AC power to operate devices such as heaters and lights, I am dropping my original plan to make this project solar-powered.  The new plan is to have a device which will always be on, sending periodic updates to a web server so that the greenhouse conditions can be logged and viewed online.  The code will support up to 16 devices controlled by a bank of relays and allow setting unique conditions to trigger each device.

The initial greenhouse sketch, including Adafruit driver for BME280, a custom font file, and the icons used on the display

Zip Archive - 17.82 kB - 04/02/2018 at 15:56


  • 1 × ESP32
  • 1 × BME280 Temperature, humidity, and barometric pressure sensor
  • 2 × Soil Hygrometer Reads the ground moisture
  • 2 × Photoresistor Detect daily sunlight
  • 1 × 20A relay board Control heaters, fans, water lines, etc.

View all 6 components

  • Schematic posted

    Jeff Taylor06/13/2019 at 16:14 0 comments

    The schematic for the current build has been posted, but I wanted to ad some notes on it.  Currently I use a micro-USB power pack to supply the ESP32 board, but I also use a separate 5V power supply to provide power to the relay board.  Note that the 5V supply ONLY goes to the relay board, and all other 5v sources are coming from the 5v pin on the ESP32 board.  Ideally I should be able to feed a single 5V supply directly to this ESP board and also feed the relay board, eliminating the need for dual power supplies.

    There is also an issue with the setup of the soil moisture sensor.  Apparently these types of sensors can oxidize when they have a continuous power supply.  Since there are plenty of pins still available on the ESP32 the best solution is to use one of those pins in digital mode as the power for the moisture sensor, and only check it once every few minutes.  The better solution is to use capacitive moisture sensors, of which I have ordered a handful to experiment with.

    The relay board is just a general representation for the variety of boards that are available.  You can use boards with 1, 2, 4, 8, or more relays.  The 74hc595 chip is expandable, meaning if you add a second chip you will have eight more ports available and could run 16 relays, so there is no practical limit to how many devices could be operated.  Unfortunately the software still needs some minor tweaks to handle multiple 595 chips, but that will be a simple variable to set how many chips you are using.  The real trick would be in trying to display more than 16 icons on the screen since there is such limited space.

    Finally, the CdS sensor will require some calibration.  I plan to add a trimmer pot so the value can be fine-tuned, but I also need to increase the range of the sensor to provide full coverage from dawn until the sun is directly overhead.  I may be able to use two trimmers for this -- one would set the maximum value for the mid-day sun and the other would set the minimum value as it gets dark outside.

  • Washed out...

    Jeff Taylor05/22/2019 at 18:27 0 comments

    We had a big rain late last week, and somehow it found it's way through both layers of roof material to drop on the BME280 sensor, causing it to read temperatures of 30+ degrees over the actual reading. I replaced the sensor with my last spare, checked over the roof plastic and made adjustments to prevent more water leakage, and thought I was good to go.

    But no!  A larger storm came through this weekend and absolutely drenched my whole workbench area in the greenhouse, pouring directly onto my poor little exposed ESP32 (which has been running all this time on the original solderless protoboard).  I thought for sure the ESP had taken it's last sleep, but when I brought it in the house to work on I discovered the computer itself is still working just fine.  Turns out the replacement BME280 has completely died and it locking up the ESP when connected.  I have several more on order, but it will probably be next week before any of them arrive.

    In the meantime, this finally gives me the break that everyone has been waiting for!  With the system out of commission I took several pictures of the wiring, and will get started on drawing up the schematic for this project.  I know, I've procrastinated on the details for far too long, and I do apologize for that.  Thanks to all the followers who have shown an interest in this project, I'll get you the goods soon...

  • Spring 2019 is here already

    Jeff Taylor04/09/2019 at 15:58 0 comments

    Wow, a number of people have started following this project recently, and I realized I haven't written any updates in several months... So just to let you all know, yes this project is still alive!

    One of the problems I had with the code was random lockups every few days (and always in the middle of the night).  After posting about the problem on Reddit I found an answer -- the horizontal scroll bar at the bottom of the display was sucking up resources because of the timing constraints, however I didn't want to completely eliminate the option because it still shows a lot of useful information.  The solution was to disable the scrolling whenever it gets dark out.  Because of the sunlight sensor, the scrolling will resume if you turn the lights on, but at night when nobody is looking at it anyway there is no need to continue showing the information.  This has worked fantastic!  I've had the ESP32 running in the greenhouse all Winter, and only had a single lockup during that time.

    I also upgraded to an 8-port relay board.  I want to rewire my small heaters so I can control both the fan and heating elements of each of the heaters.  It would also be nice if I could control the high/low setting of each of the heaters.  At most this would require up to six relays, however a reasonable setup would be to use a single relay to turn on both heating elements to low, a second relay to turn on both heating elements to high, and two more relays to individually turn on each heater (if the heating elements are turned off then only the fans will be running).  I'll have to tear apart the heaters over the Summer to see if this is even possible with these particular units.

    One other issue I ran into at the end of last year's growing season... these heaters REALLY pull a lot of juice!  I have electrical cords rated for 15 amps, however the three-way blocks I plugged in to the end of each cord apparently could not take the heat, and literally melted.  I would assume since I've been using this setup for a few years now that corrosion in the plugs increased the heat, but I also noted the blocks were only rated for 12A.  I have replaced the blocks with some heavy-duty power strips, and we'll see if that helps.  Gotta be real careful with that stuff, it would really suck to burn down my greenhouse!

    And finally, I got a 3D printer this year.  Exciting stuff, and I've already started designing boxes for other projects, so I may design a box for this one as well, unless I find a suitable ready-made box at the hardware store.  I basically need something large enough to hold all of the electronics plus eight power outlets isolated from the electronics, plus two more outlets wired in before the relays to provide power to the electronics.  Whew, that's a lot of outlets...

  • Fall is here again

    Jeff Taylor10/06/2018 at 06:31 0 comments

    The cold weather started moving in so I set up the greenhouse again.  I completely re-covered all the roof panels due to bad wind damage this Spring.  I'm trying out a different idea which has more plastic wrapping around the underside and fewer staples that can rip holes through the plastic when the wind whips up.  This also included an idea to close the gaps between the roof and top of the walls, which I'm happy to say was a great success.  I haven't felt any wind blowing inside the greenhouse now, so it won't suck away all my heat.

    I got the ESP32 set up again, but still had trouble with the relays not wanting to kick over.  This was especially bad the day the sun came back out and the greenhouse temps hit 120F but the fan never came on.  However I finally found the problem, and a temporary solution!  The ESP32 board I'm using has 3.3v and 5v pins around the edges, and I was using the 5V pins to feed the relay.  However it appears there is a regulator on the ESP that severely limits the current being fed through it, and thus starving the relay board of power.  As a temporary solution I plugged in a second 5V power pack and fed this straight to the relay board (keeping common grounds between both boards.  Success!  All of the relays have been reliably tripping for the last three days.

    To permanently resolve this problem, I have some small regulators that will take a 5V source and drop it to 3.3v @ 800mA.  I think I'll wire the 5V components directly from the power supply and then power the ESP from this regulator, unless I can figure out a way to also power the ESP from a direct 5V source.

    Today I've been trying to work out some code to rebuild the routine that interprets the math strings used for the relay rules.  There's a technique called the shunting-yard which converts a formula into Reverse Polish Notation.  From there it's supposed to be easy to work the formula.  I might just do the conversion server-side and let the ESP solve the RPN string.  I think that could cut out a serious chunk of processing time.

    I also added in the code to perform over-the-air sketch updates.  I tested it on the ESP on my desk and it works great, so I'll get it flashed to the greenhouse computer one of these days.  The next thing I want to tackle is being able to store variables (such as the device name and rules table) to the ESP's flash space.  Having the device name stored will allow me to have a single code image for all devices.  Having the rules stored means it can take off running as soon as it boots, even without a wifi connection to the server.  After a power outage or some other issue I want it to be able to kick the heaters or fans on immediately as needed, but new rules could still be updated from the web server.

    So that's about it for now.  I still need to work on getting the hardware into a box so everything is tidy.

  • A Quiet Summer

    Jeff Taylor08/10/2018 at 18:20 0 comments

    Haven't worked much on this project over the Summer, however I have been ordering parts to transfer the circuit onto a soldered breadboard and mount it in a case.  I picked up a 10m 3.5mm stereo extension cord and cut that in half to solder to the soil moisture probes.  The idea was to have them plug into standard sockets mounted in the case.  Unfortunately it appears that the Chinese sellers on ebay of what a "female stereo jack" actually means... the last two orders I received only have pins for MONO plugs!?!  Silly me for thinking that ebay sellers have any concept of the standard industry terminology.

    Beyond that, I have a waterproof case with a clear lid... and a nice casting cutoff point right in the middle of the clear lid.  Again, are any of these people paying attention?  Of course the sales pictures show a perfectly clear lid with no blemishes.  I think if I'm careful I can clean up the spot and use the dremel to polish the plastic out again.

    I have some circuit boards, various switches, a bunch of different 2.54mm headers and plugs, and headers to plug in the ESP32 module and allow it to still be replaceable.  I also got a power supply with a larger current output, hoping that will fix the problem with the relays not reliably switching.  Before I get everything put together I still need to update my code to allow OTA programming.

    In September I'll be re-covering my roof panels.  The way I wrapped the plastic around last time turned out to work very poorly and the Spring winds tore the plastic from several panels.  This time I'll cut the plastic much larger to allow for a lot more wrapping around the sides.  I also figured out that if I leave an extra 6 inches hanging from the bottom edges, I can use that to tuck inside the greenhouse framework and completely seal off the large gap I've always had between the roof and wall panels, eliminating a huge source of heat loss.  Maybe this year I'll be able to keep things going beyond December!  Thanks to other changes, the tomatoes and cucumbers are growing like mad this year so it would be great if they continue to produce for awhile.

    The greenhouse walls will go back up around the beginning of October, and with that I will be setting up my ESP monitor again (hopefully with all the new hardware and sealed in a case).

  • Code updates and web page

    Jeff Taylor04/26/2018 at 17:06 0 comments

    I finally finished the code updates to allow storing the rules on the web server.  Unfortunately I had no luck working with char* types so I ended up writing it using strings, but at least it works.  I have added a new variable to the code to name each device.  This is used for storing the data in the database, but can also be used to define custom rules for each device.  If there is no custom rule file for that device name then it falls back to a common rule file.  Each time a data packet is sent to the server it also checks the timestamp on the current rule file, and if that timestamp has changed then it will reload the new file.

    As an example of what the rules look like...

    // Heaters
    f>56 : R0=0
    f<54 : R0=1
    f>48 : R1=0
    f<46 : R1=1
    // Fan control
    (R0=1) | (R1=1) : R2=0
    (R0=0) & (R1=0) : R2=1
    // Lights
    (t<0600) | (t>2020) | (L1>90) : R3=0
    (t>=0600) & (t<=2020) & (L1<60) : R3=1

    Starting from the top, the first rule says that if the temperature in fahrenheit is greater than 56, turn off relay 0 (heater 1).  The second rule says that if the temp is less than 54, turn relay 0 on.  The fan controls turn the fan on if both heaters are off (my heaters also have fans in them) ensuring something is always running that keeps the air moving.  The rule conditions are fairly simple but they do have access to a number of variables including all of the sensors.  I would also like to add a math function for % which lets you check for incremental conditions.  For example (m%10) would let you turn a fan on and off every 10 ten minutes.  It would also be helpful to know the month, day, and day of the week.  I've read there is now a full time/date function available on the ESP32, so if I find that maybe I can pull out all of my own functions performing timekeeping and have access to full date lookups.  But all of that is just features in addition to what is already working.

    I have added a new image to the gallery showing the web page.  To build this I'm using PHP and pChart.  I still need to work on the labeling for the hour of the day, but this graph will show results from the past three days.  You can see a gap in the data from yesterday where the ESP32 did something odd... it stopped reading ALL of the sensors (no results at all from the BME280 and zero values for sunlight and moisture) however it continued to send out sensor data every minute.  This resulted in f being zero which turned on both heaters, however since it was still reading the rules file I was able to add more conditions to turn off the heaters and turn on the fan, preventing my plants from being roasted until I could get back home.  Whew!

    So obviously my watchdog code still isn't working quite right.  During yesterday's odd occurrence the OLED display locked up as well.  Since the watchdog timer is connected to updates to the display, I would have assumed the watchdog would cause the system to reset, but it didn't.  It is critical that I get the watchdog to do resets any time something fails, so I'll have to re-think my strategy.  Maybe I'll connect it to the BME and reset if it fails to read twice in a row...?

    Someone I work with is planning on building a greenhouse this Summer and has been curious about the project.  Except he doesn't have access to all the servers like I do.  I think at some point I'll build an image for a raspberry pi that contains the web server, mySQL, and PHP.  You would still have to set the SSID and key for wifi access, and set a static IP address, but I would think most folks that could build this project could also handle that bit with some easy instructions.

  • A watchdog would be nice

    Jeff Taylor04/12/2018 at 20:23 0 comments

    I made a quick update to the code last night to implement better rules for the lights and heaters.  Basically I added a range, similar to how a thermostat works.  So now instead of turning the heater on when the temp drops below 55 degrees, and back off again when the temp goes above 55, I added a 2-degree buffer range.  Now when the temp goes below 54 the heater comes on, and when the temp goes back above 56 the heater is shut off.  This way the heater will actually stay on for a few minutes at a time rather than performing a rapid on/off cycle right around the target temperatures.  I think I mentioned a similar problem with the light controls, where the lights would be turned on, then the light sensor detected it was bright inside the greenhouse and turned the lights back off again, resulting in a 10-second cycle period.

    The next step is implementing an actual rule system that can be changed on the fly.  I built some code for this but unfortunately it makes heavy usage of strings, which of course are very badly handled in the arduino environment.  I don't really know much about working with chars in C though, and the rule interpreter makes heavy use of substring to break apart the rules and handle parenthesis within the structure.  I'm going to try and finalize my version of the routine and get it working with live data, but hopefully someone else will come along that can rewrite the routines in a more standardized (and memory-friendly) way.

    Had my first lockup since putting the ESP32 in the greenhouse.  I knew it would happen eventually, so I started looking at how to implement a watchdog today.  It seems that most methods require compiling under IDF rather than the arduino IDE, which I have no experience with.  I did find a bug report and some sample methods that should work in the arduino IDE however, so I'll try adding in one of those tonight.

  • And we're up and running

    Jeff Taylor04/10/2018 at 22:18 0 comments

    I finished building out the electrical box and hooking everything up this weekend.  The unit is now in place in the greenhouse, and the real-world is presenting issues I hadn't thought about...

    • When you control the lights based on a light sensor, the lights coming on indicate there is plenty of light and the lights are turned back off.  Yeah that worked out well.  I did find that simply tipping the sensor over by 90 degrees allows it to read indirect sunlight without being affected by the electric lights.
    • The light sensor itself still needs adjustment.  It seems to max out before the sun is even overhead.  I think it might be worthwhile to have two sensors tuned differently, so one detects the general daylight and the other is more sensitive to low-light conditions.  Finding a sensor with an exponential rather than linear response might also be helpful.
    • Things spend a lot of time switching on and off.  I need to create a buffer to smooth out the information so that, for example, the heaters stay on for five minutes at a time instead of bouncing on and off for only a few seconds.
    • Code updates are now a major issue.  I had intended to set up the ESP for remote updates but never got around to it.  Still have to work on that.

    The data is being fed into a mySQL database now, but the current code is updating every 30 seconds.  That's way more data than I really need to store.  I wrote up a quick web page to display the last 24-hours of info and found it best to average out every 5 minutes worth of data to smooth out spikes.  That also made a huge difference in the time required to render the graphs... for each 5-minute period I now have a single value to plug in rather than 600.

    As  for the outlet box itself, that was as easy as expected.  I took a metal outlet box with a faceplate for four outlets, purchased one each of black and white outlets, and removed the tabs from one side to isolate each outlet.  I have two power cords, one black and one white, which feed power to the corresponding outlet, and then from all of this I feed eight wires from the outlets to the relays.  The socket colors allow me to keep track of the source of power for each device.  Since the heaters pull so much juice I have to run two extension cords to the greenhouse, and each one feeds one heater plus one other device.  It's not much of an issue right now because the heaters only run at 50% power, and only one of those stay on all night.

    So far so good... now I just have to work out the issues with the code...

  • The hardware is complete

    Jeff Taylor04/02/2018 at 15:32 0 comments

    Looks like it's been a couple months since my last update.  Too many simultaneous projects, however with the weather changing I thought I would try to get some plants going in the greenhouse despite the overnight lows being around freezing temps.  If only I had temperature controlled heaters in the greenhouse... :)

    I had to transfer the ESP32 to a larger breadboard to accommodate the 74HC595 chip and then check over the wiring.  The 20A relay board I got has a jumper on it to select if you wish to use active-low or active-high inputs -- in my case I chose active-high so that the default state at power-on will be for all the relays to be off.  I had to make some minor changes to the code including setting the pin numbers I'm using to talk to the 595, but then all the relays lit up.  So at this point it appears the hardware is functioning just fine.  Previously I had just randomized the changing of the relay status to show the outputs, but I wiped out that code and put in some requirements to trigger each relay (as a precursor to how I want to set up the interface for defining the relay settings).  For sitting at my computer desk the settings were fairly simple.  I plan to use two heaters, a fan, and a switch for the lights.  I coded the first heater to come on if the temp drops below 75F, and the second comes on when the temp drops below 72F (in the greenhouse I will probably use temperatures of 55F and 45F).  The fan is currently on all the time, but to save on electricity I thought I would cut that down to 50%, so I added a line to switch the fan on and off every 10 ten minutes.  Finally I programmed the light switch to be on between 6am-7pm, but only if the light sensor is below 25%.  This set of settings allowed the relays to change during the day and everything seems to be responding as expected.

    So the software is functional now, although not really complete.  I also added some code to include the relay statuses in the data sent to the server.  I think my next software focus will be on the server side, to actually collect and record the data being sent from the ESP32.  I have also noticed periodic lockups of the software so I'm thinking perhaps having the ESP reboot itself once per day, preferably in the late afternoon so if the reboot fails then I can reset it manually when I get home from work.

    The last step on the hardware side is the electrical outlets to plug in my actual devices.  I have seen metal junction boxes that will hold four outlets (to match my four relays).  I have two extension cords going to the greenhouse so I will wire it so that each pair of outlets plugs into one of the cords, however each socket will be individually controlled by a different relay.  I was trying to find cheap power cords online that I could use for plugging in to the cords, then realized I already have a source for that -- I have a ton of computer power cords laying around that should work fine.  They seem to only be 18AWG, although I would have preferred 16AWG, but since I'm splitting up my power requirements between two extension cords I think these will be fine.

    I will try to get the code and some schematics posted soon, in case others are interested in trying this out for themselves...

  • Relay control

    Jeff Taylor01/30/2018 at 04:00 0 comments

    A quick update tonight...  I've been looking at chips to handle the relay operations without the need for using 1 pin for every relay.  I thought something like a 74LS259, a 3-to-8 decoder with latching outputs, would be the way to go but adding more lines appears to be less than ideal.  I kept finding references to a 74HC595 and finally looked into it.  The chip takes a serial input using only three I/O lines, and there is already an arduino driver available to operate this chip.  Even better, you can add multiple chips together and they still only require the same three I/O lines to talk to all of them.  Now being a serial operation means that talking to these chips will be slower than other options, but we're talking about relays that will see cycle times in minutes or hours, so speed is not really a priority here.  I have a bag of these chips on order so once they come in I'll see how they perform at 3.3v.

    In the meantime I will start setting up the code changes.  I'm going to add a variable to hold the number of relays in use, then I just need to create a bit register to push out the on/off state of all relays each time there is an update and pad it out to an even multiplier of 8 bits (one set for each 595 that is being used).  Of course the real problem will be figuring out how to display a virtually unlimited number of relays on this screen.  I might have to write some code to vertically scroll that section of the display.

    If anyone is curious, there is a nice article here that describes the usage of this chip with a regular arduino:

View all 15 project logs

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates