Arduino, HomeAssistant, and a Garden

Arduino, HomeAssistant, and a Garden

Last year I started a garden in my backyard. I chose to grow a few plants including tomatoes, peppers, and zucchini. This was my first time gardening and I learned a lot! Tomatoes can grow up to 6 feet tall and are rather bushy. They are really fun to watch grow, but if you put them close together they shade each other out! In fact they even shade out the plants behind them if you don’t consider plant height and the direction of the sun. This year I am determined to do better, but I’m a nerd, so I need data! So I built a fun little device with Arduino and HomeAssistant to help me out.

Setting Up HomeAssistant on a RaspberryPi

Arduino and HomeAssistant require their own setups and then a glue to connect them. So I started with setting up HomeAssistant. I run HA on a RaspberryPi4 under my desk using the HA OS. Some eggheads out there use virtual instances, but a RaspberryPi takes about 10 minutes to setup. All you need to do is download the Raspberry Pi Imager and follow these instructions from the HomeAssistant website. HA fans will tell you to always use an ethernet connection. This is to ensure stability and low latency, but I also couldn’t get wifi access to the Pi with the default setup anyways.

Once your RaspberryPi is setup, go to your router and ensure your RaspberryPi has a static IP address. For most routers you just need to login to (http://10.0.0.1 or http://192.168.0.0.1) your router and then find a tab called “Devices”. From there find the RaspberryPi in the device list, click on edit, and change any setting like “DHCP” or “Dynamic” to “Static”. Now navigate to http://homeassistant.local:8123/ and login using the credentials you made following the HA website tutorial. HomeAssistant is a large and expansive topic that I can’t tell you enough about it. Mostly because I don’t know enough about it yet. But I do know that HomeAssistant can talk to smart devices and the most common way to do that for your DIY devices is MQTT.

Setting Up MQTT For HomeAssistant and Arduino

MQTT is a protocol used for low bandwidth communication. Everyone always says why it was created during this bit but I, a trailblazer, will leave that as an exercise to the reader. Long story short, MQTT uses a broker, a subscriber, and a topic to send messages between devices. A broker mediates the messages from topics to all devices subscribed to that topic. In this project I created a topic named homeassistant/garden/sunlight that I published some json to. Then I created a configuration in HomeAssistant to subscribe to these messages and display a cool graph.

You need to decide on a broker for HomeAssistant. I chose EMQX. The other popular choice is Mosquito. I don’t know the full difference here, but they are both free and should work well enough for this project regardless of your choice. While you are still logged into HomeAssistant, go to the settings panel, click “Add-Ons” and search “EMQX”.

Create MQTT Users

Once you install this add-on go to EMQX’s UI in the sidebar of HomeAssistant. Log in using the default admin/password login and then go to “Authentication”. You need a user for MQTT authentication and this user needs to be stored in a database. On the Authentication page click on “+ Create” and use the default values selected for you along the prompts. This creates a local database using password based authentication. Back at the Authentication page, select “users” for this newly created database and create two users. One superuser for HomeAssistant and one user for your Arduino to authenticate with. Yes, you need to remember these credentials.

Making Arduino Talk To HomeAssistant

It’s at this point that we take a holiday from HomeAssistant to focus on the Arduino half of “Arduino and HomeAssistant”. You need an Arduino Mega (or an Elegoo Mega if you want to save $20) for it’s storage space. This project uses some libraries for the sensors that are sizeable and made the sketch too large for my Arduino Uno. You also need an Si7021 temp and humidity sensor a WINC1500 WiFi Shield, and some run of the mill photo-resistors.

Plug in the Wi-Fi shield on your mega, and set up a connection to your Si7021. The sensor is labeled with the pins. Use a breadboard for the sensor and plug in your photo resistors somewhere that is not shaded by the wired connections. The photo resistors should have one lead going to A0 and A1 pins on your board. This is where we will read the current coming in from the resistors. The other lead is connected to ground with some small ohm resistor for each photo resistor. In the end your set up should look similar to the image below (don’t mind the GPS breakout).

Arduino mega with wifi breakout board and solderless board. Wires from A0 and A1 to photo resistors

Creating the Arduino Sketch

The entire sketch is in my arduino- github repo. The first portion of the sketch just sets up the wifi board by creating a secrets.h header. This will contain the wifi network to connect to and it’s password. I recommend using a random date as the password if you’re going to post it in github though.

#include <WiFi101.h> // Arduino library for use with most wifi shields.
#include "secrets.h"

WiFiClient wifiClient;

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    ;  // wait for serial to begin
  }

  while (WiFi.begin(WIFI_SSID, WIFI_PASS) != WL_CONNECTED) {
    Serial.print(".");
    delay(5000);
  }

And BOOM! You got internet on your board! Just make sure to define WIFI_SSID and WIFI_PASS in secrets.h. I chose the 115200 baud rate at random, so choose what every value you prefer. Now for the the MQTT integration. This is the meat of the project. With the same code as above, update it to look like the following. The new lines are in bold.

MQTT Code

#include <WiFi101.h>
#include <ArduinoMqttClient.h>
#include "secrets.h"

const char BROKER[] = "10.0.0.94"; // using DNS did not work for me
int port = 1883;
char light_topic[] = "homeassistant/garden/sunlight";

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    ;  // wait for serial to begin
  }

  while (WiFi.begin(WIFI_SSID, WIFI_PASS) != WL_CONNECTED) {
    Serial.print(".");
    delay(5000);
  }

  mqttClient.setUsernamePassword(MQTT_USER, MQTT_PASS); // non super user created        
                                                       //earlier in HomeAssistant.

  Serial.println("Attempting to connect to mqtt broker");
  if (!mqttClient.connect(BROKER, port)) {
    Serial.print("Failure to connect to MQTT Broker: ");
    Serial.println(mqttClient.connectError());
    while(1) {
      ;
    }
  }
}

This code connects to the MQTT broker after the wifi connection is established. In my case, I couldn’t use the homessistant.local DNS to connect to the broker. Try it out and maybe that will work on your network. It makes your code look prettier. The port at this point is also not a constant… I will fix that in my next commit. At this point you should see nothing after the board connects to the MQTT broker. If you see a failure, check that EMQX is properly set up. The last step is to set up and read from the sensor to send data to HomeAssistant. Keep in mind that this means you can integrate your arduino and HomeAssistant however you want.

Sending Messages to MQTT

#include <WiFi101.h>
#include <ArduinoMqttClient.h>
#include "Adafruit_Si7021.h"
#include "secrets.h"

const char BROKER[] = "10.0.0.94"; // using DNS did not work
int port = 1883;
char light_topic[] = "homeassistant/garden/sunlight";

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
Adafruit_Si7021 sensor = Adafruit_Si7021();

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    ;  // wait for serial to begin
  }

  while (WiFi.begin(WIFI_SSID, WIFI_PASS) != WL_CONNECTED) {
    Serial.print(".");
    delay(5000);
  }

  mqttClient.setUsernamePassword(MQTT_USER, MQTT_PASS);

  Serial.println("Attempting to connect to mqtt broker");
  if (!mqttClient.connect(BROKER, port)) {
    Serial.print("Failure to connect to MQTT Broker: ");
    Serial.println(mqttClient.connectError());
    while(1) {
      ;
    }
  }
  sensor.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
  mqttClient.poll();
  if(mqttClient.available()){
    Serial.println(mqttClient.read());
  }

  delay(1000);

  int resistance_1 = analogRead(A0);
  int resistance_2 = analogRead(A1);
  int average_resistance = (resistance_1 + resistance_2) / 2;

  Serial.print("Avg:\t");
  Serial.println(average_resistance);
  Serial.print("{\n\"resistance\": ");
  Serial.print(average_resistance);
  Serial.print(",\n\"temperature\": ");
  Serial.print(sensor.readTemperature());
  Serial.print(",\n\"humidity\": ");
  Serial.println(sensor.readHumidity());
  Serial.println("}");

  mqttClient.beginMessage(light_topic);
  mqttClient.print("{\n\"resistance\": ");
  mqttClient.print(average_resistance);
  mqttClient.print(",\n\"temperature\": ");
  mqttClient.print(sensor.readTemperature());
  mqttClient.print(",\n\"humidity\": ");
  mqttClient.println(sensor.readHumidity());
  mqttClient.print("}");
  mqttClient.endMessage();
}

Back to HomeAssistant

Now Arduino is sending data to HomeAssistant, but EMQX doesn’t see anyone subscribed to the topic and is dropping all messages. Go to your EMQX dashboard in HomeAssistant to verify this. Now that you can see the messages dropping it is time to create a configuration for HomeAssistant that reads from the MQTT topic. Go to the settings menu in HomeAssistant and select Add-Ons. Now in the bottom right click on Add-On Store and search for “File Editor”. Install it and then on the hot bar select the wrench icon for File Editor. Click on the folder at the top left of the screen and look for a file named “configuration.yaml”. Create the file if it is not there. The following YAML creates three MQTT statistics based on the Arduino sensor data. After you copy the configuration, go to the “Developer Tools” section on the hot bar and select “ALL YAML CONFIGURATION” under the “YAML configuration reloading” tab. This reloads all of the YAML configurations in used by HomeAssistant including the default configuration.yaml file you created.

default_config:
mqtt:
  sensor:
    - name: "garden_temperature"
      device_class: "temperature"
      state_topic: "homeassistant/garden/sunlight"
      value_template: "{{ value_json.temperature }}"
      unit_of_measurement: "C"
      state_class: measurement
      
    - name: "garden_sunlight"
      state_topic: "homeassistant/garden/sunlight"
      value_template: "{{ value_json.resistance }}"
      state_class: measurement
      
    - name: "garden_humidity"
      device_class: "humidity"
      state_topic: "homeassistant/garden/sunlight"
      value_template: "{{ value_json.humidity }}"
      unit_of_measurement: "%"
      state_class: measurement

Now go to the developer settings and select “Statistics”. Each of the above statistics will be listed there and are available for all the analysis you want! I chose to create a card on the overview page. Select edit on the top right of the screen and add a graph card if you want to do the same.

Leave a Reply

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