This guide has ended up to be a bit more verbose, also including details from the journey that took me to this point rather than being a brief set of instructions to follow. The reason for this is that during this journey I've encountered many choices and I believe that providing a bit more detail here and there might help anyone who is - like me - starting out as a maker, an indoor gardener or a programmer.
Every piece of knowledge that I used in this project was self-taught and picked up from materials freely available on the internet. I hope this might encourage you to learn, experiment, make life better for you and your communities and to have a lot of fun on the way. I surely do :)The garden
It all started about 2 years ago with receiving a small basket of basil and parsley as a housewarming gift and I quickly got hooked on the idea of cooking with fresh herbs even in the middle of winter. Since I've also spent these years on a sabbatical leave things were bound to spiral out of control - in a good way.
First I started buying new basil plants ad-hoc from the local supermarket, and soon I had 6-7 of them in my window and countless new plans and ideas in my head.
Then a few months later, following an unfortunate mass extinction event I've found myself back at square one.. ending up with a lot of good pesto though.
So I chose the patience game and started from scratch with good quality seeds from a family-owned Italian farm.
While the seeds were sprouting I had plenty of time to watch countless instructional videos and gardening tutorials. So the only logical next step was to buy a few grow lights and eventually evolve the project into a semi-automated aeroponics garden where only the nutrient solution needs to be manually changed every now and then.
This was also my introduction to the Maker world.Grow container and aeroponics
I ended up choosing aeroponics over other approaches because it seemed to be the most resource efficient and the thought of having a huge bucket of roots, dangling in vaporized nutrient solution in the middle of my home was also strangely appealing.
Since it was planned to be an experimental build, I used an IKEA box (probably not food grade so I wouldn't recommend it) cut a few holes in the top for the netcups and that was it.
The single container approach works fine but it has its downsides: once the roots reach the nutrient solution it becomes hard to control root rot as the mist maker does not oxygenate the water enough. I regularly have to apply hydrogen-peroxide(H2O2) to disinfect it. There are other, better variants (see: high pressure aeroponics) but this one is the easiest to build.
using an ultrasonic mist maker is by far not the best solution but it is an easy introduction to aeroponics with good results and low maintenance.
Make sure to get one with a "floater" as they only work in an ideal depth. It also helps if the mist maker has a submersion sensor so that it does not switch on and damage itself when it's out of the water (eg. when the container drains faster on hot summer days).
Also make sure to clean both the unit and the floater when you change the nutrients as it can be an incubator for bacteria.Enclosure:
For a few months I've been watching a rather ugly tent in the middle of my living room, erected from a reflective emergency blanket, tinfoil and wires, making it look more like an abandoned makeshift meth lab than a basil garden. So I've decided to upgrade the enclosure using a wooden frame and two-sided reflective sheets. It's cheap, easy to make and ended up greatly increasing the growlight's efficiency.
Use materials that are built for the task: heat resistant, reflective with an uneven surface (to avoid developing heat spots), durable, non-transparent, with a color on one side that fits your environment. Generally a simple heat screen would suffice as well.
At this point I have to add that I'm only an enthusiast, not an engineer so it's always a good idea to challenge my solutions. That said the current setup is the result of months of research in countless number of projects and guides, looking for best practices to build an affordable but safe solution.
It has been through multiple iterations and and there is always plenty of room for improvement, but the current prototype has been serving in my garden around the clock for more than a year now and has proven to be reliable.Mains connections:
Note that both the in and outgoing mains connectors are IEC_60320 C14 allowing for an easy swap and also standard for many grow light and computer manufacturers.
I used a PC power cable for input and assembled custom connectors for the outputs.
The mains input is distributed via wire connectors, I'm using wago 221s. There is a 5V DC power supply for the microcontroller (3V3) and Relay module (5V) and the rest is routed to the grow lights and irrigation through a relay module.
- Relay shortcomings: For the outgoing mains connectors the ground is directly wired but from the live and neutral wires only one is switched by the relay as it is common for these kinds of home projects. So for a good measure whatever is on the end should still be considered live even if the relay is in an off state. Completely disconnect them from the unit before any manual interaction.
- Inlets and outlets: For newbies like me it also might not be immediately evident to differentiate the inlets and outlets of the same connector standard (I was only familiar with the inlets from PC power supplies) but there are very obvious and logical safety reasons for only using the outlets as outgoing connectors, otherwise you will end up having mains voltage on exposed metal pins on the side of your unit.. and that's sub-optimal :)
After a few attempts, I've found that the easiest way to connect my sensors to the units is via 3.5mm audio connectors with 3 or more poles and audio cables with at least the same number of wires. Both ports, connectors and cables are easy to source, easy to assemble and comply with the 3V3-5V standards.
In this project I've only used a waterproof variant of the DS18B20 temperature sensor to monitor the nutrient solution's temperature. But on the other side of the room there is a similar unit looking after the soil-grown basils and that one uses a capacitive soil moisture sensor, a DHT11 temp-humidity sensor and these can also be found in the modules of the MCU side project template:: https://github.com/tlvlp/iot-mcu-modules/tree/master/modulesRelay module:
The one I used takes 5V as supply and 3V3 to control making it ideal for an ESP32.
Make sure that it's rated to switch mains voltage and that it can bear the load of your irrigation and grow lights.Note the safety warning in the "Mains connections" section!Grow lights:
There is plenty of material available online on selecting the right light for your garden and it is art on its own depending on your plants' requirements and mostly nerdness level :)
Since the controller can handle any grow light that is supplied by mains voltage you only need to consider the rating of your relay module or select a relay that's appropriate for your choice of lighting.
- ESP32 WROOM or WROVER development board
- Solid State Relay module
- AC/DC 5V power supply
- 3.5mm audio connector
- 3+ wire audio cables
- signal cables
- DS18B20 water temp sensor
- PC power cable plug
- mains compatible switch for the input
- mains outlets
- 3 mains rated wire connectors https://www.wago.com/221/us/
- project box - preferably watertight
Choosing a microcontroller - ESP32
First I've tried my luck with Arduino Nanos that were good for learning but almost unusable for IoT purposes. I ended up with ESP32 WROVER and WROOM development boards since even when they were new on the market, they were relatively cheap for an MCU that has built in WiFi with good performance and storage capacity.
I've built a small docking platform for the ESP and connected all the sensors, relay control and the power supply to that to make the development board removable from the setup.
Choosing a language - MicroPython
After about a month of using C++ and PlatformIO I was quickly out of my depth once I wanted to modularize the project and eventually gave up when had to debug some obscure mqtt connection problems.
That's when I've found MicroPython and ended up using it in the project.
It certainly has its drawbacks on the performance side, but with the relatively powerful ESP chips I was happy to trade some performance loss for the ease of readability, development and debugging.
Unlike the compiled C++, MP also has to have its interpreter in memory, taking up more space. But it has the advantage of not having to recompile and upload the whole project with every change, but you only have to upload the scripts that has been modified.
The REPL via a serial connection is also a great feature to speed up writing and testing code.
Writing custom modules for your hardware
Since there is an endless variety of hardware modules out there, there is a good chance that you'll write your custom software modules for them.
The best way to start would be to decide on your hardware setup, clone the modules repository from below, implement your solution. Also see the Sensors section above for more info.
UAsyncIO and cooperative multitasking:
When customizing the MCU modules and for your setup make sure to use the uasyncio (the micro version of Python's asyncio) library similarly to the existing implementation, especially for slower modules, to keep the unit responsive - otherwise eg. waiting for a slower sensor would block the unit from receiving MQTT calls.
- https://github.com/tlvlp/iot-mcu-modules - MCU side API details and a generic template to start your own project
- https://github.com/tlvlp/iot-mcu-modules - MCU side API details and a generic template to start your own project
- https://github.com/tlvlp/iot-mcu-bazsalikon-aero - Here you can find an implementation of the above template that is currently used in my garden
Updating the firmware and uploading the project to MCUs:
- https://github.com/tlvlp/micropython-upload - A collection of scripts that I use to update firmware, upload project files, access REPL, etc.
- https://micropython.org/ - Official MicroPython resources including board specific firmwares and a great and helpful community
Since at the time of making this project I was also in the process of changing careers and becoming a software developer, I've found that using this project as a driving force to learn new technologies was a great idea.
As a result the server side is not as lightweight as you would expect for a maker project of similar size and instead of running on an MCU or a Raspberry Pi, it requires an average size home server or computer but in return it is scalable to handle a larger number of MCUs :)
The project summary repo can be found here containing all necessary details and materials for deployment: https://github.com/tlvlp/iot-project-summary
- Unit monitoring
- Modul level control in each unit (eg. relays)
- Automation in the form of scheduled tasks
- Reporting: dynamically generate Module-level reports for units with raw data and hourly, daily, weekly, monthly and yearly averages.
- Secure - All exposed endpoints use TLS, authentication and authorization rules. All passwords are generated during installation and stored in Docker secrets.
- Dockerized service stack provides security reliability and separation from the rest of your server
- Most services are scalable via Docker Swarm (details are in the deployment repo)
- Linux server
- Internet connection
- TLS certificate (preferably Let's Encrypt with a domain)
The below diagram shows an overview of the possible API calls between the services. All services except the MQTT broker uses the database so I have omitted those connections for the sake of clarity.
The API Gateway controls most of the processes, but the MQTT Client and the Scheduler can also call the gateway via a dedicated internal user account.
I have written install, deployment and uninstall scripts for several scenarios.
After obtaining a TLS certificate and a short configuration, the installation is completely automatic.
All details can be found in the https://github.com/tlvlp/iot-server-deployment repo.Web portal:
The https://github.com/tlvlp/iot-api-gateway is the most stable way to interact with the services and you can make your own front end implementation.
At the time of writing this summary I'm relatively new to the frontend world so in the current state the portal that comes with the project is crude at best, especially when it comes to the UX but it is secure and functional.
- Fully implements the backend API
- Secured by TLS
- Desktop and mobile compatible
- PWA (Progressive Web Application) that you can install as an application to your desktop and phone for convenient access
The Unit Details section contains all details and available actions for a single unit selected from the Unit List view, eg.:
- Switching relay modules
- Adding, editing scheduled events
- Viewing unit activity logs
- Generating reports for a given module of the unit
The Reporting section displays a customizable report for a single unit module.
Different average scopes can be displayed at the same time that will be more useful when the current text-based reporting will be replaced by a visual chart.
The report parameters are pre-populated with the unit and module specific details if it is opened from a Unit Details view.
The Admin section is only accessible for users with ADMIN roles and currently is the only way to register new users.
You can replace the backend part of the project with your own solution.
As long as the below criteria are met you can use any language and library that you are familiar with:
- It needs to include an MQTT server and client
- It has to implement the MCU-side API detailed in the README of https://github.com/tlvlp/iot-mcu-modules
If you know a bit of java and SpringBoot, one way to quickly build a lightweight monolithic backend that runs on a RaspberryPi would be to:
- Install and configure an MQTT broker (eg. Mosquitto or VerneMQ)
- Clone the https://github.com/tlvlp/iot-mqtt-client repo
- Inside the /mqtt/MessagingService.java add your custom logic to these methods: handleIncomingMessage() and handleOutgoingMessage()
- Add authentication and TLS using Spring security. An example can be found in the https://github.com/tlvlp/iot-api-gateway/ repo's src/.../config package
- You can also find scheduling, reporting and unit handling related logic in their respective repos, all referenced in the https://github.com/tlvlp/iot-project-summary