Problems with DS3231

hello, I’d like to build an “Zeitschaltuhr” (in German I Don’t know the english word).

I’ve found a good code at:

#define EIN LOW
#define AUS HIGH

struct schaltRelais_t{
  byte pin;
  int ein1; int aus1;
  int ein2; int aus2;
  int ein3; int aus3;
  int ein4; int aus4;
};

// Hier die Relais-Pins definieren mit Ein- und Ausschaltzeiten
schaltRelais_t schaltRelais[3]={
  {10, 800, 815, 830, 845, 1800, 1815, 1830, 1845},  // pin, Einschaltzeit, Ausschaltzeit
  {11, 805, 1935},
  {12, 810, 1940},
};


struct timerRelais_t{
  byte pin;
  byte dauer;
  int timer1;
  int timer2;
};

// Hier den Kurzzeittimer definieren
timerRelais_t timerRelais={4, 25, 830, 2043}; // Timer an Pin-4 für 25 Sekunden um 0830 und 2000

void relaisTimerNachZeit(int thishour, int thisminute)
{
  int thisTime= thishour*100+thisminute;
  if (thisTime==timerRelais.timer1 || thisTime==timerRelais.timer2)
  {
    Serial.println("Timer Start");
    digitalWrite(timerRelais.pin,EIN);
    delay(timerRelais.dauer*1000L);
    digitalWrite(timerRelais.pin,AUS);
    Serial.println("Timer Stopp");
  }
}


void relaisSchaltenNachZeit(int thishour, int thisminute)   
// Schaltet die Zeitschaltuhr ein und aus und setzt den Ausgang entsprechend
{
  boolean state;
  // Aus der aktuellen Zeit eine Schaltzeit bilden
  int thisTime= thishour*100+thisminute;
  // Alle Schaltzeiten durchgehen, falls eine davon EIN sagt, einschalten
  for (int i=0;i<sizeof(schaltRelais)/sizeof(schaltRelais_t);i++)
  {
    state=AUS;  // Amnahme: Es sei nichts geschaltet
    if (
       (thisTime>=schaltRelais[i].ein1 && thisTime<schaltRelais[i].aus1)||
       (thisTime>=schaltRelais[i].ein2 && thisTime<schaltRelais[i].aus2)||
       (thisTime>=schaltRelais[i].ein3 && thisTime<schaltRelais[i].aus3)||
       (thisTime>=schaltRelais[i].ein4 && thisTime<schaltRelais[i].aus4)
       )
    {   
        state=EIN;
    }
    if (digitalRead(schaltRelais[i].pin)!=state) // Falls geschaltet werden soll
    { // ein paar Debug-Ausgaben machen
      Serial.print("Relais ");
      Serial.print(i+1);  // Relais-Index zählt ab 0, einfach 1 dazuzählen
      Serial.print(": ");
      if (state==EIN) Serial.println("EIN"); else Serial.println("AUS");
    }
    digitalWrite(schaltRelais[i].pin, state); // Schaltzustand setzen
  }
} 



#include <Wire.h>
// I2C Adresse der RTC ist 0x68 für DS1307 und DS3231
#define RTC_I2C_ADDRESS 0x68

int jahre,monate,tage,stunden,minuten,sekunden;
// wochentag bleibt in diesem Test-Sketch unberücksichtigt

void rtcReadTime(int &jahre, int &monate, int &tage, int &stunden, int &minuten, int &sekunden)
// aktuelle Zeit aus RTC auslesen
{
// Reset the register pointer
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(RTC_I2C_ADDRESS, 7);
  // A few of these need masks because certain bits are control bits
  sekunden    = bcdToDec(Wire.read() & 0x7f);
  minuten     = bcdToDec(Wire.read());
  stunden     = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  /*wochentag   = */bcdToDec(Wire.read());
  tage        = bcdToDec(Wire.read());
  monate      = bcdToDec(Wire.read());
  jahre       = bcdToDec(Wire.read())+2000; 
}

void rtcWriteTime(int jahre, int monate, int tage, int stunden, int minuten, int sekunden)
// aktuelle Zeit in der RTC speichern
{
  Wire.beginTransmission(RTC_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(sekunden));    // 0 to bit 7 starts the clock
  Wire.write(decToBcd(minuten));
  Wire.write(decToBcd(stunden));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
                                 
  Wire.write(decToBcd(0)); // Wochentag unberücksichtigt
  Wire.write(decToBcd(tage));
  Wire.write(decToBcd(monate));
  Wire.write(decToBcd(jahre-2000));
  Wire.endTransmission(); 
}

byte decToBcd(byte val) // Hilfsfunktion zum Lesen/Schreiben der RTC
// Convert decimal number to binary coded decimal
// Hilfsfunktion für die Echtzeituhr
{
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)  // Hilfsfunktion zum Lesen/Schreiben der RTC
// Convert binary coded decimal to decimal number
// Hilfsfunktion für die Echtzeituhr
{
  return ( (val/16*10) + (val%16) );
}


int getIntFromString (char *stringWithInt, byte num)
// input: pointer to a char array
// returns an integer number from the string (positive numbers only!)
// num=1, returns 1st number from the string
// num=2, returns 2nd number from the string, and so on
{
  char *tail;
  while (num>0)
  {
    num--;
    // skip non-digits
    while ((!isdigit (*stringWithInt))&&(*stringWithInt!=0)) stringWithInt++;
    tail=stringWithInt;
    // find digits
    while ((isdigit(*tail))&&(*tail!=0)) tail++;
    if (num>0) stringWithInt=tail; // new search string is the string after that number
  } 
  return(strtol(stringWithInt, &tail, 10));
} 


void setup()
{
  Wire.begin();       // initialisiert die Wire-Library
  Serial.begin(9600); // Serielle Kommunikation starten
  while (!Serial);    // wait for serial port to connect. Needed for Leonardo only
  Serial.println("\r\nZeitschaltuhr- und Kurzzeittimer-Demo Sketch");
  Serial.println("Coded by jurs for German Arduino Forum.");
  Serial.println("Jede Minute wird die aktuelle Zeit im 'Seriellen Monitor' angezeigt.");
  Serial.println("Ebenso alle Ein- und Ausschaltungen und die Kurzzeittimer-Aktion");
  Serial.println();
  Serial.println("Du kannst die Zeit mit einem 'set' Befehl im 'Serial Monitor' neu setzen.");
  Serial.println("\r\nBeispiel:");
  Serial.println("set 28.08.2013 10:54\r\n");
  for (int i=0;i<sizeof(schaltRelais)/sizeof(schaltRelais_t);i++)
  {
    digitalWrite(schaltRelais[i].pin,AUS);
    pinMode(schaltRelais[i].pin,OUTPUT);
  } 
  digitalWrite(timerRelais.pin,AUS);
  pinMode(timerRelais.pin,OUTPUT);
}


void behandleSerielleBefehle()
{
  char linebuf[30];
  byte counter;
  if (Serial.available())
  {
    delay(100); // Warte auf das Eintreffen aller Zeichen vom seriellen Monitor
    memset(linebuf,0,sizeof(linebuf)); // Zeilenpuffer löschen
    counter=0; // Zähler auf Null
    while (Serial.available())
    {
      linebuf[counter]=Serial.read(); // Zeichen in den Zeilenpuffer einfügen
      if (counter<sizeof(linebuf)-1) counter++; // Zeichenzähler erhöhen
    }
    // Ab hier ist die Zeile eingelesen
    if (strstr(linebuf,"set")==linebuf) // Prüfe auf Befehl "set" zum Setzen der Zeit
    { // Alle übermittelten Zahlen im String auslesen
      tage=getIntFromString (linebuf,1);
      monate=getIntFromString (linebuf,2);
      jahre=getIntFromString (linebuf,3);
      stunden=getIntFromString (linebuf,4);
      minuten=getIntFromString (linebuf,5);
      sekunden=getIntFromString (linebuf,6);
    }
    else
    {
      Serial.println("Befehl unbekannt.");
      return;
    }
    // Ausgelesene Werte einer groben Plausibilitätsprüfung unterziehen:
    if (jahre<2000 || monate<1 || monate>12 || tage<1 || tage>31 || (stunden+minuten)==0)
    {
      Serial.println(linebuf);
      Serial.println("\r\nFehlerhafte Zeitangabe im 'set' Befehl");
      Serial.println("\r\nBeispiel:");
      Serial.println("set 28.08.2013 10:54\r\n");
      return;
    }
    rtcWriteTime(jahre, monate, tage, stunden, minuten, sekunden);
    Serial.println("Zeit und Datum wurden auf neue Werte gesetzt.");
  }
}


void loop()
{
  char buffer[30];
  static unsigned long lastMillis;
  static int lastMinute;
  int stunden, minuten, sekunden, dummy;
  if (millis()-lastMillis>1000) // nur einmal pro Sekunde
  {
    lastMillis=millis();
    rtcReadTime(dummy, dummy, dummy, stunden, minuten, sekunden);
    if (minuten!=lastMinute) // die aktuelle Minute hat gewechselt
    {
      lastMinute=minuten;
      snprintf(buffer,sizeof(buffer),"%02d:%02d Uhr",stunden,minuten);
      Serial.println(buffer);
      relaisSchaltenNachZeit(stunden,minuten);
      relaisTimerNachZeit(stunden,minuten);
    }
  }
  behandleSerielleBefehle();
}

I’d like to trigger 3 Relais with different times 6 hours on/ 18 hours off ( every day)

-change the start time with an potentiometer form 00:00am to 01:00am or 12:00am
1024/64 = 16 different start times (0-15)

I hope somebody can help me to build such a sketch.

thx for your help :wink:

It's a time switch in English. I'd start by building it a simulation on a breadboard with real time clock module, LEDs (instead of relays) and connecting your Arduino. Before you load the main sketch, just try out the RTC, using the serial console to set and read the time, and continue from there.

thx,

yes I’ve done setting up the time into the ds3231 and it works very good, I’m using a LCD 2004 for showing the date nd time

my actually sketch is this here:

#include <Wire.h>//wire LIB
#include <DS3231.h>//DS 3231 RTC LIB
#include <LiquidCrystal_I2C.h>//LCD i2c LIB
#include "DHT.h"// DHT22 LIB
#define DHTPIN 2     // what digital pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 20, 4);//LCD 2004 BUS ID 0x27
DS3231  rtc(SDA, SCL);
Time  t;

int Poti2 = A3;// Poti Pin
int Poti1 = A2;// Poti Pin
int Poti3 = A6;// Poti Pin
int Poti4 = A7;// Poti Pin
int val1;    // variable to read the value from the analog pin
int val2;    // variable to read the value from the analog pin
int val3;    // variable to read the value from the analog pin
int val4;    // variable to read the value from the analog pin

int ledPin = 8;// LED Pin
int ledPin2 = 9;// LED Pin
int ledPin3 = 10;// LED Pin
int ledPin4 = 11;// LED Pin


void setup()
{
  pinMode(ledPin, OUTPUT);// LED Output
  pinMode(ledPin2, OUTPUT);// LED Output
  pinMode(ledPin3, OUTPUT);// LED Output
  pinMode(ledPin4, OUTPUT);// LED Output
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  pinMode(A6, INPUT);
  pinMode(A7, INPUT);
  Serial.begin(9600);// Serial 9600 Start
  rtc.begin();//RTC Start
  lcd.begin();//LCD Start
  dht.begin();//DHT22 Start
  lcd.setCursor(0, 0);//1.zeile
  //lcd.print("DAWS");  //logo beim booten
  lcd.setCursor(0, 1);//2.zeile
  //lcd.print("by DonDennisDTensta");//logo beim booten
  lcd.print("DAWS");  //logo beim booten
  lcd.setCursor(0, 2);// 3.zeile
  //lcd.write("xyz")); //logo beim booten
  lcd.print("by DonDennisDTensta");//logo beim booten
  lcd.setCursor(0, 3); //4.zeile
  //lcd.write("xyz");//logo beim booten
  delay (2000);
  lcd.clear();

}

void loop()
{
  val1 = analogRead(Poti1) / 64; //0-1023 zu 0-15
  val2 = analogRead(Poti2) / 64; //0-1023 zu 0-15
  val3 = analogRead(Poti3) / 64; //0-1023 zu 0-15
  val4 = analogRead(Poti4) / 64; //0-1023 zu 0-15
  t = rtc.getTime();
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h2 = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t2 = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  Serial.println("----------------------------------------");
  Serial.println("val1");
  Serial.println(val1);
  Serial.println("val2");
  Serial.println(val2);
  Serial.println("val3");
  Serial.println(val3);
  Serial.println("val4");
  Serial.println(val4);
  Serial.println("----------------------------------------");

  delay(200);


  lcd.setCursor(0, 0); // In der ersten Zeile soll der Text „Messwert:“ angezeigt werden.
  lcd.print(rtc.getDateStr()); //Datum
  lcd.print("  ");
  lcd.print(rtc.getTimeStr());//Uhrzeit
  //lcd.print("Du Doeddel");
  lcd.setCursor(0, 1); // In der zweiten Zeile soll der Text „Temp:“ angezeigt werden.
  lcd.print("T:");
  //lcd.write("Temp:");//Temperatur
  lcd.print(" ");
  lcd.print(t2);
  lcd.print((char)223);//Grad symbol
  lcd.print("C");
  lcd.print(" / ");
  lcd.print(t2);
  lcd.print((char)223);//Grad symbol
  lcd.print("C");
  lcd.setCursor(0, 2); // In der dritten Zeile soll der Messwert „Luftf.:“ angezeigt werden.
  lcd.print("H: ");
  lcd.print(h2);
  lcd.print(" %");
  lcd.print(" /  ");
  lcd.print(h2);
  lcd.print(" %");

  Poti1 = analogRead(A2); // Der Messwert vom Analogen Eingang A0 soll ausgelesen, und unter der Variablen „messwert“ gespeichert werden.
  Poti2 = analogRead(A3);
  Poti3 = analogRead(A6);
  Poti4 = analogRead(A7);
  delay(200);
  }





}

but, I need a sketch in which I have the following functions:

setting a start time with a potentiometer like Poti1

thx,

yes I’ve done setting up the time into the ds3231 and it works very good, I’m using a LCD 2004 for showing the date nd time

my actually sketch is in the attachment as .txt

the timer switch function is ok but not finish for my project.

I’d like to trigger 3 Relais with different times
-change the start time with an potentiometer from 00:00am to 01:00am or 12:00am
1024/64 = 16 different start times (0-15)

and i want to show on my LCD the activity of my relais if Relais 1 goes ON
I like to see Relais: 1=ON /2=OFF
if Relais 1 goes OFF
I like to see: Relais: 1=OFF/2=ON

if both are on: Relais: 1=ON /2=ON

if both are OFF: Relais: 1=OFF/2=OFF

I just need 2 state instead of 3

so The first and the second Relais state should be on my LCD.

that’s the things i need at the moment.

thx for your help.

SWA1.5.2.txt (12.9 KB)

The program is quite complex. I guess it is too big to include in your post between code tags?

I think that first of all you should try to describe in words, what the current behaviour of this system is, then start describing what you want to keep and your desired modifications.

What I understand from the sketch is that it : 1. consists of 3 relays (or leds in place of the the relays) 2. each relay has a maximum of 4 on and 4 off times in 24Hour format, each time packed into an integer. 3. there appears to be a short term timer, with 2 in times 24Hour format at which a Led is lit for a few seconds. 4. a complex code structure which operates the relays depending on the current time and the hard coded on/off shedule of the relays. 5. You appear to have a temperature/humidity sensor 6. You have an LCD screen.

In your code, you have defined 4 potentiometers. To define the on/off times of 3 relays, with 4 on and 4 off settings you are going to need up to 24 values. These are currently hard coded. How do you see these 4 potentiometers controlling so many values ? Are you going to have a menu selection allowing you to store the current potentiometer time value against a particular on/off value for a specific relay ? Is it foreseen that the potentiometer would completely replace all the hard codes values eg for relay 1: {pin8, 2254, 2255, 830, 845, 1800, 1815, 1830, 1845}

The stored time values (on/off) times are in 24Hour format , each packed into an integer so (int) 1815 represents a quarter past 6 in the evening. So it looks like the analog value from a potentiometer 0..1023 has to be converted first to minutes, then into a 24Hour format and written into an integer for storage to avoid disturbing the rest of the logic.

As for your last request, showing the current status of each relay on the LCD screen is a simple matter.

I've used a pot for entering values but I only use it for one digit at a time. I think you'll find that a single turn pot is only practical for entering 2 decimal digits at a time. That would be about 15 minute steps. Rather than trying to do all with one setting, it makes more sense to be able to step through the digits. In my case it was necessary because my application required 6 digits. Dwight

good evening,

thx for your time.

I’m sorry for the withheld key informations.

So I decided to begin telling you want this sketch should do:

#1 the first poteniometer should only switch the first Relais (a bulb) trigger times
I want to set the start time to 0:00-16:00 (1024/64=16, Value 0-15)

#2 the second poteniometer should change the on time form 12hours on (12hrs off) to 18 hours on (6hrs off) (1024/256=4)
0=12hrs mode & showing all set times on the LCD instead the normal things you could see on the picture
1=12hrs mode, just show the date time… like on the picture
2=18hrs mode, just show the date time… like on the picture
3=18hrs mode & showing all set times on the LCD instead the normal things you could see on the picture

#3 the third poteniometer should trigger a fan if relais 1 is off at 12hrs set
after 2,25 hrs on, 3,25 hours off &
after 5,50 hrs on, 6,50 hours off &
after 8,75 hrs on, 9,75 hours off &
(at each a hour on)

OR 18 hrs set if the relais 1 is off it should trigger
after 1,00 hrs on until 1,5 hours &
after 2,75 hrs on until 3,25 hours &
after 4,5 hrs on until 5,0 hours &
(at each a half hour on)

example if I choose 12hrs mode with poti 2 & set start time to 00:00
the fan should trigger on at 14:15 and off at 15:15 &
the fan should trigger on at 17:30 and off at 18:30 &
the fan should trigger on at 20:15 and off at 21:45

==>
so you see that the third relay switches in-dependence of the first and second potentiomer

#4 I would display the 12hrs mode or 18hrs mode at the right side of the temperatur on the lcd

at the 4th line on my 2004 LCD I would like to show if Relais 1 is triggerd on or off and relais 2 is triggerd on or off

I’ve just used LED’s for testing this sketch (txt document)
I’ve got some pictures of the project and from the LCD
nd my new sketch from today, I just changed the decimal of temp. nd humidity (if somebody would know what’s changed)

I wish u a great weekend nd hope for help

:slight_smile:

kindly regard
Don Dennis

20160930_220659.jpg

20160930_220710.jpg

LCD.jpg

SWA1.5.4.txt (12.3 KB)

Ok, It all seem reasonable what is the problem? Dwight

the problem is that i don't know the sketch code for making this functions :-(

can anybody help me with the sketch and integrate the functions ?

The first thing to say is that you have defined quite a complex project. Secondly, your choice of input device (potentiometer) for entering time values is unusual.

I'd suggest that you start by splitting the project into a number of stages so that you can get something working, then optimise it later.

For the time inputs, I'd plan initially to keep these as hard coded values (arrays and structs). Any additions you make should preserve the original format as much as possible to keep it all consistent. You don't use the potentiometers at this stage.

Once you've configured it with all the values and tested it, get the display right as you want it.

Then swap the LEDs for relays so you have something useable.

Then focus on how you change the configuration using the potentiometers you had originally, or another method.

I currently have a time switch in use which requires a complex configuration. It has a sunrise/sunset table and other on/off times. When I rebuild it, I'll use an ESP8266 and I'll design a web browser interface so I can configure it over wlan. For the number of inputs you have specified, maybe that would also be a solution for your project.

thx 6v6gt,

okay now i want to set the defined times with the potis, what for an example code could you give me that this is working?

of course i want a code which is easier than the code I’ve posted in Post #1

because i don’t really understand what is it making/ how it works

i want to exchange them with an easier to use code which the function that a potentiometer could change the start time llike this ( if hour=16, min=00 & PotPin1 = 15, start hour is 16:00)
but the codes I’ve seen doesn’t work with my DS3231 so that’s my primary problem
the arduino IDE says everytime some keywords lik now.hour… are not defined or not in the library :frowning:

after that i want to show the relais on/off status in my lcd. I’ve confused because if I change the print.serial to print.lcd it doesn’t make the same on my lcd as on th serial monitor :frowning:

so my last sketch without the timer is this, I’m still confused, I can’t make the next steps because it doesn’t is working how I want .

thx for your help

kindly regards
Don Dennis

DAWS_I2C_LCD_RTC_Test_DAWS0_1_4_1.ino (4.18 KB)

As I said, I would have left the potentiometers until the end. But anyway, since you want to start there, here is a stand alone sketch to illustrate how you could extract a time value from a potentiometer, also in the special "2 Byte" format used in your sketch. The comments should make it clear:

/*
 *  Convert analog reading ( 0..1023 ) to various representations of hours and minutes
 *  Granularity: 15 minute blocks.
 *  
 *  Use a 10 K potentiometer on A0 
 *  connect the wiper (middle terminal) best via a 1 k resistor to A0
 *  connect the remaining two terminals to 0 and +5V respectively
 * 
 */

void setup() {
  Serial.begin(9600) ;
}

void loop() {

  int ar = analogRead( A0 ) ;                // read value 0..1023 from potentiometer on A0
  int arC = constrain( ar, 20, 1000 ) ;      // clean up edges (optional)
  int arM = map( arC, 20, 1000 , 0, 64 ) ;   // divide time period into 64 X 15 minute blocks (16 hours) eg 17 = 04:15 (on clock)
                                             // if you want 24 hours, just change the 64 to 96 etc.
  float hoursDecMin = arM/4.0 ;              // calculate hours and decimal minutes  eg 13.75  (= 13:45 on clock)

  // in the Zeitschaltuhr sketch, time is represented by an integer
  // byte 1 of the integer is the hours
  // byte 2 of the integer in minutes
  int clockHours = int( hoursDecMin ) * 100 ;       // hours part * 100
  int clockMinutes = ( arM % 4 ) * 15 ;             // arM modulus 4 give 0..3. X 1 gives minutes
  int hoursClockMinutes = clockHours + clockMinutes ; //  eg 1345   ( 13:45 on the clock) 
  
  Serial.print("analog value= " ) ;
  Serial.print(ar) ;
  Serial.print("; arC= " ) ;
  Serial.print(arC) ;
  Serial.print("; arM= " ) ;
  Serial.print(arM) ;
  Serial.print("; hoursDecMin= " ) ;
  Serial.print(hoursDecMin) ;
  Serial.print("; hoursClockMinutes= " ) ;
  Serial.println(hoursClockMinutes) ;

  delay( 1000 ) ;
}