Go Down

Topic: Temperaturmessung mit mehreren DS18S20 (Read 12738 times) previous topic - next topic

Knippi

Hallo,
ich möchte gerne mit meinem Mega 2560 + 16x2 Display und zwei DS18S20 zwei Temperaturen messen. Ein DS18S20 soll die Temperatur in meinem Aquarium messen und der andere die Temperatur im Unterschrank.
Die Temperatur im Aquarium messe ich bereits mit nachfolgenden Sketch. Nun soll ein weiterer DS18S20 mit eingebunden werden und zur Anzeige gebracht werden. So wie in etwa ein Innen- und Außenthermometer.
Z.Z. habe ich den einen DS18S20 wie im Bild dargestellt angeschlossen.

Code: [Select]
#include <LiquidCrystal.h>
#include "Wire.h"
#include <OneWire.h>
#define DS1307_I2C_ADDRESS 0x68  // This is the I2C address
// Arduino version compatibility Pre-Compiler Directives
#if defined(ARDUINO) && ARDUINO >= 100   // Arduino v1.0 and newer
  #define I2C_WRITE Wire.write
  #define I2C_READ Wire.read
#else                                   
  #define I2C_WRITE Wire.send
  #define I2C_READ Wire.receive
#endif

// Initialisierung des LCD
LiquidCrystal lcd(22, 23, 24, 25, 26, 27);
OneWire  ds(28);

// Globale Variablen
byte i;
byte present = 0;
byte data[12];
byte addr[8];
float Temp;
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
int u, j, k = 0;
//float temp_in, temp_out;
byte zero;
char  *Day[] = {"","So","Mo","Di","Mi","Do","Fr","Sa"};
char  *Mon[] = {"","Jan.","Feb.","Mar.","Apr.","Mai.","Jun.","Jul.","Aug.","Sep.","Okt.","Nov.","Dez."};

// Wandelt BCD-Werte in Dezimalwerte um
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// Daten von RTC erhalten
void getDateDs1307()
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  I2C_WRITE(zero);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
}

void setup()
{
 
// Start des IIC-Modi
  Wire.begin();


};

void loop()
{
// Ausgabe von Datum und Uhrzeit inkl. Abfrageroutine der IIC-RTC
while(u <= 10)//die Zeit für der Anzeigendauer

  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  I2C_WRITE(zero);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

// Maskierung der Bits vom RTC-Modul
  second     = bcdToDec(I2C_READ() & 0x7f);
  minute     = bcdToDec(I2C_READ());
  hour       = bcdToDec(I2C_READ() & 0x3f);  // Need to change this if 12 hour am/pm
  dayOfWeek  = bcdToDec(I2C_READ());
  dayOfMonth = bcdToDec(I2C_READ());
  month      = bcdToDec(I2C_READ());
  year       = bcdToDec(I2C_READ());

// Ausgabe des Datums im Format DD,_dd._mmm._'yy
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(Day[dayOfWeek]);
  lcd.print(", ");
  if (dayOfMonth < 10)
    lcd.print("0");
  lcd.print(dayOfMonth, DEC);
  lcd.print(".");
  lcd.print(" ");
  lcd.print(Mon[month]);
  lcd.print(" '");
  lcd.println(year, DEC);


// Ausgabe der Uhrzeit im Format hh:mm:ss
  lcd.setCursor(4, 1);
  if (hour < 10)
     lcd.print("0");
  lcd.print(hour, DEC);
  lcd.print(":");
  if (minute < 10)
    lcd.print("0");
  lcd.print(minute, DEC);
  lcd.print(":");
  if (second < 10)
    lcd.print("0");
  lcd.print(second, DEC);
  lcd.print("  ");
  lcd.noCursor();
  u++;
  delay(500);
  j = 0;
  k = 0;
};

while(j <= 10)
{



  // display Sensor data on LCD:
  if ( !ds.search(addr)) {
    // No more Dallas chips present:
    Serial.print("No more addresses.\n");
    ds.reset_search();
    //delay(250);
    //return;
     // Check for family code which is not DS18B20:
  if ( addr[0] != 0x28) {
    Serial.print("Device is not a DS18B20 family device.\n");
    return;
   
  }
  // The DallasTemperature library can do all this work for you!
  ds.reset();
  ds.select(addr);
  ds.write(0x44,0);          // start conversion, with parasite power off
   present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);             // Read Scratchpad 
  // Check whether chip is present:
  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);             // Read Scratchpad
 
   Serial.print("P=");         // Present = 1
  Serial.print(present,HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {   // we need 9 bytes of data
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
   Serial.print(" CRC=");
  Serial.print( OneWire::crc8( data, 8), HEX);
  // Calculate temperature. data[1] High Byte, data[0] Low Byte.
  Temp =  ((data[1] << 8) + data[0] ) * 0.0625;  // 12Bit = 0,0625 C per Bit
  Serial.print( " T=");
  Serial.print( Temp, 2);
  Serial.print( " C");
  Serial.println();
  }
  char line[17];
lcd.clear();
  lcd.setCursor(0,0);
  //sprintf(line, "T=%f C", Temp); funktioniert nicht, Fehler in Compiler?
  dtostrf(Temp, 5, 2, line);
  lcd.print("T=");
  lcd.print(line);
  lcd.print(" C");
j++;
delay(500);
  u = 0;
  };
}


Meine Frage wäre nun, wie binde ich einen zweiten DS18S20 in die Schaltung und in den Sketch ein?

Danke.
Gruß Jens


uwefed

Die DS18S20 einfach paralell schalten und mit ihrer Adresse ansprechen.
http://fluuux.de/2012/09/arduino-adressen-aller-ds1820-ermitteln/
http://fluuux.de/2012/09/arduino-gezielt-einen-ds1820-temperatur-sensor-auslesen/

Grüße Uwe

Nighti

Der Sensor ist über 1-wire angeschlossen. D.h. alle Geräte haben eine gemeinsame  Datenleitung (ein Kabel) und werden über ihre Adresse angesprochen.
Falls dir das nicht klar sein sollte, dann empfehle ich dir dich in das 1-wire Protokoll einzulesen.

Knippi

Hallo,

danke für die "Wegbereitung".
Ich habe die Fühler nun parallel geschaltet und den von uwfed vorgeschlagenen Sketch mit den zuvor ausgelesenen Adressen der beiden DS18S20 umgesetzt.
Leider bekomme ich die Werte der beiden Fühler in Fahrenheit anstatt in °Celsius.
Muss man hier noch so etwas wie eine Umrechnungsformel mit einsetzen?
Anbei der Sketch:
Code: [Select]
#include <OneWire.h>
#include <DallasTemperature.h>

OneWire  ds(28); //pin für ds1820

//DeviceAdressen der einzelnen ds1820 Temperatursensoren angeben. (loop anpassen)
DeviceAddress sensor1 = { 0x28, 0x36, 0x2F, 0x99, 0x4, 0x0, 0x0, 0x3A };
DeviceAddress sensor2 = { 0x28, 0xB1, 0xB7, 0xBD, 0x4, 0x0, 0x0, 0xA2 };


char sensor1Name[] = "Unterschrank: ";
char sensor2Name[] = "W.-Temp: ";


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

void writeTimeToScratchpad(byte* address)
{
  //reset the bus
  ds.reset();
  //select our sensor
  ds.select(address);
  //CONVERT T function call (44h) which puts the temperature into the scratchpad
  ds.write(0x44,1);
  //sleep a second for the write to take place
  delay(1000);
}

void readTimeFromScratchpad(byte* address, byte* data)
{
  //reset the bus
  ds.reset();
  //select our sensor
  ds.select(address);
  //read the scratchpad (BEh)
  ds.write(0xBE);
  for (byte i=0;i<9;i++){
    data[i] = ds.read();
  }
}

float getTemperature(byte* address)
{
  int tr;
  byte data[12];

  writeTimeToScratchpad(address);

  readTimeFromScratchpad(address,data);

  //put in temp all the 8 bits of LSB (least significant byte)
  tr = data[0];

  //check for negative temperature
  if (data[1] > 0x80)
  {
    tr = !tr + 1; //two's complement adjustment
    tr = tr * -1; //flip value negative.
  }

  //COUNT PER Celsius degree (10h)
  int cpc = data[7];
  //COUNT REMAIN (0Ch)
  int cr = data[6];

  //drop bit 0
  tr = tr >> 1;

  return tr - (float)0.25 + (cpc - cr)/(float)cpc;
}

void loop(void)
{
  float temp1 = getTemperature(sensor1);
  float temp2 = getTemperature(sensor2);


  Serial.print(sensor1Name);
  Serial.print(temp1);
  Serial.println(" Celsius");

  Serial.print(sensor2Name);
  Serial.print(temp2);
  Serial.println(" Celsius");


  Serial.println();
  delay(1000);
}



Gruß Jens

maverick1509

Hallo Jens,
ich benutze in meinen Anwendungen den Befehl sensors.getTempC(Sensor)
und da ist der Wert dann in °Celsius-
Gruß

Knippi

Hallo maverick1509,

meinst du so:

Code: [Select]
#include <OneWire.h>
#include <DallasTemperature.h>

OneWire  ds(28); //pin für ds1820

//DeviceAdressen der einzelnen ds1820 Temperatursensoren angeben. (loop anpassen)
DeviceAddress sensor1 = { 0x28, 0x36, 0x2F, 0x99, 0x4, 0x0, 0x0, 0x3A };
DeviceAddress sensor2 = { 0x28, 0xB1, 0xB7, 0xBD, 0x4, 0x0, 0x0, 0xA2 };


char sensor1Name[] = "Unterschrank: ";
char sensor2Name[] = "W.-Temp: ";


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

void writeTimeToScratchpad(byte* address)
{
  //reset the bus
  ds.reset();
  //select our sensor
  ds.select(address);
  //CONVERT T function call (44h) which puts the temperature into the scratchpad
  ds.write(0x44,1);
  //sleep a second for the write to take place
  delay(1000);
}

void readTimeFromScratchpad(byte* address, byte* data)
{
  //reset the bus
  ds.reset();
  //select our sensor
  ds.select(address);
  //read the scratchpad (BEh)
  ds.write(0xBE);
  for (byte i=0;i<9;i++){
    data[i] = ds.read();
  }
}

float [color=orange]getTempC[/color](byte* address)
{
  int tr;
  byte data[12];

  writeTimeToScratchpad(address);

  readTimeFromScratchpad(address,data);

  //put in temp all the 8 bits of LSB (least significant byte)
  tr = data[0];

  //check for negative temperature
  if (data[1] > 0x80)
  {
    tr = !tr + 1; //two's complement adjustment
    tr = tr * -1; //flip value negative.
  }

  //COUNT PER Celsius degree (10h)
  int cpc = data[7];
  //COUNT REMAIN (0Ch)
  int cr = data[6];

  //drop bit 0
  tr = tr >> 1;

  return tr - (float)0.25 + (cpc - cr)/(float)cpc;
}

void loop(void)
{

  float temp1 =getTempC(sensor1);
  float temp2 =getTempC(sensor2);
 


  Serial.print(sensor1Name);
  Serial.print(temp1);
  Serial.println(" Celsius");

  Serial.print(sensor2Name);
  Serial.print(temp2);
  Serial.println(" Celsius");


  Serial.println();
  delay(1000);
}


zeigt aber leider immer noch die Temperatur in Fahrenheit an.

Gruß Jens

rudirabbit

#6
Apr 29, 2013, 07:04 pm Last Edit: Apr 29, 2013, 08:27 pm by rudirabbit Reason: 1
Hi -  ich denke du machst es komplizierter als es ist  :)
Die Lib DallasTemperature nimmt dir die Arbeit ab.

Code: [Select]

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2

const int MaxSensors=4;
float temp[MaxSensors];

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);



Dann in der Loop:
sensors.requestTemperatures();
temp[index]=sensors.getTempCByIndex(index);

index wird ab 0 hochgezählt und bezeichnet den Temparaturfühler den du haben willst.
Die Funktion requestTemperatures();  dauert ein bisschen, also blockiert quasi die Loop.

Das will man meist nicht haben, vorher ein sensors.setWaitForConversion(false);  dann wird nicht gewartet.
Nur musst du dann dafür sorgen das die Funktion innerhalb der Spezifikation der Sensoren angesprungen wird. (Je nach config im Sekundentakt) 

Also so läuft es bei mir.... 
Du hast die Lib DallasTemperature zwar eingelinkt, aber IHMO im Projekt nicht benutzt
Arduino UNO,MEGA  Fremdgänger mit dem  Nucleo L152RE   
Dunkel die andere Seite ist. - Klappe, Yoda, und iss deinen Toast :-)

Knippi

Hallo rudirabbit,

danke für die Hilfe, aber wie bekomme ich denn nun die 2 Temp.-Fühler angezeigt?
Bei mir wird immer der gleiche Wert für beide Temp.-Fühler angezeigt.
Hier der Sketch dazu:

Code: [Select]
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 28

//DeviceAdressen der einzelnen ds1820 Temperatursensoren angeben. (loop anpassen)
DeviceAddress sensor1 = {
  0x28, 0x36, 0x2F, 0x99, 0x4, 0x0, 0x0, 0x3A };
DeviceAddress sensor2 = {
  0x28, 0xB1, 0xB7, 0xBD, 0x4, 0x0, 0x0, 0xA2 };

const int MaxSensors=4;


float temp[MaxSensors];

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

char sensor1Name[] = "Unterschrank: ";
char sensor2Name[] = "W.-Temp: ";


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

void loop(void)
{

  //sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  temp[1]=sensors.getTempCByIndex(1);
  temp[2]=sensors.getTempCByIndex(2);


  Serial.print(sensor1Name);
  Serial.print(temp[1]);
  Serial.println(" Celsius");

  Serial.print(sensor2Name);
  Serial.print(temp[2]);
  Serial.println(" Celsius");
}


Gruß Jens

Knippi

Hallo an alle,

hat jemand eine Idee und kann mir helfen?

Bei meinem Code wird immer der gleiche Wert für beide Temp.-Fühler angezeigt.

Gruß Jens

Kalli

Hallo Jens,

probier mal

temp[1]=sensors.getTempCByIndex(0);
temp[2]=sensors.getTempCByIndex(1);

dann geht es.

Gruss Kalli

MaFu

Oder besser noch

temp[0]=sensors.getTempCByIndex(0);
temp[1]=sensors.getTempCByIndex(1);
_______
Manfred

Knippi

Hallo Kalli,
hat funktioniert. :)
Vielen Dank dafür.
Der Tipp von MaFu funktioniert nicht. Es wird ein Sensor angezeigt und der andere Zeigt immer den Wert 0 an.

Gruß Jens

MaFu


Hallo Kalli,
hat funktioniert. :)
Vielen Dank dafür.
Der Tipp von MaFu funktioniert nicht. Es wird ein Sensor angezeigt und der andere Zeigt immer den Wert 0 an.

Gruß Jens

Hast Du bei der Serial Ausgabe dann auch temp[0] und temp[1] verwendet?
Oder weiterhin temp[1] und temp[2]?

Arrays in C beginnen bei 0. Bei "MaxSensors=4" geht Dein Array somit von temp[0] bis temp[3] und NICHT von temp[1] bis temp[4]. Wenn Du dann irgendwann den Bereich von MaxSensors ausnutzt und vier Sensoren dranhängst, stehst Du vor dem nächsten Problem wenn Du erst bei temp[1] beginnst.
Code: [Select]
for (int i = 0; i < MaxSensors; i++)
  temp[i]=sensors.getTempCByIndex(i);
_______
Manfred

Warix

@Jens
Hallo Jens,
kannst Du mir sagen welchen Sensor Du genau genommen hast für die Temperaturmessung im Aquarium? Bin gerade dabei mir einen Aqua Computer auf Arduino Basis zu basteln.
lg Marko

maverick1509

Hallo Marko,
ich würde sowas empfehlen:
http://www.ebay.de/itm/5PCS-Waterproof-Digital-Thermal-Probe-or-Sensor-DS18B20-/261152181792?pt=Mess_Pr%C3%BCftechnik&hash=item3ccde20e20
gruß

Go Up