Indra Irrigation Controller

Nothing has been more exciting over the past few years than developing an understanding of the overall depth and breadth in the field of computer engineering.  As I get closer to finishing my computer engineering degree at Iowa State I have gained a lot of passion for embedded systems, software and hardware development.

Indra is a personal project that I developed, encompassing all of the areas I’m interested in.  It is a full stack IoT solution that ranges from circuit & board design to web server development.  There are even some other fun areas thrown in, like designing and printing enclosures.


A few years ago my parents purchased an 80-acre plot of land in central Missouri, which is about four hours from where they currently live.  Farming an orchard is of their central goals for the land.

Currently there are about 20 trees planted on the property with drip line irrigation.  The drip irrigation line is currently supplied with well water through a manual valve.

In order to save a four hour trip down to the property to operate the valve or change an irrigation timer’s schedule, I wanted to design a cloud-connected electronic valve that could be dynamically scheduled and controlled through a web interface.

Electricity is the only utility on the farm, so there is no internet connection to rely on to connect the valve to the cloud.  Finding a reliable method to get the device connected to the cloud would be the central challenge in designing the irrigation controller.


The general solution that I developed was to use a server to host the user interface website and also command the valve controller.  The server would be connected to the valve controller through AWS IoT, which is an MQTT broker that communicates over a TLS/SSL connection.  The valve controller would be connected through some type of wireless signal to the cloud and would electronically actuate a valve based on commands sent from the server.


Web server

The web server that controls the valve controller and hosts the user interface website is a Raspberry Pi 3 Model B.  In order to protect the server, the Pi is enclosed in a standard case and also has the basic heat sinks installed on the top of the board.  The Pi will be connected to my parents router through an Ethernet cable, serving the website and communicating with AWS IoT through this cable.  I decided to serve the website on a Pi because keeping the server locally on my parents wireless network would provide a strong layer of security, only allowing users on their network access to the website.

Valve controller

Designing a valve controller for the farm was where most all of the hardware development time was spent.

Initially I started development solely with development boards.  A Raspberry Pi served as the microcontroller, which used a Adafruit Fona 2G modem to connect to the cloud.  The Pi was also connected to a relay board to control the valve, which requires a higher voltage than the Pi.  In order to only use one AC to DC converter, a DC voltage regulator would be needed to provide a lower voltage for the Pi and other electronic components.

I was not a big fan of this design from the start because it felt like overkill.  Using a Pi as a microcontroller felt like I was using a Lamborghini for a job a Honda Civic could accomplish.  I eventually decided to look for alternatives and ended up stumbling on the ESP32 after watching a DEFCON presentation about its predecessor, the ESP8266.  At this time I was also learning about LPWAN wireless protocols, which seemed exciting to me and useful for creating a network on the farm.

Eventually I found the Pycom FiPy, a relatively new development board built around the ESP32 that featured LoRa, Sigfox, and LTE-M in addition to the ESP32’s WiFi and Bluetooth.  I wanted to experiment with Bluetooth, LoRa, and Sigfox for inter-farm communciation and LTE-M to connect to the cloud.

The last component worth mentioning is the actual valve that supplies water to the irrigation line.  Initially I designed around a solenoid valve, but this was quickly scrapped after testing.  The solenoid valve I ordered required 12 volts and drew three amps of current.  Since the valve could be opened for multiple hours, I didn’t want to have to develop and test a board that could supply 36 watts of power to the valve for extended periods of time.  The solenoid valve was replaced with a normally closed motorized ball valve.  This similarly used a two-wire connection.  When 12 volts were supplied the valve would open and stay open.  Super capacitors inside the valve would also charge, which would close automatically close the valve once the supplied voltage is removed.  I really liked this design because it added redundancy that would ensure the valve would be closed on power loss or any other unexpected hardware issues.



The user interface website runs on a basic “LAMP” stack (In this case Linux, Apache2, Sqlite, and Python).  Since the server is running on a Raspberry Pi, the OS is Raspbian Stretch Lite.  Apache2 serves the pages and scripts requested by the user.  Sqlite stores the scheduled waterings.  The CGI scripts are written in Python.  Additionally, the two services that check the status of the valve controller and schedule waterings are written in Python.

The user interface website is very simplistic, allowing for rapid deployment.  Also, since the number of users is very limited, I wanted to focus on ease of use over aesthetics.  Creating CSS to style the website may be added in the future.  There are only a couple pages that are static html, like the landing page and page to add a watering to the schedule.  The rest of the pages are generated with CGI scripts written in Python.  One of the CGI scripts uses a template HTML file with Jinja2 to generate a dynamic table that shows the watering schedules.

The user can modify a weekly schedule that starts on Sunday and ends on Saturday.  Waterings added to this schedule are added to a Sqlite table, which is read by one of the services, which sends the valve commands through MQTT.

The other service that is constantly running ensures that the valve is connected and requests information about the controller.  The returned data from the valve controller is stored in a local JSON file, which is read by a CGI script when a web user navigates to the status page.

IoT gateway

All the messages sent between the valve controller and server are formatted in JSON.  There are two types of commands sent through the broker to the valve controller.

The first command instructs the valve to open or close.  If the command is to open, there’s an additional element in the JSON object that gives the valve controller the time the valve should be open in minutes.  When a watering is over, the web server will instruct the valve to close, but the time sent with the open command serves as additional protection in case the connection is broken while the valve is currently open.

The other command is a request for data from the valve.  Currently, the only parameter is the valve status, but this could extend to temperature or other parameters desired by the user.  Since the broker is only used to relay messages between the two devices, no code currently exists on AWS, but I have considered using AWS lambda functions to send text messages on critical message events, like when the valve opens and closes, or the last will of the valve controller is received.

Valve controller

The valve controllers current software build is pretty simple.  Software running on the valve controller is written in Micropython.  This is the first time I have used Micropython and while there are definitely pros and cons with using it instead of C, it has enabled me to quickly get the MQTT client set up and implement callback functions when messages are received.  Currently the valve will listen for valve open commands.  When the valve opens, the controller will start a timer that closes the valve after it reaches the length of time specified in the open message.  The valve also checks a switch on the front panel that will manually open the valve when the switch is flipped on.  Since there is an RGB led on the front of the FiPy, I use it to display the current status of the board to help with debugging when testing out on the farm.

Current status

Integration testing at home has proven that the software for the server and valve controller are able to interface with each other and both work as designed.  There are some slight issues that have shown up in testing the board, which have all been temporarily fixed with some ‘minor’ alterations.

Testing on the farm on this past weekend has shown there is one big issue, the device is unable to reliably connect to AT&T’s LTE-M network.  According to my diagnostic lights, the device did connect several times while testing, but missed the waterings scheduled over the weekend, presumably to becoming disconnected.

Future plans

After getting home from testing this past weekend, I read in PyCom’s forums that other antennas could be used than the small flat antenna that was provided, as long as the antenna has 50 ohms of impedance and supports the required frequencies.  I will likely look into higher dB antennas that could also be suspended on a pole to get the reception needed to connect the device to the cloud.  I also would like to reach out to Verizon, the only other LTE-M provider, to see if their network would provide better reception.

Some minor board revisions need to be made before I feel comfortable with releasing a final solution that will permanently go out in the field.  These changes will be made before ordering the final revision.

The board changes may shrink the dimensions of the board, so I also would like to make some changes to the valve controller enclosure.  Adding gaskets, epoxy coatings, and heat set screw insets would ensure a better seal for the enclosure, increasing the enclosure’s tolerance to weather.


Source code

Raspberry Pi server code

Valve controller code


Circuit board design

Enclosure (Final version will be uploaded to Thingiverse in the future!)

Leave a Reply

Your email address will not be published. Required fields are marked *