Temperatur- und Verschlussüberwachung mittels Arduino 8


Wenn man so wie wir viele Netzwerkschränke in ganz Deutschland verteilt hat und diese alle per VPN mit der Hauptniederlassung verbunden sind, dann möchten wir schon wissen, wenn sich einer am Schrank zu schaffen macht. Wir haben nämlich Kollegen die gerne mal selber schauen möchten ob alles noch „in Ordnung“ ist. Oft passiert es das diese freundlichen und hilfsbereiten Kollegen eher das Gegenteil tun. Nach dem Motto „Das Internet ging nicht. Da hab ich mal beim Server den Stecker gezogen. Seid dem geht irgendwie nichts mehr“.

Auch haben wir Probleme mit Temperaturen. Gerade in den „älteren“ Niederlassungen befinden sich einfach zu kleine Netzwerkschränke ohne aktive Kühlung und mit viel zu vielen aktiven Bauteilen, wie Modem, Firewall, Server und Switchen. Letzteres hat gerade mit der Temperatur ein Problem und droht gerne mal auszufallen. Nun da wir nicht für jede Niederlassung ein SNMP fähiges Switch verbaut haben, kommt jetzt eine „Bastel“-Lösung via Arduino.

Folgende Aufgaben sollte meine Lösung können.
1. Temperatur und Verschluss überwachen. Und bei überschreiten der Temperatur oder beim öffnen des Netzwerkschrankes eine EMail an die EDV Abteilung senden.

2. Die Daten der Temperatur und des Magnetkontaktes via Modus an unsere Firmenübergreifende Gebäudeautomation senden.

3. Einen eigenen Webserver zu Verfügung stellen, um direkt die Daten einzusehen.

Nun drei Tage bastel-, Löt- und Programmierarbeit später kann ich einen Erfolg melden. Dat Ding geht!

BlackBox

Hier das Ergebnis. Eine kleine Box mit großem Inhalt

Inhalt der Blackbox

In dieser Blackbox befindet sich ein Arduino Uno, ein Netzwerkshield und eine kleine Platine zur Verteilung der Anschlüsse. An der Platine befinden sich zwei One-Wire Temperatursensoren, sowie ein Magnetkontakt.

Ansicht Platine

Vorteil der One-Wire Temperatursensoren. Diese belegen nur einen einzigen Digitalen Pin. Somit benötige ich lediglich zwei Digitale Pins für meine Aufgaben.


/*
*******************************************************************************
*******************************************************************************
*** Temperatur- und Verschlussüberwachung Bereich IT ***
*** ***
*** ***
*** Messung von 2 Temperaturzonen über das One-Wire Protokoll ***
*** sowie die Verschlussüberwachung durch einen Magnetkontakt. ***
*** ***
*** Bereitstellung der Daten über einen Internen Webserver ***
*** wie auch über das Modbusprotokoll für die interne Gebäudeautomation. ***
*** ***
*** Meldung von Temperaturüberschreitungen via Mail an definierte Empfänger ***
*** ***
*** Verbaute Schield's: ***
*** Etherntkarte ***
*** ***
*** Belegte Pin's ***
*** Digital PIN 2 = Temperatur Sensoren via One-Wire ***
*** Digital PIN 3 = Magnetkontakt ***
*******************************************************************************
*******************************************************************************
*/

/*
--------------------------------------
| Festlegung der benötigten Libaries |
--------------------------------------
*/
//Libary für die Ethernetkarte
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp.h>
#include <util.h>
#include <SPI.h>

// Libary für Modbus
#include <Mudbus.h>

//Libary für das One-Wire Protokoll
#include <OneWire.h>
//Libary für den Temperatursensor
#include <DallasTemperature.h>

/*
--------------------------------------
| Definition der Variablen |
--------------------------------------
*/

// ****** Hier die Ethernetconfig anpassen ******

// MAC Adresse für das Ethernetshield definieren.
// Achtung diese Adresse darf nicht doppelt im Netzwerk vorkommen
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x59, 0x67 };

// Definition der IP-Adresse
IPAddress ip( 192, 168, 178, 100 );
IPAddress gateway( 192, 168, 178, 1 ); //DNS und GATEWAY
IPAddress subnet( 255, 255, 255, 0 );

//IP des EMailservers
//byte mailserver[] = { xxxxxxxx}; // IP Mailserver ohne DNS
char mailserver[] = "xxxxxxxx; //Addresse bei DNS
EthernetClient client;
// Definition des Ethernetport des Webservers
EthernetServer server(80);

// Modbus aufrufen
Mudbus Mb;

// ****** Hier die Konfig des One-Wire-Bus

// Pin für One-Wire-Bus festelgen. Standart = 2
#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);

// One-Wire-Bus mit dem Temperatursensor verbinden
DallasTemperature sensors(&oneWire);

// ****** Hier die Digital Eingänge anpassen ******

// Pin für Magnetkontat festlegen. Standart = 3
int Magnetkontakt = 3;

// ***** Definition von Textvariablen *****
char Title [] = "Webserver DV11";
char Object [] = "DV11";

// **** Wichtige Daten
Hier stehen eigentlich die EMail Zugänge drin. Aus Sicherheit habe ich diese aber entfernt. Möchte ja schließlich nicht das einer diese hackt!

char hello [] = "EHLO xxxxxx";
char user [] = "xxxxxxxx";
char pwd [] = "xxxxxxxx";
char MailFrom [] = "MAIL From: xxxxxxxx";
char MailTo [] = "RCPT To: xxxxxxxx";
char SendTo [] = "To: BASTIAN xxxxxxxx";
char SendFrom[] = "From: xxxxxxxx";

// ***********

int flag = 0;
int flag1 = 0;
/*
--------------------------------------
| SETUP BEIM STARTEN DES ARDUINO'S |
--------------------------------------
*/
void setup(void)
{
 // PinMode für Magnetkontakt definieren
 pinMode(Magnetkontakt, INPUT);

//Serial initalisieren für das debugging
 Serial.begin(9600);

//Ethernetschnittstelle initalisieren
 Ethernet.begin(mac, ip, gateway, gateway, subnet);

//Temperaturabfrage initalisieren
 sensors.begin();
 delay(1000);
 //Webserver initalisieren
 server.begin();

//Warten bis alle Einstelungen übernommen wurden
 delay(5000);

Serial.print("Server startet at ");
 Serial.println(Ethernet.localIP());
}

/*
----------
| LOOP |
----------
*/

void loop(void)
{

// Temperaturwerte und Magnetkontakt auslesen
 sensors.requestTemperatures();
 float TemperatureId0 = sensors.getTempCByIndex(0);
 delay (500);
 float TemperatureId1 = sensors.getTempCByIndex(1);
 delay(500);
 int MagnetStatus = digitalRead(Magnetkontakt);

 //Webserver aufrufen und Werte übergeben
 EthernetClient client = server.available();
 if (client.available()) {
 Webservice(TemperatureId0, TemperatureId1, MagnetStatus);
 }
 Modbus(TemperatureId0, TemperatureId1, MagnetStatus);
 delay(250);
 if (MagnetStatus == 0 && flag == 0) {
 sendEmail (TemperatureId0, TemperatureId1, "magnet");
 flag = 1;
 Serial.println("Kontakt geoeffnet!");
 }
 if (MagnetStatus == 1 && flag == 1) {
 flag = 0;
 Serial.println("Kontakt geschlossen");
 }
 if (TemperatureId0 > 29.99 or TemperatureId1 > 29.99) {
 if (flag1 == 0) {
 Serial.println("Temperatur ueberschritten");
 Serial.println(flag1);
 sendEmail (TemperatureId0, TemperatureId1, "temperatur");
 flag1 = 1;
 } else {
 Serial.println(TemperatureId0);
 Serial.println(TemperatureId1);
 }

 }
 if (TemperatureId0 < 30.00 and TemperatureId1 < 30.00) {
 Serial.println(TemperatureId0);
 Serial.println(TemperatureId1);
 flag1 = 0;
 }

 //Debuggin
 //Serial.println(TemperatureId0);
 //Serial.println(TemperatureId1);
 //Serial.println(MagnetStatus);
 delay(1000);
}

/*
----------------
| Funktionen |
----------------
*/

/*
----------------
| Webserver |
----------------
*/
void Webservice(float Temp1, float Temp2, int Magnet) {
 EthernetClient client = server.available();
 //Debugging
 Serial.println(Temp1);
 Serial.println(Temp2);
 Serial.println(Magnet);
 //Webserver starten
 if (client) {
 Serial.println("new client");
 boolean currentLineIsBlank = true;
 while (client.connected()) {
 if (client.available()) {
 char c = client.read();
 Serial.write(c);
 if (c == '\n' && currentLineIsBlank) {
 client.println("HTTP/1.1 200 OK");
 client.println("Content-Type: text/html");
 client.println("Connection: close"); // the connection will be closed after completion of the response
 client.println("Refresh: 5"); // refresh the page automatically every 5 sec
 client.println();
 client.println("<!DOCTYPE HTML>");
 client.println("<html>");
 client.println("<head>");
 client.print("<title>");
 client.print(Title);
 client.print("</title>");
 client.println("</head><body>");
 client.print("Temperatur f&uuml;r Messpunkt 1: ");
 client.println(Temp1);
 client.println("<br />");
 client.print("Temperatur f&uuml;r Messpunkt 2: ");
 client.println(Temp2);
 client.println("<br />");
 if (Magnet == 0 ) {
 client.println("Kontakt ge&ouml;ffnet!");
 } else {
 client.println("Kontakt geschlossen!");
 }
 client.println("</body></html>");
 if (c == '\n') {
 // you're starting a new line
 currentLineIsBlank = true;
 } else if (c != '\r') {
 // you've gotten a character on the current line
 currentLineIsBlank = false;
 }
 // give the web browser time to receive the data
 delay(1000);
 // close the connection:
 client.stop();
 Serial.println("client disconnected");
 }
 }
 }
 }
}

/*
----------------
| Modbus |
----------------
*/

void Modbus(float Temp1, float Temp2, int Magnet) {
 //Modbus starten
 Mb.Run();

//Analog inputs 0-1023
 Mb.R[0] = Temp1;
 Mb.R[1] = Temp2;
 Mb.C[2] = Magnet;
}

/*
----------------
| Mailing |
----------------
*/

byte sendEmail(float Temp1, float Temp2, char action[])
{
 byte thisByte = 0;
 byte respCode;

if(client.connect(mailserver,25)) {
 Serial.println(F("connected"));
 } else {
 Serial.println(F("connection failed"));
 return 0;
 }

if(!eRcv()) return 0;
 Serial.println(F("Sending helo"));

// change to your public ip
 client.println(hello);

if(!eRcv()) return 0;
 Serial.println(F("Auth"));
 client.println(F("AUTH LOGIN"));
 Serial.println(F("user"));
 delay(500);
 client.println(user);
 Serial.println(F("pwd"));
 delay(500);
 client.println(pwd);
 if(!eRcv()) return 0;

 Serial.println(F("Sending From"));

// change to your email address (sender)
 client.println(MailFrom);

if(!eRcv()) return 0;

// change to recipient address
 Serial.println(F("Sending To"));
 client.println(MailTo);

if(!eRcv()) return 0;

Serial.println(F("Sending DATA"));
 client.println(F("DATA"));

if(!eRcv()) return 0;

Serial.println(F("Sending email"));

// change to recipient address
 client.println(SendTo);

// change to your address
 client.println(SendFrom);
 if (action == "temperatur") {
 client.println(F("Subject: Temperaturüberschreitung\r\n"));
 client.print(F("Die Temperatur im "));
 client.print(Object);
 client.println(F(" wurde überschritten."));
 client.print(Temp1);
 client.print(F("°C und "));
 client.print(Temp2);
 client.println(F("°C."));
 } else if (action == "magnet") {
 client.println(F("Subject: Zugriff auf Netzwerkschrank\r\n"));
 client.print(F("Der Netzwerkschrank "));
 client.print(Object);
 client.println(F(" wurde geöffnet!"));
 }

client.println(F("."));

if(!eRcv()) return 0;

Serial.println(F("Sending QUIT"));
 client.println(F("QUIT"));

if(!eRcv()) return 0;

client.stop();

Serial.println(F("disconnected"));

return 1;
}

byte eRcv()
{
 byte respCode;
 byte thisByte;
 int loopCount = 0;

while(!client.available()) {
 delay(1);
 loopCount++;

// if nothing received for 10 seconds, timeout
 if(loopCount > 10000) {
 client.stop();
 Serial.println(F("\r\nTimeout"));
 return 0;
 }
 }

respCode = client.peek();

while(client.available())
 {
 thisByte = client.read();
 Serial.write(thisByte);
 }

if(respCode >= '4')
 {
 efail();
 return 0;
 }

return 1;
}
void efail()
{
 byte thisByte = 0;
 int loopCount = 0;

client.println(F("QUIT"));

while(!client.available()) {
 delay(1);
 loopCount++;

// if nothing received for 10 seconds, timeout
 if(loopCount > 10000) {
 client.stop();
 Serial.println(F("\r\nTimeout"));
 return;
 }
 }

while(client.available())
 {
 thisByte = client.read();
 Serial.write(thisByte);
 }

client.stop();

Serial.println(F("disconnected"));
}

Hier das vollständige Script des Arduino.

Eigentlich ist es ganz einfach. Im oberen Bereich werden alle Variablen definiert und initialisiert. z.B. IP-Adressen, Passwörter oder Textvariablen.

In der Funktion Setup wird alles für den Arduino geladen. Im Loop werden die Temperatursensoren und der Magnetkontakt abgefragt und jedes mal in der Funktion Modus gespeichert. Hier stehen sie dann in den Registervariablen für die Gebäudeautomation zu Verfügung. Sobald sich ein Client auf dem Webserver anmeldet wird zusätzlich die Funktion Webserver ausgeführt. Dort werden ebenfalls die Variablen dargestellt und alle 5 sec aktualisiert.

Wird der Magketkonakt geöffnet oder übersteigt die Temperatur 30°C so wird die Funktion sendMail ausgeführt. Mit der Variable Action übergebe ich der Funktion zusätzlich was sie denn nun für eine EMail schreiben soll. Also Netzwerkschrank geöffnet oder Temperatur im Netzwerkschrank überschritten. Damit diese EMail nicht jedes mal im Loop ausgeführt wird (Das wäre ja eine EMailbome!) setze ich einen Flag für den Magnetkonatkt und einen Flag für die Temperatur. Wird als die Bedingung true und ist der Flag false (also 0) dann wird die EMail Funktion aufgerufen. Gleichzeitig wird der Flag aber auf true (also 1) gesetzt. Somit wird im nächsten durchlauf keine EMail gesendet. Der Flag wird erst auf false gesetzt bis die Bedingung auf false steht. Also Tempertur unter 30°C oder Magnetkontakt geschlossen.

Eigentlich ganz simpel. Aber man (also ich) musste sich doch ganz schön durch die Programmierung graben und alles aus tausend Beispielen ableiten! PUH. Aber Spass macht es 😀


Schreibe einen Kommentar zu Peter Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

8 Gedanken zu “Temperatur- und Verschlussüberwachung mittels Arduino

  • Christian

    Hallo,
    danke für diese super Beschreibung!
    Kannst du mir sagen, welche Modbus Library du genutzt hast?
    Dank dir & Gruß
    Christian

    • Bastian Strauß Autor des Beitrags

      Hi Christian,

      schau doch einfach bei mir im Sketch ->

      // Libary für Modbus
      #include Mudbus.h

      Und dann einfach bei google mudbus.h suchen. Ich glaube der zweite eintrag ist es schon!

      Gruß Bastian

  • Peter

    Hallo,

    ich wollte mal danke für dieses ausführliche Tut danke sagen – habe aber gleich mal eine anregung an dich.
    Überwache den Schrank nicht nur über einen magnetkontakt – schalte IN REIHE noch einen Türkontaktschalter (weißt schon die mit denen normal die schaltschrankbeleuchtung geschaltet wird)
    WIr haben oft das Problem gehabt dass die oben erwähnten freundlichen kollegen ihren Pinwand Magneten Mitnehmen und so die Tür-Offen-Meldung überbrücken. Auf die Idee den Türkontaktschalter mit Klebeband zusätzlich zu brücken ist noch keiner gekommen ^^ evtl weil die leute meinen „das ist doch für´s licht da“

    sind nur meine erfahrungen aus der zutrittskontrolle

    • Bastian Strauß Autor des Beitrags

      Hi Peter,

      Danke für Deinen Tipp. So schlimm sind unsere freundlichen Mitarbeiter dann doch nicht, dass Sie den Magneten nutzen 😀

  • Sven

    Hallo,
    ich bin über die IP-Symcon Seite auf Dein Script gestoßen. Sehr gut und durchdacht. Einen Verbesserungsvorschlag habe ich auf die Schnelle. Und Zwar wenn der Temperaturwert auf der Schwelle 29,99 und 30,00 ist, würde Dein Flag eventuell rasch wechseln. Als Idee kann man den TempGrenzwert in eine Variable setzten und das Flag erst:
    ****************
    if (TemperatureId0 < TempGrenzwert-1 and TemperatureId1 < TempGrenzwert-1) {
    Serial.println(TemperatureId0);
    Serial.println(TemperatureId1);
    flag1 = 0;
    }
    ****************
    LG
    //Sven