How connect arduino mega with Home Assistant?

Hi guys, i’m new here, i have create in my home a domotic project using arduino mega 2560 connect with lan and about 40 sensor, relays. Now i use blynk but i would use Home Assistant. How proceed?

1 Like

Hello , did you get it to work ? I have a mega and Ethernet shield with 4 relays and I can’t get it to work , everyone uses esp

I have relays hanging off an uno (same outcome)

I use MQTT to control and get state on the relays (as well as a temp/hum sensor).

Therefore, I setup the switches and sensor as MQTT type in homeassistant core.

If you dont have an “agnostic” communication protocol like MQTT or http etc, you may need to re-load your sketch for soemthing that homeassistant core understands.

Would you share your sketch please?

Not pretty, but here is the arduino sketch:

It is for speakers, so I am switching the 8 relays as 4 pairs (left and right channel)

I also have a DHT sensor attached fro temp & humidity

#include <SPI.h>
#include <Ethernet.h>

//#include <WiFiUdp.h>
#include <PubSubClient.h>

#include <DHT.h>
DHT dht(9, DHT22, 20); // DHT 22 on pin 9 - get power from pin 8 (cant use 10-13 as used for SPI by the ethernet card)
long previousMillis = 250000;
long interval = 300000;

// Update these with values suitable for your network.
const char* mqtt_server = "10.1.1.235";
const char* client_name = "speakerswitch";

String switch1;
String strTopic;
String strPayload;


int PinsA[] = { 2, 5 }; // pins for Zone A left & Right
int PinsB[] = { 3, 6 }; // pins for Zone B left & Right
int PinsC[] = { 4, 7 }; // pins for Zone C left & Right
int Status[4] = { 1, 1, 0, 0 }; //Pin status. zone A, B, C, D (d not used). 1 represents zone active. Zone A&B are wired to NC ie default is on.
byte mac[] = { 0xDE, 0xAD, 0xFD, 0xEF, 0xFE, 0xED };   //physical mac address
byte ip[] = { 10, 1, 1, 179 };                      // ip in lan (that's what you need to use in your browser. ("192.168.1.178")
byte gateway[] = { 10, 1, 1, 1 };                   // internet access via router
byte subnet[] = { 255, 255, 255, 0 };                  //subnet mask
//EthernetServer server(80);                             //server port     
String readString;

// Callback function header
void callback(char* topic, byte* payload, unsigned int length);

EthernetClient ardClient;
PubSubClient client( mqtt_server, 1883, callback, ardClient);


void setup() {
 // Open serial communications and wait for port to open:
  Serial.begin(57600);

  pinMode(PinsA[0], OUTPUT);
  pinMode(PinsA[1], OUTPUT);
  pinMode(PinsB[0], OUTPUT);
  pinMode(PinsB[1], OUTPUT);
  pinMode(PinsC[0], OUTPUT);
  pinMode(PinsC[1], OUTPUT);
  pinMode(8, OUTPUT); // power supply for the DHT22 - data on 9, VCC on 8 as I ran out of 5v pins
  digitalWrite(8, HIGH); // turn on the power to the DHT!!

  // start the Ethernet connection and the server:

  Serial.println("about to begin ethernet"); 
  Ethernet.begin(mac, ip);
  delay(1500);   // Allow the hardware to sort itself out
//  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  if (!ardClient.connected())
    {  Serial.println("about to retry ethernet");  
        ardClient.stop();
        Ethernet.begin(mac, ip);
          Serial.print("server is now at ");
          Serial.println(Ethernet.localIP());
    }
}

void callback(char* topic, byte* payload, unsigned int length) {
  payload[length] = '\0';

  strTopic = String((char*)topic);

  Serial.println(strTopic); //debug if we got a topic
  
  switch1 = String((char*)payload);
  if(strTopic == "ha/speakerswitch/za/set") // Zone A
    {
    if(switch1 == "ON")
      {
        digitalWrite(PinsA[0], LOW);//wired to the NC (ie default is on, actuate for off)
        digitalWrite(PinsA[1], LOW);
        client.publish("ha/speakerswitch/za" , "ON" ); // confirm action performed to the state topic   
      }   
    else
      {
        digitalWrite(PinsA[0], HIGH);//wired to the NC (ie default is on, actuate for off)
        digitalWrite(PinsA[1], HIGH);
        client.publish("ha/speakerswitch/za" , "OFF" ); // confirm action performed to the state topic      }
      }
    }

  if(strTopic == "ha/speakerswitch/zb/set") // Zone B
    {
    if(switch1 == "ON")
      {
        digitalWrite(PinsB[0], LOW);//wired to the NC (ie default is on, actuate for off)
        digitalWrite(PinsB[1], LOW);
        client.publish("ha/speakerswitch/zb" , "ON" ); // confirm action performed to the state topic
      }
    else
      {
        digitalWrite(PinsB[0], HIGH);//wired to the NC (ie default is on, actuate for off)
        digitalWrite(PinsB[1], HIGH);
        client.publish("ha/speakerswitch/zb" , "OFF" ); // confirm action performed to the state topic
      }
    }

  if(strTopic == "ha/speakerswitch/zc/set") // Zone C
    {
    if(switch1 == "ON")
      {
        digitalWrite(PinsC[0], HIGH);//wired to the NO (ie default is on, actuate for on)
        digitalWrite(PinsC[1], HIGH);
        client.publish("ha/speakerswitch/zc" , "ON" ); // confirm action performed to the state topic
      }
    else
      {
        digitalWrite(PinsC[0], LOW);//wired to the  NO (ie default is on, actuate for on)
        digitalWrite(PinsC[1], LOW);
        client.publish("ha/speakerswitch/zc" , "OFF" ); // confirm action performed to the state topic
      }
    }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(client_name)) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.subscribe("ha/speakerswitch/#");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void loop() {
  if (!client.connected()) {
    Serial.println(" not connected - will try agin - calling reconect");
    reconnect();
  }
  client.loop();

  unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > interval) {
      float h = dht.readHumidity();
      float f = dht.readTemperature(false);
        if (isnan(h) || isnan(f)) {
          client.publish("ha/speakerswitch/temperature" , "DHT problem" );
          previousMillis = currentMillis; // add on and try again next loop
          return;
        }
      previousMillis = currentMillis;
      

      Serial.println(String(f));      
      client.publish("ha/speakerswitch/temperature" , String(f).c_str() );
      Serial.println(String(h));      
      client.publish("ha/speakerswitch/humidity", String(h).c_str());
    }
}

Been running for several years

I then use MQTT switches in my configuration.yaml: (example of 1 switch)

switch:
  - platform: mqtt
    name: "speakerBar"
    state_topic: "ha/speakerswitch/za"
    command_topic: "ha/speakerswitch/za/set"
    qos: 0
    payload_on: "ON"
    payload_off: "OFF"
    optimistic: false
    retain: true

Thank you very much, one question, doesn´t the arduino code have to include user password information about mosquito broker?

Do you get 6 switches on hassio after this?

This is my test board with 4 relays , I tried your code but I don’t understand the relay section , I got mqtt broker to see the board activating anonymous login. Also with the hassio sketch I only see 1 switch

I use anonymous MQTT, so no login required

If you need to add password, check the syntax for the PubSubClient command - need to add the additional variables.

For the switches in homeassistant core, you need to setup the other switches - I included one for an example.

Note, I have 8 relays, but switching them in pairs as I am using for speaker switch.

Not published as you answer, but a working example you could modify.

Just an idea; you can also use the mega arduino as mysensors gateway+sensor.

I’m going crazy, almost did it, got to work 1 switch and then when I tried to modify the code for the rest it stopped working (I didn’t save everything when it worked, dumb me)

Ahhh - the joy of the computer!

I recommend saving different versions as you go - I assume you are now doing that.

Note that I used arrays for the variables as I was controlling the switches in pairs and thought that might work for me. I also have a W5100 ethernet shield attached to the uno … but it seems you have etehrnet working.

Up to you what will work in your situation.

Phil

Looking good so far, i started again and now i have control over my 4 relays (Funny thing 3 of them are for speakers too). I really appreciate your help.

One question, do you know how to get a pulse instead of on&off ?, like when i clic the command wherever instead of turning on and statying on it will just send a quick pulse, like for a a garage opener.

Sharing you my code and yaml (Thanking you)

//ARDUINO MEGA FUNCIONANDO 4 relays gracias a Phil

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

// estos son los valores del cliente MQTT
const char* mqtt_server = “192.168.1.170”;
const char* client_name = “burmqttswitch”;

String switch1;
String strTopic;
String strPayload;

int PinsA[] = { 2 }; // pins for Zone A left & Right
int PinsB[] = { 3 }; // pins for Zone B left & Right
int PinsC[] = { 4 }; // pins for Zone C left & Right
int PinsD[] = { 5 }; // pins for Zone C left & Right
int Status[4] = { 1, 1, 0, 0 }; //Pin status. zone A, B, C, D (d not used). 1 represents zone active. Zone A&B are wired to NC ie default is on.

//Estos son los valores del adaptador Ethernet Shield

byte mac[] = { 0xDE, 0xAD, 0xFD, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 22 }; // ip in lan (that’s what you need to use in your browser. (“192.168.1.178”)
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
String readString;

// Callback function header
void callback(char* topic, byte* payload, unsigned int length);

EthernetClient ardClient;
PubSubClient client( mqtt_server, 1883, callback, ardClient);

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(57600);

pinMode(PinsA[0], OUTPUT);
pinMode(PinsA[1], OUTPUT);
pinMode(PinsB[0], OUTPUT);
pinMode(PinsB[1], OUTPUT);
pinMode(PinsC[0], OUTPUT);
pinMode(PinsC[1], OUTPUT);
pinMode(PinsD[0], OUTPUT);
pinMode(PinsD[1], OUTPUT);
pinMode(8, OUTPUT); // power supply for the DHT22 - data on 9, VCC on 8 as I ran out of 5v pins
digitalWrite(8, HIGH); // turn on the power to the DHT!!

// start the Ethernet connection and the server:

Serial.println(“about to begin ethernet”);
Ethernet.begin(mac, ip);
delay(1500); // Allow the hardware to sort itself out
// server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
if (!ardClient.connected())
{ Serial.println(“about to retry ethernet”);
ardClient.stop();
Ethernet.begin(mac, ip);
Serial.print("server is now at ");
Serial.println(Ethernet.localIP());
}
}

void callback(char* topic, byte* payload, unsigned int length) {
payload[length] = ‘\0’;

strTopic = String((char*)topic);

Serial.println(strTopic); //debug if we got a topic

switch1 = String((char*)payload);
if(strTopic == “ha/speakerswitch/fG/set”) // Zone A
{
if(switch1 == “ON”)
{
digitalWrite(PinsA[0], HIGH);//wired to the NC (ie default is on, actuate for off)
digitalWrite(PinsA[1], HIGH);
client.publish(“ha/speakerswitch/fG” , “ON” ); // confirm action performed to the state topic
}
else
{
digitalWrite(PinsA[0], LOW);//wired to the NC (ie default is on, actuate for off)
digitalWrite(PinsA[1], LOW);
client.publish(“ha/speakerswitch/fG” , “OFF” ); // confirm action performed to the state topic }
}
}

if(strTopic == “ha/speakerswitch/DB/set”) // Zone B
{
if(switch1 == “ON”)
{
digitalWrite(PinsB[0], LOW);//wired to the NC (ie default is on, actuate for off)
digitalWrite(PinsB[1], LOW);
client.publish(“ha/speakerswitch/DB” , “ON” ); // confirm action performed to the state topic
}
else
{
digitalWrite(PinsB[0], HIGH);//wired to the NC (ie default is on, actuate for off)
digitalWrite(PinsB[1], HIGH);
client.publish(“ha/speakerswitch/DB” , “OFF” ); // confirm action performed to the state topic
}
}

if(strTopic == “ha/speakerswitch/zc/set”) // Zone C
{
if(switch1 == “ON”)
{
digitalWrite(PinsC[0], LOW);//wired to the NO (ie default is on, actuate for on)
digitalWrite(PinsC[1], LOW);
client.publish(“ha/speakerswitch/zc” , “ON” ); // confirm action performed to the state topic
}
else
{
digitalWrite(PinsC[0], HIGH);//wired to the NO (ie default is on, actuate for on)
digitalWrite(PinsC[1], HIGH);
client.publish(“ha/speakerswitch/zc” , “OFF” ); // confirm action performed to the state topic
}
}

if(strTopic == “ha/speakerswitch/F1/set”) // RELAY 4
{
if(switch1 == “ON”)
{
digitalWrite(PinsD[0], LOW);//wired to the NO (ie default is on, actuate for on)
digitalWrite(PinsD[1], LOW);
client.publish(“ha/speakerswitch/F1” , “ON” ); // confirm action performed to the state topic
}
else
{
digitalWrite(PinsD[0], HIGH);//wired to the NO (ie default is on, actuate for on)
digitalWrite(PinsD[1], HIGH);
client.publish(“ha/speakerswitch/F1” , “OFF” ); // confirm action performed to the state topic
}
}
}

void reconnect() {
// Loop until we’re reconnected
while (!client.connected()) {
Serial.print(“Attempting MQTT connection…”);
// Attempt to connect
if (client.connect(client_name)) {
Serial.println(“connected”);
// Once connected, publish an announcement…
client.subscribe(“ha/speakerswitch/#”);
} else {
Serial.print(“failed, rc=”);
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}

void loop() {
if (!client.connected()) {
Serial.println(" not connected - will try agin - calling reconect");
reconnect();
}
client.loop();

unsigned long currentMillis = millis();

    }

CODIGO Hassio

switch:

  • platform: mqtt
    name: “speakerBar”
    state_topic: “ha/speakerswitch/fG”
    command_topic: “ha/speakerswitch/fG/set”
    qos: 0
    payload_on: “ON”
    payload_off: “OFF”
    optimistic: false
    retain: true

switch 2:

platform: mqtt
name: "speakerBar2"
state_topic: "ha/speakerswitch/DB"
command_topic: "ha/speakerswitch/DB/set"
qos: 0
payload_on: "ON"
payload_off: "OFF"
optimistic: false
retain: true

switch 3:

platform: mqtt
name: "speakerBar3"
state_topic: "ha/speakerswitch/zc"
command_topic: "ha/speakerswitch/zc/set"
qos: 0
payload_on: "ON"
payload_off: "OFF"
optimistic: false
retain: true    

switch 4:

platform: mqtt
name: "speakerBar4"
state_topic: "ha/speakerswitch/F1"
command_topic: "ha/speakerswitch/F1/set"
qos: 0
payload_on: "ON"
payload_off: "OFF"
optimistic: false
retain: true

2 choices in my opinion:

  1. Have the logic in homeassistant - and use an automation or a script to turn on and then turn off (after a small delay) the relevant switch through mqtt. This would require you to only use homeassistant to trigger the switch. If you use a script, you could show the script as your “switch” in homeassistant.

  2. Change the logic in the arduino sketch for the relevant switch to turn on then off after an appropriate delay. If you did this, look in the section that includes turning on the switch (ie with the digitalWrite commands for the pin controlling the relay), and adjust as you see fit. This would mean anything could send an mqtt message and the arduino would treat it consistently.

Hello Phil,

I tried several times with multiple configurations to get an automation working, weird case the switches work but the automation doesn´t, what i see is that the entities do not show up in the list of entities nor the mqtt integration, it says it doesn´t have devices, any clue?

Hey Guy
I need a help. My house have 2 arduinos mega some broadlinks and now I am using Home assistant. I have more then 70 reles and sensore. the arduinos board are connected on net via lan. My question is: How can I control arduino pins by Home assistant. I need control if the pin is High or Low. But I have no Idea I try some tutoriais but nothing is work. Someone can help me?

Hi Phil,

I am using your code , and it is working fine , but can I you give help in the part of the dht , I do not know how to put de topic of the dht in sensor.yaml.

Can you send me example of your?

Normaly I use tasmota on nodemcu and It is a lot more easy to use.

thanks
best regards
Rui Machado

Hi @ruighionis

If you used my code for arduino, here is what I have for the sensors from the DHT:

  - platform: mqtt
    state_topic: "ha/speakerswitch/temperature"
    name: "Speaker Temperature"
    unit_of_measurement: "°C"
    value_template: '{{ value | round(1) }}'
  - platform: mqtt
    state_topic: "ha/speakerswitch/humidity"
    name: "Speaker Humidity"
    unit_of_measurement: "%"
    value_template: '{{ value | round(0) }}'

Hope it helps - it is updating from the mqtt topic defined in the arduino sketch and converting it into a number.

Phil

Hello Phil,

Thank you very mutch.

Greetings
Rui Machado

Hi guys, I’m pretty new to HA. I’ve bought the things shown om the picture that was posted earlier, only my relayboard has 16 channels.

Do you know a tutorial (preferably a video) how I should program this?

1 Like

Hello, for those coming here from a search engine, a solution for Arduino Ethernet is OpenMQTTGateway. You do not have to code, only to uncomment the lines with the feature you want and set the pins. For outputs you don’t even have to set them in the code, it works directly from MQTT message.
And for input you have auto-discovery in Home Assistant :slight_smile: