Dallas ds18b20 con Raspberry Pi Pico (rp2040): introduzione e modalità parassita


Il DS18B20 è un sensore di temperatura digitale che può essere facilmente integrato con un microcontrollore Raspberry Pi Pico (rp2040). In questa risposta, fornirò un’introduzione al sensore DS18B20 e spiegherò come utilizzarlo in modalità parassita con un Raspberry Pi Pico.

Raspberry Pi Pico (rp2040) e DS18B20: introduzione e modalità parassita
Raspberry Pi Pico (rp2040) e DS18B20: introduzione e modalità parassita

Ho già mostrato alcuni sensori di temperatura e umidità in questa serie di articoli: “Sensori di temperatura e umidità: come fare e confronto“, ma ora vorrei spiegare meglio il Dallas ds28b20. Questo sensore di temperatura a un filo può essere gestito in serie senza grandi limiti.

In particolare, ha una buona precisione (±0,5°) e un notevole intervallo di temperatura (-55°C a +125°C o -67°F a +257°F), ma puoi aggiungere in un singolo filo molti dispositivi, supporta anche una modalità di alimentazione parassita che permette di utilizzare solo due fili per la connessione.

Ma ora aggiungerò la spiegazione dal datasheet per una migliore comprensione.

Il termometro digitale DS18B20 fornisce misurazioni della temperatura in gradi Celsius da 9 a 12 bit e ha una funzione di allarme con punti di attivazione superiore e inferiore programmabili dall’utente non volatili. Il DS18B20 comunica attraverso un bus a 1 filo che richiede solo una linea dati (e massa) per la comunicazione con un microprocessore centrale. Inoltre, il DS18B20 può derivare l’alimentazione direttamente dalla linea dati (“parasite power”), eliminando la necessità di un’alimentazione esterna.

Ogni DS18B20 ha un codice seriale unico a 64 bit, che permette a più DS18B20 di funzionare sullo stesso bus a 1 filo. Così, l’uso di un microprocessore per controllare molti DS18B20 distribuiti su un’ampia area è semplice. Le applicazioni che possono beneficiare di questa caratteristica includono controlli ambientali HVAC, sistemi di monitoraggio della temperatura all’interno di edifici, attrezzature o macchinari, e sistemi di monitoraggio e controllo dei processi.

Datasheet

Caratteristiche

  • Interfaccia 1-Wire® unica richiede solo un pin di porta per la comunicazione
  • Riduci il numero di componenti con sensore di temperatura e EEPROM integrati
    • Misura temperature da -55°C a +125°C (-67°F a +257°F)
    • Precisione di ±0.5°C da -10°C a +85°C
    • Risoluzione programmabile da 9 a 12 bit
    • Nessun componente esterno richiesto
  • La modalità di alimentazione parassita richiede solo 2 pin per il funzionamento (DQ e GND)
  • Semplifica le applicazioni di rilevamento della temperatura distribuite con capacità multidrop
    • Ogni dispositivo ha un codice seriale unico a 64 bit memorizzato nella ROM interna
  • Impostazioni di allarme non volatili (NV) definibili dall’utente flessibili con comando di ricerca di allarme identifica i dispositivi con temperature al di fuori dei limiti programmati
  • Disponibile nei pacchetti SO a 8 pin (150 mils), µSOP a 8 pin e TO-92 a 3 pin

Datasheet

No online PDF viewer installed. Download!

Schema dei pin

Schema dei pin Dallas ds18b20
Schema dei pin Dallas ds18b20

Il sensore ha più varianti, ma il cablaggio rimane lo stesso.

GND: collega a GND.
DATA: Bus dati One-Wire.
VCC: alimentazione (3,3 – 5 V), ma in modalità parassita, puoi collegare a GND.

Ecco il sensore AliExpress

Cablaggio

La libreria One-Wire è uno standard per tutti i microcontrollori, quindi il dispositivo può essere utilizzato con molti microcontrollori.

Raspberry Pi Pico

Ecco lo schema dei pin delle schede prototipo Raspberry Pi Pico.

Schema dei pin Raspberry Pi Pico rp2040 bassa risoluzione
Schema dei pin Raspberry Pi Pico rp2040 bassa risoluzione

O la variante WeAct:

Schema dei pin WeAct Studio RP2040
Schema dei pin WeAct Studio RP2040

Ecco alcune schede prototipo rp2040 Official Pi Pico - Official Pi Pico W - Waveshare rp2040-zero - WeAct Studio rp2040

Modalità normale

In modalità normale, useremo una linea di alimentazione a 3,3v, quindi la connessione diventa così.

Raspberry Pi Pico (rp2040) e ds18b20: cablaggio
Raspberry Pi Pico (rp2040) e ds18b20: cablaggio

La connessione è molto semplice.

esp32ds18b20
GNDGND
3.3vVCC
D22 pulled-upDATA
Schema

Ecco lo schema semplice.

Schema Raspberry Pi Pico (rp2040) e ds18b20
Schema Raspberry Pi Pico (rp2040) e ds18b20

Modalità parassita

Nella modalità parassita, collegherai anche la linea VCC del sensore a GND, e il sensore riceve alimentazione dalla linea dati.

Cablaggio in modalità parassita: Raspberry Pi Pico (rp2040) e ds18b20
Cablaggio in modalità parassita: Raspberry Pi Pico (rp2040) e ds18b20
esp32ds18b20
GNDGND
GNDVCC
D22 pulled-upDATA

In seguito analizzeremo in dettaglio questa modalità, ma per ora non hai bisogno di altre informazioni.

Schema

Ecco lo schema.

Schema modalità parassita: Raspberry Pi Pico (rp2040) e ds18b20
Schema modalità parassita: Raspberry Pi Pico (rp2040) e ds18b20

Libreria

Ora, mentre scrivo questo articolo, c’è un bug nella libreria più famosa OneWire, quindi inserisco il link a questa libreria, quindi non usarla.

Usa OneWireNg e non la libreria OneWire standard

Non usarla fino a quando il bug non sarà corretto.

Prima di tutto, devi ricordare che questo sensore utilizza il protocollo One-Wire, quindi devi aggiungere la libreria OneWire.

Arduino IDE: libreria OneWire sul manager delle librerie
Arduino IDE: libreria OneWire sul manager delle librerie

Usa questa per ora

Arduino IDE: libreria OneWireNg sul manager delle librerie
Arduino IDE: libreria OneWireNg sul manager delle librerie

Dopo, devi installare una libreria che implementa il protocollo e le funzioni del sensore.

Ho scelto la più utilizzata, la DallasTemperature (in passato Dallas, ora Maxim).

Arduino IDE: libreria DallasTemperature per il ds18b20 dal manager delle librerie
Arduino IDE: libreria DallasTemperature per il ds18b20 dal manager delle librerie

Dispositivi supportati

Come descritto nel repository, questa libreria supporta i seguenti dispositivi:

  • DS18B20
  • DS18S20 (alcuni problemi su questo dispositivo)
  • DS1822
  • DS1820
  • MAX31820
  • MAX31850

Averai bisogno di una resistenza di pull-up di circa 4.7KOhm tra la linea dati 1-Wire e il tuo VCC. Se utilizzi il DS18B20, puoi usare la modalità parassita e puoi collegare a GND il VCC come descritto.

Risoluzione dei problemi

In caso di problemi di conversione della temperatura (il risultato è -85), potrebbe essere necessaria un’impostazione di pull-up forte. Vedi la sezione Alimentazione del DS18B20 nel datasheet del DS18B20 (pagina 7) e usa il costruttore DallasTemperature(OneWire*, uint8_t).

Alimentazione del DS18B20 (normale/parassita)

Il DS18B20 può essere alimentato da una fonte esterna sul pin VDD, o può operare in modalità “parasite power”, che permette al DS18B20 di funzionare senza una alimentazione esterna locale (colleghi il VDD a GND). Il DS18B20 “ruba” energia dal bus 1-Wire tramite il pin DQ quando il bus è alto. L’energia rubata alimenta il DS18B20 mentre il bus è alto, e parte dell’energia viene immagazzinata nel condensatore di alimentazione parassita (CPP) per fornire energia quando il bus è basso.

Schema modalità parassita: Raspberry Pi Pico (rp2040) e ds18b20
Schema modalità parassita: Raspberry Pi Pico (rp2040) e ds18b20

Ma quando il DS18B20 esegue conversioni della temperatura o copia dati dalla memoria scratchpad all’EEPROM, la corrente operativa può essere alta fino a 1,5mA. Questa corrente può causare una caduta di tensione inaccettabile attraverso la resistenza di pull-up 1-Wire debole ed è più corrente di quanto CPP possa fornire.

Pull-up forte per la modalità parassita

Per garantire che il DS18B20 disponga di una sufficiente alimentazione, è necessario fornire un pull-up forte sul bus 1-Wire ogni volta che si verificano conversioni della temperatura o si copiano dati dalla scratchpad all’EEPROM.
Questo può essere realizzato utilizzando un MOSFET per tirare il bus direttamente al rail.

Schema pull-up forte parassita con P-MOSFET: Raspberry Pi Pico (rp2040) e ds18b20
Schema pull-up forte parassita con P-MOSFET: Raspberry Pi Pico (rp2040) e ds18b20

Il bus 1-Wire deve essere commutato al pull-up forte entro 10µs (max) dopo le conversioni della temperatura, e il bus deve essere mantenuto alto dal pull-up per la durata della conversione o del trasferimento dei dati. Nessun’altra attività può avere luogo sul bus 1-Wire mentre il pull-up è abilitato.

Un esempio di m

Il DS18B20 può anche essere alimentato con il metodo convenzionale collegando una fonte di alimentazione esterna al pin VDD, come mostrato. Il vantaggio di questo metodo è che il pull-up MOSFET non è richiesto e il bus 1-Wire è libero di trasportare altro traffico durante il tempo di conversione della temperatura.

Cablaggio pull-up forte parassita con P-MOSFET: Raspberry Pi Pico (rp2040) e ds18b20
Cablaggio pull-up forte parassita con P-MOSFET: Raspberry Pi Pico (rp2040) e ds18b20

L’uso dell’alimentazione parassita non è raccomandato per temperature superiori a +100°C poiché il DS18B20 potrebbe non essere in grado di mantenere le comunicazioni a causa delle maggiori correnti di dispersione che possono esistere a queste temperature.

Riduci le dimensioni della libreria

Abbiamo incluso una definizione REQUIRESNEW e REQUIRESALARMS. Se vuoi ridurre il codice, sentiti libero di usare uno di questi includendo

#define REQUIRESNEW 

o

#define REQUIRESALARMS

all’inizio di DallasTemperature.h

Codice

E ora, possiamo iniziare con alcuni esempi.

Recupero temperatura

Prima di tutto, il modo più rapido per mettere in funzione il sensore.

// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port D22
#define ONE_WIRE_BUS D22

// 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);

/*
 * The setup function. We only start the sensors here
 */
void setup(void)
{
  // start serial port
  Serial.begin(115200);
  while (!Serial) { delay(100); }

  Serial.println("Dallas Temperature IC Control Library Demo");

  // Start up the library
  sensors.begin();
}

/*
 * Main function, get and show the temperature
 */
void loop(void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");
  // After we got the temperatures, we can print them here.
  // We use the function ByIndex, and as an example get the temperature from the first sensor only.
  float tempC = sensors.getTempCByIndex(0);

  // Check if reading was successful
  if(tempC != DEVICE_DISCONNECTED_C)
  {
    Serial.print("Temperature for the device 1 (index 0) is: ");
    Serial.println(tempC);
  }
  else
  {
    Serial.println("Error: Could not read temperature data");
  }

  delay(2000);
}

L’output seriale è molto semplice.

Dallas Temperature IC Control Library Demo
Requesting temperatures...DONE
Temperature for the device 1 (index 0) is: 20.50
Requesting temperatures...DONE
Temperature for the device 1 (index 0) is: 20.50
Requesting temperatures...DONE
Temperature for the device 1 (index 0) is: 20.50
Requesting temperatures...DONE
Temperature for the device 1 (index 0) is: 20.50
Requesting temperatures...DONE
Temperature for the device 1 (index 0) is: 20.44
Requesting temperatures...DONE
Temperature for the device 1 (index 0) is: 20.44

Recupera informazioni sensore e temperatura (tramite indice)

Raspberry Pi Pico (rp2040) e ds18b20 su breadboard
Raspberry Pi Pico (rp2040) e ds18b20 su breadboard

Prima di tutto, andremo a recuperare l’indirizzo, le informazioni sulla connessione (parassita o meno) e la temperatura.

/**
 * Retrieve information about a single sensor
 * minor change by Renzo Mischianti <www.mischianti.org>
 *
 * www.mischianti.org
 */

// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port D22
#define ONE_WIRE_BUS D22

// 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 address
DeviceAddress insideThermometer;

/*
 * Setup function. Here we do the basics
 */
void setup(void)
{
  // start serial port
  Serial.begin(112500);
  Serial.println("Dallas Temperature IC Control Library Demo");

  // locate devices on the bus
  Serial.print("Locating devices...");
  sensors.begin();
  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");

  // Assign address manually. The addresses below will beed 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)
  // Note that you will need to use your specific address here
  // insideThermometer = { 0x28, 0xFF, 0x64, 0x0E, 0x79, 0x69, 0x3A, 0x1A };
  // we can check if the address is correct and if It's all ok
  // if (!oneWire.search(insideThermometer)) Serial.println("Unable to find address for insideThermometer");

  // 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).
  if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");

  // show the addresses we found on the bus
  Serial.print("Device 0 Address: ");
  printAddress(insideThermometer);
  Serial.println();

  Serial.print("Device 0 HEX Address: ");
  printHEXAddress(insideThermometer);
  Serial.println();

  // set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
  sensors.setResolution(insideThermometer, 9);

  Serial.print("Device 0 Resolution: ");
  Serial.print(sensors.getResolution(insideThermometer), DEC);
  Serial.println();
}

/*
 * Main function. It will request the tempC from the sensors and display on Serial.
 */
void loop(void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");

  // It responds almost immediately. Let's print out the data
  printTemperature(insideThermometer); // Use a simple function to print out the data

  delay(4000);
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

void printHEXAddress(DeviceAddress deviceAddress)
{
    Serial.print("  { ");
    for (uint8_t i = 0; i < 8; i++)
    {
      Serial.print("0x");
      if (deviceAddress[i] < 0x10) Serial.print("0");
      Serial.print(deviceAddress[i], HEX);
      if (i < 7) Serial.print(", ");
    }
    Serial.println(" }");
}

// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
  // method 1 - slower
  //Serial.print("Temp C: ");
  //Serial.print(sensors.getTempC(deviceAddress));
  //Serial.print(" Temp F: ");
  //Serial.print(sensors.getTempF(deviceAddress)); // Makes a second call to getTempC and then converts to Fahrenheit

  // method 2 - faster
  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.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
}

Riceviamo questo quando gli output seriali.

Dallas Temperature IC Control Library Demo
Locating devices...Found 1 devices.
Parasite power is: OFF 
Device 0 Address: 28FF640E79693A1A
Device 0 HEX Address:   { 0x28, 0xFF, 0x64, 0x0E, 0x79, 0x69, 0x3A, 0x1A }

Device 0 Resolution: 9
Requesting temperatures...DONE
Temp C: 22.50 Temp F: 72.50
Requesting temperatures...DONE
Temp C: 22.50 Temp F: 72.50
Raspberry Pi Pico (rp2040) e ds18b20 su breadboard
Raspberry Pi Pico (rp2040) e ds18b20 su breadboard

Come puoi vedere, ho impostato il pin OneWire su 22:

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 22

// 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);

Controlla quanti sensori recuperiamo nella linea:

  // locate devices on the bus
  Serial.print("Locating devices...");
  sensors.begin();
  Serial.print("Found ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" devices.");

Controlla se facciamo una connessione parassita:

  // report parasite power requirements
  Serial.print("Parasite power is: ");
  if (sensors.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");

Metti in insideThermometer l’indirizzo del sensore 0:

  // 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).
  if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");

Ora possiamo leggere la temperatura (in Celsius):

  float tempC = sensors.getTempC(deviceAddress);

Poi convertire in Fahrenheit:

  Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converte tempC in Fahrenheit

Puoi fare una lettura diretta in Fahrenheit, ma all’interno, fai le stesse operazioni:

  Serial.print(sensors.getTempF(deviceAddress)); // Makes a second call to getTempC and then converts to Fahrenheit

Grazie

  1. Schede Raspberry Pi Pico e rp2040: pinout, specifiche e configurazione IDE Arduino
  2. Schede Raspberry Pi Pico e rp2040: filesystem LittleFS integrato
  3. Scheda Raspberry Pi Pico e rp2040: ethernet w5500 e requests HTTP e HTTPS (SSL)
  4. Schede Raspberry Pi Pico e rp2040: WiFiNINA con coprocessore WiFi ESP32
  5. Schede Raspberry Pi Pico e rp2040: come utilizzare una scheda SD
  6. Dallas ds18b20