La sonda basata sul sensore DS18B20 consente a chi utilizza Arduino di effettuare precise misurazioni di temperatura legate a gas e liquidi.
In un articolo di diversi anni fa, intitolato Elaborazione elettronica delle temperature, spiegammo l’utilizzo della sonda termometrica DS18B20 collegata con un Raspberry PI 3. Oggi mostriamo invece come configurare la sonda con Arduino.
Lavoreremo con la sonda dotata di cavo e protezione metallica distribuita da AZ-Delivery, ma il software funzionerà egregiamente per qualsiasi altro sistema basato sul sensore DS18B20.
Controlliamo le connessioni
Collegare le sonde DS18B20 alla scheda del microcontrollore come mostrato nel seguente schema di collegamento:
NOTA: il resistore pull up da 4,7 kΩ è collegato tra il pin DATA e VCC.
Per utilizzare la sonda DS18B20 con schede a microcontrollore, dobbiamo prima scaricare la relativa libreria. Vai su: Strumenti > Gestisci librerie, apparirà una nuova finestra. Digita “Dallas” nella casella di ricerca e scarica la libreria “DallasTemperature” di “Miles Burton, Tim Newsome Guil Barros e Rob Tillaart”, come mostrato nell’immagine seguente:
Ora vai su: File > Esempi > DallasTemperature > … e troverai molti sketck di esempio. Utilizzeremo e modificheremo uno sketch chiamato “Multiplo” per leggere i dati di temperatura da tre diverse sonde DS18B20.
Se usi solo una sonda DS18B20, sarà sufficiente lavorare con lo sketch chiamato “Semplice”.
Il software
Quello che segue è l’esempio di sketch per tre sonde DS18B20 sulla stessa interfaccia One-Wire. L’esempio ne prevedeva solo due, ma a noi piace sporcarci le mani…
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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
// Include the libraries we need #include <OneWire.h> #include <DallasTemperature.h> // Data wire is plugged into port 2 on the Arduino #define ONE_WIRE_BUS 2 #define TEMPERATURE_PRECISION 12 // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) OneWire oneWire(ONE_WIRE_BUS); // Pass our oneWire reference to Dallas Temperature. DallasTemperature sensors(&oneWire); // arrays to hold device addresses DeviceAddress uno, due, tre; // Assign address manually. The addresses below will need to be changed // to valid device addresses on your bus. Device address can be retrieved // by using either oneWire.search(deviceAddress) or individually via // sensors.getAddress(deviceAddress, index) // DeviceAddress insideThermometer = { 0x28, 0x1D, 0x39, 0x31, 0x2, 0x0, 0x0, 0xF0 }; // DeviceAddress outsideThermometer = { 0x28, 0x3F, 0x1C, 0x31, 0x2, 0x0, 0x0, 0x2 }; void setup(void) { // start serial port Serial.begin(9600); Serial.println("Dallas Temperature IC Control Library Demo"); // Start up the library sensors.begin(); // locate devices on the bus Serial.print("Locating devices..."); Serial.print("Found "); Serial.print(sensors.getDeviceCount(), DEC); Serial.println(" devices."); // report parasite power requirements Serial.print("Parasite power is: "); if (sensors.isParasitePowerMode()) Serial.println("ON"); else Serial.println("OFF"); // Search for devices on the bus and assign based on an index. Ideally, // you would do this to initially discover addresses on the bus and then // use those addresses and manually assign them (see above) once you know // the devices on your bus (and assuming they don't change). // // method 1: by index if (!sensors.getAddress(one, 0)) Serial.println("Unable to find address for Device 0"); if (!sensors.getAddress(two, 2)) Serial.println("Unable to find address for Device 2"); if (!sensors.getAddress(three, 2)) Serial.println("Unable to find address for Device 3"); // method 2: search() // search() looks for the next device. Returns 1 if a new address has been // returned. A zero might mean that the bus is shorted, there are no devices, // or you have already retrieved all of them. It might be a good idea to // check the CRC to make sure you didn't get garbage. The order is // deterministic. You will always get the same devices in the same order // // Must be called before search() //oneWire.reset_search(); // assigns the first address found to insideThermometer //if (!oneWire.search(insideThermometer)) Serial.println("Unable to find address for insideThermometer"); // assigns the seconds address found to outsideThermometer //if (!oneWire.search(outsideThermometer)) Serial.println("Unable to find address for outsideThermometer"); // show the addresses we found on the bus Serial.print("Device 0 Address: "); printAddress(one); Serial.println(); Serial.print("Device 1 Address: "); printAddress(two); Serial.println(); Serial.print("Device 1 Address: "); printAddress(two); Serial.println(); // set the resolution to 9 bit per device sensors.setResolution(one, TEMPERATURE_PRECISION); sensors.setResolution(two, TEMPERATURE_PRECISION); sensors.setResolution(three, TEMPERATURE_PRECISION); Serial.print("Device 0 Resolution: "); Serial.print(sensors.getResolution(one), DEC); Serial.println(); Serial.print("Device 1 Resolution: "); Serial.print(sensors.getResolution(two), DEC); Serial.println(); Serial.print("Device 2 Resolution: "); Serial.print(sensors.getResolution(three), DEC); Serial.println(); } // function to print a device address void printAddress(DeviceAddress deviceAddress) { for (uint8_t i = 0; i < 8; i++) { // zero pad the address if necessary if (deviceAddress[i] < 16) Serial.print("0"); Serial.print(deviceAddress[i], HEX); } } // function to print the temperature for a device void printTemperature(DeviceAddress deviceAddress) { float tempC = sensors.getTempC(deviceAddress); if(tempC == DEVICE_DISCONNECTED_C) { Serial.println("Error: Could not read temperature data"); return; } Serial.print("Temp C: "); Serial.print(tempC); Serial.print(" Temp F: "); Serial.print(DallasTemperature::toFahrenheit(tempC)); } // function to print a device's resolution void printResolution(DeviceAddress deviceAddress) { Serial.print("Resolution: "); Serial.print(sensors.getResolution(deviceAddress)); Serial.println(); } // main function to print information about a device void printData(DeviceAddress deviceAddress) { Serial.print("Device Address: "); printAddress(deviceAddress); Serial.print(" "); printTemperature(deviceAddress); Serial.println(); } /* Main function, calls the temperatures in a loop. */ void loop(void) { // call sensors.requestTemperatures() to issue a global temperature // request to all devices on the bus Serial.print("Requesting temperatures..."); sensors.requestTemperatures(); Serial.println("DONE"); // print the device information printData(one); printData(two); printData)three); delay(1000); } |
Esecuzione del programma
Carica lo sketch sulla scheda del microcontrollore e apri Monitor seriale (Strumenti> Monitor seriale). L’output dovrebbe assomigliare a quello mostrato nell’immagine seguente:
Come (e perché) funziona
Quella che segue è una spiegazione dello sketch.
Usiamo la variabile ONE_WIRE_BUS per definire su quale pin digitale collegheremo l’interfaccia One-Wire. E’ possibile utilizzare qualsiasi pin digitale della scheda del microcontrollore, ad eccezione di quelli utilizzati nell’interfaccia seriale, D0 e D1.
Abbiamo utilizzato la variabile TEMPERATURE_PRECISION per impostare la precisione per le sonde DS18B20. Il numero salvato in questa variabile è un numero di conversione digitale in bit e può essere compreso tra 9 e 12, qualsiasi altro numero risulterà in errore.
Abbiamo utilizzato la seguente riga di codice:
1 |
DeviceAddress uno, due, tre |
per creare variabili per gli indirizzi delle sonde. Nel nostro esempio ne abbiamo creati tre.
Abbiamo definito e creato l’oggetto oneWire, utilizzato per l’interfaccia One-Wire:
1 |
OneWire oneWire(ONE_WIRE_BUS); |
Quindi abbiamo utilizzato l’oggetto oneWire per definire e creare l’oggetto sensors, che viene utilizzato per tutte le sonde collegate:
1 |
DallasTemperature sensors(&oneWire); |
Per inizializzare l’oggetto sensori abbiamo utilizzato la seguente riga di codice:
1 |
sensors.begin(); |
Con questa linea del codice l’oggetto sensors rileva tutte le sonde collegate all’interfaccia One-Wire. Rileva anche tutti gli indirizzi delle sonde.
Ora possiamo verificare se le sonde funzionano correttamente, utilizzando le seguenti righe di codice per ogni sonda che colleghiamo all’interfaccia One-Wire:
1 2 |
if(!sensors.getAddress(uno, 0)) { Serial.println("Impossibile trovare l'indirizzo: Dispositivo 0"); } |
dove uno è l’indirizzo della prima sonda.
Per impostare la precisione della conversione da analogico a digitale della sonda specifica abbiamo utilizzato la seguente riga di codice:
1 |
sensors.setResolution(uno, TEMPERATURE_PRECISION); |
Se si desidera leggere la precisione della conversione da analogico a digitale della sonda specifica, è possibile utilizzare la seguente riga di codice:
1 |
sensors.getResolution(uno); |
La funzione restituisce un valore esadecimale e per convertirlo in valore decimale utilizziamo la seguente riga di codice:
1 |
Serial.print(sensors.getResolution(uno), DEC); |
Per poter leggere i dati di temperatura, dobbiamo prima richiedere tutti i dati a tutte le sonde, utilizzando la seguente riga di codice:
1 |
sensors.requestTemperatures(); |
Solo dopo quella riga di codice possiamo leggere i dati di una particolare sonda, utilizzando la seguente riga di codice:
1 |
float tempC = sensors.getTempC(indirizzodispositivo); |
dove passiamo l’argomento deviceAddress alla funzione per leggere i dati di temperatura da una sonda specifica. Questi dati rappresentano il valore della temperatura in gradi Celsius e per convertirlo in Fahrenheit abbiamo utilizzato la seguente riga di codice:
1 |
DallasTemperatura::toFahrenheit(tempC); |
Il loop() richiede le temperature e stampa i valori ottenuti attraverso l’indirizzo di ciascuna sonda, quindi si ferma per un secondo e ricomincia.
NOTA: Un ambiente rumoroso dal punto di vista elettromagnetico, la lunghezza dei cavi di collegamento e il numero di sonde utilizzate nel progetto influiscono negativamente sulla precisione e sulla stabilità del progetto.
Link utili:
- 5 x Sonda temperatura DS18B20
- 2 x Sonda temperatura DS18B20 con cavi da 1m e protezione in metallo
- 2 x Sonda temperatura DS18B20 con cavi da 3m e protezione in metallo
- 5 x Sonda temperatura DS18B20 con cavi da 3m e protezione in metallo
Join our groups on Telegram…