lcd 16x2 - ds1302 - arduino uno - rele

Ciao a tutti ho un problema che non riesco a risolvere.
Ho provato a scrivere in diversi modi ma da sempre problemi.
Con arduino uno voglio che dal clock del ds1302 confronti l’ora e secondo una certa ora che imposto io attivi un relè.
Con il display ho visualizzato solo alcuni segnali e l’ora per avere un riferimento.
Il problema che ho ora è che il rele è sempre attivo. prima invece all’ora stabilita partiva ma non si staccava.
Ecco il progetto:

#include <Time.h>
#include <DS1302RTC.h>
#include <LiquidCrystal.h>

// Intestazione PIN DS1302 CLOCK
#define kCePin 2 // DS1302 - Chip Enable
#define kIoPin 3 // DS1302 - Input/Output
#define kSclkPin 4 // DS1302 - Serial Clock

DS1302RTC RTC(kCePin, kIoPin, kSclkPin);

// Intestazione PIN LCD 16x2
#define kRSLCD 11//LCD RS
#define kELCD   10//LCD E
#define kD4LCD 9 //LCD D4
#define kD5LCD 8 //LCD D5
#define kD6LCD 7 //LCD D6
#define kD7LCD 6 //LCD D7

LiquidCrystal lcd(kRSLCD, kELCD, kD4LCD, kD5LCD, kD6LCD, kD7LCD);

#define led1 13
#define STATE_OFF  0
#define STATE_ON   1
int fsm_state;
int rele=0;


void setup()
{

  pinMode(led1,OUTPUT);
  // Setup Serial connection
  Serial.begin(9600);
  lcd.begin(16, 2);


  Serial.println("RTC module activated");
  Serial.println();
  delay(500);


  if (RTC.haltRTC()) {
    Serial.println("The DS1302 is stopped.  Please run the SetTime");
    Serial.println("example to initialize the time and begin running.");
    Serial.println();
  }
  if (!RTC.writeEN()) {
    Serial.println("The DS1302 is write protected. This normal.");
    Serial.println();
  }

  delay(1000);
}


void loop()
{

  digitalWrite(led1,LOW);

  tmElements_t tm;

  if (! RTC.read(tm)) {        

    lcd.setCursor(0 , 0);
    lcd.print("Ore = ");
    lcd.setCursor(6 , 0);
    print3digits(tm.Hour);
    lcd.setCursor(8 , 0);
    lcd.write(':');
    lcd.setCursor(9 , 0);
    print3digits(tm.Minute);
    lcd.setCursor(11 , 0);
    lcd.write(':');
    lcd.setCursor(12 , 0);
    print3digits(tm.Second);
    lcd.setCursor(15 , 0);
    lcd.write('  ');

  }

  else {
    Serial.println("DS1302 read error!  Please check the circuitry.");
    Serial.println();
    delay(9000);
  }

  allarme(tm.Hour,tm.Minute,rele);

  if (rele=1)
  {
    digitalWrite(led1,HIGH);
  }
  if (rele=0) 
  {
    digitalWrite(led1,LOW); 
  }
  lcd.setCursor(0 , 1);
  lcd.print(led1);
  lcd.setCursor(3 , 1);
  lcd.print(rele);

}



void print2digits(int number) {
  if (number >= 0 && number < 10)
    Serial.write('0');
  Serial.print(number);

}


void print3digits(int number2) {
  if (number2 >= 0 && number2 < 10)
    lcd.write('0');
  lcd.print(number2);
}


void allarme(int ora_gen,int minuti_gen,int fsm_state)
{
  //   tmElements_t tm;

  int ora1=13;
  int ora2=13;
  int minuti1=40;
  int minuti2=42;
  //int rele1=LOW;
  //int mem_val=0;
  int differenza;
  fsm_state=0;

  switch(fsm_state) {
  case STATE_ON:
    if(minuti1 >= minuti_gen < minuti2) 
    {
      fsm_state = STATE_ON;
    }
    break;
  case STATE_OFF:
    if(minuti_gen >= minuti2) {

      fsm_state = STATE_OFF;
    }
    break;
  }

  differenza=abs(minuti1-minuti2);


  //  lcd.setCursor(3 , 1);
  // lcd.print(rele1);
  lcd.setCursor(5 , 1);
  lcd.print(minuti_gen);
  lcd.setCursor(8 , 1);
  lcd.print(minuti1);
  lcd.setCursor(11 , 1);
  lcd.print(fsm_state);
  lcd.setCursor(14 , 1);
  lcd.print(differenza);

}

Avete qualche consiglio da darmi?

Questo non è corretto, viene accettato dal linguaggio C ma per il confronto devi usare ==

if (rele=1)         // errato per cosa vuoi fare tu, ma viene accettato perchè lecito in C
if (rele==1)       // corretto

HIGH e LOW sono valori interi, quindi semplifichi se a rele assegni in giro HIGH e LOW (1 e 0) e quindi fai direttamente:

digitalWrite(led1,rele);

Comunque nel codice che hai postato hai commentato il settaggio di rele !?!

Anche questo è un test mi pare errato:

if(minuti1 >= minuti_gen < minuti2)

Per fare due confronti devi separarli da AND && oppure OR ||

if(minuti1 >= minuti_gen && minuti_gen < minuti2)

Per il rele ho provato in tutti e due i modi ed avevo lo stesso problema, sia con uno che con due uguali.
Per il confronto prima era scritto in quel modo e ho provato anche in questo perchè nel corso che avevo seguito il tecnico lo usava anche.

Ho effettuato la modifica che mi avete consigliato, il rele rimane diseccitato ma se imposto l’ora dell’allarme non cambia stato, ne “fsm_state” e ne “rele”.

#include <Time.h>
#include <DS1302RTC.h>
#include <LiquidCrystal.h>

// Intestazione PIN DS1302 CLOCK
#define kCePin 2 // DS1302 - Chip Enable
#define kIoPin 3 // DS1302 - Input/Output
#define kSclkPin 4 // DS1302 - Serial Clock

DS1302RTC RTC(kCePin, kIoPin, kSclkPin);

// Intestazione PIN LCD 16x2
#define kRSLCD 11//LCD RS
#define kELCD   10//LCD E
#define kD4LCD 9 //LCD D4
#define kD5LCD 8 //LCD D5
#define kD6LCD 7 //LCD D6
#define kD7LCD 6 //LCD D7

LiquidCrystal lcd(kRSLCD, kELCD, kD4LCD, kD5LCD, kD6LCD, kD7LCD);

#define led1 13
#define STATE_OFF  0
#define STATE_ON   1
int fsm_state;
int rele;


void setup()
{

  pinMode(led1,OUTPUT);
  // Setup Serial connection
  Serial.begin(9600);
  lcd.begin(16, 2);


  Serial.println("RTC module activated");
  Serial.println();
  delay(500);


  if (RTC.haltRTC()) {
    Serial.println("The DS1302 is stopped.  Please run the SetTime");
    Serial.println("example to initialize the time and begin running.");
    Serial.println();
  }
  if (!RTC.writeEN()) {
    Serial.println("The DS1302 is write protected. This normal.");
    Serial.println();
  }

  delay(1000);
}


void loop()
{

  digitalWrite(led1,LOW);

  tmElements_t tm;

  if (! RTC.read(tm)) {        

    lcd.setCursor(0 , 0);
    lcd.print("Ore = ");
    lcd.setCursor(6 , 0);
    print3digits(tm.Hour);
    lcd.setCursor(8 , 0);
    lcd.write(':');
    lcd.setCursor(9 , 0);
    print3digits(tm.Minute);
    lcd.setCursor(11 , 0);
    lcd.write(':');
    lcd.setCursor(12 , 0);
    print3digits(tm.Second);
    lcd.setCursor(15 , 0);
    lcd.write('  ');
    //  lcd.setCursor(0 , 1);
    //    lcd.print(RTC.read(tm));
  }

  else {
    Serial.println("DS1302 read error!  Please check the circuitry.");
    Serial.println();
    delay(9000);
  }

  allarme(tm.Hour,tm.Minute,rele);

  if (rele==1)
  {
    digitalWrite(led1,rele);
  }
  if (rele==0) 
  {
    digitalWrite(led1,rele); 
  }
  lcd.setCursor(0 , 1);
  lcd.print(led1);
  lcd.setCursor(3 , 1);
  lcd.print(rele);

}



void print2digits(int number) {
  if (number >= 0 && number < 10)
    Serial.write('0');
  Serial.print(number);

}


void print3digits(int number2) {
  if (number2 >= 0 && number2 < 10)
    lcd.write('0');
  lcd.print(number2);
}


void allarme(int ora_gen,int minuti_gen,int fsm_state)
{
  //   tmElements_t tm;

  int ora1=18;
  int ora2=18;
  int minuti1=38;
  int minuti2=40;
  //int rele1=LOW;
  //int mem_val=0;
  int differenza;
  fsm_state=0;

  switch(fsm_state) {
  case STATE_ON:
    if(minuti1 >= minuti_gen && minuti_gen < minuti2) 
    {
      fsm_state = STATE_ON;
    }
    break;
  case STATE_OFF:
    if(minuti_gen >= minuti2) {

      fsm_state = STATE_OFF;
    }
    break;
  }

  differenza=abs(minuti1-minuti2);


  //  lcd.setCursor(3 , 1);
  // lcd.print(rele1);
  lcd.setCursor(5 , 1);
  lcd.print(minuti_gen);
  lcd.setCursor(8 , 1);
  lcd.print(minuti1);
  lcd.setCursor(11 , 1);
  lcd.print(fsm_state);
  lcd.setCursor(14 , 1);
  lcd.print(differenza);

}

Codice tuo o l’hai copiato ?
Ribadisco: da nessuna parte tu setti la variabile “rele” a 1 oppure a 0, mica lo può fare magicamente Arduino. :o

Questo, ma è solo una miglioria:

 if (rele==1)
  { digitalWrite(led1,rele);
  }
  if (rele==0) 
  { digitalWrite(led1,rele); 
  }

sostituiscilo TUTTO con:

 digitalWrite(led1,rele);

Questo NON ha senso:

fsm_state=0;
  switch(fsm_state) {
  case STATE_ON:
    if(minuti1 >= minuti_gen && minuti_gen < minuti2) 
    { fsm_state = STATE_ON;
    }
    break;
  case STATE_OFF:
    if(minuti_gen >= minuti2) 
    { fsm_state = STATE_OFF;
    }
    break;
  }

La prima cosa che fai è AZZERARE fsm_state quindi è come se lo imponessi SEMPRE a STATE_OFF
Perciò dello switch farà sempre e solo il secondo case. Lo devi fare SOLO nella setup ed è meglio scrivere fsm_state=STATE_OFF; che non =0

Poi, se vuoi verificare un orario, DEVI verificare sia l’ora che i minuti.
Conviene, secondo me, creare una variabile unica moltiplicando sempre le ore per 100.
Ovvero se l’ora X deve essere le 18:40 meglio scrivere una unica variabile = 1840 (milleottocentoquaranta)
Se poi dal RTC ricevi ora e minuti, i tuoi ora_gen e minuti_gen allora crea una variabile hhmm con la moltiplicazione:

int hhmm=ora_gen*100+minuti_gen;       // 13:30        13*100+30=>1300+30=>1330
if ( hhmm>1840 && hhmm<1159) ...

Come vedi negli if, il confronto è facilitato, hhmm contiene sia ora che minuti.

Il codice l'ho fatto io seguendo alcuni esempi presi in rete.

Ho già sostituito tutto con "digitalWrite(led1,rele);"
ma il problema c'è sempre.
La variabile "rele" viene impostata nel
"void allarme(int ora_gen,int minuti_gen,int fsm_state)"
e sarebbe "int fsm_state"

Riguardo l'ora adesso facevo in questo modo solo per comodità visto che facevo prove per vedere se il relè funzionava.
Il risultato finale dovrebbe essere che dal display regolo l'ora e i minuti per l'Allarme.

Non ho capito cosa dovrei mettere nel SETUP.

Una curiosità nella maggior parte degli esempi che trovo nel forum o in rete usano il DS1307 e non il DS1302, è per comodità per l' I2C o perchè funziona meglio?

albon87:
La variabile "rele" viene impostata nel
"void allarme(int ora_gen,int minuti_gen,int fsm_state)"
e sarebbe "int fsm_state"

@albon, senza offesa. Studiati un manuale di C.
Come fai a dire che la variabile rele la modifichi perchè modifichi fsm_state ? E' una cavolata !!
Ti ho detto che azzerare dentro ad allarme() la variabile fms_state =0 è un errore, lo devi spostare nel setup().

Ti ho anche detto che togliere quei due if() non risolveva nulla, solo semplificava il codice. Non mi pare di scrivere in tedesco.

Scusa per la mia ignoranza, ho fatto le modifiche che mi hai suggerito.
Il problema continua a persistere.
Comunque grazie ancora per l’aiuto che mi dai.

#include <Time.h>
#include <DS1302RTC.h>
#include <LiquidCrystal.h>

// Intestazione PIN DS1302 CLOCK
#define kCePin 2 // DS1302 - Chip Enable
#define kIoPin 3 // DS1302 - Input/Output
#define kSclkPin 4 // DS1302 - Serial Clock

DS1302RTC RTC(kCePin, kIoPin, kSclkPin);

// Intestazione PIN LCD 16x2
#define kRSLCD 11//LCD RS
#define kELCD   10//LCD E
#define kD4LCD 9 //LCD D4
#define kD5LCD 8 //LCD D5
#define kD6LCD 7 //LCD D6
#define kD7LCD 6 //LCD D7

LiquidCrystal lcd(kRSLCD, kELCD, kD4LCD, kD5LCD, kD6LCD, kD7LCD);

#define led1 13
#define STATE_OFF  0
#define STATE_ON   1
int fsm_state;
int rele;


void setup()
{

  pinMode(led1,OUTPUT);
  fsm_state = STATE_OFF;

  // Setup Serial connection
  Serial.begin(9600);
  lcd.begin(16, 2);


  Serial.println("RTC module activated");
  Serial.println();
  delay(500);


  if (RTC.haltRTC()) {
    Serial.println("The DS1302 is stopped.  Please run the SetTime");
    Serial.println("example to initialize the time and begin running.");
    Serial.println();
  }
  if (!RTC.writeEN()) {
    Serial.println("The DS1302 is write protected. This normal.");
    Serial.println();
  }

  delay(1000);

}


void loop()
{

  digitalWrite(led1,LOW);

  tmElements_t tm;

  if (! RTC.read(tm)) {        

    lcd.setCursor(0 , 0);
    lcd.print("Ore = ");
    lcd.setCursor(6 , 0);
    print3digits(tm.Hour);
    lcd.setCursor(8 , 0);
    lcd.write(':');
    lcd.setCursor(9 , 0);
    print3digits(tm.Minute);
    lcd.setCursor(11 , 0);
    lcd.write(':');
    lcd.setCursor(12 , 0);
    print3digits(tm.Second);
    lcd.setCursor(15 , 0);
    lcd.write('  ');

  }

  else {
    Serial.println("DS1302 read error!  Please check the circuitry.");
    Serial.println();
    delay(9000);
  }

  int ora1=21;
  int ora2=21;
  int minuti1=25;
  int minuti2=27;
  int differenza;
  int minuti_gen = tm.Minute;


  switch(fsm_state) {
  case STATE_ON:
    if(minuti1 >= minuti_gen && minuti_gen < minuti2) 
    {
      fsm_state = STATE_ON;
    }
    break;
  case STATE_OFF:
    if(minuti_gen >= minuti2) 
    {
      fsm_state = STATE_OFF;
    }
    break;
  }

  differenza=abs(minuti1-minuti2);


  lcd.setCursor(5 , 1);
  lcd.print(minuti_gen);
  lcd.setCursor(8 , 1);
  lcd.print(minuti1);
  lcd.setCursor(11 , 1);
  lcd.print(minuti2);
  lcd.setCursor(14 , 1);
  lcd.print(differenza);

  digitalWrite(led1,fsm_state);

  lcd.setCursor(0 , 1);
  lcd.print(led1);
  lcd.setCursor(3 , 1);
  lcd.print(fsm_state);

}



void print2digits(int number) {
  if (number >= 0 && number < 10)
    Serial.write('0');
  Serial.print(number);

}


void print3digits(int number2) {
  if (number2 >= 0 && number2 < 10)
    lcd.write('0');
  lcd.print(number2);
}

Di nulla. Di consigli te ne ho dati anche altri, ad esempio nello switch setti fms_state con lo stesso valore che verifichi.

Modifica questo:

case STATE_OFF:
    if(minuti_gen >= minuti2) 
    { fsm_state = STATE_OFF;
    }
    break;

cosi:

case STATE_OFF:
    if(ore_gen*100 + minuti_gen >= 1830) 
    { fsm_state = STATE_ON;
      rele=HIGH;
    }
    break;

Con questo esempio, dalle 18:30 dovrebbe accendere.

Ciao, ho effettuato le tue modifiche in più ho aggiunto una and nello STATE_OFF perchè mi dava interferenza con lo STATE_ON.
Unico problema che al relè fisico quando il suo stato va a 1 il suo led si accende ma il relè non chiude il contatto.

#include <Time.h>
#include <DS1302RTC.h>
#include <LiquidCrystal.h>

// Intestazione PIN DS1302 CLOCK
#define kCePin 2 // DS1302 - Chip Enable
#define kIoPin 3 // DS1302 - Input/Output
#define kSclkPin 4 // DS1302 - Serial Clock

DS1302RTC RTC(kCePin, kIoPin, kSclkPin);

// Intestazione PIN LCD 16x2
#define kRSLCD 11//LCD RS
#define kELCD   10//LCD E
#define kD4LCD 9 //LCD D4
#define kD5LCD 8 //LCD D5
#define kD6LCD 7 //LCD D6
#define kD7LCD 6 //LCD D7

LiquidCrystal lcd(kRSLCD, kELCD, kD4LCD, kD5LCD, kD6LCD, kD7LCD);

#define led1 12
#define STATE_OFF  0
#define STATE_ON   1
int fsm_state;
int rele;


void setup()
{

  pinMode(led1,OUTPUT);
  fsm_state = STATE_OFF;
  // Setup Serial connection
  Serial.begin(9600);
  lcd.begin(16, 2);


  Serial.println("RTC module activated");
  Serial.println();
  delay(500);


  if (RTC.haltRTC()) {
    Serial.println("The DS1302 is stopped.  Please run the SetTime");
    Serial.println("example to initialize the time and begin running.");
    Serial.println();
  }
  if (!RTC.writeEN()) {
    Serial.println("The DS1302 is write protected. This normal.");
    Serial.println();
  }

  delay(1000);

}


void loop()
{

  digitalWrite(led1,LOW);

  tmElements_t tm;

  if (! RTC.read(tm)) {        

    lcd.setCursor(0 , 0);
    lcd.print("Ore = ");
    lcd.setCursor(6 , 0);
    print3digits(tm.Hour);
    lcd.setCursor(8 , 0);
    lcd.write(':');
    lcd.setCursor(9 , 0);
    print3digits(tm.Minute);
    lcd.setCursor(11 , 0);
    lcd.write(':');
    lcd.setCursor(12 , 0);
    print3digits(tm.Second);
    lcd.setCursor(15 , 0);
    lcd.write('  ');

  }

  else {
    Serial.println("DS1302 read error!  Please check the circuitry.");
    Serial.println();
    delay(9000);
  }

  int ora1=21;
  int ora2=21;
  int minuti1=35;
  int minuti2=37;
  int differenza;
  int minuti_gen = tm.Minute;
  int ore_gen = tm.Hour;

  switch(fsm_state) {
  case STATE_ON:
    if(ore_gen*100 + minuti_gen >= 1845) 
    {
      fsm_state = STATE_OFF;
      rele=LOW;
    }
    break;

  case STATE_OFF:
    if((ore_gen*100 + minuti_gen >= 1843)&&(ore_gen*100 + minuti_gen < 1845) ) 
    { 
      fsm_state = STATE_ON;
      rele=HIGH;
    }
    break;
  }

  digitalWrite(led1,rele);

  differenza=abs(minuti1-minuti2);


  lcd.setCursor(5 , 1);
  lcd.print(minuti_gen);
  lcd.setCursor(8 , 1);
  lcd.print(minuti1);
  lcd.setCursor(11 , 1);
  lcd.print(minuti2);
  lcd.setCursor(14 , 1);
  lcd.print(differenza);



  lcd.setCursor(0 , 1);
  lcd.print(led1);
  lcd.setCursor(3 , 1);
  lcd.print(fsm_state);

}



void print2digits(int number) {
  if (number >= 0 && number < 10)
    Serial.write('0');
  Serial.print(number);
}


void print3digits(int number2) {
  if (number2 >= 0 && number2 < 10)
    lcd.write('0');
  lcd.print(number2);
}

albon87:
Unico problema che al relè fisico quando il suo stato va a 1 il suo led si accende ma il relè non chiude il contatto.

Cioè il led presente sul modulino si accende ma il led no ?

Non praticamente al posto del led in uscita ho messo un rele,(modulo relè 1 canale) dove al tempo predisposto si accende solo il suo led ma il contatto non varia...
Non capisco il perchè... non credo sia troppi assorbimenti......

Transistor :slight_smile:

Testato:
Transistor :slight_smile:
https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcSsmGHxf0pNexbsLwzE-XZrlnQTw7CufLJ2jW_MSRMCU9JtNr5BbA

e già predisposto in quel modo, non credo che ora abbia più assorbimento di prima visto che quando rimaneva sempre eccitato andava.... ora l'ho spostato sul pin 12 perchè all'avvio dell'arduino lampeggiava e si eccitava.
Non è cambiato niente da prima ad ora... Non saprei cosa potrebbe essere........ Un impostazione sbagliata?

se prima funzionava ed ora no e' rotto il rele', visto che dici che il led accende.
Posta una foto e lo schema di come lo hai connesso

no il rele funziona ho provato ad inserire un nuovo programma facendo con un semplice pulsante accendere e spegnere il rele e funziona senza modificare lo schema....
Facendo delle prove ora funziona ma il rele si accende e si spegne in continuazione molto velocemente...
Non credo sia un errore di circuito....

albon87:

...

switch(fsm_state) {
 case STATE_ON:
   if(ore_gen100 + minuti_gen >= 1845)
   { fsm_state = STATE_OFF;
     rele=LOW;
   }
   break;
 case STATE_OFF:
   if((ore_gen
100 + minuti_gen >= 1843)&&(ore_gen*100 + minuti_gen < 1845) )
   { fsm_state = STATE_ON;
     rele=HIGH;
   }
   break;
 }

A me pare hai impostato orari strani e/o usato male AND &&
Se in stato ON verifichi se orario >=18:45 lo metti a OFF
Se in stato OFF verifichi se orario >=18:43 AND orario <18:45 ??

Spiega un pò che volevi fare, dal codice non è chiaro.

Ho aggiunto questa parte “(ore_gen*100 + minuti_gen < 1845)” perchè prima mi dava problemi peggiori…
facendo la prova con un pulsante in questo programma il rele mi fa lo stesso lavoro di lampeggiare velocemente…

quindi rpima avevi rpoblemi di contatto,
ora sara' il sw.
la cosa importante e' che il led ed il rele' si comportano uguali, perche' se tu dici che il led risponde bene ed il rele' no allora non se ne esce visto che il led fa parte del pcb del rele'