(dramatic music) (tense music) - [Instructor] Hi folks, in today's video, we will do a walkthrough of a project that utilizes our Arduino
programming skills, and an internet of
things app, called Blynk, to make an automated hydroponic garden so we can grow our own tasty food. "Why?" you may ask. Well first, because
hydroponics is super cool. And through this project, we will demonstrate many
potential uses of the Arduino. Hopefully with this walkthrough,
we'll give you some skills, but more importantly, some
inspiration to create dozens of other cool IOT projects
powered by Arduino. But hold on, what the heck is an Arduino? A sub sandwich? And who is this IOT lady? If you're asking yourself
these questions, have no fear, we have some great videos
on our YouTube channel that introduce exactly what an
Arduino is and its many uses, and we'll provide those links below. We've also included
timestamps for this video, since it's on the long side, in case you wanna jump
to a specific section. If you're unfamiliar with
the term internet of things or IOT, we also have a great mini course for our members at Programming
Electronics Academy, that teaches all the
essentials to get your projects up and running and connected to the cloud. And this is just the tip of the iceberg. We've got eight courses and counting, which cover everything from
electronics fundamentals, all the way to using LCDs
and servos in your projects. If this is your first dip into the world of making and
prototyping, welcome aboard, you're in the right place to
start your Arduino adventures. So what is hydroponics anyway? Hydroponics is a method of
growing plants without soil, by using a water-based
nutrient solution instead. There are many different types
of hydroponics, and they vary in how the nutrient solution
is distributed to the plants, as well as how the nutrients
are mixed into the water. Take aeroponics for example. That's a method of misting the
plant roots with fine drops of the nutrient solution,
usually on a timed schedule. For our project, we're going
to create a drip system that is similar to the
popular tower garden set up. If you're looking for an excellent product that requires no building on your own, definitely check out towergarden.com. Hold on, what about aquaponics? Isn't that the same thing as hydroponics? Well, not exactly. Aquaponics is the method
of combining aquaculture. Like raising aquatic animals,
such as fish, in hydroponics. Essentially, you use the fish poop to add the required nutrients
to your water solution, and then you distribute
the water to the plants. Why should you build this project? Well, like we said before, we hope it will show
you how cool Arduino is, and give you the
inspiration and confidence to build other microcontroller projects. But more than just that, growing your own food is fun and easy. Adding the Arduino to the
traditional hydroponic setup, helps automate the process, so even the most unskilled
gardeners can find success. It also tastes great and you know exactly what's
going into your plants. Hydroponic gardens don't require weeding, and there's no messy soil involved. And it allows you to grow
vertically, taking up less space. So even people in small apartments or those who don't have
backyards of their own, can grow. It allows you to grow your
favorite produce anywhere, at any time of the year. I even grew these vegetables
in England, in the middle of winter, during weeks of
freezing temperatures and no sun. And lastly, it uses up to 90% less water than traditional growing methods. Although your power bill may
be higher, so we're definitely not arguing it's more
green than using soil, that's for someone else to discuss. Before we jump in, just
a quick disclaimer. We normally go much more in depth when it comes to walkthroughs and lessons. But we were so excited about this video, we wanted to get the content
out relatively quickly. If you'd like to see a full-blown PEA-style course on how we made this, similar to our IOT Barbecue
Wi-Fi Thermometer course, please let us know in the comments. And if there's enough
interest, we'll go ahead and develop a multi-part series that will dig much deeper
into the construction and the code analysis for this project. Another thing to note, we used a 3D printer to create our system, but you can definitely
create a similar system from common materials available at your local hardware store. Check out this really
excellent walkthrough from the Over 60 Crafter. We think this is one of the best DIY hydroponics available on YouTube. See below for a link to her video. And if you have a 3D printer
or maybe a friend that has one, or perhaps want to use
a 3D printing service available online, you
can access our STL files for free at programmingelectronics.com. See below for a direct link. So how did this project
get started anyway? Well, we won't mention any names, but someone who happens to be the spouse of one of our PEA staff members, has tried many times to
start a garden at home. While the attempts have been valiant, each and every time the garden
resulted in a bed of death. This was usually caused
by the spouse becoming very busy due to work commitments, and the plants would
unfortunately be neglected and not watered regularly. We're not talking one bed of death, we're talking many,
many gardens of despair. So the spouse teamed up
with the husband to come up with a solution where
the watering is automated and can be monitored from afar. That's what's born the idea for the Programming
Electronics Academy Garden, or the PEA Garden. Well, it's a working title. If you can think of something more witty, please let us know in the comments. To recap, the project has to be automated, i.e self-watering, and monitored from afar,
i.e the nutrient level and the reservoir has to be
monitored via the internet, in case the system starts
running low on nutrients. The initial iteration was left next to a window for two weeks, and the side that was away
from the direct sunlight ended up dying and the side
closest to the window thrived. So the second iteration
incorporates rotation, thus ensuring all the plants receive
equal amounts of sunlight. Let's review the various
components of the system. See below for a link to
the bill of materials, which will provide links
to all the components. At the very bottom, you
can see we have a reservoir which holds about two
gallons of nutrient solution. We bought this one from
IKEA for around 20 bucks, but a regular old bucket
would work just as well. Next, you can see how
the system interfaces with the reservoir. We'll call this red
part, the base adapter. Here you can see there's a small gap between it and the parts sitting above it. This gap needs to be there just right, so that the top piece can rotate freely. Someday, we'll add some
ball-bearings here, but for right now, this
seems to do the job. While we're looking at the base adapter, you can see the water
level sensor, we got this from an online electronics
retailer called adafruit.com. The product is called a 12-inch standard eTape
liquid level sensor. This allows us to measure
how much nutrient solution is left within the reservoir. Also, here you can see the
water pump, the three servos, three gears allowing the servos to couple to the main system, and a flexible pipe that connects the pump to
the rest of the system. A quick note on the servos. Yes, the easiest solution
and least complicated is adding some grow lights
that surround the garden. We were trying to avoid this option so we could reduce the electrical bill and harness the power of the sun. In the end, we ended up
buying two grow lights as the sunlight available in the UK winter was just not sufficient. The rotation does make it snazzier. So if you live in a region that has plenty of gorgeous sunshine, this solution may work just fine for you. Also, three servos may
seem a little overkill, but we found that this worked best versus one extra powerful servo. Mileage may vary for your garden however. Next is the large extended spur gear. This is the first of the
large pieces that rotate, and the large gear is what interfaces with the three smaller gears
attached to the servos. Notice that the top of
the part is threaded, this is how it connects
to all the parts above it. This makes it modular as well, so you can add or subtract
as many levels as you want. Next is the threaded module. Add as many levels as you'd like, each module contains six
spots for two-inch net cups. From this view, we can also see the stationary pipe that's in the center. The pipe, the base adapter
and the distributor at the top of the pipe, do not rotate. The modules and top reservoir rotate around the stationary pipe. That leads us to the top reservoir. The purpose of this is to
collect the nutrient solution and allows for even distribution on all sides of the system
via these small holes. It has a top lid and a handle to make it easier to transport. Last but certainly not least, is the brains of our operation. Here you'll see our enclosure with a power supply going in
on one end, and the other end are the wires that power
and control the servos, the water pump and the water level sensor. Inside the enclosure, we
have the microcontroller. We went with the ESP8266 node MCU, due to its low cost and ease of use. You could just as easily use another board that's compatible with the Arduino IDE. The power supply takes
100 to 240 volts AC power from the wall, or 230 in our case, and converts it to 12 volts DC. The water pump operates at 12 volts, and we have a relay that
allows our microcontroller to signal it on and off. We also have a buck converter
that steps down the voltage from 12 volts to five volts to power the microcontrollers and the servos. Here you'll see a simple on/off switch allowing us to control
power to the system. Lastly, you'll notice that we've got a beefy terminal block in the enclosure. Since the pump will be
drawing a substantial amount of current, we wanna make
sure that the electrical connections and wires that
we are using can handle it. That's all of the components
for the PEA Garden. We won't cover the materials you'll need to actually grow the plants. Like the seeds, nutrients,
net cups, et cetera. But as a reminder, if you
head over to the PEA website, you'll find our bill of materials which has all the relevant parts and links to where you can buy
them, as well as links to all the plant stuff you
may need to start growing. If you're savvy with hydroponics, you might be wondering
why we didn't include a parts-per-million sensor or a pH sensor. While admittedly it would be
cool to monitor this remotely, we discovered that they
were just not necessary for our final project. As long as you check the PPM and the pH when you make a new batch of solution, the pH and PPM doesn't
normally drift enough to make a difference in
between solution swap outs. At first, we were swapping
solution every seven days. But as our plants got
bigger and thirstier, we were having to swap it out
every four to five days or so. The wiring of the brain is a bit complex, simply due to the number of
total wires in the project. But generally, it follows this schematic. Now this is the final solution and we're going to break
it down bit by bit. But first, we'll write a high
level algorithm that goes over the main functions that we
want our project to accomplish. Our four main objectives are
one, turning the water pump on and off for a specified amount of time. Two, periodically rotating the
garden 1/6th of a rotation. Three, sending the water level to our app. And four, making some settings
adjustable from our app, such as the pump running time. Seems pretty easy when
we lay it out like that. And to be honest, from
a coding perspective, it is a pretty straightforward problem if you know how to program the Arduino. Likely, the hardest part
of this project will simply be constructing the
apparatus in the first place. We're going to start
tackling this algorithm by using the lowest
hanging fruit mentality. That is, we're going to solve
the easiest problem first and try to build some momentum in our project creation process. The easiest thing here will
be turning the pump on, allowing it to run for
a set amount of time and then turning it off, letting it rest for a set amount of time,
and then repeating the cycle. Next, we'll get the servos operating and the garden rotating. After that, we'll get the water
level data sent to our app. This will involve connecting
our microcontroller to the Wi-Fi, reading our sensor, and then sending that data to our app. And lastly, we'll combine
all three and make it so you can adjust some of
the settings via the app. So if you want, you can make small tweaks and you won't have to
upload new code every time. So let's take a crack at function
one, turning the pump on. We will do this using a relay. If you're not familiar
with relays, they basically are an electromagnetic
switch that is operated by a relatively small
electric current that turns off or on a much larger electric current. So we need to send a small
amount of current to our relay. At which point it will
activate and close the circuit between our pump and the power supply, and the pump will then turn on. We can do this via the
digitalWrite command from our microcontroller. We tell the ESP8266 to make a pin high. The relay then closes the
switch and our pump turns on. We wait a predetermined amount of time and then make the same pin low. The switch opens again, and
our pump turns off, easy. One method that's very
helpful when prototyping, is to build the experimental
circuit in Tinkercad. There you can see if it works and if so, then you can build it in the real world. If you're unfamiliar with Tinkercad, we have a great video
detailing the features of it, and the link is down below. So let's take a look at the circuit we've created in Tinkercad. Our power supply takes
220 VAC, or volts AC power from the wall, and then
converts it into 12 volts DC. Up to six amps, which is represented by our power supply here. From there, we connect
to our terminal block. You can see that we've got the 12 volts power bus represented by the
red wired breadboard here. The ground bus is
represented by the lower half of both these breadboards and is wired so that anything connected
here will be in parallel. Finally, this LM7805
five volt regulator here, represents our buck converter. And as you can see, it has 12 volts coming in
and five volts going out, which is connected to
the five volt power bus. Generally speaking, the
12V bus will power the pump and the 5V will power everything else, including the ESP8266. For the purposes of testing our circuit, we'll use an Arduino UNO, because Tinkercad doesn't
have an ESP8266 available. It should work the same, but
we just need to keep in mind that the ESP board uses 3.3V
logic and the UNO uses 5V. The motor represents our pump. And when it's running, we can assume our pump
will be running instead. Finally, we have our relay. You can see the high voltage circuit here, and the red 12V wire from the
12V bus goes into the circuit, then comes back out and
goes into the motor. This is the circuit
that's open or not active. When we write digital pin two, high, this sends 3.3V because
it's an ESP8266 in real life and not an UNO, to the relay, which energizes the magnetic coil. This closes the relay switch,
and then the pump turns on. When pin two goes low, the
switch opens and the pump stops. Essentially what we're doing in this sketch, is no different
than the first program most coders learn when they learn to code, which is just blinking and LED on and off. Now if you've never coded
anything in your life, this may look and sound pretty foreign. But I assure you, with just a
little background knowledge, you can learn this relatively quickly. Do yourself a favor and take our Arduino Course for Absolute Beginners, and the code in this project
will seem like child's play. Even if you're unfamiliar
with coding, stick with us, you'll be able to
understand the broad strokes of what we're doing and it might persuade
you to start learning. All right, pep talk over. (upbeat music) Now let's go line-by-line
through our code. First, we start by
declaring two variables, our pumpOnTime and pumpOffTime. We've gone with 15 minutes for both, so to convert that to milliseconds we need to multiply 15
times 60, then times 1000. But feel free to modify these times, that's just what we've found
works best for our plans. For our Tinkercad experiment however, we'll reduce this just to a few seconds, so we can test it out and
not have to wait 15 minutes. Next, per our wiring diagram,
we declare relayPin as 2. In setup, we'll make
that pinMode an OUTPUT. In the loop, we turn on the pump, delay. Let it run for our
pumpOnTime variable duration, then we turn it off. We then let it rest or not run for the duration of our
pumpOffTime variable. So we verify the code and it checks out. Then we copy and paste it into Tinkercad, change the variables to 2000
milliseconds, or two seconds, and start the simulation. Viola, it works as expected. Here you can see a video of our very first iteration
of our hydro garden. This is the first time
we turned it on using the code we just wrote. (water flowing) Okay, next, we're going to
get the garden rotating. Again, back to Tinkercad so we can set up our experimental circuit. We'll keep the relay and pump around, but let's delete all these wires so that things look a
little less cluttered. In the actual project, our servos are the
continuous rotation type. Which allows them to spin continuously, either clockwise or counterclockwise. This is different from the standard servos that are usually limited to a
90 or 180 degree of movement. And Tinkercad, they actually
don't have the 360 degree servos, so we'll use the
standard ones that they offer. But just realize the
positions they go in are not what it will look like in real life. To move servos with an
Arduino compatible board, we use the built-in Servo Library. The write function of the Servo Library is what we'll use for rotation. For continuous servos, instead of telling them
what position to go to, you tell them what speed
and direction to rotate in. When 90 is written, the
servo speed equals zero. When zero is written,
the servo speed rotates at maximum speed in the
counterclockwise direction. When 180 is written, the servo rotates at maximum speed in a clockwise direction. So for our purposes, we'll
write 120, which equates to about one third max speed
in a clockwise direction. And we'll rotate this
for about three seconds, which roughly equates to one sixth total
rotation for the garden. This means every six full cycles, the garden will have rotated 360 degrees. If any of this is
unfamiliar to you, we have an excellent servo course at
programmingelectronics.com, that will teach you the fundamentals of using servos with Arduino. With everything wired correctly,
let's jump into our code. So first, we include the Servo Library. Next we create the instances
of the servo class, called myServoA, myServoB, and myServoC. We declare a few variables. First, we define the speed
like we talked about before, and we also define the rotation time. Again, these two can be tweaked to get the right amount of rotation. We recommend turning the garden a fraction of the total number of
openings you have per module. We have six, so we're going to turn it one sixth of a full rotation
or about 60 degrees. Next, we'll define the
pins where the servo signal wires are attached. In setup, we'll attach each of
the servo instances to a pin. Down in the loop, we'll start off writing a servo
speed to each of the servos. Then we delay for the
defined rotation time. Lastly, we turn the
servos off by writing 90. We added a delay of five
seconds, so you can appreciate the end of a cycle. Okay, let's copy the code, put it into Tinkercad,
and hit Start simulation. (upbeat music) (upbeat music) Looks like it works. All right, it's time to
test it in the real world. Here's a video of a test we ran with 20 pounds of weight on top of the garden, to simulate
the massive plants we would be growing in the near future. We simulated it running for three months by reducing the duty cycle
and ran it overnight. Thankfully even under load, it held up. Okay, we're making some
serious progress here. Next, let's see if we can get the water level sensor working. Our eTape liquid level
sensor has one pin for power, either three volts or
five volts will work. One pin for ground, and on the third pin, we can
measure voltage and relate it to the amount of liquid
remaining in our reservoir. It's got a pre-built
voltage divider on board. So we know the output
voltage we'll be measuring will be somewhere between
zero and one volts. We also know that this
voltage varies linearly with the amount of water it's measuring. So to keep things very simple, we'll measure the voltage
when the reservoir is full, and we'll take another measurement when the reservoir is just about empty, when the water level is just above the top of the water pump. We'll call these two variables lowEtapeValue and highEtapeValue. Then we'll use the map
function to calibrate an output that makes sense. If you're getting a little lost here, check out our IOT course for more information
regarding voltage dividers. And our Arduino basics course, to find out more about the map function, both which are available at
programmingelectronics.com. So let's see what we can build
at Tinkercad for this one. While our eTape is not
available as a part, we can still use a temperature
sensor that they offer as a substitute to check
our code and our wiring. As you can see, you can
adjust the temperature the sensor is exposed to,
which changes the voltage that's sent to the microcontroller. So this will replicate
our eTape quite nicely. Let's take a look at the code. So after quite a bit of trial and error, I can tell you that those readings for lowEtapeValue and
highEtapeValue are accurate for the reservoir which we chose. But you'll need to do some experimentation to determine the correct
values for your system. You'll see how this is done
once we jump over to Tinkercad. So let's copy and paste this
code and see what happens. As you can see, after we
open the serial monitor, the raw data and the
liquid level at printed. As we adjust the
temperature at the sensor, these values go up and down. But the liquid level is
showing some negative values, this is because the eTape values are set for the actual project. So let's see what happens
when the temperature is at its minimum, looks
like the value is 20. Now what about when it's at the maximum? Looks like it goes up to 358. So let's pop these values into the code and see what happens. Now you can see when we slide
the temperature all the way down to the minimum, the
liquid level shows as 0%. And when we slide to the maximum,
it shows 100%, nice work. This is the exact technique
you'll use to apply this to your own project in order
to calibrate the liquid level. The next part of this walkthrough is going to assume a bit of knowledge. First, that you're familiar
with the Blynk app. If you're not, check out our
Barbecue Thermometer class, it goes super in depth into Blynk. You can find this course at
programmingelectronics.com. The second thing we'll assume is that you're familiar
with the millis function. The millis function allows us to get rid of any delays in our code,
which would essentially jam up the connection between
our device and the Blynk app. We want tight, tight loops,
otherwise Blynk fails. If you're unfamiliar with millis, check out our free Millis mini-course, and you'll see below, the
link is in the details. Now, using the same wiring for the eTape, let's revise the code. So the goal here is to
take what we already have to find the liquid level, and add some IOT functionality to it
by injecting some Blynk code. First, we include the
required Blynk libraries, and then we also supply the
unique authentication token which we'll get from the Blynk app. We also provide the Wi-Fi
network name, as well as the password, so
our device can connect. previousTime we'll set to zero. And sampleTime, well, this
how often we want to push the data from our eTape sensor to our app. Let's start with every two seconds. The next new bit of code will be in setup, where we add Blynk.begin. This function instructs
our device to connect to the Blynk servers with our credentials. We put it in setup, because we only need to connect once. Next in the loop, you'll see that instead
of using delay sampleTime, we're going to instead
utilize the millis function. This allows as us to keep
running through the loop. A delay would stop
everything, and therefore a connection to the Blynk
server would be severed. We set currentTime to millis, which means currentTime
will always correspond to the internal stopwatch
within the ESP8266 board. It starts at zero and goes
for approximately 50 days, and then starts back over at zero. So this is something to keep in mind if you're ever going to leave your garden for more than 50 days. Next is the Blynk.run function, which is required to
maintain our connection to the Blynk servers. Next, you'll see an if statement. If currentTime, let's
say 1000 milliseconds, minus previousTime, which
right now is zero, is greater than or equal to sampleTime, then it will run the code below. If not, it will skip down
to the next bit of code. Well in this case, 1000
minus zero is 1000, and that doesn't exceed 2000, which is what we've set as our sampleTime. Therefore, we'll skip this if statement. But there's nothing else in the loop, so we'll just start right back
at the top of the loop again and we hit Blynk.run, which is perfect, that's what we want to
maintain connection. If we delayed, it would be two seconds before Blynk.run would be executed and we'd have some major problems. What happens when millis equals 2000? Well, 2000 minus zero equals 2000. So our if statement is true, this means we'll execute the code. All of this should look familiar from when we initially set up the sensor. At the end, you'll see three new lines, Blynk.virtualWrite (V1, rawLiquidReading), then Blynk.virtualWrite (LiquidLevel). And finally, previousTime = currentTime. When we execute virtual.Write,
we're pushing data to the virtual pin. On our Blynk app, we'll add widgets, which are
set up to receive this data. We've designated virtual pin V1 and V0. So when we make our app, we'll need to remember to assign
our displays to these pins. Lastly, we have
previousTime = currentTime. So after the first time through, previousTime will now equal 2000. When we execute the loop again and arrive at the if statement this time, currentTime we'll say is 2,500. And we subtract previousTime, which is currently 2000, we get 500. Is 500 greater than or equal
to our sampleTime of 2000? No, it's not, so we continue
running through the loop. We've got two more bits
of code at the bottom, which aren't really necessary but I added them to help
me do some troubleshooting. We've got a function called BLYNK_WRITE, for virtual pin two. When we change the value of V2 on the app, this data will be pushed to whatever we designate
inside this function. So on our app, if we
changed the value of V2, it will be pushed to the
device, assigned to sampleTime, and converted to milliseconds. This allows us to adjust the sample time or refresh rate on the fly. Last we've got BLYNK_CONNECTED. This is executed only once, when the device first
connects to the Blynk app. Blynk.syncVirtual ensures that before the code is
executed, we sync our pins. Therefore, if we had V2 equal to four, and the device connects,
sampleTime would be assigned to 4,000 instead of the
default 2000, which we declared at the beginning of the sketch. Before we test it out, let's take a quick look at our Blynk app. First, we have a SuperChart widget. You can put all kinds of
data streams into this guy, but for our purposes, we're going to just display
the liquid level percentage, which is virtual pin zero. Next, we have the Value Display widget, for our raw liquid reading. This really isn't
necessary, but it's nice to see what value is
actually being read at A0. This will correspond to virtual pin one. Next, we've got another
Value Display widget, this time liquid level. This should match exactly
what's on the chart, but again, nice to see data read out instead of just in a line on a chart. Last but not least, we have a Step widget. This allows us to adjust the
sample time or refresh rate. You can adjust the step
if you wanna increase or decrease how much the value changes every time you hit the up or down button. We'll leave this at 1 for now, and this corresponds to virtual pin two. So that's about it for the app, let's see this thing in action. (water pouring) (water pouring) (water pouring) Okay, we're just about there. The last thing we need to do is combine all these sections into one big sketch, and make sure they're all
compatible with the Blynk app. Remember that delay functions
won't work with Blynk, so that means we need
to edit both the pump on and off, as well as the servo code. We'll check out the new edits in the code, then we'll check out the Blynk app. And finally, we'll show
this baby in all her glory. So the big picture strategy for the code, we know we have to get rid of the delays. In order to do this, we're
going to break everything down into states, or for
clarity, we'll call them phases. The first phase is that
we'll rotate the garden. The second phase, we'll turn the pump on and then shut it off. And third, we'll let the pump
rest, and at the same time, we'll take a measurement
of the liquid level. That equals one full duty cycle, then we'll do it all over again. Let's dig into the new lines of code that we haven't seen yet. First up, is where we
declare the string variable pumpState, this will be used later. Everything else, all the way
to the loop, we've seen before, just never altogether in one sketch. The next new line is
static byte state = 1, this is to make sure the sketch starts where we expect it to,
at our state one code. We put static in there, which means it will only be executed the
first time through the code. The next time through,
this line will be ignored. So let's jump into state one. The first part, the if statement, is checking to see if we've
exceeded rotation time. And if not, we'll jump down
to the else if statement. This is checking if we're
in state one, which we are, and if the servos are attached. If not, then we'll run the user function, servoAttachThenRotate. This is a mini function which we created to attach all the servos and write them to the servo speed variable,
which we previously defined. We don't wanna constantly
write the servos, We just wanna set the speed
once and then let them run. That's why in the else if statement, we're checking if they're attached or not. So the second time through the loop, they are attached and thus the
else if statement is skipped, and we're just continuously
running through the code until the if statement is satisfied. Once rotation time has been reached, we'll execute the code
in the if statement. We'll run the servoStopThenDetach
user function, which surprisingly does
exactly what the name says. And we'll change the state to two. We'll then set previousTime
to currentTime. And as you can see, state
one is accomplished, and onto state two. So now the same deal with state two. We first check to make sure
we're still in state two, i.e pumpOnTime has not yet been exceeded. If not, let's jump down to else if. Similar to the servos,
we're checking to see if the pump is already on, by checking the variable pumpState. Remember, we've declared
this before as off, and we're in state two,
so we can execute the code in the else if statement. We'll write our relayPin to HIGH, which activates our relay
and then turns the pump on. We'll also change our pumpState to on. The next time through the loop, because the pump is already on, we'll skip this else if
statement and keep running through the loop until
pumpOnTime is reached. At this point, we'll
write the relayPin LOW, which will turn off the pump. We'll change the variable
pumpState to "Off", for the next time we get to state two. And as normal we'll change state to three, and previousTime to currentTime. Okay, onto state three. Finally for state three, this is really just our code from the last sketch. We'll check if pumpOffTime
has been reached, and if not, the pump stays off and the loop runs. Once it's reached, we'll
check the liquid level, push it out to our Blynk
app, and then set the state back to one, and the circle
of life begins all over again. And that's it, everything after the end of our loop is the custom functions. One thing to note, we did add some additional
Blynk write functions, so you can fine tune your
project from the app. You can adjust servoSpeed, rotationTime, pumpOnTime and pumpOffTime. This is useful, so you
don't have to re-upload any code to your device, you can just use the app
to adjust these parameters. We made it, we really hope
you enjoyed this video and that you have great success building your very own hydroponic garden. As a reminder, you can find
all the code, STL files and much, much more at
programmingelectronics.com. And listen, if you made it this far and you're still wondering if this Arduino stuff
is too tough to learn, I can assure you it's
definitely attainable. You'll be amazed at what you can do with just a little
Arduino coding knowledge. And if you want a jumpstart, check out the training program at
programmingelectronics.com. (bright music)