Filtro antidisturbo su relè per serra automatizzata

Salve a tutti,
Purtroppo anch'io preso dall'entusiasmo sono cascato nel tranello di voler inserire nel mio progetto un Lcd ed una scheda da 2 relè.
Ho letto un po' in giro sul forum che in tanti si sono imbattuti nel mio stesso problema, con l'lcd che impazzisce all'attivazione del relè, specie se in ballo ci sono carichi induttivi, proprio come nel mio caso.
A differenza di molti però il mio Lcd non impazzisce appena il relè attacca la piccola pompa da 12V per innaffiare la serra automatizzata, anzi il tutto funziona egregiamente come da sketch, almeno fino a quando, dopo qualche giorno, con cadenza completamente casuale e senza alcun motivo evidente, il display smette di funzionare come deve e riporta caratteri casuali, senza però compromettere il normale funzionamento dell'Arduino.
Adesso ho letto che in molti suggeriscono di filtrare gli spike del relè attraverso dei condensatori, in quanto molto spesso sono proprio questi la causa delle interferenze con Lcd.
Premetto che avevo già provato a risolvere il problema separando le alimentazioni di Arduino e dei dispositivi comandati (nello specifico la suddetta pompa dell'acqua e una ventola da computer sempre da 12V), senza però che il problema sia sparito.
Visto che la mia conoscenza dell'elettronica è molto limitata vorrei cortesemente sapere se qualcuno potrebbe indicarmi come montare i condensatori in modo da far filtrare questi benedetti spike, e se secondo voi la radice del mio problema è effettivamente quella, oppure potrebbe essere un'altra..
Grazie mille!

... mmm ... potrebbe anche essere il sintono dell'esaurimento della memoria SRAM, ma senza vedere il codice è difficile da dirsi. ::slight_smile: Usi per caso la classe String ?

Guglielmo

Innanzi tutto grazie mille per la risposta..
Mi dispiace ma non so cosa sia la "classe String" quindi non so rispondere alla domanda :frowning:
In ogni caso allego il codice se può essere utile:

#include <LiquidCrystal.h>
#include "DHT.h"
#define DHTPIN 6
#define DHTTYPE DHT11
#define LCD_LIGHT_ON_TIME 4000
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int pompa=7;
const int ventola=8;
const int pulsante = 13;  //pulsante al pin 13
const int accensioneLcd = 10;   //comando transistor per accensione LCD al pin 10
const int galleggiante = 9;   //sensore galleggiante al pin 9
const int sensoreUmidita=A0;
const int led=A1;

int buttonState;
int lastButtonState = LOW;
int buttonPushCounter = 0;
int statoGalleggiante;

int lcdAcceso = 0;
int terreno;
int statoPompa = 0;
int statoVentola = 0;

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
unsigned long pausaGalleggiante1 = 150;
unsigned long pausaGalleggiante2 = 300;

String message = "       Attenzione!   Livello Acqua Insufficente        ";
int ii = 0;
int strLength;
String toShow;


void setup() {

  lcd.begin(16, 2);
  pinMode(led, OUTPUT);
  pinMode(pulsante, INPUT);
  pinMode(galleggiante, INPUT);
  pinMode(sensoreUmidita, INPUT);
  pinMode(pompa, OUTPUT);
  pinMode(ventola, OUTPUT);
  strLength = message.length();
  digitalWrite(accensioneLcd, HIGH);
  digitalWrite(pompa, HIGH);
  digitalWrite(ventola, HIGH);
  lcd.setCursor(3,0);
  lcd.print ("Benvenuto");
  delay(5000);
  lcd.clear();
  lcd.setCursor (3,0);
  lcd.print ("GReeNHoUse");
  lcd.setCursor(1,1);
  lcd.print ("firmware v.1.0");
  delay(5000);
  lcd.clear();
  delay(1000);
  Serial.begin(9600);
}



void loop() {

  statoGalleggiante = digitalRead(galleggiante);
  int reading = digitalRead(pulsante);
  int t = dht.readTemperature();
  int h = dht.readHumidity();
  int umiditaTerreno = analogRead(sensoreUmidita);
  int livelloAcqua = analogRead(galleggiante);
  terreno = map (umiditaTerreno, 540, 0, 0, 100);
  Serial.println(umiditaTerreno, DEC);

  if (reading != lastButtonState){
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay){
      if (reading != buttonState) {
      buttonState = reading;
      if (buttonState == HIGH && statoGalleggiante == HIGH){
      buttonPushCounter++;
      }
    }
  }

  lastButtonState = reading;

  if ( buttonPushCounter >= 4)
   {
      buttonPushCounter = 0;
   }
  

   switch ( buttonPushCounter){
    case 0:
            digitalWrite(accensioneLcd, HIGH);
            lcd.setCursor(0,0);
            lcd.print ("Umidita' Terreno: ");
            lcd.setCursor(0, 1);
            lcd.print("       ");
            lcd.setCursor(7, 1);       
            lcd.print(terreno, DEC);
            lcd.print("%      ");
            break;
 
    case 1:
            digitalWrite (accensioneLcd, HIGH);
            lcd.setCursor(0,0);
            lcd.print ("Hum. Aria: ");
            lcd.setCursor(0,1);
            lcd.print("Temperat.: ");
            lcd.setCursor(11, 0);
            lcd.print(h, DEC);
            lcd.print(" %   ");
            lcd.setCursor(11, 1);
            lcd.print(t, DEC);
            lcd.print((char)(223)); 
            lcd.print("C   ");
            break;

    case 2:
              digitalWrite (accensioneLcd, HIGH);
              if (statoVentola == 1){
              lcd.setCursor(0,0);
              lcd.print("Ventola:  ON      ");
            }
            
             if (statoVentola==0){
              lcd.setCursor(0,0);
              lcd.print("Ventola: OFF     "); 
            }
                                      
              if(statoPompa == 1){
              lcd.setCursor(0,1);
              lcd.print("Pompa:    ON      ");
              }
           
            if(statoPompa == 0){
              lcd.setCursor(0,1);
              lcd.print("Pompa: OFF      ");
              
            }
            break;
    case 3:
            digitalWrite (accensioneLcd, LOW);
            lcd.clear();
            break; 
              
 }




    
   
  if(statoGalleggiante == LOW){
    digitalWrite (pompa, HIGH);
    digitalWrite (led, HIGH);
    lcd.clear();
    digitalWrite(accensioneLcd, HIGH);
    toShow = message.substring(ii,ii+16);
    
    lcd.print(toShow);

    ii = ii + 2;

 
    if(ii>(strLength-16)) {
      
      ii = 0;
    }

  delay(500);
  }
    
   else{
    digitalWrite(led, LOW);
   }





  if (t>28){
  digitalWrite (ventola, LOW);
  statoVentola=1;
  }
  if (h>50){
    digitalWrite (ventola, LOW);
    statoVentola=1;
  }
    else if (t<=20 && h<=25){
      digitalWrite (ventola, HIGH);
      statoVentola=0;
    }
   
  if (terreno<=7 && statoGalleggiante == HIGH){
    digitalWrite (pompa, LOW);
    statoPompa=1;
  }
  else if (terreno>=30 && statoGalleggiante == HIGH){
    digitalWrite (pompa, HIGH);
    statoPompa=0;
  }


       
  }

serra.ino.ino.ino (4.6 KB)

F1L1PP0:
Mi dispiace ma non so cosa sia la "classe String" quindi non so rispondere alla domanda :frowning:

... emmm ... quindi siamo alle solite ... copia/incolla senza analizzare "cosa" si stà copiando/incollando ... :confused:

Certo che usi la classe String ...

String message = "       Attenzione!   Livello Acqua Insufficente        ";
...
String toShow;

... stai dichiarando delle variabili di tipo String !

Comunque procediamo per gradi, prima di tutto hai un'infinità di lcd.print() di stringhe costanti che puoi togliere dalla SRAM e mandare il flash ...
... ogni volta che hai una: lcd.print("... quello che c'è dentro ..."); trasformala in una: lcd.print(F("... quello che c'è dentro ...")); così da ridurre l'occupazione della SRAM e prova come va.

Fammi sapere ...

Guglielmo

Uhm...

lcd.begin(16, 2);
lcd.setCursor(0,0); lcd.print ("Umidita' Terreno: ");

Sono 18 caratteri! :slight_smile:

I vari const int, poi, non essendo necessario modificare i valori nel corso del programma, possono essere vantaggiosamente sostituiti con delle semplici direttive #define, con cui il valore viene inserito stabilmente al momento della compilazione.

P.s.: "DEC" in lcd.print non è necessario: basta scrivere lcd.print(terreno);

Ho provato a sostituire i vari lcd.print("... quello che c'è dentro ...") con lcd.print(F("... quello che c'è dentro ...")) ogni volta che potevo, dato che in alcuni casi, come ad esempio quando stampo sull'Lcd valori variabili (umidità del terreno, temperatura ecc.) l'aggiunta del suddetto comando mi genera un errore nella compilazione.
In ogni caso l'lcd stanotte mi è di nuovo impazzito...
Questo è il codice modificato:

#include <LiquidCrystal.h>
#include "DHT.h"
#define DHTPIN 6
#define DHTTYPE DHT11
#define LCD_LIGHT_ON_TIME 4000
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int pompa=7;
const int ventola=8;
const int pulsante = 13;  //pulsante al pin 13
const int accensioneLcd = 10;   //comando transistor per accensione LCD al pin 10
const int galleggiante = 9;   //sensore galleggiante al pin 9
const int sensoreUmidita=A0;
const int led=A1;

int buttonState;
int lastButtonState = LOW;
int buttonPushCounter = 0;
int statoGalleggiante;

int lcdAcceso = 0;
int terreno;
int statoPompa = 0;
int statoVentola = 0;

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
unsigned long pausaGalleggiante1 = 150;
unsigned long pausaGalleggiante2 = 300;

String message = "       Attenzione!   Livello Acqua Insufficente        ";
int ii = 0;
int strLength;
String toShow;


void setup() {

  lcd.begin(16, 2);
  pinMode(led, OUTPUT);
  pinMode(pulsante, INPUT);
  pinMode(galleggiante, INPUT);
  pinMode(sensoreUmidita, INPUT);
  pinMode(pompa, OUTPUT);
  pinMode(ventola, OUTPUT);
  strLength = message.length();
  digitalWrite(accensioneLcd, HIGH);
  digitalWrite(pompa, HIGH);
  digitalWrite(ventola, HIGH);
  lcd.setCursor(3,0);
  lcd.print (F("Benvenuto"));
  delay(5000);
  lcd.clear();
  lcd.setCursor (3,0);
  lcd.print (F("GReeNHoUse"));
  lcd.setCursor(1,1);
  lcd.print (F("firmware v.1.0"));
  delay(5000);
  lcd.clear();
  delay(1000);
  Serial.begin(9600);
}



void loop() {

  statoGalleggiante = digitalRead(galleggiante);
  int reading = digitalRead(pulsante);
  int t = dht.readTemperature();
  int h = dht.readHumidity();
  int umiditaTerreno = analogRead(sensoreUmidita);
  int livelloAcqua = analogRead(galleggiante);
  terreno = map (umiditaTerreno, 540, 0, 0, 100);
  Serial.println(umiditaTerreno, DEC);

  if (reading != lastButtonState){
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay){
      if (reading != buttonState) {
      buttonState = reading;
      if (buttonState == HIGH && statoGalleggiante == HIGH){
      buttonPushCounter++;
      }
    }
  }

  lastButtonState = reading;

  if ( buttonPushCounter >= 4)
   {
      buttonPushCounter = 0;
   }
  

   switch ( buttonPushCounter){
    case 0:
            digitalWrite(accensioneLcd, HIGH);
            lcd.setCursor(0,0);
            lcd.print (F("Umidita' Terreno"));
            lcd.setCursor(0, 1);
            lcd.print(F("       "));
            lcd.setCursor(7, 1);       
            lcd.print(terreno);
            lcd.print(F("%      "));
            break;
 
    case 1:
            digitalWrite (accensioneLcd, HIGH);
            lcd.setCursor(0,0);
            lcd.print (F("Hum. Aria: "));
            lcd.setCursor(0,1);
            lcd.print(F("Temperat.: "));
            lcd.setCursor(11, 0);
            lcd.print(h);
            lcd.print(F(" %   "));
            lcd.setCursor(11, 1);
            lcd.print(t);
            lcd.print((char)(223)); 
            lcd.print(F("C   "));
            break;

    case 2:
              digitalWrite (accensioneLcd, HIGH);
              if (statoVentola == 1){
              lcd.setCursor(0,0);
              lcd.print(F("Ventola:  ON      "));
            }
            
             if (statoVentola==0){
              lcd.setCursor(0,0);
              lcd.print(F("Ventola: OFF     ")); 
            }
                                      
              if(statoPompa == 1){
              lcd.setCursor(0,1);
              lcd.print(F("Pompa:    ON      "));
              }
           
            if(statoPompa == 0){
              lcd.setCursor(0,1);
              lcd.print(F("Pompa: OFF      "));
              
            }
            break;
    case 3:
            digitalWrite (accensioneLcd, LOW);
            lcd.clear();
            break; 
              
 }




    
   
  if(statoGalleggiante == LOW){
    digitalWrite (pompa, HIGH);
    digitalWrite (led, HIGH);
    lcd.clear();
    digitalWrite(accensioneLcd, HIGH);
    toShow = message.substring(ii,ii+16);
    
    lcd.print(toShow);

    ii = ii + 2;

 
    if(ii>(strLength-16)) {
      
      ii = 0;
    }

  delay(500);
  }
    
   else{
    digitalWrite(led, LOW);
   }





  if (t>28){
  digitalWrite (ventola, LOW);
  statoVentola=1;
  }
  if (h>50){
    digitalWrite (ventola, LOW);
    statoVentola=1;
  }
    else if (t<=20 && h<=25){
      digitalWrite (ventola, HIGH);
      statoVentola=0;
    }
   
  if (terreno<=7 && statoGalleggiante == HIGH){
    digitalWrite (pompa, LOW);
    statoPompa=1;
  }
  else if (terreno>=30 && statoGalleggiante == HIGH){
    digitalWrite (pompa, HIGH);
    statoPompa=0;
  }


       
  }

F1L1PP0:
... dato che in alcuni casi, come ad esempio quando stampo sull'Lcd valori variabili (umidità del terreno, temperatura ecc.) l'aggiunta del suddetto comando mi genera un errore nella compilazione.

.... scusa, ma io cosa avevo scritto ? ? ?

gpb01:
....hai un'infinità di lcd.print() di stringhe costanti che puoi togliere dalla SRAM e mandare il flash ...

... stringhe costanti e non ho mai parlato di variabili che, ovviamnete, in Flash non possono finire.

F1L1PP0:
In ogni caso l'lcd stanotte mi è di nuovo impazzito...

Quindi non basta recuperare memoria ... a questo punto serve che disegni uno schema esatto dei collegamenti, evidenziando bene come sono fatte le alimentazioni e come sono collegati tutti i vari moduli.

Guglielmo

Sono disturbi dei relè che non sempre arrivano al LCD ma quando arrivano ti fanno apparire $$$ ### ecc. ecc.
Ne abbiamo parlato diverse volte risolvendo il problema sui relé con dei filtri e sulla scheda LCD che penso sia la classica 16x2 oppure 20x4.
La differenza sostanziale è se ha l'interfaccia I2C oppure se il display è collegato a Arduino direttamente pin-to-pin e in questo caso è "normale" avere questi problemi.

Anzi, ho visto adesso che è collegato con tutti quei fili.

Ti consiglio vivamente di mettere una interfaccia I2C appiccicata al display (come quelle che vendono già I2C) ed in questo modo elimini il grosso dei disturbi e risparmi un sacco di porte di arduino

Ho recuperato il post dove parlavamo dei disturbi lcd (ho cercato "steve-cr lcd")

I piedini del display sono numerati dall'uno al 16

  • Tra piedino 6 e piedino 1 - Condensatore .1 (100nF)
  • Tra piedino 6 e piedino 2 - Resistenza 4k7

Fammi sapere.

Un condensatore fra un'uscita del processore e massa non è bello. Inoltre, non capisco che cosa faccia... Ritarda l'Enable...
Il problema sta nel fatto che il PCF8574, pur avendo uscite push-pull, per limitare l'occupazione di spazio nel chip (così dice il produttore) ha un piccolo MOSFET di pull-up con corrente limitata a 100uA (addirittura, se è un generatore di corrente costante, ha resistenza dinamica infinita). Quando le uscite sono a livello alto, quindi, è più o meno come se avessero in serie una resistenza di 50kOhm, perciò è facile che captino disturbi. Per evitare ciò, è sufficiente mettere una resistenza di pull-up tra ciascuna uscita del PCF8574 e +Vcc.

Il display è un 16x2 senza interfaccia l2c..quindi mi consigliate di montarne una e aggiungere le condensatori e resistenze?

Prova, prima, col condensatore e la resistenza, poi sei sempre a tempo a mettere le altre, no?

Per ultimo, se vedi che non te la cavi, passa alla I2C e vedrai che risolvi.

Ah...
Io non ho mai avuto problemi simili, ma mettendo l'ATMega328, il quarzo e il display su millefori non ho mai avuto problemi di interferenze, anche se, in realtà, non ho mai usato relè.

Datman:
Ah...
Io non ho mai avuto problemi simili, ma mettendo l'ATMega328, il quarzo e il display su millefori non ho mai avuto problemi di interferenze, anche se, in realtà, non ho mai usato relè.

Se vuoi averli basta che tocchi con un dito o con la punta di un cacciavite i piedini del display e... Voilà !

Ok grazie mille appena posso provo e poi vi do sapere

Se vuoi averli basta che tocchi con un dito o con la punta di un cacciavite i piedini del display e... Voilà !

Proverò... :slight_smile: