Go Down

Topic: Alarm / Zeitschaltuhr (Read 8728 times) previous topic - next topic

Gerlitschka

Hallo, bin ja noch Anfänger bei dem programmieren der Andruino. Kann mir jemand sagen, wie ich am besten den Alarm für Temperatur zu Warm und zu kalt einbinde? Ich dachte mir es so, aber klappte nicht wirklich! Nutze den DS18B20.

Code: [Select]
If (Thermometer_1 < 24)
 {
   lcd.setCursor(0, 0);
   lcd.print("Alarm zu kalt");
  }

If (Thermometer_1 > 27)
 {
   lcd.setCursor(0, 0);
   lcd.print("Alarm zu warm");
  }





Code: [Select]
//////########################################## ANFANG WICHTIGE DATEN ############################### \\\\\\\\
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>
#include <Wire.h>
#include "RTClib.h"
#define ONE_WIRE_BUS 12
OneWire oneWire(ONE_WIRE_BUS);
LiquidCrystal lcd(10, 11, 5, 4, 3, 2);
DallasTemperature sensors(&oneWire);
DeviceAddress Thermometer_1 = { 0x28, 0xC0, 0x8B, 0xDB, 0x02, 0x00, 0x00, 0xE0 };
DeviceAddress Thermometer_2 = { 0x28, 0x51, 0xE0, 0xB6, 0x02, 0x00, 0x00, 0xA };
DeviceAddress Thermometer_3 = { 0x28, 0x27, 0x7B, 0xDB, 0x02, 0x00, 0x00, 0xEA };
RTC_DS1307 RTC;
//////########################################## ANFANG WICHTIGE DATEN ###############################









//////########################################## ANFANG SETUP ###############################
void setup(void)
{
 Serial.begin(9600);
 sensors.begin();
 lcd.begin(20, 4);
 Wire.begin();
 RTC.begin();
 sensors.setResolution(Thermometer_1, 10);
 sensors.setResolution(Thermometer_2, 10);
 sensors.setResolution(Thermometer_3, 10);
 if (! RTC.isrunning()) {
   Serial.println("RTC is NOT running!");
   // following line sets the RTC to the date & time this sketch was compiled
   //RTC.adjust(DateTime(__DATE__, __TIME__));
}
}
//////########################################## ENDE SETUP ###############################




//////########################################## ANFANG WICHTIGE DATEN TEMPERATURSENSOR ###############################
void printTemperature(DeviceAddress deviceAddress)
{
 float tempC = sensors.getTempC(deviceAddress);
 if (tempC == -127.00)
 {
   Serial.print("Error getting temperature");
   lcd.setCursor(0, 0);
   lcd.print("Error getting temperature");
 }
 else
 {
   Serial.print("C");
   Serial.print(tempC);
   lcd.print(tempC);
 }  
}
//////########################################## ENDE WICHTIGE DATEN TEMPERATURSENSOR ###############################



//////########################################## ANFANG LOOP ###############################
void loop(void)
{
 Serial.print("Getting temperatures...\n\r");
 sensors.requestTemperatures();
 
 Serial.print("Temp.1: ");
 lcd.setCursor(0, 1);
 lcd.print("Becken  ");
 printTemperature(Thermometer_1);
 lcd.print("C");
 Serial.print("\n\r");
 
 
 Serial.print("Temp.2: ");
 lcd.setCursor(0, 2);
 lcd.print("Technik ");
 printTemperature(Thermometer_2);
 lcd.print("C");
 Serial.print("\n\r");
 
 
 Serial.print("Temp.3: ");
 lcd.setCursor(0, 3);
 lcd.print("Raumtem ");
 printTemperature(Thermometer_3);
 lcd.print("C");
 Serial.print("\n\r\n\r");
 
 
 
 
 
   DateTime now = RTC.now();

   Serial.print(now.year(), DEC);
   Serial.print('/');
   Serial.print(now.month(), DEC);
   Serial.print('/');
   Serial.print(now.day(), DEC);
   Serial.print(' ');
   Serial.print(now.hour(), DEC);
   Serial.print(':');
   Serial.print(now.minute(), DEC);
   Serial.print(':');
   Serial.print(now.second(), DEC);
   Serial.println();
   
   lcd.setCursor(12, 0);
   lcd.print(now.hour(), DEC);
   lcd.print(':');
   lcd.print(now.minute(), DEC);
   lcd.print(':');
   lcd.print(now.second(), DEC);

   Serial.print(" since 1970 = ");
   Serial.print(now.unixtime());
   Serial.print("s = ");
   Serial.print(now.unixtime() / 86400L);
   Serial.println("d");

   // calculate a date which is 7 days and 30 seconds into the future
   DateTime future (now.unixtime() + 7 * 86400L + 30);

   Serial.print(" now + 7d + 30s: ");
   Serial.print(future.year(), DEC);
   Serial.print('/');
   Serial.print(future.month(), DEC);
   Serial.print('/');
   Serial.print(future.day(), DEC);
   Serial.print(' ');
   Serial.print(future.hour(), DEC);
   Serial.print(':');
   Serial.print(future.minute(), DEC);
   Serial.print(':');
   Serial.print(future.second(), DEC);
   Serial.println();

}
//////########################################## ENDE LOOP ###############################



Des weiteren, wollte ich 3-4 Ausgänge mit einer Zeitschaltuhr versehen, leider stehe ich total auf dem Schlauch. Kann mir jemand ein kleinen Tipp geben?

Grüße Timo

TelosNox

Thermometer_1 ist ja nur die Adresse von deinem Sensor. Wenn du jetzt schaust, ob die Adresse vom Sensor < 24 ist, dann ist das ja Käse. Du willst doch den Messwert des Sensors prüfen.


float tempC = sensors.getTempC(Thermometer_1);
if (tempC < 24) {
lcd.setCursor(0, 0);
lcd.print("Alarm zu kalt");
} else if (tempC > 27)  {
lcd.setCursor(0, 0);
lcd.print("Alarm zu warm");
}


Damit du nicht öfter als nötig die Temperaturen aus dem Sensor ausliest, solltest du das auslesen aus printTemperature() rausnehmen und die Temperaturen lieber direkt in einer Variablen speichern und an printTemperature dann die Temperatur übergeben.

Gerlitschka

Vielen Danke TelosNox,
Funktioniert einwandfrei ;)
Jetzt nochmal an die Zeitschaltuhr klemmen!
Grüße

Gurkengraeber

Quote
Jetzt nochmal an die Zeitschaltuhr klemmen!


@Gerlitschka: Du willst jetzt nicht wirklich den "temperatur-gesteuerten Arduino" an eine Zeitschalt-Uhr hängen ?
Ich hoffe, ich habe das falsch verstanden  :smiley-eek: !

Die Zeitschalt-Uhr programmierst du natürlich auch mit dem Arduino ( mit dem selben Modul - damit keine miss-Verständnisse aufkommen ).
Und dazu programmierst du natürlich noch etwas Komfort ( keine Ahnung zu welchem Zweck du das brauchst ) z.B.:
* Ein/Aus wird über LED angezeigt.
* Über- oder Unter-Temperatur löst Alarm aus ( Vorsicht die Beeper sind verdammt laut !)


TelosNox

Also so wie ich das lese hab ich ihn schon so verstanden, dass er selbst die Zeitschaltuhr realisieren will.

Dazu hast du 2 Möglichkeiten.

1. Du misst mit dem Arduino die Zeit (Millisekunden zählen) und hast ihn dauerhaft am laufen. Dann musst du allerdings dafür sorgen, dass er korrekt resettet (wenn der Millisekundenzähler überläuft) und hast Probleme, wenn er mal ausfallen sollte und sich resettet.

2. Du organisierst die Uhr irgendwie extern mit eigener Batterie und liest dort die Uhrzeit aus. Das wäre meiner Meinung nach die sicherere Methode. Allerdings weiß ich da nicht, wie man das umsetzen sollte. Vielleicht spuckt ja Google was aus.

kurti

#5
Aug 02, 2011, 09:47 pm Last Edit: Aug 03, 2011, 06:26 am by kurti Reason: 1
dann eben nicht ...
Zitat Jurs: falsche Verkabelung ist sowieso immer wenig förderlich für das Funktionieren der Hardware



hier könnte Ihre Werbung stehen

Gerlitschka

#6
Aug 02, 2011, 11:26 pm Last Edit: Aug 02, 2011, 11:33 pm by Gerlitschka Reason: 1
Haha, ich will die Zeitschaltuhr schon über den Arduinomachen. Hab den DS1307 Rtc am laufen, via Code oben, aber weiss nicht ganz wie ich die Schaltzeiten programmiere. Die Uhrzeit läuft. Danke
Achja, gibt es eine Möglichkeit SetCursor zb auf 20,1 zu setzen und zb den Text somit rechts bündig zu machen?

bytzmaster


Achja, gibt es eine Möglichkeit SetCursor zb auf 20,1 zu setzen und zb den Text somit rechts bündig zu machen?


Einfach ein paar Leerzeichen vorne weg setzen, dass er nach rechts rückt. Das ist die einfachste Lösung.

TelosNox

Man kann die LCD Lib auch so setzen, dass sie von rechts nach links schreibt. Dann musst du aber auch alles, was du schreibst, invertieren, damit es wieder richtig rum da steht.
Einfacher ist die Länge der Ausgabe zu berechnen und den Startcursor richtig zu setzen (Leerzeichen sind nicht nötig).

Was die Zeitschaltung angeht:

DateTime now = RTC.now();

    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();


Da liest du doch schon Jahre, Tage, Stunden u.s.w. aus.
Wenn die Zeitschaltuhr jeden Tag um 8:00 einschalten soll, dann prüfst du dort, ob sie noch nicht eingeschaltet ist (in globaler Variable speichern) und ob 8:00 vorüber ist (also ob Stunden >= 8 und Minuten >= 0). Wenn ja, einschalten und Variable setzen. Ähnlich verfährst du mit ausschalten (Uhrzeit erreicht und ist noch eingeschaltet).
Brauchst du am Tag mehrere Schaltvorgänge, dann musst du dir merken, bei welchem Schaltvorgang du gerade bist. Dann reicht kein einfacher boolean mehr zum ein/ausschalten sondern du brauchst noch einen Zähler, der dir sagt, bei welchem der eingetragenen Zeitintervalle du bist.

Beispiel:
1 = 8:00 einschalten, 9:00 ausschalten
2 = 14:00 einschalten, 16:00 auschalten
3 = 20:00 einschalten, 1:00 ausschalten


if (status == 1 && !eingeschaltet && stunde >= 8 && minute >= 0){
  digitalWrite(zeitschaltpin, HIGH);
} else if (status == 1 && eingeschaltet && stunde >= 9 && minute >= 0){
  digitalWrite(zeitschaltpin, LOW);
} else if (status == 2 && !eingeschaltet && stunde >= 14 && minute >= 0){
...

so in der Art.
Den status würde ich persönlich aber dann mit einem switch durchgehen.
Also:

switch(status) {
case 1:
if (!eingeschaltet && stunde >= 8 && minute >= 0){
  digitalWrite(zeitschaltpin, HIGH);
} else if (&& eingeschaltet && stunde >= 9 && minute >= 0){
  digitalWrite(zeitschaltpin, LOW);
break;

case 2:
if (!eingeschaltet && stunde >= 14 && minute >= 0){
}
break;
}


ACHTUNG:
Mein code berücksichtigt bisher nicht den jeweiligen Sprung der Minuten bei der vollen Stunde. Das müsste man auch noch regeln.
Das lässt sich aber auch einfach lösen, indem man die Uhrzeiten nicht direkt nimmt, sondern in minuten umwandelt. 8:00 wäre dann 420 minuten. Die aktuelle Uhrzeit auch in Minuten umrechnen und nur noch die Minuten vergleichen.

Dann bleibt noch ein letztes Problem. Der 0:00 Durchgang. Wenn ich vor 0:00 einschalte und nach 0:00 ausschalten will, hab ich ein Problem. Denn 20:00 ist größer als 1:00.
Eine mögliche Lösung wäre den Ausschaltzeitpunkt nicht explizit zu nehmen, sondern nur das Zeitintervall bis zum Ausschaltzeitpunkt zu ermitteln (also 240min eingeschaltet bleiben). Dann müsste man halt irgendwie zählen, wieviel Zeit seit dem Einschalten vergangen ist (z.B. indem man den aktuellen Minutenwert abspeichert und immer wenn sich der Minutenwert ändert addiert man das zu den bereits vergangenen Minuten und vergleicht dann die vergangenen Minuten mit dem Zeitintervall. Natürlich muss man die vergangenen Minuten immer beim Einschalten resetten.

Ob das die Ideale Lösung ist, weiß ich nicht, aber so auf die Schnelle wäre das jetzt mal meine erste Idee. Vielleicht hilfts dir ja für den ersten Ansatz.

Gerlitschka

Danke für deine Idee, aber bin zufällig über eine Info von Uwe geflogen :D


Code: [Select]
//Ich möchte um 8 Uhr an schalten und um 23.30 aus!


//8 * 60 + 0 = 480 an!

//23 * 60 + 30 = 1410 aus!




void loop(void)
{

  DateTime now = RTC.now();

    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();


    now.hours * 60 + now.minute = Minutenuhrzeit

    if ( ((480 < 1410) && (Minutenuhrzeit >= 1410)) || ((480 >= 1410) && (Minutenuhrzeit < 480) && (Minutenuhrzeit >= 1410) )
  {
    digitalWrite(Schaltpin, LOW);
  }

  else

  {
    digitalWrite(Schaltpin, HIGH);
  }
}


Werde das jetzt gleich mal testen :D vielleicht klappt es =)

TelosNox


if (
  (
    (480 < 1410)
    &&
    (Minutenuhrzeit >= 1410)
  )
  ||
  (
    (480 >= 1410)
    &&
    (Minutenuhrzeit < 480)
    && (Minutenuhrzeit >= 1410)
  )


1. dir fehlt am Ende eine schließende Klammer
2. kann der Teil nach dem "oder" niemals true sein, weil schon die erste Klammer nicht true sein kann. Außerdem kann Minutenuhrzeit niemals < 480 und gleichzeitig >= 1410 sein.
3. Wir die Uhr um 0:00 einschalten und um 23:30 ausschalten.

Im Endeffekt ist die Version von Uwe ja das, was ich am Ende meines Posts erwähnt habe. Du musst die Stunden in Minuten umrechnen und diese Werte vergleichen. Du musst aber auch irgendwie noch mit dem Überlauf um 0:00 umgehen (außer deine Zeiten gehen nie über 0:00 hinaus, dann ist es egal).

Hier mal noch die richtige Version deiner Bedingung zum einschalten:

if (minutenUhrzeit >= 480 && minutenUhrzeit < 1410) {
  digitalWrite(SCHALTPIN, HIGH);
} else {
  digitalWrite(SCHALTPIN, LOW);
}

MueThoS

Hallo zusammen,
ich würde es noch etwas anders machen.
Bei den gewünschten Zeiten würde ich mit angeben ob die Zeit zum ein oder zum ausschalten ist.
also 23:00 1 = um 23 Uhr einschalten
und 01:00 0 = um 1 uhr ausschalten
Dann ist es dem System auch egal wann es aktiviert wird (reset zb).
Ich meine das machen auch gekaufte Schaltuhren zum Teil so.

Wenn 1 uhr ist dann wird abgeschaltet weil ich um 1 das Licht aus haben will und nicht weil irgendwann es angegangen ist.
Ist besonders dann wichtig wenn zB nur ein Funksignal an eine Funksteckdose geschickt wird weil ich da ja garnicht weiß ob das Licht gerade an ist oder nicht. Ich weiß aber das ich es aus haben will!

Denke ich zumindest...  :)

Gerlitschka

Stimmt nicht ganz, weil wenn um 1 mein Licht angeschalten wird und um 2 mein arduino resettet wird, wird das Licht nicht in dem richtigen zustand gesetzt!

MueThoS

Das ist richtig.
Die Frage ist wie wichtig ist das?
Ich sag mal beim Aquarium sollte natürlich das Licht in der Zeit wo es an sein sollte auch so lange wie möglich an sein.
Aber mal angenommen es ist nur eine Anwesenheitssimulation dann ist es nicht so tragisch obs mal etwas länger aus ist wie geplant.

Es ist aber eben auch eine Frage der Ansteuerung.
Wenn du sehen kannst obs gerade an ist und es auch an sein sollte kannst du nach einem reset den Status wieder anpassen.
Kannst du das nicht und es ist auch nicht so tragisch wäre mir das erstmal egal und wenn der nächste Schaltzeitpunkt kommt schalte ich einfach in den gewünschten Zustand egal was vorher war.

Hängt halt von den Anforderungen ab.
Und war auch nur ein Gedanke der mir so durch den Kopf geschossen ist.

Noch ein kleines Beispiel:
Rollos. Die Zeituhren fahren um z.B. um 18 Uhr runter egal ob du um 17:45 das schon von Hand getan hast.
Das meinte ich damit.

Gruß
Thorsten

TelosNox

Also mir wäre es wichtiger, dass das System sicher und zuverlässig den gewünschten Zustand hält, als den Code um 3 Zeilen einfacher zu haben.

Was ist, wenn ich um 23:00 einschalten soll, aber 23:00 gar nicht eintritt, weil mein Arduino zufällig 60sec irgendwas am rechnen ist und erst um 23:01 das nächste mal prüft, ob er einschalten soll? Dann hat er 23:00 verpasst und schaltet nicht ein.

Daher MUSS ich immer den Zeitraum betrachten und nicht nur den Einschaltzeitpunkt (Reset wurde ja auch noch als Fehlerquelle angeführt).

Wie ich bereits erwähnte, kann man den 0:00 Durchgang mit gescheitem Code lösen. Und das sollte man auch machen. Der Grundsätzliche Ansatz ist ja: if (einschaltMinuten <= aktuelleZeitMinuten < ausschaltMinuten) { einschalten } else { ausschalten }
Jetzt muss man halt zusätzlich noch testen, ob ausschaltMinuten < einschaltMinuten ist. In dem Fall muss man invertieren.

if (einschaltMinuten < ausschaltMinuten) {
  if (einschaltMinuten <= aktuelleZeitMinuten && aktuelleZeitMinuten < ausschaltMinuten) {
    //einschalten
  } else {
    //ausschalten
  }
} else {
  if (ausschaltMinuten <= aktuelleZeitMinuten && aktuelleZeitMinuten < einschaltMinuten) {
    //ausschalten
  } else {
    //einschalten
  }
}


Ich denke so müsste es zuverlässig funktionieren, auch nach einem Reset

Go Up