ArduinoMega + Relaisplatine, Tastereingänge, autark, optional MQTT über W5100

Begonnen von Rince, 22 Februar 2017, 16:55:20

Vorheriges Thema - Nächstes Thema

Rince

Edit:
Wollte das zunächst über USB machen, Ethernet ist doch schlauer, Thema angepasst

Hi,

gibt es was fertiges?

Ich brauche folgendes:
Arduino Mega
16-Relaisplatine (für Steckdosen und Lampen)
16 Eingänge (da hängen Taster dran)

Soll:
autark funktionieren (also ohne irgend einen Steuercomputer / Server)
Optional per USB an nem RasPi angeschlossen werden, so dass fhem über den Status der Relais bescheid weiß und die Relais auch schalten kann

Wichtig ist, dass das ganze auch ohne irgend einen anderen Server funktioniert. Nur Arduino + Strom.

Gibt es da etwas fertiges?
Wer zu meinen Posts eine Frage schreibt und auf eine Antwort wartet, ist hiermit herzlich eingeladen mich per PN darauf aufmerksam zu machen. (Bitte mit Link zum betreffenden Thread)

Beta-User

MySensors könnte sowas in die Richtung. Für einen teilautarken Betrieb muß aber eine Option definiert sein bzw. eine max. Wartezeit, siehe MY_TRANSPORT_WAIT_READY_MS.

Könntest Du als serielles GW umsetzen.

Homebrewired ging evtl. auch, da kenn e ich mich aber nicht aus.

Gruß, Beta-User
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Rince

#2
Mercy.

Nach einigem einlesen habe ich beschlossen, das mit dem USB zu streichen und ein W5100 Shield zu nehmen.
Nachdem es auch da nichts wirklich fertiges gibt, schreibe ich das Ding selber:

Beschreibung:
Arduino Mega
16x Relais Platine (5V Schaltspannung, nicht 12V), per Optokoppler isoliert
W5100 Ethernetshield

Zielsetzung:
Zu jedem Input Port soll ein Output Port zugeordnet sein
An den Inputs werden normale Taster angeschlossen
autarker Betrieb
Wenn per Netzwerk mit fhem verbunden, soll fhem den Zustand der Outputs kennen (Licht an / aus) sowie selber die Ports steuern können

Was geht bis jetzt:
Hardware:
läuft

Software:
Statemachine für die I/O Paare läuft
Umschalten Licht an / aus dementsprechend auch
Taster sind mit bis zu 20m an Cat 6 Kabel an Arduino Mega angeschlossen, 5V eingebauter PullUp, scheint auch zu laufen (kurzer Test war jedenfalls erfolgreich)
Debouncing wird gefiltert

Reconnect zum Broker läuft auch, non blocking
aktuellen state publishen => läuft auf Arduio Seite (bekomme ihn aber noch nicht in fhem sichtbar, ist andere Baustelle)

ToDo:
Subscriben der Topics und Einbau in die Schaltlogik

ToDo (später):
Absichern MQTT mit Username / Passwort

Ich nenne es mal Hausautomatisierung für Arme:
Die Mehrkosten / Taster belaufen sich quasi auf ca. 2 €...


Wenn jemand mit etwas Erfahrung im Umgang it GitHub hat, würde ich gerne den Code zur Verfügung stellen, damit wir gemeinsam daran basteln können. Ich denke, das macht mehr Sinn als ihn hier in einem Thread zu posten?

Wer zu meinen Posts eine Frage schreibt und auf eine Antwort wartet, ist hiermit herzlich eingeladen mich per PN darauf aufmerksam zu machen. (Bitte mit Link zum betreffenden Thread)

Rince

Falls es wen interessiert, hier mal mein aktueller Code:


/*
  Liesmich
  Gedacht für einen Arduino Mega
  16 Tastereingänge
  16 Relaisausgänge

  W5100 Ethernetshield

  MQTT (Nonblocking)

  Im Skript eigene Werte anpassen:
  byte mac
  IPAddess ip
  IPAdress server
 
  Taster taster_1(38, 22, InputTopic, OutputTopic); <= hier Input Pin und Output Pin angeben, Befehle werden von InputTopic angenommen, Zusatnd aufOutputTopic geschrieben
  Name ist im Prinzip egal;
  Wichtig ist, im Skript unter void loop() auch die Namen anpassen, bzw. nicht benötigte Aufrufe auszukommentieren
 



*/

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


// Update these with values suitable for your hardware/network.
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(192, 168, 5, 10);
IPAddress server(192, 168, 5, 2);

void callback(char* topic, byte* payload, unsigned int length) {
  // handle message arrived
}

EthernetClient ethClient;
PubSubClient client(ethClient);

long lastReconnectAttempt = 0;

boolean reconnect() {
  if (client.connect("arduinoClient1")) {
    // Once connected, publish an announcement...
    client.publish("outTopic","hello world");
    // ... and resubscribe
    client.subscribe("inTopic");
  }
  return client.connected();
}


class Taster
{
//Definieren der Namen für die Input PINs

int Input_PIN;


//Definieren der Namen für die Output Pins


int Output_PIN;

//Definieren der Sates
int state = HIGH;


//Readings der Input Pins
int reading;


//Previous Reading Input Pins
int previous = HIGH;


//Variablen für die Zeit
long debounce = 1500;
long time_1 = 0;


//String fuer Input und Output Topics
const char* InputTopic;
const char* OutputTopic;

//


public:
Taster(int input, int output, const char* mqttInput, const char* mqttOutput)
{
  Input_PIN = input;
  Output_PIN = output;
  pinMode(Input_PIN, INPUT_PULLUP);
  digitalWrite(Output_PIN, HIGH);  // verhindert das Schalten wenn der RelaisPin auf OUTPUT gesetzt wird
  pinMode(Output_PIN, OUTPUT);

 
  InputTopic = mqttInput;
  OutputTopic = mqttOutput;
 
}

void Update()
{
reading = digitalRead(Input_PIN);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  // habe LOW und HIGH umgedreht, um invertierter Logik gerecht zu werden
  // https://www.arduino.cc/en/tutorial/switch
 
  if (reading == LOW && previous == HIGH && millis() - time_1 > debounce) {
    if (state == LOW)
      state = HIGH;
    else
      state = LOW;

    time_1 = millis();
    Serial.println();
    Serial.println("*****");
    Serial.println("Arbeit!");
    Serial.println("Taster auf folgendem Pin");
    Serial.println(Input_PIN);
    Serial.println("Hat folgenden PIN geschaltet");
    Serial.println(Output_PIN);
    Serial.println("Die Laufzeit ist");
    Serial.println(time_1);
    Serial.println("Der Zustand des Output PINs ist jetzt");
    Serial.println(state);
    Serial.println("Achtung, fuer das Relais ist es invertiert!");
    Serial.println();
    Serial.println("Der wirkliche Status wurde in folgendes Topic published:");
    Serial.println(OutputTopic);

    digitalWrite(Output_PIN, state);
    previous = HIGH;

  if (state == LOW)
    client.publish(OutputTopic,"on");
  else
    client.publish(OutputTopic,"off");
  }
  //Hier kommt der Teil für MQTT subscribe
  //client.subscribe(InputTopic);

}
 
};

Taster taster_1(38, 22, "Wohnort/Wohnhaus/1_OG/Kueche/Licht/set", "Wohnort/Wohnhaus/1_OG/Kueche/Licht/state");
//Taster taster_2(39, 23);
//Taster taster_3(40, 24);
//Taster taster_4(41, 25);
//Taster taster_5(42, 26);
//Taster taster_6(43, 27);
//Taster taster_7(44, 28);
//Taster taster_8(45, 29);
//Taster taster_9(46, 30);
//Taster taster_10(47, 31);
//Taster taster_11(48, 32);
//Taster taster_12(49, 33);
//Taster taster_13(50, 34);
//Taster taster_14(51, 35);
////Taster taster_15(52, 36);
//Taster taster_16(53, 37);


void setup() {
  // put your setup code here, to run once:

//********************************************************************************
//******************** Ausgabe auf der seriellen Schnittstelle *******************
//********************************************************************************
  Serial.begin(9600);
  Serial.println("Configuration:");
  Serial.println(" ");
  Serial.println("Output: PIN 22 - 37");
  Serial.println("Jeder Output Pin wird bei Start des Aduinos auf HIGH gelegt");
  Serial.println("d.h. durch die Optokoppler auf der Relaisplatine gehen alle Lichter AUS");
  Serial.println(" ");
  Serial.println("Input: PIN 38 - 53");
  Serial.println("die Input Pins verwenden den eingebauten PullUp");
  Serial.println("d.h. es liegen immer 5V an");
  Serial.println("Ein Tasterdruck bewirkt einen Spannungsabfall und dann wird geschaltet");
  Serial.println(" ");
  Serial.println("Ethernet:");
  Serial.println("Die IP Adresse des Arduinos ist:");
  Serial.println(ip);
  Serial.println("Die MQTT Broker Adresse muss eingestellt sein auf:");
  Serial.println(server);
  Serial.println("der Reconnect ist non-blocking, ein Ausfall des MQTT Servers hat keine Konsequenzen");
  Serial.println("Prinzipiell braucht man also auch gar keinen");
  Serial.println("sobald er da ist, wird er nach spaetestens 5 Sekunden benutzt");
 


//*********************************************************************************
  client.setServer(server, 1883);
  client.setCallback(callback);

  Ethernet.begin(mac, ip);
  delay(1500);
  lastReconnectAttempt = 0;
//*********************************************************************************


 
}

void loop() {

//********** Prüfen, ob Verbindung besteht ***********************
if (!client.connected()) {
    long now = millis();
    if (now - lastReconnectAttempt > 5000) {
      lastReconnectAttempt = now;
      // Attempt to reconnect
      if (reconnect()) {
        lastReconnectAttempt = 0;
      }
    }
  } else {
    // Client connected

    client.loop();
  }
//*****************************************************************

taster_1.Update();
//taster_2.Update();
//taster_3.Update();
//taster_4.Update();
//taster_5.Update();
//taster_6.Update();
//taster_7.Update();
//taster_8.Update();
//taster_9.Update();
//taster_10.Update();
//taster_11.Update();
//taster_12.Update();
//taster_13.Update();
//taster_14.Update();
////taster_15.Update();
//taster_16.Update();






}
Wer zu meinen Posts eine Frage schreibt und auf eine Antwort wartet, ist hiermit herzlich eingeladen mich per PN darauf aufmerksam zu machen. (Bitte mit Link zum betreffenden Thread)