Lueftersteuerung um den Keller zu trocknen

Was ich nicht verstehe, wenn ich die Schematik richtig verstehe, (und es sieht von hinten auf der Platine auch so aus) sind die Pins 4,5,6,7 nicht mit der Schaltung des Shields verbunden, sondern werden nur durchgeschliffen, andererseits wieder: LiquidCrystal lcd(8, 9, 4, 5, 6, 7);. Ich verstehe es wirklich nicht.

Es werden diese PINs für das Keypad Shield benötigt: LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
Nutzte auch das Shield.

Dies hier musst du auf andere PINs verlegen:

#define dhtA 5
#define dhtI 6
#define relais 7

Für das Menü empfehle ich das hier: http://forum.arduino.cc/index.php/topic,73816.0.html

RTC kannst du dir sparen und selber programmieren oder mich fragen, ist genau so ungenau wie die 1307.

Welche Pin´s kann ich denn nehmen, bzw wo muss ich anlöten?

Ausserdem seh ich noch D10 , mit dem die Beleuchtung des LCD-Shields geschaltet wird.

Auf dem LCD Shield kannst du
an J5 die Signale D0..D3 und D11..D13 und
an J6 die Signale A1 .. A5 "frei" verwenden.

So lese ich jedenfalls deine pdf Datei...

Punkt 4 ist ganz einfach:

if(wert >= schaltpunkt + hysterese)
{
      Lüfter an
}
else if(wert < schaltpunkt - hysterese)
{
     Lüfter aus
}

Dann behält er innerhalb von 2 * hysterese seinen Zustand. "Schaltpunkt +/- Hysterese" kann man natürlich auch als eine Konstante schreiben

@Serenifly:

Mach dir mal keine Sorgen, mit

const int SCHALTPUNKT=100;
const int HYSTERESE = 20;

wird der Compiler auch SCHALTPUNKT+HYSTERESE direkt beim Compilieren ausrechnen und genauso wie 120 verwenden.

Ich war mehr um die Übersichtlichkeit als die Speicherverwendung besorgt :slight_smile:

Ist auch Geschmackssache hier. Eventuell braucht man das ja gar nicht getrennt.

So, ich hab jetzt die Sensoren an Pin 12 und 13 und das Relais an Pin 3 angelötet. jedoch springt das Relais nach wie vor ständig an?

:wink:
dann such doch mal, wie du statL verwendest :wink:

( Oder nimm die erste Stelle

  if(statL == 1)  //notwendig um Relais zu schalten!!
    {
      digitalWrite(relais, LOW);       
    }
    
    else
    {
      digitalWrite(relais, HIGH);        
    }

einfach mal weg :wink:

Julianchr, Deine Auflistung hat einen Fehler:
"2. Arduino R3 (China)"
Es gibt keinen Arduino R3 Made in China. Wenn Du ihn in China gekauft hast, ist es kein Arduino.
Grüße Uwe

Wie meinst du das mit dem Fehler in statL?

Ja, der Arduino ist eine Replik!

Nachtrag: Hab mal das Relais an PIN 11 gelötet, und siehe da es klappt :sweat_smile:
Pin 3 war wohl dorch irgendwie mit dem LCD verbunden

Wie meinst du das mit dem Fehler in statL?

Entweder du hast es inzwischen korrigiert oder ich hab mich verguckt. :wink:

( Sorry, klar. Ich muss mich wohl verguckt haben )

(statL=1) und digitalWrite(relais, LOW), sowie dessen Gegenteil, müssen immer zusammenpassen. Und das tun sie auch.

Allerdings fehlt die Hysterese, also ein Bereich, in dem nichts verändert wird, sondern nur der alte Zustand beibehalten wird.
Und mehrmals in loop() einen Digitalausgang setzen muss nicht falsch sein, könnte aber :wink:

Blinkt der "unbenutzte" Pin 3 denn jetzt ( wenn du eine LED mit Vorwiderstand dransteckst )?
Dass das Relais permanent hin und her geschaltet hat, kann ja nur mit der loop - Zeit von 2 * delay(500) zusammenhängen, schätze ich...

So, im Prinzip funktioniert jetzt alles XD
mal sehen, was noch dazu kommt.
Vielen Dank für die kompetente Hilfe.

___________________________________                                                                                                                        
Verwendete Teile:

Arduino R3
Sainsmart 1602 LCD Keypad Shield
optoelektronisches Relais
2x DHT22
___________________________________
Key Codes (in left-to-right order):

None   - 0
Select - 1
Left   - 2
Up     - 3
Down   - 4
Right  - 5
___________________________________

*/

#include <dht.h>
#include <LiquidCrystal.h>
#include <DFR_Key.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


dht DHT;
DFR_Key keypad;

#define dhtA 12
#define dhtI 13
#define relais 11


int localKey = 0;      //Tastenerkennung
String keyString = ""; //??

double dewPointFast(double celsius, double humidity) //Taupunkt berechnung
{
        double a = 17.271;
        double b = 237.7;
        double temp = (a * celsius) / (b + celsius) + log(humidity/100);
        double Td = (b * temp) / (a - temp);
        return Td;
}

float dewI = 0; //Taupunkt Innen
float dewA = 0; //Taupunkt Aussen
float tempI = 0;//Temperatur Innen
float tempA = 0;//Temperatur Aussen
float humI = 0; //Luftfeuchtigkeit Innen
float humA = 0; //Luftfeuchtigkeit Aussen
int hysterese = 1; //Hysterse (mal 2) für die Schaltung 

long count = 0;  //Counter fuer die Eingabe
int statL = 0;  //Status der Luefter 
int menueH = 0; //Durchs Hauptmenue gehen
//int menueS = 0; //Menue bei Select
int menueC = 0;
int intro = 0;

long previousMillis = 0;
long milliMil = 0;
long milliMin = 0;
long milliStd = 0;



void setup()
{
  Serial.begin(115200); //Verbindung Computer
  pinMode(relais, OUTPUT);
  digitalWrite(relais, HIGH);

  
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Fan Control");
  lcd.setCursor(0, 1);
  lcd.print("Version 0.1.9");
  
  while(intro < 5)
  {
    lcd.setCursor(15, 1);
    lcd.print((char)0x7C);
    delay(500);
    lcd.setCursor(15, 1);
    lcd.print((char)0x2D);
    delay(500);    
    intro++;
  }
  
  delay(2500);  
}

void loop()
{
  unsigned long currentMillis = millis();
  milliMil = currentMillis - previousMillis;
  milliMin = milliMil / 60000;
  milliStd = milliMin / 60;
  
  
  
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Hello Dave,");
  lcd.setCursor(0, 1);
  lcd.print("I'm very busy");
  
  

    
  DHT.read22(dhtI); //Sensor Innen auslesen
  //delay(500);
  //DHT.read22(dhtI);
  float humI = DHT.humidity;
  float tempI = DHT.temperature;
  float dewI = (dewPointFast(DHT.temperature, DHT.humidity));    
  
  delay(1500);
  
  DHT.read22(dhtA); //Sensor Aussen auslesen
  //delay(500);
  //DHT.read22(dhtA);
  float humA = DHT.humidity;
  float tempA = DHT.temperature;
  float dewA = (dewPointFast(DHT.temperature, DHT.humidity)); 
  
  //dewA = dewA - 5; //Test!!!!!!!!!!!!!!!!!!!
 
  if (dewA <= dewI - hysterese)  //Ueberprueft die Luftfeuchtigkeit schaltet die Luefter und speichert den Status in statL
  {   
    digitalWrite(relais, LOW); //Luefter einschalten
    
    if (statL == 0)
    {
    previousMillis = millis();
    }
    statL = 1;
  }
  
  else if (dewA > dewI + hysterese)
  {
    digitalWrite(relais, HIGH); //Lufter ausschalten
    
    if (statL == 1)
    {
    previousMillis  = millis();
    }
    statL = 0;
    
  }
  
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("HAL:Im waiting");
    lcd.setCursor(0, 1);
    lcd.print("    for command");
    
    
    count = 0; 
 
  while(count < 300000) //Menuefunktion
  {
    keypad.getKey();
    menueH = keypad.getKey();
        
    switch (menueH) //Einzelne Menuepunkte
    {
      case 1:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Luefter:");
      lcd.setCursor(9, 0);
      Serial.println(statL);//loeschen
      if(statL == 1)
      {
        lcd.print("AN");
      }
      if(statL == 0)
      {
        lcd.print("AUS");
      }
      
      lcd.setCursor(0, 1);
      lcd.print(milliStd);
      lcd.print("Std ");
      lcd.print(milliMin);
      lcd.print("Min ");
      delay(1000);
      break;          
      
      case 2: //Relais ausschalten Pfeil nach links
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Luefter: Aus");
      digitalWrite(relais, HIGH); //Schalte Relais AUS
      delay(1000);//Verzögere um erneute Eingabe zu verhindern
      
      menueC = 0; //setze Schaltzustand auf 0      
      while(menueC != 1) //Manueller Luefter
      {
        keypad.getKey();
        localKey = keypad.getKey();
         
        if (localKey == 2) //Wenn 2 gedrückt wird wird die Schleife beendet
        {
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Automatikmodus");
          lcd.setCursor(0, 1);
          lcd.print("ist AN");
          previousMillis  = millis(); //setze Timer auf Null
          digitalWrite(relais, HIGH); //Schaltet Luefter wegen Hysterese aus!
          delay(1000);
          menueC = 1; //beende Schleife
        }
         
      }
      break;
      
        
      case 3: //Anzeige Daten Aussen Pfeil nach oben
  
      //Erste Zeile
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Aussen: ");
      
      lcd.print(dewA);
      lcd.print((char)223);
      lcd.print("C");
  
      //Zweite Zeile
      lcd.setCursor(0, 1);
      lcd.print(tempA);
      lcd.print((char)223);
      lcd.print("C ");
  
      lcd.print(humA);
      lcd.print((char)0x25);
      delay(1000);
      break;
      
      case 4: //Anzeige Daten Keller Pfeil nach unten
  
      //Erste Zeile
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Keller: ");
  
      lcd.print(dewI);
      lcd.print((char)223);
      lcd.print("C");
  
      //Zweite Zeile
      lcd.setCursor(0, 1);
  
      lcd.print(tempI);
      lcd.print((char)223);
      lcd.print("C ");
  
      lcd.print(humI);
      lcd.print((char)0x25);
      delay(1000);
      break;
      
      case 5: //Luefter einschalten Pfeil nach rechts
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Luefter: An");
      digitalWrite(relais, LOW); //Schalte Relais AN
      delay(1000);//Verzögere um erneute Eingabe zu verhindern
      
      menueC = 0; //setze Schaltzustand auf 0      
      while(menueC != 1) //Manueller Luefter
      {
        keypad.getKey();
        localKey = keypad.getKey();
         
        if (localKey == 5) //Wenn 5 gedrückt wird wird die Schleife beendet
        {
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Automatikmodus");
          lcd.setCursor(0, 1);
          lcd.print("ist AN");
          previousMillis  = millis(); //setze Timer auf Null
          digitalWrite(relais, HIGH); //Schaltet Luefter wegen Hysterese aus!
          delay(1000);
          menueC = 1; //beende Schleife
        }
         
      }
      break;
    }
      
    if(menueH != SAMPLE_WAIT) //Setzt den Counter auf Null wenn Eingabe erfolgt ist.
    {
      count = 0;
    }
    
    
    else   
    {
      count++; //Ohne Einmgabe laueft der Counter
    } 
    
    
 }
 
 
  Serial.println ("Innensensor:");
  Serial.print ("humI: ");
  Serial.println (humI);
  Serial.print ("tempI: ");
  Serial.println (tempI);
  Serial.print ("dewI: ");
  Serial.println (dewI);
  Serial.println ("");
  
 
  Serial.println ("Aussensensor:");
  Serial.print ("humA: ");
  Serial.println (humA);
  Serial.print ("tempA: ");
  Serial.println (tempA);
  Serial.print ("dewA: ");
  Serial.println (dewA);
  Serial.println ("____________________");

}

Für Code musst du diese Tags verwenden:
[.code]
[./code]

Ohne die Punkte. Oder Einfach auf den # Knopf klicken.

Deine Ausgabe auf dem LCD solltest du zumindest teilweise in eine Methode auslagern und die Position auf dem Display und den Inhalt mit Parametern übergeben. Das wird dann wesentlich übersichtlicher. z.B. so ähnlich:

void printLCD(byte x, byte y, char* str)
{
    lcd.setCursor(x,y);
    lcd.print(str);
}

Oder eine PrintTemp Methode die das "°C" dranhängt, da du das mehrmals machst

Double bringt dir hier übrigens keine höhere Präzision als Float. Beide haben auf dem Arduino 4 Byte

String keyString = ""; //?? <--- das ist einfach ein leeres String-Objekt falls dich das noch wundert

Wenn du nur zwei Zustände in einer Variable speichern willst ist int Verschwendung. Da nimmt man bool/boolean. Der nimmt true/false an.

Das kannst du einfach so abfragen:

bool state = false;

void loop()
{
     if(state)    //oder deutlich: if(state == true)
     {
         ...
     }
}

Andersherum:

if(!state)    //oder: if(state == false)
{
}

Also wie ich jetzt den Code poste habe ich irgendwie noch nicht verstanden :roll_eyes:

Pin 3, hing am Shield und deshalb hat er bei jeder LCD Ausgabe geschaltet.

Ja, der Code muss noch aufgeräumt werden :wink:
bin aber froh, dass er zumindest rudimentär funktioniert.
Dass mit der Hysterese war ein super Tipp, der macht das deutlich einfacher...
Danke nochmal, ich werde aber weiterhin über das Projekt schreiben. Vielleicht kann das ja jemand gebrauchen.

Das sind die normalen Tags in eckigen Klammern wie sie in allen Foren sind.

[.code]
//Code hier
[./code]

Und die Punkte nach der ersten Klammer weglassen. Die habe hier nur reingemacht damit man es sieht.

Oder: Code markieren und oben bei den Icons auf den #-Knopf klicken (untere Reihe, dritter von rechts)

Die Variablen um millis() abzuspeichern müssen unsigned long sein ansonsten gibt es nach 25 Tagen Probleme weil die Zahl dann negativ wird.
Grüße Uwe

So, habe heute den ersten Aufbau installiert. Soweit ich das sagen kann ,funktioniert alles. Ich werde den Code aber noch weiter aufräumen. Mein größtes Problem ist, dass die Tasten nur unzuverlässig funktionieren. Keine Ahnung ob das an der unzureichenden Entprellung in der Library oder am Code liegt. Naja dafür, dass ich zum ersten Mal programmiert habe, bin ich stolz^^.

Für die Zukunft sind geplant:

Datenlogger;
RTC;
anderes LCD bzw Tasten;
Umrüsten auf Arduino mini pro;

Hier also der Staus Q : da mehr als 9500 Zeichen: http://pastebin.com/FJDEUndK

P.S.
Danke Uwe!, ist gemacht;
Dass mit dem Code bekomme ich mittlerweile hin, aber der ist wohl zu groß^^. Danke Serenifly!;
Ja, diese Relais, haben mich auch schlaflos gemacht, danke Michael!;

P.P.S Für die Ausgabe der Zeit habe ich vorerst die Methode von Fribbe verwendet, da mich die fehlenden 0en gestört haben: macherzin.net

Hat jemand Erfahrungswerte, welche Hysterese man für die Schaltung verwenden sollte?

Momentan sieht es so aus: hysterese = 1
dewA = Taupunkt Aussen
dewI = Taupunkt Innen

if (dewA <= dewI - hysterese) //Ueberprueft die Luftfeuchtigkeit schaltet die Luefter und speichert den Status in statL
{
digitalWrite(relais, LOW); //Luefter einschalten

if (statL == 0)
{
previousMillis = millis();
time_t Zeitstempel = now();
}
statL = 1;
}

else if (dewA > dewI + hysterese)
{
digitalWrite(relais, HIGH); //Lufter ausschalten

if (statL == 1)
{
previousMillis = millis();
time_t Zeitstempel = now();
}
statL = 0;

}

Das muss man ausprobieren. Das hängt auch damit zusammen wie schnell sich deine Werte ändern (die Regelgröße) und wie groß der Raum ist (die Regelstrecke)