Arduino si blocca dopo ore o giorni di funzionamento

Salve a tutti,
dopo un pò di tempo sono costretto a chiedervi di nuovo aiuto.
Ho realizzato un termoregolatore che grazie a 2 sonde DS18B20, mi legge 2 diverse temperature, e in base a quella più alta mi eccita o meno un relè. Inoltre se una delle 2 temperature è al di sotto di una certa soglia e ho un consenso esterno, mi abilita una seconda uscita.
Il sistema funziona, ma dopo alcune ore, o dopo uno o 2 giorni si blocca.
La lettura della temperatura resta congelata e cosi le uscite a relè.
Sono passato da Nano ad Uno e non è cambiato nulla.
Ho separato le alimentazioni di Arduino e del resto del circuito e non è cambiato nulla.
Ho alimentato le sonde da 3,3V a 5V e non è cambiato nulla.
Ho sostituito i relè, con relè shield module e niente.
Ho cercato di rendere meno pesante lo sketch ma nulla.
avete qualche idea o suggerimento?
di seguito il code e lo schema di collegamento.
Grazie.


#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>

#define Consenso 13
#define P_Caldaia 3
#define P_Boiler 5
#define ONE_WIRE_BUS_1 2
#define ONE_WIRE_BUS_2 4
#define P_Auto 7
#define Uscita_EV 6
#define Uscita_Ricircolo 10

#define Led_Cal 12
#define Led_Boi 11
#define Led_Man 9
#define Led_Aut 8
int isteresi = 1.0f;
int stato = 1;
int x = 0;
int T_C = 65.0; // Setpoint temperatura Caldaia ( superiore a:)
int T_B = 54.0;  // Setpoint temperatura Boiler (inferiore a:)
int T_MAX_C= 74.0; // Setpoint alta temperatura Caldaia                                                     
                         
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
                          
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

OneWire oneWire_in(ONE_WIRE_BUS_1);
OneWire oneWire_out(ONE_WIRE_BUS_2);

DallasTemperature sensor_Caldaia(&oneWire_in);
DallasTemperature sensor_Boiler(&oneWire_out);

//LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C LCD1(0x27,16,2);

void setup() {
  //Serial.begin(9600); //Inizializzazione porta seriale. Nascondo tutto per evitare il funzionamento in caso non sia connesso al PC 
  pinMode(P_Caldaia, INPUT); // PULSANTE CALDAIA IN MANUALE
  pinMode(P_Boiler, INPUT); // PULSANTE BOILER IN MANUALE
  pinMode(P_Auto, INPUT); // PULSANTE AUTOMATICO
  pinMode(Consenso, INPUT); // CONSENSO ESTERNO
  pinMode(Led_Aut, OUTPUT); // LED AUTOMATICO INSERINTO
  pinMode(Led_Man, OUTPUT); // LED MANUALE INSERINTO
  pinMode(Uscita_EV, OUTPUT); // USCITA Uscita_EV SE HIGH FUNZIONA BOILER
  pinMode(Uscita_Ricircolo, OUTPUT); // USCITA Uscita_EV SE HIGH FUNZIONA BOILER
  pinMode(Led_Cal, OUTPUT); // LED FUNZIONAMENTO A CALDAIA
  pinMode(Led_Boi, OUTPUT); // FUNZIONAMENTO A BOILER
  digitalWrite(Uscita_EV, LOW); // IMPOSTA LO STATO 0 DELL'EVALL'AVVIO DEL PROGRAMMA
  digitalWrite(Led_Cal, HIGH); // IMPOSTA LO STATO 0 DEL LED CALDAIA ALL'AVVIO DEL PROGRAMMA
  
  //Inizializzazione display OLED. 
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {for(;;);}
  display.display();display.clearDisplay();
  
  //Inizializzazione display LCD 16x2.
  Wire.begin();
  LCD1.init();
  LCD1.backlight();
  
  sensor_Caldaia.begin(); //Inizializzazione sensore 1
  sensor_Boiler.begin(); //Inizializzazione sensore 2
}

void loop() {  
  //leggo lo stato dei pulsanti pulsanti
  int p1 = digitalRead(P_Caldaia);
  int p2 = digitalRead(P_Boiler);
  int p3 = digitalRead(P_Auto);
  int p4 = digitalRead(Consenso);

   float Temp_Caldaia = sensor_Caldaia.getTempCByIndex(0);
   float Temp_Boiler = sensor_Boiler.getTempCByIndex(0);
   sensor_Caldaia.requestTemperatures();
   sensor_Boiler.requestTemperatures();
   
   // Impostazioni riga 1 per scrittura su display OLED   
   display.clearDisplay();  
   display.setTextSize(2);      // Normal 1:1 pixel scale
   display.setTextColor(WHITE); // Draw white text
   display.setCursor(x, 0);     // Start at top-left corner
   display.cp437(true);
                              
  float tempC = (Temp_Caldaia); 
  if (tempC == -127.00) {display.print("Err.Cald.");}else {display.print("Cal ");display.print(tempC,1);display.print(" C");}

  if (tempC == -127.00) {LCD1.setCursor(0,0); LCD1.print("Errore Caldaia  ");}else {LCD1.setCursor(0,0);LCD1.print("Temp.Cal. ");LCD1.print(tempC,1); LCD1.print(" C");}

  // Impostazioni riga 2 per scrittura su display OLED                        
  display.display();
  display.setTextSize(2);      // Normal 1:1 pixel scale
  display.setTextColor(WHITE); // Draw white text
  display.setCursor(x, 16);     // Start at top-left corner
  display.cp437(true); // Use full 256 char 'Code Page 437' font
                         
  float tempB = (Temp_Boiler);
  if (tempB == -127.00) {display.print("Err.Boil.");}else {display.print("Boi ");display.print(tempB,1);display.print(" C");}
  display.display();
  if (tempB == -127.00) {LCD1.setCursor(0,1); LCD1.print("Errore Boiler   ");}else {LCD1.setCursor(0,1);LCD1.print("Temp.Boi. ");LCD1.print(tempB,1);LCD1.print(" C");} 
  
  if (x >= 128) x = 0;
  switch (stato){
    case 1:
    digitalWrite(Led_Aut, HIGH);
    digitalWrite(Led_Man, LOW);
   if (Temp_Caldaia > Temp_Boiler + isteresi) {
    digitalWrite(Uscita_EV, LOW);
    digitalWrite(Led_Cal, HIGH);
    digitalWrite(Led_Boi, LOW);
   }if (Temp_Caldaia < Temp_Boiler - isteresi) {
    digitalWrite(Uscita_EV, HIGH);
    digitalWrite(Led_Cal, LOW);
    digitalWrite(Led_Boi, HIGH);   }
  
  if (Temp_Boiler < T_B && p4 == HIGH || Temp_Caldaia > T_MAX_C && p4 == HIGH){      // Avvia la circolazione se temp. boiler è bassa
  digitalWrite(Uscita_Ricircolo, HIGH);} else { digitalWrite(Uscita_Ricircolo, LOW);}
  
    //cambio di stato se:
    if (p1 && !p2 && !p3) stato = 2;
    if (!p1 && p2 && !p3) stato = 3;
      
    break;    
    case 2:
    digitalWrite(Led_Aut, LOW);
    digitalWrite(Led_Man, HIGH);
    digitalWrite(Uscita_EV, LOW);
    digitalWrite(Led_Cal, HIGH);
    digitalWrite(Led_Boi, LOW);
    
   if (Temp_Boiler < T_B && p4 == HIGH || Temp_Caldaia > T_MAX_C && p4 == HIGH){      // Avvia la circolazione se temp. boiler è bassa
   digitalWrite(Uscita_Ricircolo, HIGH);} else { digitalWrite(Uscita_Ricircolo, LOW);}
   
    //cambio di stato se:
    if (!p1 && p2 && !p3) stato = 3;
    if (!p1 && !p2 && p3) stato = 1;
    
    break;
    case 3:
    digitalWrite(Led_Aut, LOW);
    digitalWrite(Led_Man, HIGH);
    digitalWrite(Uscita_EV, HIGH);
    digitalWrite(Led_Cal, LOW);
    digitalWrite(Led_Boi, HIGH);
    
   if (Temp_Boiler < T_B && p4 == HIGH || Temp_Caldaia > T_MAX_C && p4 == HIGH){      // Avvia la circolazione se temp. boiler è bassa
   digitalWrite(Uscita_Ricircolo, HIGH);} else { digitalWrite(Uscita_Ricircolo, LOW);}

     //cambio di stato se:
     if (p1 && !p2 && !p3) stato = 2;
     if (!p1 && !p2 && p3) stato = 1;
    break;}
      
    delay(10);}

Non vedo nello schema elettrico l'unione del GND dell'arduino e del resto del circuito.
È una svista o manca anche nel montaggio vero e proprio?
Entrambi i GND devono essere collegati.

Ciao, i GND sono in comune. L’alimentatore 230/5v ha già in comune i GND.

Se può essere di aiuto, ne ho realizzato un altro di regolatore per l’acquario, partendo da questo sketch ed eliminando sia a livello hardware che software:
Il display LCD 16x2
La seconda sonda DS18B20
Il relè di uscita Ricircolo
Il consenso di abilitazione ricircolo.
Il sistema si bloccava irregolarmente dalle 3 alle 20 ore.

Sarebbe meglio usare uno degli alimentatori per alimentare tutta la logica (inclusi sensori e display) ed il secondo per alimentare solo i rele', in questo caso ci vorrebbero schedine rele' con fotoaccoppiatore, in modo da mantenere tutto separato (inclusa la massa dell'alimentazione rele'), e montare fisicamente il tutto in modo che i cavi dell'alimentazione rele' ed i rele' stessi fossero il piu distante possibile (compatibilmente con il contenitore) da tutto il resto, perche' a volte basta che i cavi corrano insieme per captare impulsi di disturbo.

Poi su quello "schema", non vedo alcun condensatore di filtraggio, e neppure degli antirimbalzo sui pulsanti, ma questo e' un'altro discorso.

Ciao,
Provato sulla mia pelle, assicurati che le connessioni siano stabili e non ballerine... meglio utilizzare morsetteria a vite...

Utilizzi interrupt? (Non ho visto il tuo codice) Se si ancora più attenzione alle connessioni... in caso di pullup o pulldown non utilizzare quelle interne ad arduino, meglio le esterne. Il display i2c quanto dista da Arduino? Io mi permetto di consigliarti di fare foto del tutto posto sul campo per far vedere qualità cavi e connessioni.

Io sono molto poco esperto, ma questi piccoli accorgimenti ho capito essere la prima cosa da verificare e attenzionare.

Ciao e buona fortuna :slight_smile:

Ciao, grazie delle dritte,
Ti risp alle domande.
I display sono vicino, circa 15cm.
I cavi interni sono saldati, i cavi esterni, quali sonde, consenso, alimentazione e contatti dei relè sono su morsettiera a vite.
Internamente allo strumento, i cavi ho cercato di separarli fin quanto possibile.
Comunque il problema mi capita anche ricostruendo tutto su breadboard con altro arduino altri relè altri display e sonde.

Ciao, non ci sono condensatori, dove potrei metterli? E di che taglia?
I relè ho provato quelli pilotati da transistor, a questo punto provo con i foto accoppiati.

Ma hai rele' singoli, o schedine gia fatte ?

Si, quelli hanno un transistor, ma non l'opto, e le masse dell'alimentazione rimangono in comune, per cui se qualche impulso passa (potrebbe rientrare anche attraverso la massa), potrebbe bloccare il micro o mandarlo in tilt.

Non e' detto che sia per forza quella la causa, ma e' una possibilita'.

Per avere qualche certezza in più basta togliere i relè e sostituirli con un led. E poi aspettare qualche giorno... :crazy_face:

Ciao, Ale.

Ok, provo a ricablare tutto a banco e faccio le varie prove. Nel frattempo comprobi relè optoisolati, tanto sono sempre buoni :joy:

Cosa genera il segnale "Consenso"?

Il “consenso” è associato a una variabile P4.
In realtà è un segnale esterno, contatto pulito di un relè, che mi indica quando la pompa della caldaia è in funzione. Questo mi serve ad abilitare o meno la logica del “Ricircolò”.

È stato aggiunto in un successivo step. Il programma andava in blocco già da prima.
:wink:

Se il programma stava già fallendo prima, quello che sto per dire non risolverà nulla. Ma hai sbagliato a fare il "PULL-DOWN" del segnale di consenso.
Secondo me questo sarebbe il modo corretto:

1 Like

Per la fretta sullo schema ho sbagliato il collegamento del resistore, ma in realtà è giusto. È collegato come tutti gli altri pulsanti.
Sorry.

@Snake-84: dallo schema che posti vedo adesso segnali a 230V ... ma tu suai interagendo con oggetti che lavorano a 230V ?

Guglielmo

I 230v sono gli ingressi degli alimentatori 5VDC

Ok, bene, ed i relè invece cosa comandano?

Guglielmo