PiumaLab

Idee, esperimenti, tentativi e molto altro

Display per il livello di una cisterna

pozzo In questo articolo vedremmo come costruire un dipositivo in grado di leggere e visualizzare in un display l'altezza del livello di acqua in un pozzo o una cisterna. Utilizzeremo un dispositivo hardware Open Source chiamato Arduino, un sensore ad ultrasuoni per misurare l'altezza dell'acqua, un display LCD di 16 caratteri su due linee e un buzzer che ci avvertirà se il livello supera una certa soglia.

Panoramica

Il progetto, come abbiamo già accennato, è composto da più parti. Un sensore sonar da posizionare nella parte alta del pozzo (lontano dall'acqua) che guarda verso il basso così da misurare la distanza tra il punto più alto del pozzo e l'acqua. Facendo una semplice differenza tra l'altezza dal fondo al sensore e la misura letta otteniamo l'altezza dell'acqua. Ad intervalli di tempo prestabiliti verrà letta la quantità dell'acqua e visualizzata sul display. Se il livello supera una soglia scatterà un allarme che fa suonare il buzzer fino a quando il livello scenderà di nuovo sotto la soglia o quando si disattiva manualmente la suoneria.

Arduino controlla la logica di funzionamento, tramite un programma che vedremo di seguito, e gestisce tutti i dispositivi.

Arduino

Arduino è una piattaforma elettronica open-source basata sulla semplicità e la facilità di utilizzo. È proprio per queste sue caratteristiche che viene utilizzata da artisti, design, hobbisti e chiunque si interessi di creare oggetti o ambienti interattivi.

Supporta un vasto numero di sensori ed è programmabile attraverso un linguaggio che ha molte affinità con il C. Dal sito del progetto è possibile scaricare un enviroment con editor, compilatore e funzione di upload. Tutto ciò di cui abbiamo bisogno per programmare Arduino. È possibile anche utilizzare strumenti a linea di comando ma ora non ci occuperemo di questo.

Schema elettrico

PCB

Download pcb per ExpressPCB here

Download pcb per ExpressPCB

File size: 0 Byte

Sketchbook

Di seguito c'è il programma caricato su Arduino. Il codice è molto semplice soprattutto se già si conosce il C o il C++. Da notare che manca la funzione main(), l'esecuzione inizia invocando la funzione setup() una sola volta all'avvio del dispositivo e poi ciclicamente la funzione loop().

/* -*- mode: c -*- */
/**
 * pozzo.pde
 * version: 1.2
 */
 
#include <LiquidCrystal.h>
 
#define PING_PIN 13
#define BUZZER_PIN 8
#define SWITCH_INT 0 /* 0 => pin 2 */
#define PI 3.1415926535898
#define SUPERFICE_BASE (R_POZZO * R_POZZO * PI)
#define SIZE_BAR (16 * 5)
#define ALARM_ICON 0 /* code */
#define SOUND_ICON 6 /* code */
#define SOUND_ICON_ON 7 /* code */
 
#define R_POZZO 0.5 /* raggio pozzo (m) */
#define H_POZZO 146.0 /* cm */
#define SOGLIA_ALLARME_1 100 /* cm */
#define SOGLIA_ALLARME_2 120 /* cm */
#define DELAY_0 60000 /* ms; 1000 * 60 * 1 = 1 min */
#define DELAY_1 600 /* ms */
#define DELAY_2 200 /* ms */
 
/* initialize the library with the numbers of the interface pins */
LiquidCrystal lcd(12, 11, 5, 4, 3, 6);
 
int mute = 0;
 
byte *getChar(int n, byte newChar[]) {
  int i;
  byte code[5] = {
    B10000,
    B11000,
    B11100,
    B11110,
    B11111};
 
  for (i = 0; i < 8; i++)
    newChar[i] = code[n - 1];
 
  return newChar;
}
 
void setup() {
  int i;
  float h;
  byte newChar[8];
 
  /* set up the LCD's number of rows and columns: */
  lcd.begin(16, 2);
 
  for (i = 1; i < 6; i++)
    lcd.createChar(i, getChar(i, newChar));
 
  newChar[0] = B00000;
  newChar[1] = B00100;
  newChar[2] = B01010;
  newChar[3] = B01010;
  newChar[4] = B11111;
  newChar[5] = B00100;
  newChar[6] = B00000;
 
  lcd.createChar(ALARM_ICON, newChar);
 
  newChar[0] = B00011;
  newChar[1] = B00101;
  newChar[2] = B11001;
  newChar[3] = B11001;
  newChar[4] = B11001;
  newChar[5] = B00101;
  newChar[6] = B00011;
 
  lcd.createChar(SOUND_ICON, newChar);
 
  newChar[0] = B00100;
  newChar[1] = B10010;
  newChar[2] = B01001;
  newChar[3] = B01001;
  newChar[4] = B01001;
  newChar[5] = B10010;
  newChar[6] = B00100;
 
  lcd.createChar(SOUND_ICON_ON, newChar);
 
  pinMode(BUZZER_PIN, OUTPUT);
 
  /**
   * LOW to trigger the interrupt whenever the pin is low,
   * CHANGE to trigger the interrupt whenever the pin changes value
   * RISING to trigger when the pin goes from low to high,
   * FALLING for when the pin goes from high to low.
   */
  attachInterrupt(SWITCH_INT, button, RISING);
 
  /* initialize serial communication */
  Serial.begin(9600);
}
 
void loop() {
  long hWatherCm;
  int litres;
 
  hWatherCm = read_height();
  if (check_alarm(hWatherCm) != 0) /* read again wather height */
    hWatherCm = read_height();
 
  lcd.clear();
 
  print_histogram(hWatherCm);
 
  lcd.setCursor(0, 1);
 
  lcd.print(hWatherCm);
  lcd.print(" cm - ");
 
  // litres = SUPERFICE_BASE * (hWather / 100.0) * 1000
  litres = floor(SUPERFICE_BASE * hWatherCm * 10);
  lcd.print(litres);
  lcd.print(" l ");
 
  lcd.setCursor(14, 1);
  lcd.write(SOUND_ICON);
  lcd.setCursor(15, 1);
  if (!mute)
    lcd.write(SOUND_ICON_ON);
  else
    lcd.write('X');
 
/*
  Serial.print("cm = ");
  Serial.println(hWatherCm);
*/
 
  switch (check_alarm(hWatherCm)) {
  case 1:
    lcd.setCursor(0, 0);
    lcd.write((uint8_t)ALARM_ICON);
 
    buzz(200);
    delay(DELAY_1);
    break;
 
  case 2:
    lcd.setCursor(0, 0);
    lcd.write((uint8_t)ALARM_ICON);
 
    buzz(200);
    delay(200);
    buzz(200);
    delay(DELAY_2);
    break;
 
  case 0: // no alarm
    delay(DELAY_0);
  }
}
 
void print_histogram(int hWatherCm) {
  int i;
  int bloks;
  float histogram;
 
  // hWatherCm : HPOZZO = histogram : SIZE_BAR
  histogram = (SIZE_BAR * hWatherCm) / H_POZZO;
  histogram = histogram + 0.5;
 
  bloks = (int)histogram / 5;
 
  for (i = 0; i < bloks; i++)
    lcd.write(5);
 
  if ((int)(histogram) % 5 > 0)
    lcd.write((int)(histogram) % 5);
}
 
long read_height() {
  /**
   * establish variables for duration of the ping,
   * and the distance result in centimeters:
   */
  long duration, hWatherCm;
 
  /**
   * The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
   * Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
   */
  pinMode(PING_PIN, OUTPUT);
  digitalWrite(PING_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(PING_PIN, HIGH);
  delayMicroseconds(5);
  digitalWrite(PING_PIN, LOW);
 
  /**
   * The same pin is used to read the signal from the PING))): a HIGH
   * pulse whose duration is the time (in microseconds) from the sending
   * of the ping to the reception of its echo off of an object.
   */
  pinMode(PING_PIN, INPUT);
  duration = pulseIn(PING_PIN, HIGH);
 
  /* convert the time into a distance */
  hWatherCm = H_POZZO - microseconds_to_centimeters(duration);
 
  if (hWatherCm < 0)
    return 0;
 
  if (hWatherCm > H_POZZO)
    return H_POZZO;
 
  return hWatherCm;
}
 
void buzz(int msec) {
  if (!mute)
    digitalWrite(BUZZER_PIN, HIGH);
  delay(msec);
  digitalWrite(BUZZER_PIN, LOW);
}
 
int check_alarm(int hWatherCm) {
  if (hWatherCm > SOGLIA_ALLARME_1) {
     if (hWatherCm < SOGLIA_ALLARME_2)
       return 1;
     else
       return 2;
  }
  return 0;
}
 
long microseconds_to_centimeters(long microseconds) {
  /**
   * The speed of sound is 340.29 m/s or 29.4 microseconds per centimeter.
   * The ping travels out and back, so to find the distance of the
   * object we take half of the distance travelled.
   */
  return microseconds / 29.387 / 2;
}
 
void button() {
  //  Serial.println("Pulsante premuto");
  mute = !mute;
 
  lcd.setCursor(15, 1);
  if (!mute)
    lcd.write(SOUND_ICON_ON);
  else
    lcd.write('X');
}

Immagini

24 Responses to Display per il livello di una cisterna

  1. Megabart says:

    Innanzitutto, complimenti per il progetto. Sto realizzando anche io qualcosa di simile, puoi dirmi marca e modello del sensore ad ultrasuoni e dell'lcd?

  2. Piuma says:

    Grazie per i complimenti,
    per il sensore ad ultrasuoni ho usato il Ping))) della Parallax ( http://www.parallax.com/Store/Sensors/ObjectDetection/tabid/176/ProductID/92/List/1/Default.aspx?SortField=ProductName,ProductName ), tra costo e spedizione viene una bella sommetta ma ho scelto quello perché volevo essere sicuro che funzionasse con Arduino.
    Per il display puoi sceglierne qualsiasi che sia compatibile con il driver Hitachi HD44780, che sono la maggior parte di quelli in commercio. L'unica cosa a cui devi stare attento è la piedinature perché può cambiare da modello a modello.

  3. Marco says:

    Ciao! Ho anche io fatto una cosetta molto simile, come saensore ho usato SFR05, volevo chiederti se la misura dle sensore è corretta quando il sensore è posto all'interno del serbatoio che nel mio caso è un serbatoio da 1000 litri interrato, ho notato che chiaramente l'ambiente è molto umido, e la condensa a parte il rischio di corto non so come va d'accordo con le capsule US.... Ad un primo test sembra che le misure siano inferiori a quelle reali...
    Sei a conoscenza di modificazioni delle caratteristiche dell'acqua bombardata da Ultrasuoni..?
    A presto.
    MArco

  4. Piuma says:

    Io ho una misura abbastanza precisa, dovresti fare attenzione a posizionare il sensore lontano dalle pareti del serbatorio, e perpendicolare all'acqua. Non so` se la superficie dell'acqua influisce sugli ultrasuoni, si sicuro la velocita` del suono varia a seconda dell'umidita` ma qui` stiamo parlando di pochi metri... praticamente la differenza e` trascurabile.

  5. Marco says:

    Volevo chiederti se hai adottato qualche accorgimento, sull'alloggiamento del sensore... hai usato una scatola di abs stagna sigillando con del silicone le due capsule..? io ho messo l'srf05 dentro una scatoletta di metallo bucata per far fuoriuscire le capsule.
    I problemi forse sono 2 quella del corto sul PCB del sensore data l'alta umidità e condensa, l'altra è relativsa alle capsule stesse, cioè anche se isolo bene il PCB le capsule devono per forza di cose essere a contatto con l'aria umida e la condenza... Finiranno per arruginirsi..?
    Qualche dritta?
    Thanks

  6. Piuma says:

    Esatto, ho messo il sensore ad ultrasuoni dentro una statola di derivazione, quelle di plastica e gli ho fatto i due buchi per far uscire i sensori. Se riesco gli faccio qualche fotografia. Nel pozzo ho messo solo il Ping, ci sono 3 fili (2 alimentazione + 1 del segnale) che escono dalla scatola e raggiungono il resto del circuito che sta all'asciutto.

  7. Marco says:

    Quindi se ho capito bene nella scatola stagna c'e' tutto il ping (capsule e circuitino) poi i 3 fili raggiungono il controllore (arduino o altre cose...)
    E il tutto funza..? non si crea una paurosa condensa dentro la scatola..? hai fatto dei buchini di aereazione o no..?
    Dammi i dettagli grazie...

    PS: l'idale forse sarebbe far arrivare dell'aria nella scatola, magari tramite un tubicino che arriva all'esterno del serbatoio... ma la cosa si fa più complicata poi...
    Grazie per i consigli.
    MArco

  8. Carlo says:

    Ciao
    Volevo realizzare anche io un oggetto come questo x controllare l'acqua del pozzo.

    Puoi darmi l'elenco del materiale comprato che provo a comprare tutto nella speranza di riuscirci?

    Grazie

    • Piuma says:

      Componenti:
      1 Arduino
      1 Resistenza da 10K ohm
      1 buzzer
      1 pulsante
      1 sensore ad ultrasuoni Ping))) della Parallax
      1 display lcd 16x2 compatibile con il chip Hitachi HD44780
      1 potenziometro da 10k

  9. Carlo says:

    Ciao,
    scusa ancora se rompo, un'altra domanda..
    sarebbe possibile poi vedere il tutto via LAN?
    cioe' se prendo un arduino con ethernet, posso poi vedere i dati via lan?

    • admin says:

      Si, questa e` una cosa molto carina da fare... io purtroppo ho il circuito lontano da cavi ethernet. Se hai un server a disposizione potresti memorizzare i dati in un database e poi fare una pagina web con dei grafici.

  10. Carlo Negretti says:

    Riepilogo le domande e ne aggiungo 1, perche' il pozzo e' circa 20/25m, quindi volevo capire come fare x l'ultrasuono..

    1) 1 buzzer di che dimensioni?
    2) 1 potenziometro da 10k a cosa serve??
    3) hai usato una scatoletta a 7 posti della bticino corretto? come hai fissato lcd? intendo la maschera nera che si vede
    4) Quando e' grande lo stampato, come dimensioni intendo..
    5) Hai usato un jack audio stero x collegare l'ultrasuono? quindi rosso, nero e calza ??
    6) come posso fare sapendo che il pelo dell'acqua e' tra i 20 - 25m?? il parallax mi pare di capire non vada bene.

    • admin says:

      Il sonar della Parallax legge da una distanza di 2 cm fino a 3 m, quindi non va bene per il tuo pozzo. Ho cercato qualcun'altro piu` potente ma arriva fino a 6m, non penso che esista uno che raggiunga i 25m ma magari tu hai piu` fortuna di me.

      Se non puoi farlo con il sonar potresti considerare di utilizzare un sensore di pressione da posizionare nel fondo del pozzo, in modo da leggere quanto l'acqua spinge verso il basso, in poche parole il peso dell'acqua, piu` acqua c'e` e piu` pesa. Da quel valore puoi ricavarti l'altezza. Pero` io non ho molte infomazioni da darti a riguardo.

      Per le altre domande... il buzzer e` un affare che se alimentato suona, serve uno che funziona con 5v. Il potenziometro serve per impostare la luminosita` dei caratteri del display, non serve girarlo in continuazione, una volta impostato rimane fisso, ecco perche' l'ho messo dietro al circuito. La scatolina e` della bticino 7 posti, il frontalino nero e` una piastrina di acciaio che mi sono fatto a mano. Per il jack ne puoi usare uno qualsiasi a me serviva uno con 3 cavi ed ho usato quelli audio anche se non mi piace come soluzione, se dovessi rifarlo userei dei connettori che si saldano direttamente sul pcb.

      Spero di aver chiarito tutti i tuoi dubbi

  11. Carlo Negretti says:

    secondo te posso usare questo sonar, senza dover modificare il tuo circuito o programma?
    http://www.robot-italy.com/product_info.php?cPath=15_48_144&products_id=1487&osCsid=2a5d937d87d01dab50785c31fb508eba

    e' un MB1361: XL-MaxSonar-AEL1 fa 10 metri.. ma metto 10 metri di cavo e ho risolto...

  12. Carlo Negretti says:

    Ho deciso di "allungare" il cavo e poi prendere uno che faccia 6 metri.. senti .. questo posso usarlo secondo te?

    http://www.robot-italy.com/product_info.php?cPath=15_48_146&products_id=99 e' il Devantech SRF10.
    Senza dover modificare il tuo circuito/sw, perche' cosi' prendo tutto da 1 unico sito e compro anche la scatoletta x il montaggio..
    che ne pensi?

  13. orli57 says:

    Ciao sto realizzando un progetto simile ma copiando il tuo Sketchbook mi da degli errori sai non sono un programmatore ti ringrazio fin da ora se mi invii lo sketc corretto:Complimenti x il progetto "forte"

  14. Andrea says:

    Volevo ripetere il tuo progetto, ho copiato il codice postato ma quando vado a verificarlo mi da qualche errore:

    sketch_may04a.ino: In function 'void setup()':
    sketch_may04a:58: error: expected primary-expression before '{' token
    sketch_may04a:58: error: expected `;' before '{' token
    sketch_may04a:70: error: expected primary-expression before '{' token
    sketch_may04a:70: error: expected `;' before '{' token
    sketch_may04a:82: error: expected primary-expression before '{' token
    sketch_may04a:82: error: expected `;' before '{' token
    sketch_may04a.ino: In function 'void loop()':
    sketch_may04a:146: error: call of overloaded 'write(int)' is ambiguous
    /Applications/Arduino.app/Contents/Resources/Java/libraries/LiquidCrystal/LiquidCrystal.h:82: note: candidates are: virtual size_t LiquidCrystal::write(uint8_t)
    /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Print.h:49: note: size_t Print::write(const char*)
    sketch_may04a:154: error: call of overloaded 'write(int)' is ambiguous
    /Applications/Arduino.app/Contents/Resources/Java/libraries/LiquidCrystal/LiquidCrystal.h:82: note: candidates are: virtual size_t LiquidCrystal::write(uint8_t)
    /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Print.h:49: note: size_t Print::write(const char*)

    Non conosco il C quindi vorrei un aiuto.
    Grazie 😀

    • admin says:

      In effetti con una versione aggiornata di Arduino dava degli errori. Ora ho aggiornato lo sketchbook. Grazie della segnalazione.

  15. Giovanni says:

    Salve, abitando abbastanza vicino ad un torrente che esonda spesso quando piove tanto e mi allaga casa, vorrei realizzare un misuratore del livello dell'acqua, in modo da poter sapere in anticipo se l'acqua sta salendo troppo.
    La mia idea sarebbe quella di utilizzare un co$to$o sensore ultrasonico che ho e che è idoneo alla misurazione in esterno, ma non ho esperienza di Arduino e non so come si fa a caricarvi il listato pubblicato.
    Ho letto che esiste un Arduino con LAN il che mi permetterebbe di inviare i dati al pc di casa mediate un link a 2,4GHz invece di stendere un bel po' di cavo.
    Si utilizzerebbe, in questo caso, lo stesso listato o ce ne vuole un altro?
    Credo che questo potrebbe aiutare parecchie persone visto il meteo in questi ultimi tempi...
    Un salutone
    Giovanni

  16. Stefano says:

    Ciao! Trovo molto interessante questa applicazione, e vorrei utilizzarla per un altro progetto..
    Me la cavo poco in programmazione, anche se ho alcune basi..in compenso sono un mago nella manovalanza, sia elettrica che da falegnameria/carpenteria..

    Vorrei adattare questo sistema, per il carico automatico del pellet in una caldaia..in poche parole, posizionerò sopra al serbatoio della caldaia, un sistema di caricamento pneumatico..non è altro che un aspiratore combinato con un cono, che scarica il pellet su un serbatoio sottostante..
    Cosa mi serve? Un relè, che attivi il circuito che alimenta l'aspiratore, al posto del buzzer nel tuo progetto..l'interruttore per disattivarlo, può essere utile..
    inoltre, necessito di attivare/disattivare ogni minuto il circuito, con delle pause di 15/20 secondi almeno..questo perchè, il sistema pneumatico, richiede un ambiente chiuso per funzionare, e quindi devo avere un box supplementare, sopra a quello della caldaia, che si carica. Poi, l'aspiratore si ferma, e si apre una botola sul fondo del box, per scaricare il pellet nel box della caldaia. Fuoriuscito tutto il pellet, la botola si richiude attraverso una molla meccanica, e rimane chiusa grazie ad un elettro magnete, che viene alimentato assieme al motore dell'aspiratore..

    In poche parole, il buzzer del tuo progetto, dovrebbe funzionare per 1 minuti, e poi mettersi in pausa per 15 secondi, poi ripartire per un altro minuto, e via così! Solo che, al posto del buzzer, ci sarà un relè che controlla aspiratore ed elettro magnete..

    E' fattibile come cosa? Potresti aiutarmi a realizzarla?

    Grazie mille, Stefano..

  17. Davide says:

    Complimenti per il progetto. E' possibile usare il Nano V3.0 ATmega328 16M 5V Micro-controller CH340G?
    Grazie

  18. Davide says:

    Ciao,
    ho provato a realizzare questo circuito, purtroppo ho riscontrato dei problemi e desidero avere un tuo aiuto. I problemi sono:
    Sul display vedo visualizzato solo simboli strani
    Il buzzer suona continuamente a intermittenza.
    Ho controllato con il multimetro le tensioni e non ho riscontrato niente di anomalo.
    Quali potrebbero essere i problemi? Spero in un tuo aiuto
    Grazie

  19. Davide says:

    Ciao a tutti,

    ho provato a realizzare questo progetto ma sto avendo diversi problemi, come ad esempio nel display non riesco a visualizzare i valori ma solo simboli strani, il sensore di prossimità non legge e il buzzer suona continuamente ad intermittenza. C'è qualcuno che gentilmente potrebbe aiutarmi.
    Grazie

Leave a Reply

Your email address will not be published. Required fields are marked *