Get Adobe Flash player

Allarme per filtro frigo

User Rating:  / 0
PoorBest 

Link Articolo Originale: 

http://www.grix.it/viewer.php?page=10082

Avvisa del momento in cui occorre sostituire il filtro che depura l'acqua dei frigoriferi tipo americano.

Descrizione


Ciao a tutti i Grixiani, è da un pò che seguo con interesse questo sito e fino ad oggi non avevo avuto il tempo di proporre il mio primo schema.

Due anni fa ho comprato un frigorifero di quelli americani con il dispenser dell'acqua e del ghiaccio. Questi frigoriferi incorporano un filtro che depura l'acqua del rubinetto rendendola ottima. Il problema è che, almeno per il frigorifero in mio possesso, tale filtro va sostituito ogni sei mesi e costa oltre 60€. All'interno del frigorifero c'è una scheda elettronica con un timer che con il cambio di colore di una spia, segnale che sono passati i sei mesi e che quindi occorre sostiutirlo. Le prime volte l'ho sostiuito subito, poi, leggendo le istruzioni, ho notato che il filtro può trattare fino a circa 1100 litri di acqua che diviso per 180 giorni fa poco più di 6 litri al giorno.....e chi li beve?
Un'altro problema deriva dal fatto che sul pannello di comando, c'è un tasto che se premuto per 3 secondi azzera il timer. Va premuto dopo la sostituzione del filtro, ma vallo a spiegare a mio figlio di 3 anni e mia figlia di 18 mesi!!! (ora sarà chiaro perchè non ho avuto ancora il tempo di scrivere il mio primo articolo :)  )

Per questi motivi ho pensato di realizzare il circuito di figura 1 che funziona nel seguente modo:

 

clicca per ingrandire

Sul tubo dell'acqua che alimenta il frigorifero ho installato un contatore lanciaimpulsi (costo attorno ai 30€) che genera un impulso ogni 'x' litri di acqua passati. Il valore dei litri 'x' è relativo al K del contatore stesso ed è scritto su quest'ultimo. Vedremo più avanti come settare il software per i vari contatori. Il PIC16F88 legge costantemente il contatto del contatore e al superamento dei 1100 litri emette dieci bip con il buzzer BZ1 e fa lampeggiare 10 volte il led rosso D2.

Il pulsante P1 ha una duplice funzione:

  • se premuto brevemente emette tanti lampeggi e suoni quanti sono i litri contati fino a quel punto.La visualizzazione è fatta una cifra alla volta iniziando dalle migliaia, con tanti lampeggi della durata di 1/4 di secondo equivalenti alla cifra stessa. Poi viene fatta una pausa di un secondo, quindi vengono visualizzate le centinaia di litri e così via. Nel caso in cui la cifra sia uguale a zero, viene emesso un bip della durata di 1/4 di secondo. Esempio: se sono passati 509 litri e premo brevemente il pulsante, il led emetterà 5 lampeggi - pausa - 1 bip - pausa - 9 lampeggi.
  • se premuto per 2 secondi, resetterà il numero degli litri contati. Operazione necessaria nel momento del cambio del filtro.

Nel circuito ho previsto un connettore ICSP per la programmazione on-board del micro nel caso in cui qualcuno volesse apportare delle modifiche.

Il circuito viene alimentato da due pile a bottone che possono essere delle CR2016, CR2025 oppure CR2032. Ovviamente le ultime, garantiranno una maggior durata che è stimata in circa 200 gg, in 78 gg con le CR2016 e in 148 gg con le CR2032.

Lo stato delle batterie viene monitorato dal'ingresso analogico RA0 del PIC che legge la tensione di alimetazione per mezzo del partitore formato dalle resisrenze R3 e R4. La tensione di riferimeto Vref del convertitore analogico/digitale è determinata dal generatore di tensione U2 ed è fissata a 2,5volt. Il partitore divide a metà la tensione di alimentazione e quando la tensione delle batterie scenderà sotto i 5,1 volt, il PIC farà lampeggiare il led e suonare 3 volte il buzzer per avvisare del cambio delle batterie necessario. Per limitare i consumi sia il partitore che il generatore di tensione U2 non sono sempre alimentati, ma poichè sono collegati al pin RA2, lo saranno solo quando sarà necessario il controllo della tensione delle batterie. Sempre per limitare i consumi, il PIC per gran parte del tempo, è in modalità SLEEP e viene risvegliato dagli impulsi in ingresso al pin RB5.

Realizzazione

Per realizzare il circuito ho utilizzato CIRCAD che è free e il layout del circuito stampato è visibile in figura 2.

 

clicca per ingrandire

In figura 3 e 4 si può vedere la disposizione dei componenti.

clicca per ingrandire

Ho anche realizzato un'etichetta da apporre sul contenitore. Tutti i file relativi alla realizzazione possono essere scaricati nel link sottostante:

UserFiles/davide71/Filtro_frigo.zip

Nelle foto sotto si può vedere il mio prototipo montato e il filtro del mio frigorifero.

Circuito stampato

Per la realizzazione l'unica raccomandazione riguarda il montaggio dei due slot portapile. Sono montati uno sopra e uno sotto nel lato saldature. Consiglio di saldare prima quest'ultimo.

Programma

Il programma l'ho scritto in C ed il compilatore che ho usato è il MICROC. Tutto il progetto è prelevabile al seguente indirizzo:

UserFiles/davide71/Filtro_frigo_sorgenti(1).zip

Io ho la versione completa, ma poichè la dimensione non supera 1k di memoria, dovrebbe essere complilabile anche con quella free. Il sorgente è abbastanza semplice ed è il seguente:

/*

 * Nome progetto:     Filtro_frigo

 * Scritto da:
     Davide Bandini   06 agosto 2011
     rev 1.1          19 novembre 2011

 * Descrizione:       Legge gli impulsi di un contatore e segnala quando è ora
                      di sostituire il filtro che depura l'acqua nei dispenser
                      dei frigoriferi side-by-side

 * Configurazione:
     MCU:             P16F88
     Dev.Board:       bread-board
     Oscillatore:     4.0000 MHz interno
     Software:        mikroC v.8.2

*  Note:

*/

# define      VREF        PORTA.F2
# define      IMPULSI     PORTB.F5
# define      RESET       PORTB.F4
# define      BATTERIA    PORTB.F3
# define      BUZZER      PORTB.F2
# define      ON          1
# define      OFF         0

// variabili

unsigned char cambio_filtro=0;         // flag per il cambio del filtro
unsigned char ripeti=0;                // flag per la ripetizione del bip del cambio filtro
unsigned char aggiorna_eeprom=0;       // flag per la scrittura in eeprom
unsigned char bip_batteria=0;          // contatore per il bip del cambio batteria
unsigned char k=100;                   // k del contatore (litri per ogni impulso)
unsigned char beep=0;                  // per l'emissione del suono nella visualizzazione dei litri filtrati
unsigned int temp;                     // variabile temporanea
unsigned int a;                        // variabile temporanea
unsigned int litri_max=1100;           // litri massimi che può trattare il filtro
unsigned int litri=0;                  // contatore per i litri filtrati
unsigned int v_batt=0;                 // per la misura della tensione delle batterie

/* -------------------------------------------------- */
/* ----------  gestione degli interrupts  ----------- */
/* -------------------------------------------------- */

void interrupt() {

//---------- gestisce la pressione dei pulsanti --------------------------------

     if (INTCON.RBIF) {

     // controlla se l'interrupt è l'ingresso degli impulsi

        if (!IMPULSI) {
           Delay_ms(100);                     // attesa per antibounce
           if (!IMPULSI) {
              litri=litri+K;                  // incrementa i litri
              aggiorna_eeprom=1;              // attiva flag per scrivere il nuovo valore dei litri
              if (cambio_filtro==1) ripeti=1; // fa ripetere i 10 bip ad ogni impulso
                                              // successivo a quello che determina il
                                              // cambio filtro come promemoria finchè
                                              // non viene premuto il reset
              if (litri==litri_max) {
                 cambio_filtro=1;             // attiva il flag per il cambio filtro
                 ripeti=1;
              }
           }
        }

     // controlla se l'interrupt è stato il reset

        if (!RESET) {
                    Delay_ms(100);            // attesa per l'antibounce
                    if (!RESET) {
                                Delay_ms(2000);
                                
                                // se premuto per più di un secondo resetta perchè ho cambiato il filtro
                                
                                if (!RESET) {
                                            Delay_ms(30);
                                            BATTERIA=ON;                  // accendo il led
                                            BUZZER=ON;                    // attivo il buzzer
                                            Delay_ms(2000);
                                            BATTERIA=OFF;                 // spengo il led
                                            BUZZER=OFF;                   // spengo il buzzer
                                            cambio_filtro=0;
                                            litri=0;
                                            ripeti=0;
                                            aggiorna_eeprom=1;            // scrivo 0 litri nella eeprom
                                            }

                                // altrimenti visualizza tanti lampeggi e suoni quanti sono i litri filtrati
                                
                                else {
                                      for (a=1000; a>0; a/=10){                  // eseguo il ciclo 4 volte (4 cifre)
                                      temp=(litri/a)%10;                         // seleziono una cifra alla volta
                                      
                                          // eseguo questo ciclo se la cifra>0 oppure se è=0 dopo almeno una cifra>0

                                          if (temp || beep) {
                                          
                                               // eseguo questo se la cifra è=0 dopo almeno una cifra>0

                                               if (!temp) {
                                                          BUZZER=ON;             // emetto un breve bip
                                                          Delay_ms(250);
                                                          BUZZER=OFF;
                                                          Delay_ms(250);
                                                          }

                                               // eseguo questo se la cifra è>0

                                               else  while (temp) {
                                                                 beep=1;         // questo segnala al ciclo successivo che
                                                                                 // c'è stata la prima cifra>0
                                                                 BATTERIA=ON;    // emetto un lampeggio
                                                                 Delay_ms(250);
                                                                 BATTERIA=OFF;
                                                                 Delay_ms(250);
                                                                 temp--;         // decremento temp
                                                                 }
                                                           Delay_ms(750);        // ritardo fra la visualizzazione di ogni cifra
                                                           }
                                                         }
                                     beep=0;                                     // resetto beep dopo aver visualizzato tutto
                                     }
                                }
                     }
     INTCON.RBIF = 0;           // resetta l'interrupt
     }
 }

// ---------- funzione principale ----------------------------------------------

void main() {


  ANSEL = 0x01;                      // setta RA0 analogico e gli altri digitali
  ADCON1 = 0x20;                     // imposta RB3 = Vref+
  TRISA = 0x09;                      // setta PORTA
    PORTA = 0x00;                      // azzera PORTA
  TRISB = 0x30;                      // setta PORTB
  PORTB = 0x00;                      // azzera PORTB
  OPTION_REG = 0x0F;                 // abilita le pull-up su PORTB+prescaler 1/128 al WDT
  WDTCON = 0x17;                     // reset WDT ogni 20 minuti
  INTCON = 0x08;                     // abilita interrupt su PORTB
  OSCCON = 0x6E;                     // imposta il clock interno a 4MHz
  INTCON.GIE = 1;                    // attiva gli interrupt


 // legge in eeprom i litri filtrati
 
 litri=Eeprom_Read (0x00);                  // leggo gli 8 bit più significativi
 litri<<=8;
 litri=litri+Eeprom_Read (0x01);            // leggo e sommo gli 8 bit meno significativi
 
 if (litri>=litri_max) {                    // se >=litri_max devo cambiare il filtro
                cambio_filtro=1;
                ripeti=1;
                }

 if (litri==0xFF) {                         // se acceso per la prima volta scrive i litri=0
                litri=0;
                Eeprom_Write(0x00, 0x00);   // scrive nella eeprom 0
                Eeprom_Write(0x01, 0x00);
                }
 Delay_ms(100);


 // loop infinito
 
 while(1) {
 
          // verifica se devo cambiare il filtro

          if (cambio_filtro & ripeti) {
          
                             // si allora emette 10 bip
                             
                             for (a=0; a<10; a++) {
                                 if (litri==0) break;    // se nel frattempo ho premuto reset
                                 BUZZER=ON;
                                 BATTERIA=ON;
                                 Delay_ms(500);
                                 BUZZER=OFF;
                                 BATTERIA=OFF;
                                 Delay_ms(500);
                                 }
                             ripeti=0;
                             }

          // verifica se la batteria è scarica  (al reset del WDT o ogni impulso/pressione tasto)
          
          VREF=ON;                        // accende la tensione di riferimento
          v_batt = Adc_Read(0);           // legge la tensione della batteria (canale AN0)
          VREF=OFF;                       // spegne la tensione di riferimento
          
          // se la tensione è < 5,1 V
          
          if (v_batt<=720) {
                         BATTERIA=ON;
                         Delay_ms(20);
                         BATTERIA=OFF;
                         bip_batteria++;
                         
                         // se il led ha fatto 9 lampeggi (3,5 ore) emette 3 bip
                         
                         if (bip_batteria==9) {
                         
                                      for (a=0; a<3; a++) {
                                                BUZZER=ON;
                                                Delay_ms(1000);
                                                BUZZER=OFF;
                                                Delay_ms(1000);
                                                }

                                      bip_batteria=0;
                                      }
                         }

           // se deve aggiornare i valori nella eeprom
           
           if (aggiorna_eeprom) {
                               temp=litri>>8;
                               Eeprom_Write(0x00, temp);   // scrive gli 8 bit MSB dei litri nella eeprom
                               temp=litri & 0xFF;
                               Eeprom_Write(0x01, temp);   // scrive gli 8 bit LSB dei litri nella eeprom
                               aggiorna_eeprom=0;
                               }

          // se non devo cambiare il filtro e/o la batteria è carica va in sleep

          asm {
              sleep
              nop
              clrwdt         // azzera il watchdog
              }
          }

}//~

Inizialmente c'è la definizione di alcune costanti e la dichiarazione delle variabili. Nella variabile K dovrete mettere il valore del vostro contatore affinchè il conto dei litri possa ritornare con quelli effettivamente passati. Nel mio caso il contatore è un K=100 (1 impulso ogni 100 litri). Nella variabile litri_max occorrerà mettere invece il numero massimo dei litri che il vostro filtro può trattare. Nel mio caso 1100 litri.

Segue la routine di interrupt che si occupa della gestione dell'interrupt generato dal contalitri e della pressione del pulsante P1 (RESET).

C'è poi la funzione main che inizializza gli ingressi e le uscite del PIC, setta gli interrupt, il watchdog per un risveglio ogni 20 minuti e l'oscillatore interno a 4MHz.

Poi vengono letti i litri nella EEPROM del PIC perchè nel caso di sostituzione delle batterie se non fossero stati salvati i litri letti fino a quel punto, il pic ripartirebbe da zero. 

Segue un ciclo infinito che si occupa di emettere 10 lampeggi/bip se occorre cambiare il filtro, verificare lo stato della batteria facendo un breve lampeggio seguito de 3 bip nel caso sia scarica, salvare il nuovo valore dei litri nel caso ci sia stato un nuovo impulso ed infine se non c'è il filtro da sostituire e le battrie sono buone, mettere il PIC in modalità SLEEP per ridurre al massimo i consumi. 

Il codice è abbastanza commentato e chiedo scusa se potrà contenere procedure laboriose che potrebbero essere semplificate, ma sono autodidatta e comunque così com'è funziona.

Vi ringrazio per la lettura e spero che questo circuito possa servire a qualcuno per lo scopo per cui è nato o chissà magari come contatore per altre applicazioni dovi si ha la necessità di segnalare con un allarme acustico/visivo il raggiungimento di un certo numero di impulsi.

Un saluto a tutti

Davide

Login Form

Elettronica Open Source