Dallas ds18b20 con Raspberry Pi Pico (rp2040): tutte le topologie OneWire, stub lunghi e più dispositivi


Il DS18B20 è un sensore di temperatura digitale che comunica utilizzando il protocollo OneWire, e il Raspberry Pi Pico è una scheda microcontrollore basata sul chip RP2040. In questo articolo, esploreremo come collegare i sensori DS18B20 a un Raspberry Pi Pico utilizzando il protocollo OneWire.

Raspberry Pi Pico (rp2040) e DS18B20: tutte le topologie OneWire, stub lunghi e dispositivi multipli
Raspberry Pi Pico (rp2040) e DS18B20: tutte le topologie OneWire, stub lunghi e dispositivi multipli

Copriremo tutte le possibili topologie OneWire, inclusi stella, bus e catena margherita, oltre ai metodi per gestire gli stub lunghi (cavi lunghi) che possono causare degradazione del segnale. Inoltre, tratteremo come collegare più sensori DS18B20 al Raspberry Pi Pico, che può essere utile in applicazioni come il monitoraggio ambientale o l’automazione industriale.

In generale, l’obiettivo di questo articolo è fornire una guida completa sull’uso dei sensori DS18B20 con un Raspberry Pi Pico, inclusi consigli per la risoluzione dei problemi e raccomandazioni per ottimizzare le prestazioni dei sensori.

Caratteristiche

  • Interfaccia unica 1-Wire® 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 bit a 12 bit
    • Non richiede componenti esterni
  • Modalità di alimentazione parassita richiede solo 2 pin per il funzionamento (DQ e GND)
  • Semplifica le applicazioni di rilevamento della temperatura distribuita con capacità multidrop
    • Ogni dispositivo ha un codice seriale unico a 64 bit memorizzato nella ROM interna
  • Impostazioni di allarme non volatile (NV) definibili dall’utente con comando di ricerca di allarme identifica dispositivi con temperature al di fuori dei limiti programmati
  • Disponibile nei pacchetti 8-pin SO (150 mils), 8-pin µSOP e 3-pin TO-92

Datasheet

No online PDF viewer installed. Download!

Schema dei pin

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

GND: collegare a GND.
DATA: bus dati One-Wire.
VCC: alimentazione (3,3 – 5 V), ma in modalità parassita, è possibile collegarlo a GND.

Ecco il sensore AliExpress

Rete OneWire: Introduzione

Quando si crea una rete, è necessario prestare attenzione agli amplificatori di misura della corrente (CSA), utilizzati per misurare la corrente che scorre attraverso un circuito. I CSA presentano vantaggi in varie applicazioni, tra cui la gestione dell’alimentazione, il controllo dei motori e il monitoraggio delle batterie. Ci sono diversi tipi di CSA, inclusi amplificatori ad alto lato e basso lato, e le varie architetture utilizzate nel loro design.

Non andremo nel dettaglio delle specifiche chiave e dei parametri di prestazione dei CSA, come la tensione di offset in ingresso, la larghezza di banda e il rapporto di reiezione del modo comune (CMRR). Ma descriveremo diversi tipi di resistori di misurazione della corrente e come selezionare quello giusto per una particolare applicazione.

Proseguiamo per discutere considerazioni pratiche sull’uso dei CSA, includendo tecniche di layout e messa a terra, riduzione del rumore e compensazione della temperatura. Mostreremo diversi circuiti applicativi per i CSA, come la semplice conversione tensione-corrente, la rilevazione di tensione differenziale e la rilevazione di corrente basata su shunt.

Fattori di prestazione della rete OneWire

Le due misurazioni critiche nelle prestazioni della rete 1-Wire: sono il raggio e il peso. Il raggio di una rete 1-Wire è la distanza del cavo tra il master e lo slave più lontano, misurata in metri. Il peso di una rete 1-Wire è la lunghezza totale del cavo nella rete, misurata anche in metri.

Ad esempio, una rete 1-Wire con una configurazione a stella che ha tre rami di 10m, 20m e 30m avrebbe un raggio di 30m (la distanza dal master allo slave più lontano) e un peso di 60m (la lunghezza totale del cavo nella rete, che è 10m + 20m + 30m).

In generale, il peso della rete limita il tempo di salita sul cavo, mentre il raggio determina il timing delle riflessioni di segnale più lente. Queste informazioni sono essenziali per progettare e risolvere problemi nelle reti 1-Wire per garantire che operino in modo efficiente e affidabile.

Topologie della rete OneWire

Anche se le reti OneWire sono spesso abbastanza “libere” nella struttura, di solito si adattano a poche categorie generalizzate basate sulla distribuzione degli slave 1-Wire e sull’organizzazione dei cavi di interconnessione.

Topologia lineare

Il bus 1-Wire è una coppia singola, partendo dal master e estendendosi fino allo slave più lontano. Altri slave sono collegati al bus 1-Wire con ramificazioni insignificanti (< 3m) o “stubs”.

Topologia con stub

Il bus 1-Wire è una linea principale singola, che parte dal master e si estende fino allo slave più lontano. Altri slave sono collegati alla linea principale attraverso ramificazioni o stub di 3m o più di lunghezza.

Topologia a stella

Il bus 1-Wire si divide vicino al master e si estende in più rami di lunghezze variabili. Ci sono dispositivi slave lungo o alle estremità dei rami.

È stato dimostrato che le topologie di rete a stella non interrotte (cioè quelle con diversi rami che divergono dal master) sono le più difficili da rendere affidabili. L’incrocio di vari rami presenta impedenze altamente non corrispondenti; le riflessioni dall’estremità di un ramo possono viaggiare distanze pari a quasi il peso della rete (anziché il raggio) e causare errori nei dati. Per questo motivo, la topologia a stella non interrotta non è raccomandata e non si possono fare garanzie sulle sue prestazioni.

Quando diverse topologie sono mescolate, diventa molto più difficile determinare i limiti pratici della rete. Come regola, il progettista dovrebbe applicare i criteri più conservativi in questi casi.

Reti commutate

Per consentire alle reti di crescere in complessità senza aumentare in peso e raggio, la rete è suddivisa in sezioni che vengono attivate elettronicamente una alla volta.

Utilizzando interruttori analogici a bassa impedenza e alimentazione singola, la rete può fisicamente assomigliare a una topologia ma elettricamente assomigliare a un’altra. Questo significa che una configurazione a stella con un interruttore su ogni ramo assomiglierebbe effettivamente a una topologia lineare.

In questo caso, solo un ramo è attivo in qualsiasi momento. L’esempio sopra sembra una rete a stella con un raggio di 150m e un peso di 450m. Tuttavia, quando ogni percorso commutato è considerato singolarmente, la rete è effettivamente una topologia lineare e il peso è solo 150m. Come regola, la nostra discussione sulle reti non commutate può essere applicata a ogni segmento di una rete commutata.

Limitazioni della rete OneWire

Il raggio massimo e il peso di una rete OneWire sono determinati da diversi fattori. Alcuni di questi fattori possono essere controllati, mentre altri no. L’interfaccia lato master svolge un ruolo cruciale nel determinare le dimensioni ammissibili di una rete OneWire. Deve fornire corrente di pilotaggio sufficiente per superare il peso del cavo e degli slave, generare forme d’onda OneWire con tempistiche entro le specifiche e ottimizzate per i tempi di carica e scarica della rete, e fornire un’adeguata corrispondenza di impedenza alla rete.

Il raggio di una rete 1-Wire è limitato da diversi fattori, inclusi il timing delle riflessioni delle onde, il ritardo temporale prodotto dal cavo, la resistenza del cavo e la degradazione dei livelli di segnale. Il peso della rete è limitato dalla capacità del cavo di essere caricato e scaricato abbastanza velocemente per soddisfare il protocollo 1-Wire.

Una semplice resistenza di pullup ha un limite di peso di circa 200m. In confronto, il limite di peso può essere esteso a oltre 500m utilizzando progetti avanzati di master 1-Wire con pullup attivi che forniscono correnti più elevate sotto controllo logico.

Il raggio è limitato da fattori come il timing e la resistenza del cavo, mentre il peso è limitato dalla capacità del cavo di essere caricato e scaricato abbastanza velocemente. I pullup attivi possono estendere il limite di peso di una rete 1-Wire oltre i limiti delle semplici resistenze di pullup.

Problemi della modalità parassita

Il protocollo di comunicazione 1-Wire non solo facilita la comunicazione, ma fornisce anche l’alimentazione agli slave. Gli slave attingono energia dal bus quando la tensione sul bus è superiore alla tensione sul loro condensatore di accumulo interno di energia.

Tuttavia, in reti con troppi slave, la corrente fornita dal master potrebbe non essere sufficiente a mantenere la tensione di esercizio negli slave, causando guasti intermittenti che dipendono dai dati.

Lo scenario peggiore per l’alimentazione parassita è una lunga sequenza di bit zero emessi dal master, poiché il bus trascorre la maggior parte del suo tempo nello stato basso e c’è poca opportunità di ricaricare gli slave.

Man mano che la tensione in ogni slave diminuisce, la capacità dello slave di guidare il bus diminuisce, portando infine a uno stato di reset in cui lo slave smette di rispondere.

Quando lo slave riceve di nuovo una tensione di esercizio sufficiente, emette un impulso di presenza, che può corrompere altre attività del bus.

Una possibile soluzione è mostrata nell’immagine sopra. In particolare, è utilizzata per i sensori di temperatura ds18b20.

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

Il DS18B20 può anche essere alimentato con il metodo convenzionale collegando un’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.

Abbinamento dell’impedenza distribuito

Il design del bus OneWire è semplice ed economico, e tipicamente si è evitato l’uso di componenti aggiuntivi.

Tuttavia, quando uno stub è collegato al bus, si verifica una mancata corrispondenza dell’impedenza nel punto di ramificazione, che può causare riflessioni che interferiscono con altri slave sulla rete.

Per mitigare questo problema, una resistenza in serie con lo stub può ridurre la gravità della mancata corrispondenza e l’ampiezza dell’energia riflessa.

L’implementazione più riuscita di questo concetto utilizza resistori da 150Ω in ogni punto in cui uno stub è collegato al tronco principale (considera il livello logico di 5v). Questo riduce la mancata corrispondenza nel punto di connessione di circa il 20% e attenua le riflessioni risultanti di circa il 40%. Tuttavia, è necessario prestare attenzione poiché la resistenza aggiunta può ridurre l’immunità al rumore di circa l’80%.

Alternativamente, i valori di resistenza di 100Ω hanno mostrato buone prestazioni e non riducono tanto l’immunità al rumore.

Scelta della resistenza di pull-up per risolvere i problemi

Dopo alcune ricerche in rete, ho trovato alcune soluzioni interessanti per migliorare la distanza in una rete con logica a 3,3v.

In una rete a media distanza con DS18B20, funzionava su cavo corto, falliva su cavo CAT3 di 5M. per risolvere il problema, qualcuno ha aggiunto una resistenza da 80 ohm (un valore basso scelto semi-casualmente) in serie con la linea dati ai due estremi del cavo, abbassando il slew rate e risolvendo il problema per me.

Con un cavo CAT5 non schermato di circa 40m e 7 sensori DS18B20. GROUND è collegato a 2 fili di coppie ritorte diverse. Gli ultimi fili di queste coppie ritorte sono utilizzati per DATI e alimentazione. Tra GPIO4 e 3.3v, c’è una resistenza di pull-up da 2,2k. Il maker corregge i dati dagli ultimi 2 sensori sul filo, mentre un sensore nel mezzo mostra sempre 85000. Per me, ha iniziato a funzionare quando ho cambiato la resistenza di pull-up da 4,7k a 2,2k.

Cablaggio

La libreria One-Wire è uno standard per tutti i microcontrollori, quindi il dispositivo può essere utilizzato con molti microcontrollori. Abbiamo già mostrato il collegamento del singolo sensore, ora stiamo per collegare e gestire più sensori.

Se hai bisogno di collegare solo un sensore, fai riferimento all’articolo precedente, “Dallas ds18b20 con Raspberry Pi Pico (rp2040): introduzione e modalità parassita”.

Modalità normale Raspberry Pi Pico

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

O altra variante:

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 il collegamento diventa come segue.

Il collegamento è molto semplice.

Raspberry Pi Picods18b20
GNDGND
3.3vVCC
D22 pulled-upDATA

Modalità normale sensori multipli in topologia lineare

Modalità parassita

Nella modalità parassita, metterai anche la linea VCC del sensore a GND, e ottiene l’alimentazione dalla linea Dati.

Raspberry Pi Picods18b20
GNDGND
GNDVCC
D22 pulled-upDATA

Modalità parassita sensori multipli in topologia lineare

Libreria

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

Usa OneWireNg non la libreria OneWire standard

Non usarla finché il bug non sarà risolto.

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

Usa questa per ora

Dopo di che, devi installare una libreria che implementa il protocollo e le funzionalità del sensore.

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

Dispositivi supportati

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

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

Avrai 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 utilizzare la modalità parassita e collegare il VCC a GND come descritto.

Risoluzione dei problemi

In caso di problemi nella conversione della temperatura (il risultato è -85), potrebbe essere necessario un setup 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, oppure può operare in modalità “parassita”, che consente al DS18B20 di funzionare senza un’alimentazione esterna locale (collegando 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 è conservata nel condensatore di alimentazione parassita (CPP) per fornire energia quando il bus è basso.

Tuttavia, quando il DS18B20 esegue conversioni di 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 debole resistenza di pull-up del 1-Wire ed è più corrente di quanto il CPP possa fornire.

Pull-up forte per la modalità parassita

Per assicurare che il DS18B20 disponga di una sufficiente alimentazione di corrente, è necessario fornire un pull-up forte sul bus 1-Wire ogni volta che si verificano conversioni di temperatura o la copia di dati dalla scratchpad all’EEPROM.
Questo può essere ottenuto utilizzando un MOSFET per collegare direttamente il bus al binario.

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

Il DS18B20 può anche essere alimentato con il metodo convenzionale collegando un’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.

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 correnti di perdita più elevate che possono esistere a queste temperature.

Ridurre le dimensioni della libreria

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

#define REQUIRESNEW 

oppure

#define REQUIRESALARMS

all’inizio di DallasTemperature.h

Codice

Quando si lavora con più dispositivi, è essenziale identificarli in modo univoco. Dobbiamo ricordare che il ds18bouse has an internal address that can be used as uuid.

Cerca tutti i sensori collegati alla rete

Ecco un semplice esempio che cerca tutti i dispositivi OneWire collegati a un intervallo di pin e genera un elenco di indirizzi che possono essere utilizzati per gestire il ds18b20.

/**
 * OneWire Library example
 * Find all device (select starting end ending pin)
 *
 * Renzo Mischianti <www.mischianti.org>
 */

#define STARTING_PIN D22
#define ENDING_PIN D22

uint8_t findDevices(int pin);

#include <OneWire.h>

void setup()
{
  Serial.begin(115200);
  Serial.println("//\n// Start oneWire search \n//");

  for (uint8_t pin = STARTING_PIN; pin <= ENDING_PIN; pin++)
  {
    findDevices(pin);
  }
  Serial.println("\n//\n// End oneWire search \n//");
}

void loop()
{
}

uint8_t findDevices(int pin)
{
  OneWire ow(pin);

  uint8_t address[8];
  uint8_t count = 0;


  if (ow.search(address))
  {
    Serial.print("\nDeviceAddress pin");
    Serial.print(pin, DEC);
    Serial.println("[] = {");
    do {
      count++;
      Serial.print(" {");
      for (uint8_t i = 0; i < 8; i++)
      {
        Serial.print("0x");
        if (address[i] < 0x10) Serial.print("0");
        Serial.print(address[i], HEX);
        if (i < 7) Serial.print(", ");
      }
      Serial.println("  },");
    } while (ow.search(address));

    Serial.println("};");
    Serial.print("// nr devices found: ");
    Serial.println(count);
  }

  return count;
}

Nel mio caso, l’output della seriale è:

//
// Start oneWire search 
//

DeviceAddress pin22[] = {
 {0x28, 0xFF, 0x64, 0x0E, 0x6C, 0x63, 0xD0, 0x15  },
 {0x28, 0xFF, 0x64, 0x0E, 0x6C, 0x6F, 0x7A, 0x89  },
 {0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x64, 0x7F, 0x3E  },
 {0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x5C, 0x1A, 0x3F  },
 {0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x5D, 0x66, 0xA0  },
};
// nr devices found: 5

//
// End oneWire search 
//

Ha trovato correttamente 5 ds18b20 e generato l’array degli indirizzi.

Ottieni informazioni e temperatura da un array di indirizzi

Con l’array dello sketch precedente, andremo a realizzare uno sketch per leggere la temperatura.

/**
 * From a list of thermostat address
 * generated with the previous search sketch
 * we are going to  get the
 * temperature of every device
 *
 * by Renzo Mischianti <www.mischianti.org>
 *
 * https://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
#define TEMPERATURE_PRECISION 9

// 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 array generated from the search sketch
DeviceAddress pin22[] = {
 {0x28, 0xFF, 0x64, 0x0E, 0x6C, 0x63, 0xD0, 0x15  },
 {0x28, 0xFF, 0x64, 0x0E, 0x6C, 0x6F, 0x7A, 0x89  },
 {0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x64, 0x7F, 0x3E  },
 {0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x5C, 0x1A, 0x3F  },
 {0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x5D, 0x66, 0xA0  },
};

void setup(void)
{
  // start serial port
  Serial.begin(115200);
  while (!Serial) {delay(100);}

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

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

  // set the temperature accurancy
  for (int i = 0; i < 5; i++) {
	  // set the resolution to 9 bit per device
	   sensors.setResolution(pin22[i], TEMPERATURE_PRECISION);
  }
}

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

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

  for (int i = 0; i < 5; i++) {
	  // print the device information
	  Serial.print("Device Address: ");
	  printAddress(pin22[i]);
	  Serial.print(" of ");
	  Serial.print(i);
	  Serial.print(" sensor -> ");
	  printTemperature(pin22[i]);
	  Serial.println();
  }

  delay(2000);
}

Il risultato nell’output seriale:

Dallas Temperature IC Control 
Locating devices...Found 5 devices.
Parasite power is: OFF
Requesting temperatures...DONE
Device Address: 28FF640E6C63D015 of 0 sensor -> Temp C: 19.56 Temp F: 67.21
Device Address: 28FF640E6C6F7A89 of 1 sensor -> Temp C: 19.87 Temp F: 67.77
Device Address: 28FF640E6D647F3E of 2 sensor -> Temp C: 19.62 Temp F: 67.32
Device Address: 28FF640E6D5C1A3F of 3 sensor -> Temp C: 19.69 Temp F: 67.44
Device Address: 28FF640E6D5D66A0 of 4 sensor -> Temp C: 19.62 Temp F: 67.32
Requesting temperatures...DONE
Device Address: 28FF640E6C63D015 of 0 sensor -> Temp C: 19.62 Temp F: 67.32
Device Address: 28FF640E6C6F7A89 of 1 sensor -> Temp C: 19.81 Temp F: 67.66
Device Address: 28FF640E6D647F3E of 2 sensor -> Temp C: 19.62 Temp F: 67.32
Device Address: 28FF640E6D5C1A3F of 3 sensor -> Temp C: 19.69 Temp F: 67.44
Device Address: 28FF640E6D5D66A0 of 4 sensor -> Temp C: 19.62 Temp F: 67.32

Indicizzazione dei sensori e ottenimento della temperatura

Una soluzione non molto reale è indicizzare i sensori e ottenere la temperatura. Questa soluzione non è molto utile perché non puoi sapere quale sensore diventa 0, 1… e così via.

Per semplicità, riduco il numero di sensori a 4.

/**
 * Indexing thermometer and read the temperature
 *
 * by Renzo Mischianti <www.mischianti.org>
 *
 * https://mischianti.org
 */
#include <OneWire.h>
#include <DallasTemperature.h>

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

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

DeviceAddress firstThermometer, secondThermometer, thirdThermometer, fourthThermometer;

void setup(void)
{
  // start serial port
  Serial.begin(115200);
  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");

  // assigns the first address found to insideThermometer
  if (!oneWire.search(firstThermometer)) Serial.println("Unable to find 1 address for insideThermometer");
  // assigns the second address found to insideThermometer
  if (!oneWire.search(secondThermometer)) Serial.println("Unable to find 2 address for insideThermometer");
  // assigns the third address found to insideThermometer
  if (!oneWire.search(thirdThermometer)) Serial.println("Unable to find 3 address for insideThermometer");
  // assigns the fourth address found to insideThermometer
  if (!oneWire.search(fourthThermometer)) Serial.println("Unable to find 4 address for insideThermometer");

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

  Serial.print("Device 1 Address: ");
  printAddress(secondThermometer);
  Serial.println();

  Serial.print("Device 2 Address: ");
  printAddress(thirdThermometer);
  Serial.println();

  Serial.print("Device 3 Address: ");
  printAddress(fourthThermometer);
  Serial.println();

  // set the resolution to 9 bit per device
  sensors.setResolution(firstThermometer, TEMPERATURE_PRECISION);
  sensors.setResolution(secondThermometer, TEMPERATURE_PRECISION);
  sensors.setResolution(thirdThermometer, TEMPERATURE_PRECISION);
  sensors.setResolution(fourthThermometer, TEMPERATURE_PRECISION);

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

  Serial.print("Device 1 Resolution: ");
  Serial.print(sensors.getResolution(secondThermometer), DEC);
  Serial.println();

  Serial.print("Device 2 Resolution: ");
  Serial.print(sensors.getResolution(thirdThermometer), DEC);
  Serial.println();

  Serial.print("Device 3 Resolution: ");
  Serial.print(sensors.getResolution(fourthThermometer), 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(firstThermometer);
  printData(secondThermometer);
  printData(thirdThermometer);
  printData(fourthThermometer);

  delay(2000);
}

Ogni volta che si esegue una ricerca, viene generato e assegnato un nuovo indice, e la ricerca restituisce 1 quando non vengono trovati altri sensori, restituisce 0.

  // assigns the first address found to insideThermometer
  if (!oneWire.search(firstThermometer)) Serial.println("Unable to find 1 address for insideThermometer");
  // assigns the second address found to insideThermometer
  if (!oneWire.search(secondThermometer)) Serial.println("Unable to find 2 address for insideThermometer");
  // assigns the third address found to insideThermometer
  if (!oneWire.search(thirdThermometer)) Serial.println("Unable to find 3 address for insideThermometer");
  // assigns the fourth address found to insideThermometer
  if (!oneWire.search(fourthThermometer)) Serial.println("Unable to find 4 address for insideThermometer");
  // assigns the fifth address found to insideThermometer
  if (!oneWire.search(fifthThermometer)) Serial.println("Unable to find 5 address for insideThermometer");
  // assigns the sixth address found to insideThermometer
  if (!oneWire.search(sixthThermometer)) Serial.println("Unable to find 6 address for insideThermometer");

Quindi la parte più rilevante e recente dell’output seriale è evidenziata.

Dallas Temperature IC Control Library Demo
Locating devices...Found 4 devices.
Parasite power is: OFF
Unable to find 5 address for thermometer
Device 0 Address: 28FF640E6C6F7A89
Device 1 Address: 28FF640E6D647F3E
Device 2 Address: 28FF640E6D5C1A3F
Device 3 Address: 28FF640E6D5D66A0
Device 0 Resolution: 12
Device 1 Resolution: 12
Device 2 Resolution: 12
Device 3 Resolution: 12
Requesting temperatures...DONE
Device Address: 28FF640E6C6F7A89 Temp C: 21.31 Temp F: 70.36
Device Address: 28FF640E6D647F3E Temp C: 21.19 Temp F: 70.14
Device Address: 28FF640E6D5C1A3F Temp C: 21.31 Temp F: 70.36
Device Address: 28FF640E6D5D66A0 Temp C: 21.19 Temp F: 70.14
Requesting temperatures...DONE
Device Address: 28FF640E6C6F7A89 Temp C: 21.31 Temp F: 70.36
Device Address: 28FF640E6D647F3E Temp C: 21.19 Temp F: 70.14
Device Address: 28FF640E6D5C1A3F Temp C: 21.25 Temp F: 70.25
Device Address: 28FF640E6D5D66A0 Temp C: 21.19 Temp F: 70.14

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
  7. Collegamento dell’EByte E70 ai dispositivi Raspberry Pi Pico (rp2040) ed un semplice sketch di esempio

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *