Вопрос дилетанта по использованию датчиков температуры DS18B20

avr4
Offline
Зарегистрирован: 24.12.2015

Добрый день, всем гуру!

Прошу помочь мудрым советом.

Доя реализации алгоритма управления 8 реле мне необходимо использовать измерения температуры от двух датчиков. Добавил библиотеку OneWire, вставил в скетч DS18x20_Temperature. Не могу понять, что присваивать моим переменным (int T1 и int T2) из 

#include <OneWire.h>
 
// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
//
// The DallasTemperature library can do all this work for you!
 
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(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");

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

celsius

T1 и Т2 типа float

avr4
Offline
Зарегистрирован: 24.12.2015

Спасибо за ответ, но..

T1=celsius;

T2=celsius;

Я чего-то не допонимаю... в библиотеке переменная получается одна а у меня две разных переменных должны получить данные от разных источников. Пазл в голове не складывается. Извините за невежество.

avr4
Offline
Зарегистрирован: 24.12.2015

и почему float ?

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

avr4 пишет:
Я чего-то не допонимаю... в библиотеке переменная получается одна а у меня две разных переменных должны получить данные от разных источников. Пазл в голове не складывается. Извините за невежество.

потому что вы привели код, где считывается только один датчик температуры. К слову, этот код, хоть и рабочий но морально устаревший и неэффективный.

Так как у вас два датчика, то надо заводить две переменные: celsius1 и celsius2 и опрашивать два датчика, по их адресам. Примерное направление: http://arduino.ru/forum/programmirovanie/pochistil-sketch-primera-raboty-s-ds18b20-iz-bibly-oneware

Цитата:
и почему float ?

потому что celsius имеет тип float. Если не нужна точность до десятых или сотых, то можно оставить int, но учтите, что доли не округляются, а отбрасываются, т.е. если float celsius = 22.96, а   int T1 = celsius, то в итоге значение в T1 будет равно 22, а не 23.

Nosferatu
Offline
Зарегистрирован: 04.11.2012

По моему в библиотеке DallasTemperature были примеры с подключением двух датчиков.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Tomasina пишет:

но учтите, что доли не округляются, а отбрасываются, т.е. если float celsius = 22.96, а   int T1 = celsius, то в итоге значение в T1 будет равно 22, а не 23.

T1 = celsius + 0.5;
И будет округляться.

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

а если нужно  22,5 получить а  не 22,52 ?

тогда как?

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

тогда использовать тип float  и хрустеть печеньками.

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

Tomasina пишет:

тогда использовать тип float  и хрустеть печеньками.

я обкарнал один вариант, и  использую датчик без привязки к серийнику:

 

//*************  считать температуру ***************************
float getTemp(){   // возвращает температуру с датчика
  byte data[12];   // и останавливает программу на секунду
  byte addr[8];  

  !ds.search(addr);
  ds.reset_search(); 

  ds.reset();            
  ds.select(addr);        
  ds.write(0x44);      
  delay(1000);   
  
  ds.reset();
  ds.select(addr);    
  ds.write(0xBE);          

  for (int i = 0; i < 9; i++) data[i] = ds.read(); 
  int raw = (data[1] << 8) | data[0]; // Переводим в температуру   
  if (data[7] == 0x10) raw = (raw & 0xFFF0) + 12 - data[6];  
  return raw / 16.0;
}
// ***************************************************

Serial.println(float(getTemp()));

но там да - после запятой два знака.

что использовать, чтобы  оставить один знак после запятой?  

последний кусок не смог изменить чтобы осталась одна цифра.

Или я не по тому пути иду?

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015
Serial.println(float(getTemp()), 1);

 

see_watson
Offline
Зарегистрирован: 03.11.2016

Гуру подскажите, чего подправить в коде чтобы наоборот до 10 показывал. Ничего не помогает.



#include <OneWire.h>
OneWire ds(9);
 
void setup() {
Serial.begin(9600); 
}
 
void loop() {
 
byte data[2];
ds.reset(); 
ds.write(0xCC);
ds.write(0x44);
delay(750);
ds.reset();
ds.write(0xCC);
ds.write(0xBE);
data[0] = ds.read(); 
data[1] = ds.read();
// проблема где-то здесь, если не ошибаюсь
int Temp = (data[1]<< 8)+data[0];
Temp = Temp>>4;
Serial.println(Temp);
}

 

 

bwn
Offline
Зарегистрирован: 25.08.2014

see_watson пишет:

Гуру подскажите, чего подправить в коде чтобы наоборот до 10 показывал. Ничего не помогает.

До 10 чего? Если десятичных знаков, то он только 4 умеет. И все таки float Temp = .....

 

see_watson
Offline
Зарегистрирован: 03.11.2016

Показывает 23С, а надо 23.31С 

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

у тебя переменная Temp имеет тип int, т.е. только целые числа ;)

//float Temp = 
Serial.println(Temp, 2);

 

see_watson
Offline
Зарегистрирован: 03.11.2016

Сделал так:

// библиотека 1-Wire
#include <OneWire.h> 
// подключение датчика ds18b20 к 10 контакту
OneWire ds(10);

void setup() {
// установка скорости обмена Serial port. По умолчанию 9600
Serial.begin(57600); 
}
 
void loop() {
 
byte data[2];
ds.reset(); 
ds.write(0xCC);
ds.write(0x44);
delay(750);
ds.reset();
ds.write(0xCC);
ds.write(0xBE);
data[0] = ds.read(); 
data[1] = ds.read();
float Temp = (data[1]<< 8)+data[0];
Temp = Temp/16;
Serial.print("Temp:");
Serial.println(Temp); //вывод покозаний
}

СПАСИБО

bwn
Offline
Зарегистрирован: 25.08.2014

От 17 строки избавься и вовсе супер будет. Не напрягает, пока этот код не начал встраиваться в какую то более крупную программу.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

тогда придется этот кусок работы с датчиком вынести из loop (что считаю правильным) и обращаться к нему раз в секунду.