Go Down

Topic: RTC ds3231 mit SH1106 Oled und SEesor. (Read 853 times) previous topic - next topic

Andreas87

Hallo ich beschäftige mich jetzt schon eine weile mit diesem Sketch und komme leider nicht weiter.
Grundsätzlich möchte ich ein Relay um ein bestimmte Uhrzeit anschalten und ausschalten,Allerdings nur wenn der Sensorwert <300 ist
Das funktioniert auch ohne probleme


Ist der Wert > 300 leuchtet ein Neopixel grün und auf dem Display steht Pumpe OFF pixel
Ist der Wert < 300 leuchtet ein Neopixel Rot und auf dem Display steht Pumpe wartet pixel
In dem Fall das der wert < 300  soll das Relay  um 17:30:10 Uhr HIGH sein und 21:30:50 Uhr LOW
Bis Hierher funtioniert der code ohne Probleme.

Das Problem liegt bei dem teil wo Das Relay HIGH geschaltet wird,das Display sollte jetzt eigentlich Pumpe ON anzeigen und der pixel sollte gelb leuchten aber es blinkt nur einmal auf und ist denn wieder weg aber das Relay geht erst aus wenn es auch ausgehen soll.

mir ist noch aufgefallen,das wenn der Sensorwert von <300 auf >300 in der Zeit zwischen17:30:10 Uhr und 21:31:50 Uhr,das denn das Relay nicht ausgeht

Kann mir da jemand helfen? ich bin Maler und versuch mich Stück für Stück in diese Problematik einzufinden.

danke schonmal und ich hoffe das problem ist gut erklärt.
Kann ich das irgendwie anders schreiben?


Tommy56

Meinst Du, wir sind Hellseher? Wie sollen wir ohne Deinen Sketch darauf antworten?

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Andreas87

#2
Oct 22, 2019, 10:42 pm Last Edit: Oct 22, 2019, 10:49 pm by Andreas87
Code: [Select]
#include <Wire.h>
#define RTC_I2C_ADDRESS 0x68 // I2C Adresse des RTC  DS3231
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH1106.h>


#define OLED_MOSI   9
#define OLED_CLK   10
#define OLED_DC    11
#define OLED_CS    12
#define OLED_RESET 13
Adafruit_SH1106 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

#define RTC_I2C_ADDRESS 0x68 // I2C Adresse des RTC  DS3231
#include <Adafruit_NeoPixel.h>


#define PIN 6
#define NUM_LEDS 2

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRBW + NEO_KHZ800);
int Bodenfeuchte = A1;
int sensorWert = 0;
int Einstellen;

int Relay = 2;
/*
  const int anstd = 6;
  const int anmin = 45;
  const int ansek = 6;

  const int ausstd = 6;
  const int ausmin = 6;
  const int aussek = 46;
*/
unsigned long startZeit1 = 0;
unsigned long startZeit2 = 0;
unsigned long startZeit3 = 0;
unsigned long startZeit4 = 0;

const int zeit1 = 1000;
const int zeit2 = 1000;
const int zeit3 = 100;
const int zeit4 = 0;






//Membervariablen
int jahr, monat, tag, stunde, minute, sekunde, wochentag;
int daysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
String daysInWeek[7] = {"So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"};
String monthInYear[12] = {"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"};
String outputFormat = "%s, %02d.%s %04d %02d:%02d:%02d Uhr";

void rtcReadTime() {
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(RTC_I2C_ADDRESS, 7);
  sekunde    = bcdToDec(Wire.read() & 0x7f);
  minute     = bcdToDec(Wire.read());
  stunde     = bcdToDec(Wire.read() & 0x3f);

  /* wochentag  =*/ bcdToDec(Wire.read());
  tag        = bcdToDec(Wire.read());
  monat      = bcdToDec(Wire.read());
  jahr       = bcdToDec(Wire.read()) + 2000;
}

void rtcWriteTime(int jahr, int monat, int tag, int stunde, int minute, int sekunde) {
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(sekunde));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(stunde));
  Wire.write(decToBcd(0));
  Wire.write(decToBcd(tag));
  Wire.write(decToBcd(monat));
  Wire.write(decToBcd(jahr - 2000));
  Wire.endTransmission();
}

byte calcDayOfWeek(int jahr, byte monat, byte tag) {
  static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
  jahr -= monat < 3;
  return ((jahr + jahr / 4 - jahr / 100 + jahr / 400 + t[monat - 1] + tag) % 7);
}

byte decToBcd(byte val) {
  return ( (val / 10 * 16) + (val % 10) );
}

byte bcdToDec(byte val) {
  return ( (val / 16 * 10) + (val % 16) );
}

int getIntFromString (char *stringWithInt, byte num) {
  char *tail;
  while (num > 0) {
    num--;

    while ((!isdigit (*stringWithInt)) && (*stringWithInt != 0)) {
      stringWithInt++;
    }
    tail = stringWithInt;

    while ((isdigit(*tail)) && (*tail != 0)) {
      tail++;
    }

    if (num > 0) {
      stringWithInt = tail;
    }
  }
  return (strtol(stringWithInt, &tail, 10));
}

void setup() {
  Wire.begin();
  Serial.begin(57600);
  Serial.println("Mit dem Befehl kann das Datum und die Uhrzeit gesetzt oder veraendert werden.");
  Serial.println("set 05.10.2019 14:54:00");
  display.begin(SH1106_SWITCHCAPVCC);
  pinMode(Relay, OUTPUT);
  digitalWrite(Relay, LOW);
  strip.begin();

}


void printRTCDateTime() {
  {
    long runtime = millis() / 1000;
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(3, 55);

    char linebuf[60];
    int dOW = calcDayOfWeek(jahr, monat, tag);
    String wochentagC = daysInWeek[dOW];
    String monatC = monthInYear[monat];

    String result = "";
    result += wochentagC;
    result += ", ";
    result += tag;
    result += ".";
    result += monatC;
    result += " ";
    result += jahr;
    result += " ";
    display.println(result);
  }
  {
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(40, 1);
    String result = "";

    if (stunde < 10) {
      result += "0";
    }
    result += stunde;
    result += ":";
    if (minute < 10) {
      result += "0";
    }
    result += minute;
    result += ":";
    if (sekunde < 10) {
      result += "0";
    }
    result += sekunde;
    display.println(result);
  }
  display.display();
  display.clearDisplay();
}

void setRTCTime() {

  char linebuf[30];
  byte counter;
  if (Serial.available()&& millis() > startZeit3 + zeit3) {
     startZeit3 = millis();
             
    memset(linebuf, 0, sizeof(linebuf));
    counter = 0;
    while (Serial.available()) {
      linebuf[counter] = Serial.read();
      if (counter < sizeof(linebuf) - 1) counter++;
    }
  }
  if (strstr(linebuf, "set") == linebuf) {
    tag = getIntFromString (linebuf, 1);
    monat = getIntFromString (linebuf, 2);
    jahr = getIntFromString (linebuf, 3);
    stunde = getIntFromString (linebuf, 4);
    minute = getIntFromString (linebuf, 5);
    sekunde = getIntFromString (linebuf, 6);
  } else {
    Serial.println("Befehl unbekannt.");
    return;
  }
  if (!checkDateTime(jahr, monat, tag, stunde, minute, sekunde)) {
    Serial.println(linebuf);
    Serial.println("Fehlerhafte Zeitangabe im 'set' Befehl");
    Serial.println("Beispiel: set 28.08.2013 10:54");
    return;
  }
  rtcWriteTime(jahr, monat, tag, stunde, minute, sekunde);
  Serial.println("Zeit und Datum wurden auf neue Werte gesetzt.");
}


boolean checkDateTime(int jahr, int monat, int tag, int stunde, int minute, int sekunde) {
  boolean result = false;
  if (jahr > 2000) {
    result = true;
  } else {
    return false;
  }
  // Schaltjahr prüfen
  if (jahr % 400 == 0 || (jahr % 100 != 0 && jahr % 4 == 0)) {
    daysInMonth[1] = 29;
  }

  if (monat < 13) {
    if ( tag <= daysInMonth[monat - 1] ) {
      result = true;
    }
  } else {
    return false;
  }


  if (stunde < 24 && minute < 60 && sekunde < 60 && stunde >= 0 && minute >= 0 && sekunde >= 0) {
    result = true;
  } else {
    return false;
  }

  return result;
}

void loop() {


  if (millis() > startZeit1 + zeit1) {
    rtcReadTime();
    printRTCDateTime();
    setRTCTime();
    startZeit1 = millis();
  }

  if (millis() > startZeit2 + zeit2) {
    sensorWert = analogRead(Bodenfeuchte);
    startZeit2 = millis();
  }
  else {

  }

  if (sensorWert < 300) {

    strip.setPixelColor(1, strip.Color(250, 0, 0));
    strip.show();
                                                                  // strip.clear();
    long runtime = millis() / 1000;
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(20, 35);
    display.println("Pumpe wartet");



    if (millis() > startZeit4 + zeit4 && stunde == 17 && minute == 30&& sekunde == 10) {
      digitalWrite(Relay, HIGH);

      strip.setPixelColor(1, strip.Color(250, 250, 0));
      strip.show();

      {
        long runtime = millis();

        display.setTextSize(1);
        display.setTextColor(WHITE);
        display.setCursor(20, 35);
        display.println("Pumpe ON");
      }
      startZeit4 = millis();
    }


    else if  (stunde == 21 && minute == 30 && sekunde == 50) {
      digitalWrite(Relay, LOW);

    }
  }
  else
  {
    strip.setPixelColor(1, strip.Color(0, 250, 0));
    strip.show();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(20, 35);
    display.println("Pumpe OFF");
  }

  {
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(35, 10);
    display.print("Boden  ");
    display.println(sensorWert);

  }

}




Meinst Du, wir sind Hellseher? Wie sollen wir ohne Deinen Sketch darauf antworten?

Gruß Tommy

Andreas87

Sorry musste es seperat posten da es zuviele Zeichen. und zwischen den post muss ich 5 min warten

Andreas87

bei dem const int zeit4 = 6000;
sollte eigentlich keine Zeit stehen ich hatte es nur mal probiert ob es denn geht. es sollte solange stehen bis das Relay off geschaltet wird

postmaster-ino

#5
Oct 22, 2019, 10:58 pm Last Edit: Oct 22, 2019, 11:00 pm by postmaster-ino
Hi

Kommentare sind eigentlich kein Luxus - auch würde ich die 'zeitwerte' nicht durchnummerieren.
Momentag schreibst Du wie wild auf dem Display rum und setzt den Pixel, wenn der messwert < 300 ist - und Das in JEDEM Durchgang - unschön.
Deine Zeit-Berechnungen fallen Dir nach 47,x Tagen auf die Füße:
Code: [Select]

// ****
if (millis() > startZeit1 + zeit1) {
-->
if (millis() - startZeit1 > zeit1) {
// ****

Das ganze HIGH und LOW würde ich mir ebenfalls definieren - dieses Mal sogar wirklich mit define:
#define AN=LOW
#define AUS=!AN

So kannst Du im Sketch AN und AUS schreiben, und man sieht, was das Relais machen soll - egal, wie der Pin dafür wirklich steht.
Beim Wechsel von den chinesischen Relais zu SSRs muß man nämlich z.B. die Anstsuerung 'umdrehen' - die China-Relais sind zumeist Low-Aktiv, die SSRs brauchen aber ein HIGH zum Schalten.
Mit den #define tauscht man in einer Zeile ein LOW gegen ein HIGH und ist fertig.

Dein Problem konnte ich so direkt nicht nachvollziehen, liegt aber auch daran, daß ich den fremden Code erst komplett verstehen muß - so ganz ohne einen Kommentar wird's aber echt müßig.
Denke mir, daß Du Dich in den ganzen IFs verrennst - und einen logischen Fehler in Deinen Gedanken hast.
Du denkst, daß Du die Pumpe ausschalten musst, wenn die Zeit um ist UND der Sensorwert <300 ist - hier würde wohl ein ODER besser greifen - ggf. mit 'umgedrehtem' Sensor.
Da ich auch was von Bodenfeuchte gelesen habe, denke ich, daß die 300 der Feuchtewert des Boden ist - aber auch hier könntest Du meinem Ratespiel ein jähes Ende bereiten und mit Gewissheit füllen.

MfG

PS: const ist schon Mal gut - aber warum INT?
Hast Du negative Pin-Nummern?
Oder Nummern über 255?
Ich hatte Das bisher noch nicht und kam, zumindest dort, locker mit BYTE klar.
Wenn nix Negativ -> unsigned.
Zugegeben: Bei const wohl egal, da der Kompiler Das ausmerzt, aber gewöhne Dir an, einen passenden Datentyp zu benutzen - auch Dir wird der Speicher eines Tages knapp und Da freut man sich über jedes gesparte Byte (... ok, bei Dir ist noch viel zum Sparen vorhanden ... Das sieht in einem durchdachtem Code schon wieder schmaler aus ...)
Dein Problem, Dein Sketch, Deine Bilder.
Ob ich ohne Diese an Deinem Problem arbeiten will, entscheide aber immer noch ich.
Große Buchstaben? Immer wieder, neben Punkt und Komma, gerne gesehen.

Andreas87



Der ds3231 Sketch ist so übernommen allerdings hat der Sketch nur die Uhrzeit und Datum angezeigt und den Rest hab ich gemacht, aber das hast ja schon quasi gesehen.

Genau es Handelt sich um ein Feuchtigkeitssensor für den Garten.
 Okay und  mit dem codetext den du da reingestellt hast sollte mir das denn nicht auf die füße fallen?

das Relay geht auch an und aus.
nur in dem fall das wenn der Sensorwert von <300 auf >300 in der Zeit zwischen17:30:10 Uhr und 21:31:50 Uhr,das denn das Relay nicht ausgeht.

Das mit dem HIGH und LOW werd ich machen


das mit dem thema int kenn ich nicht anders,aber auch das werde ich ändern;)

const byte zeit1 = 1000;

sollte denn so aussehen.

das

Das Glaub ich dir gerne das bei mir noch einiges einzusparen wäre, aber das kann Ich nicht,bin froh das Ich überhaupt soweit gekommen bin, für Viele Hier wäre das wahrscheinlich kein Problem das Sauber und Ordentlich zu schreiben, aber Ich kann mich damit leider  manchmal gar nicht so beschäftigen,da die arbeit ein so einnimmt;)
Hab erst vor knapp über einem Jahr gesehen das es sowas gibt und wo ich gesehen hab was man damit alles so machen kann,wurde ich Neugierig und hab immer Stück für Stück versucht. Und da ich keinen Kenne der sich mit sowas beschäftigt, muss ich alleine durchschlagen und wenn ich wirklich nicht weiterkomme denn erst frag ich hier nach.


Deltaflyer

Hi, nur kurz:
Code: [Select]
const byte zeit1 1 = 1000

funktioniert nicht! die Variable vom Typ byte kan einen maximalen Wert von 255 aufnehmen,
Wenn der Wert also höher als 255 ist muss , dann doch ein int oder ein unsigned int her:

Code: [Select]
const int zeit1 = 1000

oder, da zeit1 positiv ist, besser:
Code: [Select]
const uint16_t zeit1 = 1000
oder auch:
Code: [Select]
const unsigned int zeit1 = 1000

LG Stefan


Tommy56

Hi, nur kurz:
Code: [Select]
const byte zeit1 1 = 1000
Bei 1 = 1000 dürfte auch der Compiler streiken ;)

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

postmaster-ino

Hi
Das Glaub ich dir gerne das bei mir noch einiges einzusparen wäre, aber das kann Ich nicht,bin froh das Ich überhaupt soweit gekommen bin, für Viele Hier wäre das wahrscheinlich kein Problem das Sauber und Ordentlich zu schreiben, aber Ich kann mich damit leider  manchmal gar nicht so beschäftigen,da die arbeit ein so einnimmt;)
Hab erst vor knapp über einem Jahr gesehen das es sowas gibt und wo ich gesehen hab was man damit alles so machen kann,wurde ich Neugierig und hab immer Stück für Stück versucht. Und da ich keinen Kenne der sich mit sowas beschäftigt, muss ich alleine durchschlagen und wenn ich wirklich nicht weiterkomme denn erst frag ich hier nach.
Das war nicht als Kritik gemeint - da bei Dir der Code noch recht laienhaft ist, MUSS Da einfach mehr Einsparpotential enthalten sein, als bei einem der Cracks hier - zu Denen ich mich aber dennoch nicht zählen würde.
Wenn Du die Zeitabfrage umstellst, läuft millis() zwar auch weiterhin nach 49,x Tagen (nicht 47,x) über, aber auch während des Überlauf funktioniert die Berechnung fehlerfrei.
Den Nachweis hatte hier Mal Wer im Forum mit BYTE (0...255) gebracht - Du darfst Es aber auch einfach glauben: Das funktioniert auch am 50.ten Tag noch - Dein Code bekommt Da aber Bauchschmerzen und macht 'irgend welchen Mist'.

MfG
Dein Problem, Dein Sketch, Deine Bilder.
Ob ich ohne Diese an Deinem Problem arbeiten will, entscheide aber immer noch ich.
Große Buchstaben? Immer wieder, neben Punkt und Komma, gerne gesehen.

Tommy56

Das war hier.

Man kann auch testweise die if-Bedingung in dem Testscript mal umstellen und sieht damit, was nicht geht.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Andreas87

Das war hier.

Man kann auch testweise die if-Bedingung in dem Testscript mal umstellen und sieht damit, was nicht geht.

Gruß Tommy
Sorry aber ich weiß nicht wie?

Andreas87

#12
Oct 24, 2019, 02:38 pm Last Edit: Oct 24, 2019, 02:41 pm by Andreas87
Code: [Select]
void loop() {


  if (millis() - startZeit1 > zeit1) {
    rtcReadTime();
    printRTCDateTime();
    setRTCTime();
    sensorWert = analogRead(Bodenfeuchte);
    startZeit1 = millis();

  }
  Einstellen = map(sensorWert,  1023, 0, 0, 1023 );
  /* if (millis() - startZeit1 > zeit1) {
     sensorWert = analogRead(Bodenfeuchte);
     startZeit1 = millis();
    }
  */

 if ( Einstellen >= 601) {
    strip.setPixelColor(1, strip.Color(250, 0, 0));
    strip.show();
    digitalWrite(Relay, HIGH);
    long runtime = millis();


    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(20, 35);
    display.println("Pumpe wartet");

  } else if (Einstellen <= 600 && Einstellen >= 301) {
    strip.setPixelColor(1, strip.Color(0, 0, 250));
    strip.show();
    long runtime = millis() / 1000;

    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(20, 35);
    display.println("Pumpe ON");

  } else if (Einstellen <= 300) {
    strip.setPixelColor(1, strip.Color(0, 250, 0));
    strip.show();
    digitalWrite(Relay, LOW);
    long runtime = millis();

    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(20, 35);
    display.println("Pumpe OFF");

  }

 
  { display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(35, 10);
    display.print("Boden  ");
    display.println(Einstellen);
  }
}




Ich hab das Gestern mal anders geschrieben und
so wie der Loop teil ist funktioniert es , aber egal was Ich mache mit der Zeit funktioniert es nicht .

Ich hab noch versucht das Stück Stück mit der zeit aufzubauen aber Ich komm immer auf der selbe Ergebnis wie der Erste Sketch

Tommy56

#13
Oct 24, 2019, 03:47 pm Last Edit: Oct 24, 2019, 03:48 pm by Tommy56
Sorry aber ich weiß nicht wie?
Mache in dem verlinkten Beispiel doch mal aus:
Code: [Select]
if ((unsigned char)(aktuelleMillis - letzteMillis) >= dauer) {
Deine Variante
Code: [Select]
if (aktuelleMillis > unsigned char(letzteMillis + dauer)) {

Dann siehst Du in der Ausgabe den Unterschied.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Andreas87

ich hab es ausprobiert nur verstehe ich nicht ganz was im Serial Monitor steht.
da steht nicht immer Aktion . manchmal stehen denn auch nur zahlen ist das denn das er nicht läuft?



Code: [Select]
if (aktuelleMillis -( unsigned char)(letzteMillis + dauer)) {      // tu was






Der scheint denn aber besser zulaufen wenn ich das richtig sehe

Code: [Select]
if (aktuelleMillis -( unsigned char)(letzteMillis > dauer)) {      // tu was
 

Go Up