Do your plants despise you for your erratic watering schedule? Do you want to save water and have a more efficient watering system? Well, have no fear!
In this tutorial, we are going to build a smart watering system that will tell you when you need to water a plant based on the soil moisture, air temperature, and light levels. The project uses a Basys 3 board as well as an Arduino board that acts as an analog to digital converter. There are three external devices connected to the Arduino: a moisture sensor, a temperature sensor, and a light sensor.
By: Non Wajanakunakorn, Jason Zhou, Shu Saechao, and Brian Yoon.
California Polytechnic State University
Step 1: Materials & Software
Listed In Order of Appearance
- Basys 3 board
- Light sensor
- Moisture sensor
- 220 Ω resistor
- Temperature sensor
- Jumper Cables
- Vivado HL WebPACK Edition
Step 2: Overall Design
Black Box Diagram
- Moisture sensor (M): This will determine the levels of moisture
- Temperature sensor (T): This will determine the temperature's low or high state
- Light sensor (L): This will determine the light's low or high state
- CLK: This will control when the system changes states
- LEDs: These display the state, reset, moisture digital input, temperature input, and light input
- SEG: This display the letters "H' or "-" when the board is watering or not watering
- AN: AN controls how many 7-segment displays are in use
- Moisture digital input bus (3 bit bus): This shows the level of moisture in a 3 bit bus
- Temperature digital input: This is a 1 bit signal that sends the temperature threshold
- Light digital input: This is a 1 bit signal that sends the temperature threshold
- LEDs (9 bit bus): This displays the state (2 bit), reset (1 bit), moisture digital input (3 bit), temperature input (1 bit), watering output, and light input (1 bit)
- SEG: This displays the letters "H" when watering and "-" when not watering
- AN: This controls the 7-segment display in use
- Moisture analog sensor signal : This shows the level of moisture in an analog signal
- Temperature analog sensor signal : This shows the level of temperature in an analog signal
- Light analog sensor signal: This shows the level of light in an analog signal
- Moisture digital output bus (3 bit bus): This shows the level of moisture in a 3 bit bus
- Temperature digital output: This is a 1 bit signal that sends the temperature threshold
- Light digital output: This is a 1 bit signal that sends the temperature threshold
Step 3: Arduino Code and Hardware
To understand the code, we must first look at how an Arduino reads analog inputs. Analog inputs are in 10 bits so the highest value is 1023 at 5V. The Arduino receives in analog signals from the moisture sensors, temperature sensors, and light sensor from pins A0, A2, and A3, respectively. In our case, the moisture sensor gets to a max value of about 750, the temperature sensor gets to a room temperature of about 150, the light sensor has a average value of 250 (These values can change depending on different sensors). For us, we decided on the threshold values of 155 for room temperature and 5 for light. The Arduino code outputs a digital value for the moisture, temperature, and light. When the temperature is over the threshold, the Arduino will output a digital "1". When the light is over the threshold, the Arduino will output a digital "1". Since the moisture will be 3 bits long, pins 2, 3, and 4 will be used to output its digital value.
The moisture threshold is a little more complicated since we have 8 output values. Now, the value of the threshold only changes how much the water will be watered until. The outputs are 0-7.
When the moisture level is 0-2, we programmed the system to always water, regardless of the light or temperature. At 3, watering will only be indicated when light and temperature allow it. Lastly, at 7, we decided to indicate no watering regardless of light or temperature. In between 3 and 7, it will only water in ideal conditions and if it is currently being watered. It is like a buffer system so that the system will not constantly turn off and on. We based these threshold values based on common house plants, but it can be changed to be more realistic to another type of plant such as a succulent plant.
The smart watering system consists of three distinct sensors that measure three aspects crucial for growing plants; Light, moisture, and temperature. The light sensor detects how much light is in the environment and outputs an analog signal. The moisture sensor, as the name suggests, detects how much moisture is in the environments and outputs an analog signal. Finally, the temperature sensor as we all know, measure the temperature of the environment and outputs an analog signal as well. The analog signals from each of the sensors are put into the Arduino for an analog to digital conversion, which is described in the code section of this page. The Basys 3 board takes in the converted digital signals from the Arduino output through the pmod jc3 header pins and output appropriate state display accordingly; "H" for water or "-" for no watering.
Step 4: Programming the FPGA
The system consists of a finite state machine and a seven segment display.
1. Finite State Machine
The Finite State Machine is what controls the watering and responds to the digital inputs from the Arduino. The FSM has two states, State 0, the non-watering state, and State 1, the watering state. When the moisture level is less than or equal to 3 under normal conditions, the FSM will move from State 0 to State 1 and output a signal for the irrigation system to start watering. The FSM will continue to send the watering signal until the moisture level reaches 7, where it will move from State 1 to State 0 or until the system loses ideal watering conditions, where it will move from State 1 to State 0 if the moisture level is more than or equal to 3. Ideal conditions are where the temperature and light levels are sending a "low" signal, if they surpass a certain set threshold, the FSM will receive a "high" signal, which represents non-ideal conditions. Under non-ideal conditions, where the temperature or light levels are too high, the FSM will only move from State 0 to State 1 and start watering if the moisture level is less than or equal to 1. If non-ideal conditions are maintained, the FSM will move from State 0 to State 1 and will water until the moisture level reaches 3, where it will stop watering and move from State 1 to State 0. If conditions become ideal when the moisture level is not yet 3, the FSM will remain in State 1 and keep watering until it reaches moisture level 7, where it will move back to State 0 and stop watering.
2. Seg7 Module
The seven segment (SSEG) display on the Basys 3 board indicates whether the smart watering system is in a water or no water state. A watering state is indicated by an "H" and a no watering state is indicated by a "-".
The conditions of the ST0 and ST1 are dependent on the 4 bit ABCD variables of "1111" and "0000", respectively. When at the ST0 state, "1111", only 1 anode will be turned on as can be seen from AN <= "1110" and the SSEG will display "-" for no water. Keep in mind that the anode is tied to logic '1' so the anodes and LED segments will only be high when at '0' and low at '1'. The same idea applies to ST1 where only 1 anode will be turned on and the SSEG will display "H" for water.
When the system in in ST0, the no water state, the 8 bit segment7 variable will need to be assigned "10111111" in which the first '1' from the left corresponds to the decimal point followed by the segments G->A. In effect, the letters A-F and decimal point will be off while the G segment will be on. As a result, the SSEG will display a dash "-". Similarly, when the system is in ST1, the water state, the 8 bit segment7 variable will need to be assigned "11001000". In effect, the letters B, C, E->G, and the decimal point will be high while segments A and D will be off. As a result, the SSEG will display a "H" for water.
We included the seven segment as a component to the finite state machine. In the port map, ABCD will be assigned to X, AN to anodes, and segment7 to segments. The Seg7 module will still retain the same functionality.
Step 5: Additional Info
- VHDL FSM Code
- VHDL 7 Segement Code
- Basys 3 constraints file
- Arduino ADC Code