Integracja Arduino Mega + Ethernet Shield z HA przez MQTT

Na razie zajmuję się jednym projektem. Obecny projekt rozpocząłem 1 lutego i do dzisiaj jeszcze testuję to rozwiązanie. Nie da się od tak w jeden dzień zrobić tak złożony projekt…Piałem, że obsługę przycisków będę robił w późniejszym czasie w innym projekcie. W obecnym masz przykładowe wywołanie przycisku na bazie kontaktronu. Można to analogicznie zastosować do przycisku. Wtedy w automatyzacji wykrywa wciśnięcie przycisku i zapala światło - załącza przekaźnik.

Przy połączeniu przez ethernet shield wpisujemy adres serwera mqtt a login i hasło tez należy wpisać?
Jeśli tak jaka powinny wyglądać wpisy.

To zależy czy w konfiguracji serwera MQTT masz wpisane login i hasło. W przypadku AIS i Mosquito nie ma potrzeby wpisywania i działa tak jak w moim projekcie czyli zmieniamy tylko adres IP serwera MQTT.

Sprawdzi mi ktoś poprawność kodu ?
/
*Example MQTT-switch-relay-node with 4 buttons and 4 relays

  - connects to an MQTT server
  - subscribes to the topic "relay"
  - controls 4 relays
  - reads 4 button
  - turns on/off a specific relay when it receives a specific "on"/"off" from the "relay" topic
  - sends a specific "on"/"off" to the "relay" topic a specific button is pressed
  - multiple arduino's with same generic sketch can run parallel to each other
  - multiple arduino's need each to have a unique ip-addres, unique mac address and unique MQTT client-ID
  - control DHT11 sensor temperature and humidity sensor
  - control PIR sensor HC-SR501HC - NEED TO CHECK!
  - led for PIR sensor (showing activity) 
  - tested on arduino-mega with W5100 ethernet shield -  NEED more testing!
  - Ethernet Shield W5100
*/

//------------------------------------------------------------------------------

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <Bounce2.h>
#include "DHT.h"

// --- temp/hum sensor --//
#define DHTPIN 11     // what pin we're connected to
#define humidity_topic "home/humidity1"
#define temperature_topic "home/temperature1"
#define DHTTYPE DHT22 
DHT dht(DHTPIN, DHTTYPE);


// Set relay variables to Arduino digital pins
int relay1 = 2;
int relay2 = 3;
int relay3 = 5;                             // pin 4 used by ethernet shield
int relay4 = 6;
int relay5 = 7;
int relay6 = 8;
int relay7 = 9;
int relay8 = 31;


// Set button variables to Arduino digital pins
int button1 = 22;
int button2 = 24;
int button3 = 26;
int button4 = 28;                         // pins 0,1,4,10,50,51,52,53 used by ethernetshield
int button5 = 30;
int button6 = 32;
int button7 = 34;
int button8 = 36;

// Set variables to act as virtual switches
// Set variable values initially to LOW (and not HIGH)
int relay1Value = LOW;             
int relay2Value = LOW;
int relay3Value = LOW;
int relay4Value = LOW;
int relay5Value = LOW;
int relay6Value = LOW;
int relay7Value = LOW;
int relay8Value = LOW;


//---------------------------------------------------------------------------

// Arduino MAC address is on a sticker on your Ethernet shield
// must be unique for every node in same network
// To make a new unique address change last letter

byte mac[]    = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEE };  

// Unique static IP address of this Arduino - change to adapt to your network
IPAddress ip(192,168,100,50);

// IP Address of your MQTT broker - change to adapt to your network
IPAddress server(192, 168, 100, xx);
#define MY_MQTT_USER "moj login"
#define MY_MQTT_PASSWORD "moje haslo"
char message_buff[100]; // this buffers our incoming messages so we can do something on certain commands

EthernetClient ethClient;
PubSubClient client(ethClient);
long lastReconnectAttempt = 0;

boolean reconnect() {
  //Serial.print("Attempting MQTT connection...");
   if (client.connect("ethClient", "mqtt", "xxx")) {
    // Once connected, publish an announcement...
    client.publish("home","connected");
    Serial.println("connected");
    // ... and resubscribe
    client.subscribe("home/#");
  }
  else {
      Serial.print("fairelay, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  return client.connected();

}
// Handle and convert incoming MQTT messages ----------------------------------------

void callback(char* topic, byte* payload, unsigned int length) {
  // handle message arrived
  String content="";
  char character;
  for (int num=0;num<length;num++) {
      character = payload[num];
      content.concat(character);
  }   
  Serial.println(topic);
  Serial.println(content); // message sent out by button actions is returned from broker and serial printed


// Set specific virtual switches on basis of specific incoming messages ----------------------------
  
  if (content == "1on") {
    relay1Value = HIGH;
  }
  
  if (content == "1off") {
    relay1Value = LOW;
  }
  
  if (content == "2on") {
    relay2Value = HIGH;
  }
  
  if (content == "2off") {
    relay2Value = LOW;
  }
  
  if (content == "3on") {
    relay3Value = HIGH;
  }
  
  if (content == "3off") {
    relay3Value = LOW;
  }
  
  if (content == "4on") {
    relay4Value = HIGH;
  }
  
  if (content == "4off") {
    relay4Value = LOW;
  }
   if (content == "5on") {
    relay4Value = HIGH;
  }
  
  if (content == "5off") {
    relay4Value = LOW;
  }
   if (content == "6on") {
    relay4Value = HIGH;
  }
  
  if (content == "6off") {
    relay4Value = LOW;
  }
   if (content == "7on") {
    relay4Value = HIGH;
  }
  
  if (content == "7off") {
    relay4Value = LOW;
  }
   if (content == "8on") {
    relay4Value = HIGH;
  }
  
  if (content == "8off") {
    relay4Value = LOW;
  }
  // Set digital pin states according to virtual switch settings
    
  digitalWrite(relay1,relay1Value);
  digitalWrite(relay2,relay2Value);
  digitalWrite(relay3,relay3Value);
  digitalWrite(relay4,relay4Value);
  digitalWrite(relay5,relay5Value);
  digitalWrite(relay6,relay6Value);
  digitalWrite(relay7,relay7Value);
  digitalWrite(relay8,relay8Value);

}

// Initiate instances -----------------------------------


// Initiate a bouncer instance for each button
Bounce bouncer1 = Bounce();
Bounce bouncer2 = Bounce();
Bounce bouncer3 = Bounce();
Bounce bouncer4 = Bounce();
Bounce bouncer5 = Bounce();
Bounce bouncer6 = Bounce();
Bounce bouncer7 = Bounce();
Bounce bouncer8 = Bounce();

//-------------------------------------------------------

void setup()

{

  // setup relay, button, bouncer 1 -----------------------
  pinMode(relay1, OUTPUT);
  pinMode(button1,INPUT);
  digitalWrite(button1,HIGH);
  bouncer1 .attach(button1);
  bouncer1 .interval(5);

  // setup relay, button, bouncer 2 -----------------------
  pinMode(relay2, OUTPUT);
  pinMode(button2,INPUT);
  digitalWrite(button2,HIGH);
  bouncer2 .attach(button2);
  bouncer2 .interval(5);

  // setup relay, button, bouncer 3 -----------------------
  pinMode(relay3, OUTPUT);
  pinMode(button3,INPUT);
  digitalWrite(button3,HIGH);
  bouncer3 .attach(button3);
  bouncer3 .interval(5);

  // setup relay, button, bouncer 4 -----------------------
  pinMode(relay4, OUTPUT);
  pinMode(button4,INPUT);
  digitalWrite(button4,HIGH);
  bouncer4 .attach(button4);
  bouncer4 .interval(5);

  // setup relay, button, bouncer 5 -----------------------
  pinMode(relay5, OUTPUT);
  pinMode(button5,INPUT);
  digitalWrite(button5,HIGH);
  bouncer5 .attach(button5);
  bouncer5 .interval(5);

  // setup relay, button, bouncer 6 -----------------------
  pinMode(relay6, OUTPUT);
  pinMode(button6,INPUT);
  digitalWrite(button6,HIGH);
  bouncer6 .attach(button6);
  bouncer6 .interval(5);

// setup relay, button, bouncer 7 -----------------------
  pinMode(relay7, OUTPUT);
  pinMode(button7,INPUT);
  digitalWrite(button7,HIGH);
  bouncer7 .attach(button7);
  bouncer7 .interval(5);

  // setup relay, button, bouncer 8 -----------------------
  pinMode(relay8, OUTPUT);
  pinMode(button8,INPUT);
  digitalWrite(button8,HIGH);
  bouncer8 .attach(button8);
  bouncer8 .interval(5);

  // setup serial and ethernet communications -------------------------------
// Setup serial connection
  Serial.begin(9600);

  // Setup ethernet connection to MQTT broker
  client.setServer("192.168.100.13", 1883);
  client.setCallback(callback);
  Ethernet.begin(mac, ip);
  delay(1500);
  lastReconnectAttempt = 0;
  Serial.println(Ethernet.localIP());


}

 
 
void loop()

{
    if (!client.connected()) {
    long now = millis();
    if (now - lastReconnectAttempt > 5000) {
      lastReconnectAttempt = now;
      // Attempt to reconnect
      if (reconnect()) {
        lastReconnectAttempt = 0;
      }
    }
  }
  else {
 client.loop();  } 
// Listen for button interactions and take actions ----------------------------------------  
// Note: Button actions do send MQTT message AND do set relay(x)Value to HIGH or LOW

  if (bouncer1.update()) {
    if (bouncer1.read() == HIGH) {
      if (relay1Value == LOW) {
        relay1Value = HIGH;
        client.publish("home/relay","1on");                
      } else {
        relay1Value = LOW;
        client.publish("home/relay","1off");
      }
    }
  }  

//-----------------------------------------------
  
  if (bouncer2.update()) {
    if (bouncer2.read() == HIGH) {
      if (relay2Value == LOW) {
        relay2Value = HIGH;
        client.publish("home/relay","2on");
      } else {
        relay2Value = LOW;
        client.publish("home/relay","2off");
      }
    }
  }  
  
//------------------------------------------------  

  if (bouncer3.update()) {
    if (bouncer3.read() == HIGH) {
      if (relay3Value == LOW) {
        relay3Value = HIGH;
        client.publish("home/relay","3on");
      } else {
        relay3Value = LOW;
        client.publish("home/relay","3off");
      }
    }
  }  

//-----------------------------------------------
  
  if (bouncer4.update()) {
    if (bouncer4.read() == HIGH) {
      if (relay4Value == LOW) {
        relay4Value = HIGH;
        client.publish("home/relay","4on");
      } else {
        relay4Value = LOW;
        client.publish("home/relay","4off");
      }
    }
  }  

//-----------------------------------------------
  
  if (bouncer5.update()) {
    if (bouncer5.read() == HIGH) {
      if (relay5Value == LOW) {
        relay5Value = HIGH;
        client.publish("home/relay","5on");
      } else {
        relay5Value = LOW;
        client.publish("home/relay","5off");
      }
    }
  }  
//-----------------------------------------------
  
  if (bouncer6.update()) {
    if (bouncer6.read() == HIGH) {
      if (relay6Value == LOW) {
        relay6Value = HIGH;
        client.publish("home/relay","6on");
      } else {
        relay6Value = LOW;
        client.publish("home/relay","6off");
      }
    }
  }  
//-----------------------------------------------
  
  if (bouncer7.update()) {
    if (bouncer7.read() == HIGH) {
      if (relay7Value == LOW) {
        relay7Value = HIGH;
        client.publish("home/relay","7on");
      } else {
        relay7Value = LOW;
        client.publish("home/relay","7off");
      }
    }
  }  

 //-----------------------------------------------
  
  if (bouncer8.update()) {
    if (bouncer8.read() == HIGH) {
      if (relay8Value == LOW) {
        relay8Value = HIGH;
        client.publish("home/relay","8on");
      } else {
        relay8Value = LOW;
        client.publish("home/relay","8off");
      }
    }
  }  


}


// End of sketch ---------------------------------



do tego w HA configuration.yaml mam wpisane:
switch:
    platform: mqtt
    name: "wlacznik 1"
    state_topic: "relay1"
    command_topic: "relay1"
    payload_on: "1on"
    payload_off: "1off"
    state_on: "1on"
    state_off: "1off"
    qos: 0
    retain: true`

Wgrałem to wszystko ale jakoś nie chce mi zatrybić

Załóż proszę nowy wątek jeśli nie korzystasz z mojego projektu. Zaśmiecasz…
Jeśli wklejasz kod to użyj </> bo w tym stanie to nikt Ci tego nie zweryfikuje bez wcięć i z pozmienianymi apostrofami… Wątek zrobił się mało przejrzysty bo trzeba przewijać kilka stron treści zamiast kod.
Zrób proszę to tak jak powinno być to zerknę na kod. Napisz też jaki mikrokontroler używasz bo bez tego trudno będzie.

Poprawiłem. Nie chciałem nowego zakładać wątku bo w sumie byłby ten sam tytuł.
CH340/ATmega2560

Kompiluje się bez problemu pod Arduino Mega 2560.
Ta biblioteka jest zbędna: #include <SPI.h> bo nie łączysz się z sensorami ani innymi mikrokontrolerami via SPI.
Powinno wszystko działać. Niestety nie będę swojego projektu rozpinał żeby sprawdzić czy wszystko działa. Masz jakieś błędy ? Co wyświetla w serial monitorze? Uruchamiałeś MQTT Explorer i sprawdzałeś czy wpisy pojawiają się w brokerze?

po wgraniu sketchu i podłączeniu fizycznie przekaźniki na wstępie powinny być wyłączone a świecą.
Mógłbym je spróbować fizycznie przyciskiem wyłączyć ale boję się że jeżeli skrypt źle się wgrał do uwalę Arduino

zainstalowałem ten mqtt explorer ale co gdzie szukac

Może jak jest nowe arduino to należy wgrać coś do niego na początku.
Wgrałem sketch z tego filmiku https://www.youtube.com/watch?v=PxS7yA272kU
U gościa po podłączeniu wszystkich elementów ze sobą żarówka zaświeciła się dopiero po użyciu przycisku a u mnie odrazu świeci.

Nic nie trzeba wgrywać, w Arduino IDE tylko biblioteki brakujące i tyle.

Jeśli masz odwrotnie niż w przykładzie to może oznaczać że sterowanie odbywa się stanem niskim zamiast wysokim trzeba pozmieniać z HIGH na LOW i odwrotnie.

No tak sterowanie mam niskim sygnałem. A on ma przekaźniki sterowane wysokim stanem. Ale w tym moim przykładzie jest chyba sterowanie stanem niskim.

Sterowanie jest stanem wysokim - HIGH

Ok podłączyłem przekaźnik HI. Zwierając chwilowo pin 22 z gnd powinno mi załączyć przekaźnik na pinie nr2.
Kicha nic się nie dzieje.
A to powinno działać nawet bez ethernet shield. Mam wrażenie że ten szkic się nie wgrywa.

Masz podobny komunikat czy jakieś błędy:

w MQTT explorer powinny pojawić się też wpisy: home/humidity1

Po wgraniu mam coś takiego. Próbuję wgrać twój szkic ale przy kompilacji mam błąd “too many decimal points in number”

Za dużo czerwonego… nie ma pełnego loga… może złą płytkę wybrałeś?

image

Pobierałeś z GitHuba mój projekt?

Projekt pobrałem z tej strony. Płytkę mam wybraną taka jak na scr

ale instalowałeś Arduino IDE bo jakieś dziwne wpisy są AVRDude…