IoT Smart Home System With Arduino

by aribarz in Circuits > Arduino

277 Views, 3 Favorites, 0 Comments

IoT Smart Home System With Arduino

2.png
1.png
logo.png
IoT Smart Home System
WhatsApp Image 2024-08-14 at 21.39.48_7afd0e73.jpg

Project Capabilities


We built a smart home system with an ESP32, and you can, too! In this Instructable we will explain step-by-step how to create a system capable of:

A) Climate Detection. Detect the temperature, humidity in the living room, and also the soil moisture of your plants.

B) Automatic Climate Control: turn on the AC when it's too hot/cold, change temperature accordingly, turn off when it's no longer hot/cold...

C) Presence Detection: Detecting which of your roommates/family are home

D) As a product of B and C, turning the A/C off when nobody is in the house

E) Automatic Plant Waterer - Water the house plants when the soil is dry.

F) Remote Control Remote manual control of the A/C, from your phone or PC dashboard. You can manually set the A/C even when you're away from home! (manual input is given temporarily more priority over the automatic climate control, so it will not be turned off).

D) Voice Control w/ iPhone

This example project uses an ESP32, but all the steps should be reproducible with other microcontrollers of course, with code/library changes to your respective microcontroller; the underlying logic remains valid and our post should serve as an in-depth guide on reproducing this all yourself.


What might we expect from this Instructable?


We believe there's no such thing as too little information; that's why this instructable goes into detail on what we did, how we did it, and our thought process as to why. Feel free to skip sections you feel you understand, or to come back later when you implement it yourself.

That being said, we highly encourage you to write your own code! You can view all of our code on Github for inspiration. We will explain all the logic required to write your own code from scratch, and we may provide links to our implementation sometimes, but this isn't a coding tutorial; This Instructable will explain to you from A-Z how to construct such a project yourself, with your own code.

One last thing - this project contains lots of different elements. For this reason, we go by a partially modular approach, and develop each section in isolation with modularity in mind, before finally bringing it all together. With that being said, enjoy the ride!

This project was made by Ari Barzilai and Avi Lazerovich.


Table of Contents

Introduction

  1. Project Capabilities
  2. What might we expect from this Instructable?

Table of Contents

Supplies

Step 1: Understanding how an Air Conditioner works

Step 2: Transmitting the A/C commands

  1. Obtaining the A/C commands
  2. Sending the commands

Step 3: Presence Detection

  1. The Different Approaches
  2. Considerations
  3. Our Implementation

Step 4: Climate Detection

Step 5: Climate Control

  1. Designing the Iteration Logic
  2. On Manual Overrides

Step 6: Phone Control & Webhooks with Blynk

  1. Rationale for Blynk
  2. Setting up Blynk
  3. Integrating Blynk with Arduino
  4. Integrating with iPhone Voice commands

Step 7: Plant Control

Step 8: Integrating it All

  1. A Quick Recap
  2. Why States?
  3. State Logic
  4. Implementation

Supplies

Materials we used in the project:

  1. ESP32 Microcontroller with a Shield (we used Keystudio: MicroController, Shield)
  2. Infrared Light
  3. Infrared Receiver
  4. DHT humidity sensor
  5. Capacitive Soil Moisture Sensor v2.0
  6. Servo
  7. 9V Batteries w/ Power Module
  8. Small water pump (We used the ViaAqua VA80, a small 4w aquarium pump, but anything works)
  9. Small water container, e.g a pot (you fill this with water and place the pump in it)
  10. Plug with switch
  11. A plant


Tools we used:

Cutter, Screwdriver, Superglue

We assume your house has an A/C and its corresponding remote.


Arduino Libraries we used:

IRremote

ESPPing

Blynk

BlynkNcpDriver

DHT Sensor Library

Adafruit Unified Sensor

ESP32Servo

Understanding How an Air Conditioner Works

4.png
WhatsApp Image 2024-08-15 at 22.02.31_28f9e7d2.jpg

Before creating a smart climate system, we first need a way for the Arduino to control the Air Conditioner. To do this, let's first analyze how an A/C works.

Usually, you control an A/C with a remote: you can turn it on/off, change the temperature, change the fan speed, change the temperature mode (on heat mode / cold mode), etc., all with a remote. How does it do this?

The answer: infrared light. The remote has a an infrared light bulb attached to it, and when a button is pressed, it flashes in a series of pulses (not visible to the naked eye). These pulses are translated into binaries, 1s and 0s: 1 for when light is sent (during a pulse), and 0 when there is no light (between the pulse). The A/C has a sensor which detects these pulses.

But, how does the A/C know what to do after receiving a bunch of 1s and 0s?

Similar to how we as humans can use specific lengths of signals and breaks to convey words and letters - this language is called Morse Code, and has been used in many different places in history - there are different "languages", or protocols according to which your A/C detects input. These protocols enable your A/C remote to send instructions to your A/C, such as: POWER: ON, MODE: COLD, FAN: 3, TEMPERATURE: 16 in the form of infrared pulses, and for your A/C to understand it and act accordingly.

However, different A/C models use different protocols. There are several very standard protocols which many devices use around the world, so it most likely would use one of those. However, it might use a less well-known protocol, or even take an existing protocol and modify it, such that you'd struggle to reverse engineer the signal. Our A/C for example, used a modified version of the "NEC" protocol.

Transmitting the A/C Commands

5.png
ezgif-4-f0892ef6a9.gif

Obtaining the A/C Commands


The IRremote library is able to decode all sorts of infrared instructions into the pulses that make them up; if you have a well-known A/C model, it even has an A/C-specific fork which might be able to translate these pulses to your A\C's instructions. We didn't have a model which was supported by this fork, and struggled greatly at reverse engineering the modified protocol it used.

The good thing is, we don't actually need to reverse engineer your A/C's protocol! With a bit of time and an excel sheet, you can go through the possible instructions, and simply use your A/C remote and record each of the pulses it gives, and keep track of which pulses correspond to which instructions. Then, it's simply a matter of repeating the same pulses whenever you want to send their corresponding instruction.

Create an excel sheet with the instructions you want your smart home system to create. On our A/C, we had the following parameters:

POWER - On/Off (2 values)

TEMPERATURE MODE - Heat/Cold (2 values)

FAN SPEED - 1/2/3/Auto (4 values)

TEMPERATURE - 16-30 Celsius (15 values)

In total - 2*2*4*15=240 different instructions, as each instruction sent by your remote contains each of the parameters. If you don't particularly care for fan speeds, you can cut this down to just 60 instructions (if, for example, you record only instructions for "Auto" fan speed). If you use only one temperature mode, you can cut this down for 30 instructions.

Now, once you know which temperatures you will use for your project, it's a matter of manually going through each of these instructions, and recording each value using the IRremote library and your IRreceiver. We've attached the excel file we used to record all these, as well as a fill-in format you can use. Once you have a clear dataset of instructions, all you need to do is load them, or copy+paste them (if you prefer that) into variables. Example

Note that the IR library provides all sorts of info on the pulses it records, which you can see in the attached table; we later found out that we only needed the Raw Data cells, which should make recording the pulses much easier. Although recording these instructions can be time consuming, it's a mostly repetitive task which gives you all the control you need, while avoiding the need to decoding binary instructions.

Again, our A/C pulses posted on github will most likely not work for whichever model you use, (although feel free to experiment and check!) - rather than copy pasting our data, you should follow the steps we went through to obtain the correct IR data, which works for your air conditioner model!

Sending the Commands


Controlling the A/C via the Arduino now, is simply a matter of having your Arduino send the relevant pulse you recorded for the desired instruction, through an attached infrared light. This is a classic use of the IRremote's sendPulseDistanceWidthFromArray() function. Example

Make sure you physically place your infrared relatively close to the A/C so that it can detect it; the Arduino emits less power than your electric remote most likely, so its range isn't too large.

Presence Detection

vidGif.gif
WhatsApp Image 2024-08-14 at 21.40.09_180c28be.jpg
deviceInfo.png

The Different Approaches


Let's leave the climate aspect for later and discuss now the Presence Detection. Our Smart Home System can register users, and detect when these specific users are home. There are many different approaches to this problem, none of them perfect; we encourage you to find your own solution, but here are two possible solutions to consider. Let's look at both.

Geofencing - This is marking a certain area, and keeping track of the users location, using a phone for example. When the user's phone location falls within this area, you can send an alert to services such as Make (formerly Integromat).

IP Pinging - Pinging is the concept of sending a message to a device, and marking how long it takes to receive a response from that device. A device, when connected to a Wi-Fi network, is assigned a random IP address. This method involves reserving a specific local IP address (specific to the home router) per registered user, and pinging this address; if you receive a response, it means this specific person is home and connected to the Wifi.

----

Both methods contain drawbacks.

Geofencing Drawbacks - The drawback of Geofencing is that it requires invasive phone permissions and can be inaccurate. Permissions require you to either develop your own app (complicated with iPhone due to Apple restrictions) or use an existing app (which costs money and might not work as well as you want, and integration can get complicated if you have multiple phone types in the house, e.g iPhone and also android). Also, getting each user to download the necessary app can be a hassle.

This was our initial approach, however it was quite complicated to implement. In addition, our location currently suffers from GPS jamming due to certain world events, leading to this method being highly inaccurate for us (it said we were 200 kilometers away from our actual position).

IP Pinging Drawbacks - This is the method we ended up using, and worked surprisingly well. The main drawback of IP pinging is that every once in a while a ping might fail, and a device might be connected to the cellular network rather than your local wifi network (should be possible to find a workaround with this via things like port forwarding perhaps, but we found local IP address to be good enough). The key part of this is that the IP address must be static, so that you know which device corresponds to which person (otherwise if people owns multiple devices for example, you can't really tell how many people are present).

One benefit of IP pinging, is that it's very easy to add new users; all you need to do is to log into your router's homepage, and set the desired device's IP as static, and write it down. This takes minimal effort on your part, and no effort on your guest's part.

Considerations -


1) Both of these methods are frankly better at answering the question of "Who" is home, rather than "How many people" are home. This is because these devices rely on manually registering users, so if a guest not from the household (who hasn't been registered yet) enters, they won't recognize them.

Alternative methods such as cameras and computer vision might be better at this, but they come with their own drawbacks and considerations; we ended up considering the above two methods as they were simple enough and worked well enough; any frequent guest could simply be added to the list of known people quite easily, and non-frequent guests would most likely be accompanied by a house member.

2) A hybrid approach, which combines these two, may also work well and compensate for some of the drawbacks of both. We didn't end up doing this, because the current GPS jamming made geofencing irrelevant.

We also note that our pinging specifically targets phones, rather than PCs. this is for two reasons:

A) practical - 99% of the time, people bring their phones with them everywhere. That's not necessarily true for PCs and laptops, which might be left at home while the person themselves are away.

B) necessary - computers often have stronger firewall protocols and don't respond to random pings from unknown devices. Rude!! (of course there are workarounds for this, but that brings us to the invasive drawback of geofencing).


Our Implementation


Regarding the two drawbacks of IP pinging (ping failure and not connected to the Wifi network), we figured that the second isn't too important as it is a fair assumption that most people in our household auto-connect to the network within range.

Regarding the first assumption (ping failing to receive response sometimes), rather than defining a person as absent if pinging them has no response, we defined a person as absent if three attempts in a row had no response. As we ping every couple of minutes so as to not overload the Arduino and to perform other processes (we will expand on this at a later stage), this means that detection of a person leaving the home is not instantaneous, but it has less noise and is more precise.

Therefore, our Presence Detection algorithm works as follows:

  1. Go through the list of registered users, and ping each one of them.
  2. In between each ping, wait a short while to not overload Arduino and to do other arduino processes if necessary
  3. If a user is unreachable when pinged, increment an 'absent counter' for this user by 1.
  4. if upon incrementing, the counter reaches 3, it means they were unreachable in the last two iterations as well, and change their status to away from home.
  5. If they are pinged, mark them as present at home
  6. After all users have been pinged in the current iteration, count how many people are at home, and who.

This means that our current list of present people will be outdated by at most 3 cycles/iterations of the algorithm, but will be much more precise and have less noise.

A very important note is that we don't iterate through all of the users in one go. This is because we don't want this function to block the rest of our Arduino functions, most important of which is the Blynk.run() command, which keeps the Arduino and Blynk connected (we explain this in a later section). Instead, assume someone else instructs the Presence Detection when to ping the next user in line.

Climate Detection

FDSIZRLLZVJWEK2.png
FUG7E8MLZVJWEKP.png

Climate detection is probably the easiest portion of this project.

Temperature Detection - Connect the DHT chip to your Arduino. The DHT library has two important functions - readHumidity, and readTemperature. However, the temperature value you receive might not necessarily match what you feel, as perceived temperature depends on factors such as wind, humidity, et cetera; this is why on a breezy day you might feel colder than a humid day with no wind, for example.

For this reason, we used a simple mathematical formula to calculate the perceived temperature (although this step is optional, we felt it made it more accurate)!

Perceived Temperature = (1.1 * temperature) + (0.0261 * humidity) - 3.944

Soil Moisture Detection - This step requires a tiny bit of calibration, as different sensors may give different values (even if it's the same chip model!). To calibrate the soil moisture sensor, get a cup of water, and make sure the soil around your plant is dry (needs watering). while the soil moisture chip is connected to the arduino, hold it up in the air and print to the Serial the values it detects. This should be the minimal value your chip should detect.

Now for the maximum, stick the soil moisture detector in your cup of water, but make sure the water line does not get near the warning line. The warning line is the horizontal white line; above this there are electronic parts which aren't water-proof, so you don't want water touching these.

The value you get when the detector is in the cup of water, is the maximal value. All values will be between these two extremes.

Now, wipe the detector dry and stick it into the dry soil near your plant. Wait a minute, as it takes time for the values to update (they will slowly drop to the real value). Once it seems to not be changing too much, mark this value down;

Now, water the soil. Again, wait a minute or two. Once the values have stabilized, you know the value which represents "wet soil".

Therefore, the threshold you want to water your plant (obviously depends on the plant in question) should be a value between these two values; you can most likely eyeball it.

-------

A note on the DHT: it sometimes might fail to read the temperature/humidity; in this case, we disregard the output and sample the temperature again, after a few seconds. Try not to sample it too frequently or it won't work as well, once every 5 seconds max.

Climate Control

Flowchart.png

Designing the Iteration Logic


The "Climate Control" section is really just a long series of ifs and if else's, and uses all of the previous steps. Using input from the detect presence and temperature detection, lets first get a pen and paper and plan out our Climate Logic.

We want our A/C to act differently according to different situations. For example,

"If the AC is off and it's hot, turn on the AC on cold mode"
"If the AC is off and it's cold, turn on the AC on heat mode"
"If the AC is on and it's neither hot nor cold, turn off the AC"
"If the AC is on and on heat mode, but it's very hot, switch to cold mode"
"If nobody is home, turn off the AC and disable the Automatic Climate Control until someone is home"

These are just a few example use cases, all of which we used in our project. We can map this all out on a decision tree, for example, and in terms of code it's just a matter of following these if-else statements. Leaf nodes in the tree call upon the corresponding AC instructions as detailed in the "Transmitting the A/C commands" step.

In terms of code readability and modularity, if you really care about design and are using an OOP language, this is a great time to create an "Air Conditioner" class with properties such as the current AC settings. The Climate Handler would then check each time the air conditioner's properties (Is this AC on/off? Is it on Cold mode? etc...) and act accordingly. Example

This approach is great because if you wish your smart home system has multiple A/Cs in the home, it's merely a matter of iterating the climate handler on each A/C. In our project we had only a single A/C, but extending this to more should be a trivial task with proper implementation


On Manual Overrides


In the introduction, we discussed that it would be possible to control the A/C from your phone. What happens if I manually want the AC to be on a different setting than what the automatic climate system decides? For example, maybe the automatic system is set to cold mode, but I'm sick and don't want A/C at all. In such a case, I don't want the system to keep attempting to turn the AC on every time I turn it off. You want user decisions to have hierarchy.

A simple solution for this is, upon receiving a manual input, to add a "cooldown timer" for the Climate Control system. In pseudocode, it would look something like this:

if ManualOverride in last 30 minutes:
Skip Climate Control


This leads us to the next question - how do we detect when a manual input has been received?

Digital + Voice Control With Blynk

iPhone voice control
Screenshot 2024-08-15 185330.png
WhatsApp Image 2024-08-15 at 15.04.46_a2161d74.jpg
WhatsApp Image 2024-08-15 at 22.26.17_6416dd91.jpg
WhatsApp Image 2024-08-15 at 22.26.17_8c061085.jpg

Rationale for Blynk


In order for our automatic climate system described in the previous section to work, it needs to have perfect knowledge of the current A/C state. This is because its decisions rely on knowing the current state of the AC (its temperature, power state, etc.). Therefore, any changes / new commands to the AC need to be detected and go through the smart home system.

One possible solution for detecting manual inputs from the AC remote is to attach an IR receiver next to your AC's IR receiver, decode the signals for their corresponding instructions, and update the AC properties accordingly.

A second approach is to set aside your AC remote and have the entire controls be digital, through your smartphone, and to communicate with the Arduino whenever a command is received via webhooks. This approach enables you to add IoT integration, for example to have your voice activate a webhook responsible for turning on/off the AC.

To handle this we use Blynk. All of this is doable without Blynk of course, by setting up your own dedicated server, but Blynk takes care of all the communication and hosting for you.

Also, Blynk provides an easy to configure dashboard to view and control everything.


Setting up Blink


Start by creating a Blynk Account, and create a new device. Then, click "Developer Tools" and "Edit Dashboard".

Blynk enables you to define "Virtual Pins" with which your Arduino can read and write to; it also enables you to set webhooks such that anyone visiting a specific URL can update these pins (which your Arduino then reads).

We want pins for the following:

AC Power (On/Off)

AC Temp Mode (Heat/Cold)

AC Temperature (16-30)

AC Fan Mode (1-4)

Of course, the actual values might differ for your model. Blynk free version only allows up to 5 virtual pins, so you need to be conservative if you're not willing to pay! We considered removing the Fan Mode option due to this limitation. In the end, we ended up paying the 7$ fee for additional pins, however it's crucial to state that this absolutely isn't necessary to accomplish all of the needed functions!! We used these additional pins to show optional diagnostics, such as the current room temperature, from the comfort of our phone.

Therefore, on your device page, on the inner sidebar (just below the Home button) there should be a "Datastreams" icon. Create a virtual pin for each AC instruction - the only important variables on this page are the pin numbers and the data type (should be integer).

Below the Datastream icon on the sidebar, there is the Web Dashboard, where you can create your controllable menu for the A/C. Feel free to create your own menu, with each widget corresponding to the matching pin!

You can create a corresponding mobile dashboard by downloading the app and logging in.

Lastly, head to the Testing section of the "Developer Tools", and grab the API HTTP links for each pin; see the attached photo for an example:

https://sgp1.blynk.cloud/external/api/update?token=VXqBqE4YKtpBV7vejvomczEIRFaFUR7p&v0=1

is an example URL. This URL contains two variables - our API token "VXqBqE4YKtpBV7vejvomczEIRFaFUR7p" (which you should keep secret! This is just an example token) and the new value of the v0 virtual pin, 1 "v0=1". Whenever someone visits this URL, the v0 pin will be set to this value. If you replace the 1 with 0 ("v0=0), then whenever someone visits this URL, the v0 pin will be set to 0.

Integrating Blynk with Arduino


Thus, using the Blynk library for Arduino, we must:

1) Write to Blynk whenever the Arduino's Climate Handler changes the AC settings. This is what the virtualWrite function is for.

2) Read from Blynk whenever a value from the digital pipeline is changed. This is what the BLYNK_WRITE function is for.

By digital pipeline, we refer to directly controlling the AC data from the Blynk Dashboard, or changing it via a webhook.

Using these two functions, like magic we've created a connection between our dashboard and our arduino! You can now control your AC from your Blynk dashboard!

One main warning - ensure that only one file imports Blynk. Due to improper library configuration, your project will most likely fail to build if Blynk appears in multiple files. If you absolutely need multiple files to access Blynk functions, it's best to create a single file to handle all Blynk functions, and for helper functions which other classes can then call. Example


A second warning - with Blynk, your loop() function should be as simple as possible, and so should your functions; try to avoid functions which take too while to compute, because then the connection between your Arduino and Blynk might break. If your code is complicated, it's best to separate it into steps.


Integrating with iPhone Voice Commands


iPhone has a handy "Automations" app; using this, we can have Siri visit the desired URL upon certain voice commands.

Now that we have our REST API links (the http links you made previously), Siri will then visit these URLs depending on which voice input you give her, which will then modify our Blynk virtual pins. These pin value changes will alert the Arduino, which will then transmit new instructions to our AC using the infrared light.

For example, I suppose I had a virtual pin for the AC temperature. In this case, I could provide the voice command "Set Temperature", and then have Siri prompt the user for a number, and it would visit the corresponding URL. For example, if our temperature pin was V3 and we wished to set it to 16 degrees, this site would be visited:

https://sgp1.blynk.cloud/external/api/update?token=VXqBqE4YKtpBV7vejvomczEIRFaFUR7p&v3=16

(of course, your API token is different).


We've attached an image of the Set Temperature automation we used; the other commands are just as straightforward.


Why not Android?

It's most likely possible; however neither of us have an android so it wasn't a priority for our project. From our google search, there used to be a service called Conversational Actions by Google, but this was discontinued; we didn't find an alternative in the short time we searched, but we're sure there's one out there.


On the paid version of Blynk

As we said prior, the free system works great for all the components of this project. For additional optional diagnostics, such as showing the outputs of the climate and presence detection on your phone, or displaying a Temperature graph of the temperature throughout the day, more pins are needed. This however is entirely for convenience and does not affect the operation of the system and project in any way.

Plant Control

Closer look @ Servo
6.png
7.png

The soil is dry. Therefore, turn on the pump for X seconds. Then, turn off the pump. The soil is no longer dry. Ta-dah!

That's the main concept of the plant watering system; it obtains the soil moisture values from the sensor we calibrated in the Climate Detection step; then, if necessary, it activates the pump for a short while before turning it off. Logically, it's not complicated.

The main questions you should ask are:

How do you turn on/off the pump?

In our case, and I assume in most cases (I don't know, I'm not an expert in small aquarium pumps), the pump works consistently as long as it's connected to an electric current. This would flood our plants, which is probably bad.

For this reason, we got a plug with a switch on it; when the switch is on, electric current is let through. When it's off, none is let through. Perfect!

Using a cutter, we cut off the head of the aquarium's plug, and wired the cable to a our new plug.

So, now our pump, when placed in water, indeed pumps or doesn't pump! We just need to turn on/off the switch. However, this brings us to another question:

How do you turn on/off the switch?

That's simple. Servos!!

Servos rotate; this rotation can press the switch. In our case, we added bits of glue to the switch to provide a better angle for the servo to apply force, however this probably isn't necessary.

There's just one catch: pushing a switch may require quite a bit of force. That's fine; the arduino automatically sends more electrical power to the servo, to overcome this resistance. However, this leads us to a new problem -

Depending on your switch, the arduino might send too much power to the servo and shut off / reboot.

To solve this problem, we attached to the arduino the power module.

---------------

Finally, using our fifth virtual pin, we can create a "Water Plant" button on the Blynk dashboard to enable you to override the automatic plant waterer and water your plant even more - great if you're away from home and expecting a hot day! This implementation is identical to what was explained in the Blynk section.

Integrating It All

FSM.png

A Quick Recap


Wow! We've made it so far. To summarize:

We've made a climate detector,

A presence detector,

A climate control system, which receives information from the first two and communicates with the Blynk and AC accordingly,

A water planter which receives input on soil moisture and acts waters the plants if necessary.

Lastly, we created optional manual overrides for this automated system.

--------------

How do we integrate all of this? The answer - a finite state machine.


Why States?


This may isn't necessary, but it enables you to greatly simplify the code. Rather than having all of these different components act together all at once, and maybe interrupt with each other, it's best to give each component its own turn (e.g if time is important factor, for example amount of time watered, you don't want to start watering and then have another function take up a lot of time before you can turn off the water. Again, don't flood the plants!).

The reason this works is that it makes your system's logic simpler, easier to program, and more efficient, by providing each unit its dedicated time to work. We don't actually need to activate each of these units every single second really (for example, we can detect presence every few minutes, check the room temperature every few minutes, etc.), so this works well.

State Logic


So, lets' define four states: Climate Detection, Presence Detection, Climate Control, Plant Control. Clearly the latter two depend on the first two for information, such as soil moisture or how many people are in the house. So the first two states need to come before the latter two.

Let's also consider manual override; if the AC had a manual override, the Climate Control should skip its turn and go immediately to the next step.

Taking into account these two requirements, we can propose such a state machine as the attached image.


Implementation


One of Blynk's most powerful features is the BlynkTimer class, which activates certain functions each interval. We can have up to 16 different timers at once per timer object, but then things might get funky with constant interrupts and switches to each function.

With timers, we can avoid overloading the Arduino with constant functions (e.g temperature detection) and do so only as much as needed. When a module has finished its work after a series of timer calls, it passes its turn on to the next state in line.

With our state logic, we just need one single timer at any given time; a switch from state A to state B would look something like this (pseudocode):

reset timer(Ainterval,Afunc)
set timer(intervalB, Bfunc)


Although there are FSM libraries for Arduino such as Arduino-FSM, for our use case of a cyclical machine with 4 states, this was so simple we didn't see a point in using such a library; a simple switchState function was enough. Our code had a corresponding function for each state, as well as a switch function which switched to the state's function.

This state function was responsible for turning on its corresponding module's code, as well as deciding when to switch to the next state.

The Presence Detection system for example, switched a state after each ping.

The Plant Control state switched state only after it finished watering the plant.

The Climate Control switched states immediately if a manual override occurred recently (which we keep track of by storing a time variable using millis()), or after finishing its flow chart logic.

....And that's it!!! Congratulations for reaching so far.

To summarize, we now have a consistent cycle which goes through all of our modules at once. We have a self-regulating climate control and plant watering system, and (if you sacrificed a pin such as the Fan Speed Pin), can see from our phone how many people are home and control the AC from afar, as well as water the plants!!


Thanks for reading.