In articolul anterior, Mai multi senzori de tip DS18B20 (sau MAX31820) in paralel, am conectat 3 senzori din familia DS18x20 (unul DS18B20 si 2 de tipul MAX31820), acum ca am primit inca 2 monstre de tipul DS18B20 de la Dallas Semiconductor (Maxim Integrated), cum primisem, in ianuarie, si pe cei 2 senzori MAX31820, am zis ca pot citi temperatura in 5 puncte.
Schema de conectare a senzprilor este identica, toti 5 vor fi in paralel:
iar prezentarea datelor am facut-o pe un afisaj LCD alfanumeric cu 16 coloane si 2 randuri (1602 sau 16x2):
// full sketch by niq_ro from http://nicuflorica.blogspot.com// or http://www.tehnic.go.ro// or http://arduinotehniq.blogspot.com/
#include <Wire.h> // for i2c protocol
#include <OneWire.h>
// http://www.pjrc.com/teensy/td_libs_OneWire.html// http://milesburton.com/Dallas_Temperature_Control_LibraryOneWire ds(10); // on pin 10 (a 4.7K resistor is necessary)
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x20,16,2); // 0x20 is adresss for LCC 16x2byte grad[8] = {
B01110,
B10001,
B10001,
B01110,
B00000,
B00000,
B00000,
};
int ics =0; //count number of sensorvoidsetup(){
lcd.init();
lcd.backlight(); //backlight is now ON// set up the LCD's number of columns and rows:
lcd.createChar(0, grad);
lcd.begin(16, 2);
// Print a logo message to the LCD.
lcd.print("www.tehnic.go.ro");
lcd.setCursor(0, 1);
lcd.print("creat de niq_ro");
delay (2500);
lcd.clear();
// Print a message to the LCD.
lcd.setCursor(1, 0);
lcd.print("temperatura in");
lcd.setCursor(1, 1);
lcd.print("mai multe zone");
delay (2500);
lcd.clear();
}
voidloop(){
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius;
if ( !ds.search(addr)) {
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("doar ");
lcd.print(ics);
lcd.print(" senzor(i)");
ds.reset_search();
ics=0;
return;
}
ics++;
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the enddelay(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 Scratchpadfor ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
// 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 defaultif (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 themif (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 mselseif (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 mselseif (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms//// default is 12 bit resolution, 750 ms conversion time
}
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("ROM=");
for( i = 0; i < 8; i++) {
lcd.print(' ');
lcd.print(addr[i], HEX);
}
if (OneWire::crc8(addr, 7) != addr[7]) {
lcd.print("CRC is not valid!");
return;
}
celsius = (float)raw / 16.0;
lcd.setCursor(0,0);
lcd.print("Temp");
lcd.print(ics);
lcd.print(" = ");
lcd.print(celsius);
lcd.write(byte(0));
lcd.print("C ");
delay(3000);
}
11.02.2014 Am desenat schema completa de conectare a senzorilor din familia DS18x20 (DS18B20, DS18S20, DS1822, MAX31820) si a afisajului LCD 1602 cu interfata i2c:
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:
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_LibraryOneWire ds(10); // on pin 10 (a 4.7K resistor is necessary)voidsetup(void) {
Serial.begin(9600);
}
voidloop(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 chipswitch (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 enddelay(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 ScratchpadSerial.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 defaultif (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 themif (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 mselseif (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 mselseif (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 Variablesint sensorPin = 0; //the analog pin the LM35 Vout (sense) pin is connected to A0//the resolution is 10 mV / degree centigrade with aint 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_rofloat vmed = 0;
float ve = 0;
OneWire ds(10); // on pin 10 (a 4.7K resistor is necessary)voidsetup()
{
Serial.begin(9600); //Start the serial connection with the computer//to view the result open the serial monitor
}
voidloop() // run over and over again
{
vmed = 0;
ve=0;
for (int j = 0; j < 10; j++) {
//getting the voltage reading from the temperature sensorint reading = analogRead(sensorPin);
int reading1 = analogRead(diodePin);
// converting that reading to voltage, for 3.3v arduino use 3.3float voltage = (reading - reading1) * 5.0;
voltage /= 1023.0;
vmed = vmed + voltage;
delay(200);
}
ve = vmed/10;
// print LM35 logoSerial.println("--------------------");
Serial.print(" LM35: ");
/* // print out the voltage Serial.print(ve); Serial.println(" volts");*/// now print out the temperaturefloat 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 partbyte 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 chipswitch (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 enddelay(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 ScratchpadSerial.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 defaultif (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 themif (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 mselseif (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 mselseif (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:
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.