Go Down

Topic: DS18S20 auslesen (Read 137 times) previous topic - next topic

PhilippR

Guten Morgen,

also einmal vorneweg: Ich bin grundsätzlich noch recht neu in der Materie, habe mit einem Einsteiger Lernpaket angefangen und mich langsam über den TLC5947 weitergetastet, was mittlerweile nach ein paar Einstiegsproblemen auch wunderbar funktioniert.
Jetzt wollte ich weiter gehen und habe mir einen Feuchtigkeitssensor u. Temperatur Sensor geholt und experimentiere damit fleißig weiter :D

Der Feuchtigkeitssensor gibt mir eine Spannung von 0 - 3,3V aus und das auslesen via Analog read klappt auch tadellos.

Allerdings macht mir der Temperatursensor DS18S20 Kopfschmerzen.

Ich habe ihn über OneWire angeschlossen (Parasitäre Stromversorung), habe ein Beispielprogramm geladen und es funktioniert alles tadellos:
Code: [Select]
#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(9);  // 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(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("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
}


Er gibt mir die Temperatur in °C u. F aus.

Da man sich das ganze wohl mit der DallasTemperature library noch deutlich vereinfachen kann, habe ich mir diese auch geholt, um meine eigenen Codes einfacher (Stichwort Lernphase) zu gestalten.
Ich habe das Beispielprogramm geladen:

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

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 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);

// arrays to hold device address
DeviceAddress insideThermometer;

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

  // locate devices on the bus
  Serial.print("Locating devices...");
  sensors.begin();
  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 };

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

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

  // set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
  sensors.setResolution(insideThermometer, 9);
 
  Serial.print("Device 0 Resolution: ");
  Serial.print(sensors.getResolution(insideThermometer), DEC);
  Serial.println();
}

// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
  // method 1 - slower
  //Serial.print("Temp C: ");
  //Serial.print(sensors.getTempC(deviceAddress));
  //Serial.print(" Temp F: ");
  //Serial.print(sensors.getTempF(deviceAddress)); // Makes a second call to getTempC and then converts to Fahrenheit

  // method 2 - faster
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print("Temp C: ");
  Serial.print(tempC);
  Serial.print(" Temp F: ");
  Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
}

void loop(void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");
 
  // It responds almost immediately. Let's print out the data
  printTemperature(insideThermometer); // Use a simple function to print out the data
}

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


Und nun gibt er mir 85°C aus.

Ich habe gelesen, dass es bei dieser Library mit dem DS18S20 zu Problemen kommen kann. Ist das nun offensichtlich eines dieser Probleme oder habe ich etwas übersehen? Kann ich irgendetwas dagegen tun? Ich habe folgendes Problem -> mit dem zweiten Code komme ich zurecht; mit dem ersten nicht wirklich... Sprich ich könnte ihn zwar so anpassen, dass er mir das ausgibt was ich will, dann habe ich aber absolut keine Ahnung warum er das tut was er tut :O In die DallasTemperature library konnte ich mich soweit reinfuchsen, dass ich das wohl auch reproduzierbar hinbekommen müsste.


Ich danke euch schonmal im vorraus.

Grüße

Philipp

Doc_Arduino

#1
Mar 26, 2015, 10:56 am Last Edit: Mar 26, 2015, 10:59 am by Doc_Arduino
Hallo,

nimm mal die Library hier: v3.7.2
https://milesburton.com/Dallas_Temperature_Control_Library

und gehe die Bsp. durch. Die funktioniert bei mir und vielen andere. Versorge den Dallas auch mal richtig mit 5V, nicht parasitär. Achte auch darauf das 9 Bit und keine 12Bit Auflösung eingestellt ist. Die Wartezeit muß beim DS18B20 immer >= 750ms betragen. Wenn Du später selber Code damit schreibst, mußt Du die Wartezeit auch beachten.

Probleme mit dem DS18S20 sollte es keine geben. Alles was der B kann, kann der S auch. Der S kann nur genauer und schneller messen, falls man das unbedingt benötigt. Eine falsche Konfiguration kann aber einiges durcheinander bringen. Auch muß man die Adressen beachten ohne automatisches auslesen.

Wie gesagt, geh die Bsp. durch, das wird funktionieren. Dann kannste immer noch nachfragen.
Tschau
Doc Arduino

PhilippR

okay danke, habe es nicht parasitär betrieben und siehe da - alles funktioniert wunderbar...

#3
Mar 27, 2015, 07:45 pm Last Edit: Mar 27, 2015, 07:46 pm by Commerzgandalf
Geht auch mit noch kürzerem Code
Code: [Select]
#include <OneWire.h>
#include <DallasTemperature.h>

//Datenkabel ist am Digitalpin 2 angeschlossen
#define ONE_WIRE_BUS 2

// oneWire Bus initialisieren
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

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


void loop(void)
{
  sensors.requestTemperatures();
 
  Serial.print(sensors.getTempCByIndex(0)); //Bei mehreren Sensoren kann man die Indexnummer ändern
}

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy