Sida 1 av 1

Hur använder man dubbla DS18B20 på Arduino?

Postat: 21 december 2013, 03:35:48
av Al_Bundy
Hej!

Jag har tänkt och använda två stycken DS18B20 termometrar på min Arduino men jag får det inte fungera. Jag lyckas att koppla så jag kan använda bara en.
Då följer jag denna manual: http://www.hobbytronics.co.uk/ds18b20-arduino

Men när jag ska använda "Multiple" så lyckas jag inte.
Jag kopplar mitt schema så här:
Bild

Och jag använder denna kod:

Kod: Markera allt

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

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 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 addresses
DeviceAddress insideThermometer, outsideThermometer;

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

  // 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(insideThermometer);
  Serial.println();

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

  // set the resolution to 9 bit
  sensors.setResolution(insideThermometer, TEMPERATURE_PRECISION);
  sensors.setResolution(outsideThermometer, TEMPERATURE_PRECISION);

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

  Serial.print("Device 1 Resolution: ");
  Serial.print(sensors.getResolution(outsideThermometer), 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(insideThermometer);
  printData(outsideThermometer);
}

Denna kod ovan är redan som serverad på ett guldfat. Det enda jag behöver undera på är denna kod:

Kod: Markera allt

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 9
Jag vet att ONE_WIRE_BUS ska kopplas in i digital pin 2. Men TEMPERATURE_PRECISION vet jag att den ska kopplas in till digital pin 9.
Men då kvarstår frågan: Hur ska jag koppla så mitt schema blir rätt? Jag har bara sökt på "Multiple DS18B20 arduino" på google och sökt upp hur dom andra har kopplat. Men jag lyckas inte. Jag skulle vilja ha din hjälp för koppla rätt schema för koden är inte fel på.


EDIT:
Jag har hittat denna kod. Denna är för "single" DS18B20 som är ihopkopplade. Men jag är ändå intresserad hur man använder orginalbiblioteket för "Multiple" DS18B20. Om man måste ha någon "sheild" eller något annat?

Kod: Markera allt

// OneWire and DallasTemperature libraries from
//   http://milesburton.com/index.php?title=Dallas_Temperature_Control_Library
// Code based on examples from above and at
//   http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html
// See also http://www.arduino.cc/playground/Learning/OneWire
 
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
 
// 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);
 
int numberOfSensors;
 
void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("1-Wire DS18B20 example code");
 
  // Start up the library
  sensors.begin();
 
  delay(5000);  //important on linux as serial port can lock up otherwise
  numberOfSensors = discoverOneWireDevices();
  Serial.println();
}
 
void loop(void)
{
  printTemperaturesToSerial();
  delay(1000); //wait 10 sec
}
 
void printTemperaturesToSerial(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");
 
  // Read each of our sensors and print the value
  for(int i=0; i < numberOfSensors; i++) {
   Serial.print("Temperature for Device ");
   Serial.print( i );
   Serial.print(" is: ");
   // Why "byIndex"? You can have more than one IC on the same bus. 
   // 0 refers to the first IC on the wire
   Serial.println( sensors.getTempCByIndex(i) );
  }
 
  Serial.println();
}
 
// Based on http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html
int discoverOneWireDevices(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
  int count = 0;
 
  Serial.println("Looking for 1-Wire devices...");
  while(oneWire.search(addr)) {
    Serial.print("Found \'1-Wire\' device with address: ");
    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.println("CRC is not valid!");
        return 0;
    }
    Serial.println();
    count++;
  }
  Serial.println("That's it.");
  oneWire.reset_search();
  return count;
}
Källa: http://www.strangeparty.com/2010/12/13/ ... e-sensors/

Denna kod kan kortas ned till detta om någon är intresserad:

Kod: Markera allt

// OneWire and DallasTemperature libraries from
//   http://milesburton.com/index.php?title=Dallas_Temperature_Control_Library
// Code based on examples from above and at
//   http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html
// See also http://www.arduino.cc/playground/Learning/OneWire
 
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
 
// 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);
 
int numberOfSensors;
 
void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("1-Wire DS18B20 example code");
 
  // Start up the library
  sensors.begin();
 
  delay(5000);  //important on linux as serial port can lock up otherwise
  numberOfSensors = 2;
  Serial.println();
}
 
void loop()
{
  printTemperaturesToSerial();
  delay(1000); //wait 10 sec
}
 
void printTemperaturesToSerial() {
  // 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");
 
  // Read each of our sensors and print the value
  for(int i=0; i < numberOfSensors; i++) {
   Serial.print("Temperature for Device ");
   Serial.print( i );
   Serial.print(" is: ");
   // Why "byIndex"? You can have more than one IC on the same bus. 
   // 0 refers to the first IC on the wire
   Serial.println( sensors.getTempCByIndex(i) );
  }
 
  Serial.println();
}
 
Mvh

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 21 december 2013, 10:01:49
av BMI
Ja kopplar man på det viset hjälper väl ingen "code" i värden !! Eller har jag missat något ?

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 21 december 2013, 10:17:24
av snigelen
> Eller har jag missat något ?

Ja, de verkar vara kopplade för parasit-matning. De "lånar" då matningsspänning från data-signalen.

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 21 december 2013, 10:17:32
av Icecap
BMI: Jepp, du har missat något!

Al: hur säkrar du den förstärkta parasitmatningen under omvandlingen?

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 21 december 2013, 10:27:45
av Jonaz
#define TEMds18b20 parasite arduinoERATURE_PRECISION 9 bestämmer vilken upplösning ds18b20 skall ha, har för mig att 12 är max, och ju högre siffra desto längre tar läsningen. Så denna har inget med digital pin 9 att göra. Kolla databladet för PRECISION delen.

Vad får du för felmeddelande?
I första koden som du ger så verkar inga adresser angivna för sensorerna, så det är inte så konstigt, kolla närmare på på detta avsnitt

Kod: Markera allt

    // 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 };     

Edit sök på ds18b20 parasite arduino

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 21 december 2013, 10:35:33
av BMI
Icecap "BMI: Jepp, du har missat något!"
Hade VDD varit kopplad till DQ hade jag nog inte reagerat :-) men VDD o GND ihop

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 21 december 2013, 10:44:28
av Icecap
BMI: Jo, jag förstår. Dock är hela 1-Wire® serien lite speciell på detta vis, de kan parasitmatas. Och då SKA VDD och GND kopplas ihop.

Sedan finns det en del småsaker som att när dessa temperatursensorer ska omvandla behöver de mer energi, detta betyder att man - vid parasitmatning - måste driva DQ extra hårt en stund för att pull-up motståndet inte klarar detta.

Av den anledning kör jag alltid med 3-ledar kontakt, då är det bara att köra på.

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 21 december 2013, 13:10:22
av Al_Bundy
Icecap skrev:BMI: Jepp, du har missat något!

Al: hur säkrar du den förstärkta parasitmatningen under omvandlingen?
Jag vet inte. Vet inte vad parasitmatning är.

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 21 december 2013, 13:23:57
av Icecap
Ah... i vanlig ordning har du inte läst databladet alltså. OK, lycka till.

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 26 december 2013, 13:18:53
av Miramithe
exakt vad är det som inte lyckas?

kollar man på länken som är med det lib som kommer från dallas, alltså det du kör vill den köra parasitmatningen enligt det sättet som är i detta blad, har dock bara en sensor så jag kan inte testa...
http://milesburton.com/Main_Page?title= ... ol_Library

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 26 december 2013, 15:49:53
av Icecap
Mira: problemet är att man inte vet vilka adresser de har om man inte har läst ut dessa först. Därmed kan man inte adressera sensorerna varför en avläsning av resultat inte kan göras i annat läge än ett som "blandar ihop" databitsen.

Det finns dock en algoritm som medger att man kan läsa vilka adresser som finns, dessa kan man spara till senare användning.

Jag har fått detta att fungera - men inte utan en del problem, dessa var dock ganska mycket baserat på att jag samtidig hade alla pulser drivna av en interrupt.

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 26 december 2013, 18:37:00
av Miramithe
men det står ju i exempelkoden att man måste ha rätt adress till dessa och även hur man gör det, TS i fråga säger bara att det inte funkar men inte vad exakt som inte funkar.

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 26 december 2013, 19:13:56
av Icecap
Läs lite trådar av Al_Bundy och du förstår nog lite mer...

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 7 januari 2014, 15:14:15
av void
Nu kanske du redan löst detta, men om inte så beror problemet (som Icecap redan nämnt) på att du inte kan spänningsmata 2st sensorer genom 4,7kohm eftersom de drar för mycket ström under själva temperaturomvandlingen (ca 1,5mA styck). Du behöver endera mata +5V direkt till pin 3, eller använda "strong pullup" från din Arduino.

Re: Hur använder man dubbla DS18B20 på Arduino?

Postat: 7 januari 2014, 15:52:34
av Icecap
Det finns tre problem i detta:
1: Som void skriver måste det lösas med matningen. Antingen måste man driva datapinnen vid att driva datapinnen direkt med portpinnen som utgång om man inte har skydd mellan, annars kan man ha en transistor till att driva datalinjen till VDD under omvandlingstiden.

2: Man måste känna enhetens adress. Detta kan läsas ut med lite mjukvara ganska enkelt via den "Search ROM"-funktion som finns för detta. Har man bara en enda åt gången är det ganska enkelt att läsa adressen, har man fler blir det mer komplicerat. Men man kan alltså läsa en åt gången och notera värden och sedan göra programmet så att det innehåller dessa adresser som hårdkodade. Problemet är dock att man inte utan seriösa svårigheter kan byta sensorer. Detta kan dock lösas på lite olika sätt, ett är att ha en knapp som, vid aktivering, får styrenheten att radera alla kända adresser. En annan knapp betyder "Läs adressen på enheten som finns nu o spara i EEPROM". Då kan man bygga allt, programmera och koppla till ena sensorn samt trycka på "inlärningsknappen". När det är klart monterar man den andra sensorn efter att ha plockad bort den första, trycker på inlärningsknappen och saken är biff. Mjukvaran blir såklart lite mer komplicerat och det är tveksamt om man bara kan hämta detta från nätet, man måste alltså programmera på riktigt. Alternativt är såklart att låta styrenheten läsa alla adresser vid reset/kommando om detta, jämföra med dom som är sparade i EEPROM och lägga till nya som hittas. Jag har vald den lösningen.

3: Det är Al_Bundy som lekar. Notorisk "skiter i databladet"-person som tyvärr har en mycket hög inlärningströskel, "tyvärr" för att h*n har många intressanta idéer som kanske inte är aktuella för mig men det är kul att läsa om andras vinklar på olika projekt - och alltid lär man något. Och det finns idéer i mängder och det gillar jag! Av 1000 idéer är kanske 1 riktigt bra - men får man inte de 999 "dumma" kommer den riktiga bra inte!

Och när idé #1000 kommer är det skitroligt att läsa om den!