Определение MIN и MAX температуры и ее хранение

AndryGladky
Offline
Зарегистрирован: 09.10.2014

Здравствуйте. Подскажите пожалуйста как правельно измерять минимум и максимум. Что то сколько вариантов перепробывал, не получаэться выделить максимум и выводить на дисплей 16х2, ето значение. У меня или выдает ноль, или показывает то значение температуры которое есть в данный момент.

#include <LiquidCrystal.h>#include <OneWire.h>

OneWire  ds(8);  // Подключаем датчик к 8 цифровому пину

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //Подключаем LCD
byte gradus[8] = {
  B00011,
  B00011,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};

void setup(void) 
{
  // устанавливаем ШИМ выход: 
  pinMode (9, OUTPUT);
  analogWrite (9, 50);
  lcd.begin(16, 2); //16 знаков, 2 строки
  lcd.print("Te""\xBC\xBE""epa""\xBF""ypa: ""\xFA"); //Печатаем верхнюю строку LCD
}

void loop(void) 
{
  byte i;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  float MAX, MAX1;
  // Ищем алрес датчика
  if ( !ds.search(addr)) 
  {
    ds.reset_search();
    delay(250);
    return;
  }

  // Проверяем не было ли помех при передаче
  if (OneWire::crc8(addr, 7) != addr[7]) 
  {
      return;
  }
  // Определяем серию датчика
  switch (addr[0]) 
  {
    case 0x10:
       
      type_s = 1;
      break;
    case 0x28:
      
      type_s = 0;
      break;
    case 0x22:
      
      type_s = 0;
      break;
    default:
      
      return;
  } 

  ds.reset();            
  ds.select(addr);       // Выбираем адрес
  ds.write(0x44, 1);     // Производим замер, в режиме паразитного питания
  delay(1000);    
  
  ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Считываем оперативную память датчика

  for ( i = 0; i < 9; i++) 
  {           
    data[i] = ds.read(); // Заполняем массив считанными данными
  }  // Данные о температуре содержатся в первых двух байтах, переведем их в одно значение и преобразуем в шестнадцатиразрядное число
  int16_t raw = (data[1] << 8) | data[0]; // Переводим температуру в шкалы по Цельсию и Фаренгейту  
  if (type_s) 
  {
    raw = raw << 3; 
  }
  if (data[7] == 0x10) 
  {
    raw = (raw & 0xFFF0) + 12 - data[6];
  } else {
    byte cfg =  (data[4] & 0x60);
    if (cfg == 0x00) 
      raw = raw << 3; 
    else if  (cfg == 0x20) 
      raw = raw << 2; 
    else if  (cfg == 0x40) \
      raw = raw << 1;
  }  
  celsius =  (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0; 
  MAX = celsius;
  if ( celsius > MAX ) 
  {
  MAX = MAX1;
  }  
  lcd.setCursor(0, 1); //Пишем в LCD на 2 строке
  lcd.print(celsius); //Цельсии
  lcd.createChar(1, gradus);
  lcd.setCursor(5, 1);
  lcd.print("\1""C");
  
  lcd.setCursor(8, 1);
  lcd.print("M:"); //Фаренгейты
  lcd.setCursor(10, 1);
  lcd.print(MAX1); 
  
 }

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Необходимо оставить только переменную max и вынести ее объявление из основного цикла.
Алгоритм такой
Если температура > макс то макс = температура, а для минимума в начале программы стоит задать какое то значение (заведомо большее измеряемой температуры), а то если по умолчанию 0 то пока ниже нуля не опустица мин так и будет 0.
Если температура < мин то мин = температура.

AndryGladky
Offline
Зарегистрирован: 09.10.2014

Да я так пробывал, написал еще раз, все равно показания мах меняются с изменением температуры, не оставаясь максимальными значениями. В теории я тоже знаю что так писал когда

#include <LiquidCrystal.h>
#include <OneWire.h>

OneWire  ds(8);  // Подключаем датчик к 8 цифровому пину

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //Подключаем LCD
byte gradus[8] = {
  B00011,
  B00011,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};

void setup(void) 
{
  // устанавливаем ШИМ выход: 
  pinMode (9, OUTPUT);
  analogWrite (9, 50); //контрасность дисплея
  lcd.begin(16, 2); //16 знаков, 2 строки
  lcd.print("Te""\xBC\xBE""epa""\xBF""ypa: ""\xFA"); //Печатаем верхнюю строку LCD
}

void loop(void) 
{
  byte i;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit; //градусы и фаренгейты
  float MAX; //максимальное значение температуры
  MAX = celsius;
  // Ищем алрес датчика
  if ( !ds.search(addr)) 
  {
    ds.reset_search();
    delay(250);
    return;
  }

  // Проверяем не было ли помех при передаче
  if (OneWire::crc8(addr, 7) != addr[7]) 
  {
      return;
  }
  // Определяем серию датчика
  switch (addr[0]) 
  {
    case 0x10:
       
      type_s = 1;
      break;
    case 0x28:
      
      type_s = 0;
      break;
    case 0x22:
      
      type_s = 0;
      break;
    default:
      
      return;
  } 

  ds.reset();            
  ds.select(addr);       // Выбираем адрес
  ds.write(0x44, 1);     // Производим замер, в режиме паразитного питания
  delay(1000);    
  
  ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Считываем оперативную память датчика

  for ( i = 0; i < 9; i++) 
  {           
    data[i] = ds.read(); // Заполняем массив считанными данными
  }  // Данные о температуре содержатся в первых двух байтах, переведем их в одно значение и преобразуем в шестнадцатиразрядное число
  int16_t raw = (data[1] << 8) | data[0]; // Переводим температуру в шкалы по Цельсию и Фаренгейту  
  if (type_s) 
  {
    raw = raw << 3; 
  }
  if (data[7] == 0x10) 
  {
    raw = (raw & 0xFFF0) + 12 - data[6];
  } else {
    byte cfg =  (data[4] & 0x60);
    if (cfg == 0x00) 
      raw = raw << 3; 
    else if  (cfg == 0x20) 
      raw = raw << 2; 
    else if  (cfg == 0x40) \
      raw = raw << 1;
  }  
  celsius =  (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0; 
  if ( celsius > MAX ) //если температура больше максимума
  {
  MAX = celsius; //то мак присвоить значение температуры
  }  
  lcd.setCursor(0, 1); //Пишем в LCD на 2 строке
  lcd.print(celsius); //Цельсии
  lcd.createChar(1, gradus);
  lcd.setCursor(5, 1);
  lcd.print("\1""C");
  
  lcd.setCursor(8, 1);
  lcd.print("M:"); //установка для вывода максимума
  lcd.setCursor(10, 1);
  lcd.print(MAX); //вывод максимума
  
 }

то программы на паскале. А вот в железе не работает. 

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Читайте советы с первой строчки и будет Вам счастье!

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Float max; и max=celsius перенесите в начало кода до void setup()

mihtm
Offline
Зарегистрирован: 02.09.2014

Правильно - обьявляя их в loop ты их занова порождаешь(из кучи) обычно при рождении их значения равны 0 при этом уничтожаешь старые т.е. ты теряешь их значения

AndryGladky
Offline
Зарегистрирован: 09.10.2014

Спасибо всем, за подсказки. Заработало.

Понял свою ошибку значение максимум должно быть за цыклом что бы не изменялось, проходя снова цикл оно изменялось.

Но после перенесения строчки MAX = celsius; выдает ошибку.

Build options changed, rebuilding all
DS18B20_LCD:17: error: expected constructor, destructor, or type conversion before '=' token.
удалил ее и все заработало. Теперь буду пробовать минимум сделать, и сохранение результатов после отключения.
Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

AndryGladky пишет:

Теперь буду пробовать минимум сделать, и сохранение результатов после отключения.


О блин, чую тут одного попкорна будет мало. Про переменые несколько постов доходило. А сохранение и чтение с eprom это будет та еще веселуха

AndryGladky
Offline
Зарегистрирован: 09.10.2014

Написал все работает. Нашол на вашем сайте тему где описывают как float в eeprom записать, буду разбератся.

mihtm
Offline
Зарегистрирован: 02.09.2014

Eеprom2 библеотека: http://freeduino.ru/arduino/sample_EEPROM.html

mihtm
Offline
Зарегистрирован: 02.09.2014

Eеprom2 библеотека: http://freeduino.ru/arduino/sample_EEPROM.html

AndryGladky
Offline
Зарегистрирован: 09.10.2014

Спасибо большое, так намного проще.