sâmbătă, 11 ianuarie 2014

Noii senzori de temperatura MAX31820 fata de "clasicii" DS18B20

  Cautand la Maxim Integrated pe site, am descoperit un senzor nou, MAX31820, care are fisa de catalog (datasheet) si ca prezentare "1-Wire Ambient Temperature Sensor", asa ca am cerut si eu 2 monstre (samples) si, spre uimirea mea, in 3 zile a si sosit tocmai din Filipine:
  La inceput nu mi-am dat seama care e diferenta fata de "clasicul" DS18B20,care are fisa de catalog si are denumirea de "Programmable Resolution 1-Wire Digital Thermometer".
  Diferenta este de gama de masura cu precizie mare de +0,5 grade Celsius, care este la DS18B20 de la -10 pana la +85 grade Celsius, iar la MAX31820 de la +10 pana la +45 grade Celsius, pana si cei 8 biti de identificare ai familiei de senzori este identic 028h.
   Prima data am conectat doar un senzor MAX31280 in paralel cu DS18B20, ca sa-i aflu adresa, folosind 2 sketch-uri, unul fin cel din exemplul de la libraria OneWire si celalalt in care masoara temperaturi si cu un LM35:
 
   Am conectat si pe al doilea senzor MAX31820, folosind cele 2 sketch-uri si am obtinut:
 
   Modul de conectare in paralel este prezentat, de exemplu, in articolul Temperature Sensing using DS18B20 Digital Sensors:
   Primul sketch folosit, in care se folosesc doar senzorii DS1820, respectiv MAX31820, este cel clasic din exemplul de la libraria OneWire, cu mici modificari:
#include <OneWire.h>
// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)

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

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
  
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  
  delay(3000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
  Serial.println("-----------------------");
}
  Al doilea sketch, care masoara si cu un LM35:
// original sketch from http://learn.adafruit.com/tmp36-temperature-sensor/using-a-temp-sensor
// adapted sketch by niq_ro from http://nicuflorica.blogspot.com
// LM35 datasheet: http://www.ti.com/lit/ds/symlink/lm35.pdf
// inspired by http://www.roroid.ro/wiki/pmwiki.php/Main/TermometruCuArduino
// OneWire DS18S20, DS18B20, DS1822 Temperature Example: http://www.pjrc.com/teensy/td_libs_OneWire.html
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library
#include <OneWire.h>


//LM35 Pin Variables
int sensorPin = 0; //the analog pin the LM35 Vout (sense) pin is connected to A0
                        //the resolution is 10 mV / degree centigrade with a
int diodePin = 1;  //pin for measure voltage diode             

 /*
 * setup() - this function runs once when you turn your Arduino on
 * We initialize the serial connection with the computer
 */

// added part by niq_ro
float vmed = 0;
float ve = 0;  

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)


void setup()
{
  Serial.begin(9600);  //Start the serial connection with the computer
                       //to view the result open the serial monitor 
}
 
void loop()                     // run over and over again
{
 vmed = 0;
 ve=0;
  
 for (int j = 0; j < 10; j++)  {
  
 //getting the voltage reading from the temperature sensor
 int reading = analogRead(sensorPin);  
 int reading1 = analogRead(diodePin);  
    
 // converting that reading to voltage, for 3.3v arduino use 3.3
 float voltage = (reading - reading1) * 5.0;
 voltage /= 1023.0; 
 
 vmed = vmed + voltage;
 delay(200);
 
 }
 ve = vmed/10;
 // print LM35 logo
 Serial.println("--------------------");
 Serial.print("   LM35: ");

/* 
 // print out the voltage
 Serial.print(ve); Serial.println(" volts");
*/

 // now print out the temperature
 float temperatureC = ve * 100 ;  //converting from 10 mv per degree 
                                               //to degrees (voltage) times 100)
 Serial.print(temperatureC); Serial.println(" degrees C");
/* 
 // now convert to Fahrenheit
 float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
 Serial.print(temperatureF); Serial.println(" degrees F");
*/
 Serial.println("----------------");
 delay(1000);                                     //waiting a second

// DS18B20 part

  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;

  
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }


  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("DS18B20: ");
  Serial.print(celsius); Serial.println(" degrees C");
/*
  Serial.print(fahrenheit); Serial.println(" degrees F");
*/
delay(2000);
}
   Concluzionand, acest tip senzor MAX31820 poate fi folosit ca inlocuitor pentru DS18B20, mai ales daca domeniul de temperatura este cel ambiant (+10..+45 grade Celsius). 
   Am facut si un mic filmulet, ca un rezumat, numit noii senzori MAX31820 fata de DS18B20
   PS: Am desenat si schema de conectare a senzorilor pentru a nu aparea dificulatati in intelegerea modului de conectare:
   Daca se doreste conectarea doar a senzorilor digitali DS18B20 si/sau MAX31280  schema devine:
12.ian.2014
PS2: Am mai pus 2 filmulete (scuze pentru calitatea sunetului):
new MAX31820 vs DS18B20 and Arduino
17.01.2014
PS2: Trebuie sa mentionez ceva, de care am uitat, 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.


Niciun comentariu:

Trimiteți un comentariu