sâmbătă, 11 ianuarie 2014

Mai multi senzori de tip DS18B20 (sau MAX31820) in paralel

   In articolul anterior, Noii senzori de temperatura MAX31820 fata de "clasicii" DS18B20, am conectat in paralel un senzor DS18B20 (cu precize garantata de +0,50pe domeniul de la -10 la +850C, in rest e de +20C) si 2 de tipul MAX31820 (care este o varianta noua, cu precize garantata de +0,50doar pe un domeniu de +10...+450 Celsius, in rest e de +20C).
   Schema de conectare este simpla:
   Deoarece sunt din aceeasi clasa, ele sunt indentificate de Arduino ca fiind DS18B20.
   In articolul  Arduino 1-Wire Address Finder este prezentat un sketch, care gaseste adresele tuturor senzorilor pe comunicatia 1-Wire. L-am incarcat si eu si am obtinut:
   Sketch-ul, in care doar am pus pinul de date la 10, cum aveam eu facut, este:
// This sketch looks for 1-wire devices and
// prints their addresses (serial number) to
// the UART, in a format that is useful in Arduino sketches
// Tutorial: 
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html

#include <OneWire.h>

OneWire  ds(10);  // Connect your 1-wire device to pin 10

void setup(void) {
  Serial.begin(9600);
  discoverOneWireDevices();
}

void discoverOneWireDevices(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
  
  Serial.print("Looking for 1-Wire devices...\n\r");
  while(ds.search(addr)) {
    Serial.print("\n\rFound \'1-Wire\' device with address:\n\r");
    for( i = 0; i < 8; i++) {
      Serial.print("0x");
      if (addr[i] < 16) {
        Serial.print('0');
      }
      Serial.print(addr[i], HEX);
      if (i < 7) {
        Serial.print(", ");
      }
    }
    if ( OneWire::crc8( addr, 7) != addr[7]) {
        Serial.print("CRC is not valid!\n");
        return;
    }
  }
  Serial.print("\n\r\n\rThat's it.\r\n");
  ds.reset_search();
  return;
}

void loop(void) {
  // nothing to see here
}
   Deoarece trebuie sa le identific cumva, m-am inspirat din articolul Two DS18B20 Temp Sensors on LCD Display! in care apare si o librarie numita DallasTemperature Arduino Library, care se gaseste tot in articolul mentionat la inceput, Arduino 1-Wire Address Finder.
   Dupa descarcarea librariei, dezarhivarea si mutarea in subdirectorul de librarii al programului Arduino, am ales exemplul numit Multiple:
si l-am modificat pentru cazul meu, cu 3 senzori, in dreapta e DS18B20, iar ceilalti 2 senzori MAX31820 sunt in mijloc, respectiv stanga.
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 10 on the Arduino
#define ONE_WIRE_BUS 10
#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 rightThermometer, midleThermometer, leftThermometer;

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

  // 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)
  //insideThermometer = { 0x28, 0x1D, 0x39, 0x31, 0x2, 0x0, 0x0, 0xF0 };
  //outsideThermometer   = { 0x28, 0x3F, 0x1C, 0x31, 0x2, 0x0, 0x0, 0x2 };

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

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

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


  // set the resolution to 9..12 bit
  sensors.setResolution(rightThermometer, TEMPERATURE_PRECISION);
  sensors.setResolution(midleThermometer, TEMPERATURE_PRECISION);
  sensors.setResolution(leftThermometer, TEMPERATURE_PRECISION);

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

  Serial.print("Device 1 Resolution: ");
  Serial.print(sensors.getResolution(midleThermometer), DEC); 
  Serial.println();
  
  Serial.print("Device 2 Resolution: ");
  Serial.print(sensors.getResolution(leftThermometer), 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);
  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();
}

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(rightThermometer);
  printData(midleThermometer);
  printData(leftThermometer);
  delay(3000);
  
}
   Pe ecranul de monitorizare seriala am acum datele:
 
cu minime modificari: 
 

12.ian.2014
   M-a gandit sa nu las neterminata treaba, asa ca m-am mai jucat cu sketch-ul si pe ecram am obtinut:

iar sketch-ul folosit este:
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 10 on the Arduino
#define ONE_WIRE_BUS 10
#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 rightThermometer, midleThermometer, leftThermometer;


void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library use by niq_ro");
  Serial.println("---------------------------------------------------");

  // Start up the library
  sensors.begin();
  DeviceAddress rightThermometer = { 0x28, 0xAC, 0x7A, 0xD4, 0x4, 0x0, 0x0, 0x7E };
  DeviceAddress midleThermometer = { 0x28, 0xF5, 0xFB, 0x58, 0x5, 0x0, 0x0, 0xA0 };
  DeviceAddress leftThermometer = { 0x28, 0xCB, 0xF0, 0x58, 0x5, 0x0, 0x0, 0x2E };


  // method 1: by index
  if (!sensors.getAddress(rightThermometer, 0)) Serial.println("Unable to find address for Device 0"); 
  if (!sensors.getAddress(midleThermometer, 1)) Serial.println("Unable to find address for Device 1"); 
  if (!sensors.getAddress(leftThermometer, 2)) Serial.println("Unable to find address for Device 2"); 


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

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

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


  // set the resolution to 9..12 bit
  sensors.setResolution(rightThermometer, TEMPERATURE_PRECISION);
  sensors.setResolution(midleThermometer, TEMPERATURE_PRECISION);
  sensors.setResolution(leftThermometer, TEMPERATURE_PRECISION);

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

  Serial.print("Device 1 Resolution: ");
  Serial.print(sensors.getResolution(midleThermometer), DEC); 
  Serial.println();
  
  Serial.print("Device 2 Resolution: ");
  Serial.print(sensors.getResolution(leftThermometer), DEC); 
  Serial.println();
*/
}


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

// function to print the temperature for a device
void printTemperature(DeviceAddress device)
{
  float tempC = sensors.getTempC(device);
  Serial.print("Temp C: ");
  if (tempC == -127.00) {
  Serial.print("Error");
} else {
  Serial.print(tempC);
  Serial.print(" Temp F: ");
  Serial.print(DallasTemperature::toFahrenheit(tempC));
}
}
// function to print a device's resolution
void printResolution(DeviceAddress device)
{
  Serial.print("Resolution: ");
  Serial.print(sensors.getResolution(device));
  Serial.println();    
}

// main function to print information about a device
void printData(DeviceAddress device)
{
  Serial.print("Address: ");
  printAddress(device);
  Serial.print(" ");
  printTemperature(device);
  Serial.println();
}

void loop(void)
{ 
  DeviceAddress rightThermometer = { 0x28, 0xAC, 0x7A, 0xD4, 0x4, 0x0, 0x0, 0x7E };
  DeviceAddress midleThermometer = { 0x28, 0xF5, 0xFB, 0x58, 0x5, 0x0, 0x0, 0xA0 };
  DeviceAddress leftThermometer = { 0x28, 0xCB, 0xF0, 0x58, 0x5, 0x0, 0x0, 0x2E };

   // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  Serial.println("---------------------------------------");
  Serial.println(" ");
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures();
  Serial.println("DONE");
  Serial.println("---------------------------------------");
  Serial.println(" ");

  // print the device information
  Serial.print("Device DS18B20 (right) ");
  printData(rightThermometer);
  Serial.println("---------------------------------------");
  Serial.print("Device MAX31820 (center) ");
  printData(midleThermometer);
  Serial.println("---------------------------------------");
  Serial.print("Device MAX31820 (left) ");
  printData(leftThermometer);
  Serial.println("---------------------------------------");
  delay(3000);
}

17.01.2014
PS: Dupa cum am mentionat si la finalul articolului anterior (Noii senzori de temperatura MAX31820 fata de "clasicii" DS18B20), in datasheet-ul senzorilor MAX31820, se mentioneaza ca tensiunea de alimentare normala este intre 3 si 3,7V deci ar functiona perfect cu microcontroler-e alimentate la tensiunea de 3,3V. Tot in datasheet se mentioneaza ca tensiunea maxima admisa este de 6V, exact ca la DS18B20... Eu le-am alimentat la 5V, cat era la Arduino si au mers perfect.

5 comentarii:

  1. Scuzați-mă, am o întrebare "off topic" : cum adăugați sketch-urile ?

    RăspundețiȘtergere
  2. in blog? vezi: http://nicuflorica.blogspot.ro/2013_07_01_archive.html si http://nicuflorica.blogspot.ro/2013/10/prezentare-frumoasa-sketchprogram-in.html

    RăspundețiȘtergere
  3. Buna ziua,

    Cum se comporta modelul acesta canda vem 20-30 sensori pe un fir de 150m? Trebuie o sursa separata, rezistor mai mare?

    Multumesc,
    Cata

    RăspundețiȘtergere
    Răspunsuri
    1. nu am incercat decat cu 5 odata pe 15-20cm... trebuie vazut in datasheet-ul lui DS18B20 sau prin documentatua tehnica a producatorului (Aplication Note)

      Ștergere