Sheet Arduino n.15 (Distance Meter)

[Lezione del xx yyy 2019]

Premessa

La scheda della esercitazione n.15, richiede di implementare un misuratore di distanza, utilizando un emettitore/sensore di ultrasuoni HC-SR04.

Inoltre si richiede di utilizzare un display LCD 16x2 caratteri con interfaccia I2C. Come spiegato nell’esercitazione dello sheet 13 (AMMETER), non avendo un display LCD con questo bus di comando, ho utilizzato il display LCD fornito nello starter kit di Arduino. In questo ambito non riporto il dettaglio del collegamento di questo display avendolo già documentato nella esercitazione predetta, cui rimando.

Un’ultimo dettaglio: ho implementato direttamente la seconda parte dell’esercizio, in cui si chiede di controllare anche la temperatura dell’aria per calcolare di conseguenza la velocità del suono.

Progetto

L’interfacciamento del HC-SR04 è semplice: alimentazione, ground e due fili ai pin digitali di Arduino: uno per comandare l’avvio del pacchetto di ultrasuoni, e il secondo per misurare il tempo necessario affinché il sensore percepisca l’echo di ritorno.

Analogamente, per il sensore di temperatura (un T36GZ). Oltre l’alimentazione e il ground basta inviare il filo centrale al convertitore ADC di Arduino per leggere la relativa tensione in uscita e calcolare di conseguenza la temperatura.

Per il dettaglio dei contatti del display si faccia riferimento alla esercitazione dell’AMMETER (sheet 13).

Il circuito si presenta come segue:

_images/PIC_sh15.jpg

Video

Di seguito il video dell’esercizio.

Sketch

Lo sketch è il seguente

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
/* Embedded Systems Architecture - hardware
 *  application on sheet 15
 *  
 *  distance meter
 */
 
#include <LiquidCrystal.h>

#define ECHO    10
#define TRIGGER 9
#define LCD_RS  11
#define LCD_EN  12
#define LCD_D7  7
#define LCD_D6  6
#define LCD_D5  5
#define LCD_D4  4

#define TEMPERATURE A1               // temperature sensor output
#define TO_MV 5.0 / 1024.0 * 1000.0  // convert an analog UNO unit to mV

LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

long T;             //time (micro sec.)
long S;             //distance (cm)
double V;           //velocity of sound in air cm/micro sec.)
float degreesC;     //air temperature °C
int T_Scan = 1000;  // time pause during distance measure
int T_Setup = 4500; // time pause for banner


void setup() {
    float voltagemV;
    
    pinMode(ECHO, INPUT);
    pinMode(TRIGGER, OUTPUT);
    digitalWrite(TRIGGER, LOW);
    delay(1);
    Serial.begin(9600);            // init the serial at 9600 baud
    Serial.println("by ldfa copied from l.morresi");
    // init lcd
    lcd.begin(16, 2);
    lcd.clear();
    lcd.setCursor(0, 0);
             //1234567890123456
    lcd.print("Distance Meter");  //13 chars(ndx: 0-12)
    lcd.setCursor(0, 1);
             //1234567890123456
    lcd.print("ldfa cpy morresi");
    delay(T_Setup);
    lcd.clear();

    //get temp and calc velocity of sound in air
    voltagemV = analogRead(TEMPERATURE) * TO_MV;
    delay(1);
    degreesC = (voltagemV - 500.0) / 10.0; //degree °C, from datasheet of T36 pag.8 of 19
    V = 0.03313 + 0.0000606 * degreesC;    //sound velocity cm/microsec
}

void loop() {
    digitalWrite(TRIGGER, HIGH); //generate ultrasonic pulse
    delayMicroseconds(15);       //pause 10e-6 s
    digitalWrite(TRIGGER, LOW);  //stop ultrasonic pulse
    T = pulseIn(ECHO, HIGH);     //start timer to wait echo response => echo interval in microsec

    /*
    S = 0.03434 * T /2;          //dist.calc.with sound speed in air as 343,4 m/s => 0.03434 cm/microsec
                                 //  (std air: 0msl, 20°C); S in cm
    */
                                 
    S = V * T / 2;

    prt(degreesC, V, T, S);
    delay(T_Scan);
    lcd.clear();
}

void prt(float D, double V, long T, long S){
    Serial.print("deg: ");
    Serial.print(D);
    Serial.print("; V: ");
    Serial.print(V);
    Serial.print(";T: ");
    Serial.print(T);
        
    lcd.setCursor(0, 0);
    lcd.print("T: ");
    lcd.print(T);
    if (S>0 && S <= 100){
        Serial.print("; measure: ");
        Serial.println(S);
        
        lcd.setCursor(0, 1);
        lcd.print("measure: ");
        lcd.print(S);
    }
    else{
        Serial.println("; OUT of MAX RANGE");

        lcd.setCursor(0, 1);
                 //1234567890123456
        lcd.print("OUT of MAX RANGE");
    }
}

Non descrivo la gestione del display LCD. Per questo si faccia riferimento all’esercizio del AMMETER (sheet 13).

In testa abbiamo le definizioni dei vari pin e della conversione da unità Arduino ADC a milli Volt (ln da 9 a 19).

Le principali variabili globali (ln da 23 a 28) registrano il tempo di eco in microsecondi, la distanza in cm, la velocità del suono in aria in cm/micro sec. e la temperatura dell’aria in gradi celsius.

Nel setup inizializzo i pin, il display e la seriale verso il PC per debug. Dopo di che scrivo un banner iniziale ed infine misuro la temperatura dell’aria (ln da 53 a 55) per calcolare la velocità del suono in aria (ln 56).

Misuro la temperatura una sola volta, nel setup, in quanto essendo al chiuso, la ritengo costante per la durata dell’esercizio.

Nel loop comando l’avvio dell’impulso di ultrasuoni di rilevazione, e dopo 15 micro secondi fermo il comando (ln da 60 a 62).

Subito dopo parte il comando ad Arduino di misurare la durata del segnale di echo (ln 63). Questo comando aspetta che il segnale in questione vada HIGH 1, dopo di che lo misura in micro secondi finché non va LOW 2.

Il calcolo della distanza, in cm è alla ln 70: velocità per il tempo 3.

A questo punto si passano (ln 72) tutti i valori alla funzione prt che implementa la logica di output dei dati. Dopo di che, pausa, pulizia del display e ciclo.

La funzione prt (ln 77 e successive) stampa inizialmente tutti i valori sicuramente di rilievo. Nella seriale per debug: la temperatura, la velocità e il tempo. Nel display, dove abbiamo solo 2 linee, stampiamo solo il tempo.

Dopo di che (ln 88 e successive) verifico che la distanza calcolata sia positiva 4 e non superiore a 100 cm. In caso affermativo stampo la relativa distanza sia nella seriale che nella seconda riga del display. Altrimenti stampo un messaggio di errore.


1

Cosa che accade dopo la partenza dell’impulso di ultrasuoni per il rilevamento.

2

Cosa che accade quando arriva l’impulso di ultrasuoni di ritorno.

3

Il tempo è dimezzato perchè il suono va e torna dopo essere rimbalzato sul bersaglio.

4

Il sensore ritorna zero come tempo di echo se c’è qualcosa che non va.