DS18B20 и отрицательные температуры (отображение)

VK
Offline
Зарегистрирован: 19.11.2016

Добрый день. Хотелось сделать уличный термометр, самый простой и без заморочек. Все получилось, но выяснилось одно: он не показывает отрицательные температуры. То есть ноль показывает как ноль, а все что ниже нуля - как плюсовые температуры. Пытаюсь разобраться, что мешает. На данный момент выяснил что за знак отвечает "бит признака", где-то написано что регистр "S". Но как реализовать - темный лес (пока). Есть код самого проекта. 

#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 10 // номер пина к которому подключен DS18B20
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
#include <OLED_I2C.h>
OLED  myOLED(8, 9, 8); // 8pin - SDA , 9pin - SCL
extern uint8_t RusFont[]; // Русский шрифт
extern uint8_t MegaNumbers[]; // Подключение больших шрифтов
extern uint8_t SmallFont[]; // Базовый шрифт без поддержки русскийх символов.
void setup()
{
  sensors.begin(); 
  myOLED.begin();
}
void loop()
{
sensors.requestTemperatures();
myOLED.clrScr(); // очищаем экран
myOLED.setFont(RusFont); // Устанавливаем русский шрифт
myOLED.print("Ntvgthfnehf", CENTER, 0); // Выводим надпись "Температура"
myOLED.setFont(SmallFont);
myOLED.print("iarduino.ru", CENTER, 55); // вывод текста
myOLED.setFont(MegaNumbers);
myOLED.print(String(sensors.getTempCByIndex(0) , 1), CENTER, 9);   // Отображение температуры
myOLED.update();
delay(100);
}

Вот ссылка на источник:

https://lesson.iarduino.ru/page/termometr-na-baze-ds18b20-i-oled-displeya-128x64/

С ардуино знаком пока на уровне "мигания", вот пытаюсь продвинуться дальше. 

По термометрам находил еще один проект, хорошо формленный, но с той же проблемой. Нет "минуса".

Вот ссылка: http://arduino-project.net/oled-chasy-na-arduino/

Немного сложнее с конвертацией и загрузкой изображений, но и интереснее. Скетч который я загружал по этому проекту:

#include <OLED_I2C.h>
OLED  myOLED(SDA, SCL, 8);
extern uint8_t MegaNumbers[];
extern uint8_t RusFont[];
extern uint8_t SmallFont[];
extern uint8_t term[];
extern uint8_t grad[];

#include <DS1307.h>
DS1307 rtc(A0, A1);
Time t;

#include <OneWire.h>
OneWire ds(4);

int x = 0;

void setup() {
  myOLED.begin();
  rtc.halt(false);
  //rtc.setDOW(WEDNESDAY);
  //rtc.setTime(21, 24, 0);
  //rtc.setDate(29, 4, 2015);
}

void loop() {
  if (x >= 10) {
    temp();
    x=0;
  }
  else
  {
    watch();
  }
  x++;
}
void watch() {
  myOLED.setFont(RusFont);
  t = rtc.getTime();
  switch (t.dow)
  {
    case 1:     myOLED.print("GJYTLTKMYBR", CENTER, 0);    break;
    case 2:     myOLED.print("DNJHYBR", CENTER, 0);        break;
    case 3:     myOLED.print("CHTLF", CENTER, 0);          break;
    case 4:     myOLED.print("XTNDTHU", CENTER, 0);        break;
    case 5:     myOLED.print("GZNYBWF", CENTER, 0);        break;
    case 6:     myOLED.print("CE<<JNF", CENTER, 0);        break;
    case 7:     myOLED.print("DJCRHTCTYMT", CENTER, 0);    break;
  }
  String stringOne = rtc.getTimeStr();
  myOLED.setFont(MegaNumbers);
  myOLED.print(stringOne.substring(0, 2), 4, 12);
  myOLED.print("/", 51, 12);
  myOLED.print(stringOne.substring(3, 5), 75, 12);
  myOLED.setFont(RusFont);
  switch (t.mon)
  {
    case 1:
      myOLED.print(String(t.date), 30, 57);
      myOLED.print("ZYDFHZ", CENTER, 57);
      myOLED.print(String(t.year), 88, 57);
      break;
    case 2:
      myOLED.print(String(t.date), 26, 57);
      myOLED.print("ATDHFKZ", CENTER, 57);
      myOLED.print(String(t.year), 92, 57);
      break;
    case 3:
      myOLED.print(String(t.date), 30, 57);
      myOLED.print("VFHNF", CENTER, 57);
      myOLED.print(String(t.year), 88, 57);
      break;
    case 4:
      myOLED.print(String(t.date), 30, 57);
      myOLED.print("FGHTKZ", CENTER, 57);
      myOLED.print(String(t.year), 88, 57);
      break;
    case 5:
      myOLED.print(String(t.date), 36, 57);
      myOLED.print("VFZ", CENTER, 57);
      myOLED.print(String(t.year), 82, 57);
      break;
    case 6:
      myOLED.print(String(t.date), 35, 57);
      myOLED.print("B>YZ", CENTER, 57);
      myOLED.print(String(t.year), 81, 57);
      break;
    case 7:
      myOLED.print(String(t.date), 35, 57);
      myOLED.print("B>KZ", CENTER, 57);
      myOLED.print(String(t.year), 81, 57);
      break;
    case 8:
      myOLED.print(String(t.date), 28, 57);
      myOLED.print("FDUECNF", CENTER, 57);
      myOLED.print(String(t.year), 90, 57);
      break;
    case 9:
      myOLED.print(String(t.date), 24, 57);
      myOLED.print("CTYNZ<HZ", CENTER, 57);
      myOLED.print(String(t.year), 94, 57);
      break;
    case 10:
      myOLED.print(String(t.date), 26, 57);
      myOLED.print("JRNZ<HZ", CENTER, 57);
      myOLED.print(String(t.year), 92, 57);
      break;
    case 11:
      myOLED.print(String(t.date), 28, 57);
      myOLED.print("YJZ<HZ", CENTER, 57);
      myOLED.print(String(t.year), 90, 57);
      break;
    case 12:
      myOLED.print(String(t.date), 26, 57);
      myOLED.print("LTRF<HZ", CENTER, 57);
      myOLED.print(String(t.year), 92, 57);
      break;
  }
  myOLED.update();
  delay(450);
  myOLED.setFont(MegaNumbers);
  myOLED.print("-", 51, 12);
  myOLED.update();
  delay(450);
}

void temp() {  
  for(int x = 0; x < 10; x++){
  byte data[2];
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);
  delay(150);
  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;
  
  String stringOne = rtc.getTimeStr();
  
  myOLED.clrScr();
  myOLED.setFont(SmallFont);
  myOLED.print(stringOne.substring(0, 5), 98, 0);
  myOLED.print(rtc.getDateStr(), 0, 0);
  myOLED.setFont(RusFont);
  myOLED.print("NTVGTHFNEHF", CENTER, 57);
  myOLED.drawBitmap(4, 12, term, 19, 40);
  myOLED.setFont(MegaNumbers);
  myOLED.print(String(Temp), CENTER, 12);
  myOLED.drawBitmap(92, 12, grad, 13, 12); 
  myOLED.update();
  myOLED.clrScr();
  }
}

 

VK
Offline
Зарегистрирован: 19.11.2016

P.S. Если эта тема уже поднималась, прошу сильно не пинать. 

Logik
Offline
Зарегистрирован: 05.08.2014

Узрите на стр.6 http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf Там получаемые от датчика 2 байта расписаны подробней просто некуда. Далее несложная отладка очевидными методами.

VK
Offline
Зарегистрирован: 19.11.2016

Logik пишет:

Узрите на стр.6 http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf Там получаемые от датчика 2 байта расписаны подробней просто некуда. Далее несложная отладка очевидными методами.

Узрел, не в первый раз. Можете просветить как эти два байта прочитать, отобразить, да и про отладку и где нужно изменить код? Я не такой профессионал в программировании. 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

 а вот это разве не решает все проблемы, а остальное проблемы вывода, а не измерения и снятия данных

ds.reset();
 ds.write(0xCC);
 ds.write(0x44);
750 миллисекунд что то делаем, но не тупо ждем
ds.write(0xCC);
 ds.write(0xBE); // Read Scratchpad
  for (byte i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read ();
  }
raw =  (data[1] << 8) | data[0];//=======Пересчитываем в температуру
 temp =  (float)raw / 16.0;

 

Logik
Offline
Зарегистрирован: 05.08.2014

А теперь смотрим на оба скетча, особенно на строку 140 первого и 11 второго )))

VK
Offline
Зарегистрирован: 19.11.2016

То есть в 140 строке заменить вместо: 

Temp = Temp >> 4;

поставить 

temp =  (float)raw / 16.0;

 

XOR
Offline
Зарегистрирован: 25.04.2015

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

температуру округлять до 0.1 или до целых по неободимсти.

знак = плюс;
if (температура & 0x8000){
  знак = минус;
  температура = 0 - температура;
}
десятые = conv16to10[температура & 0x000F];
temp = hex2bcd(температура >> 4);
единицы = temp & 0x000F;
десятки = ((temp & 0x00F0) >> 4);

//табличка округления
unsigned char conv16to10[] = 
"\x00\x01\x01\x02\x03\x03\x04\x04\x05\x06\x06\x07\x08\x08\x09\x09";

 

Logik
Offline
Зарегистрирован: 05.08.2014

//идеологически более правильно выделять целую, дробную и знак.

А в чем тайный смысл такой идеи? Зачем. Там все логично, отрицательная температура в дополнительном коде как обычные отрицательные числа. Просто цена младшего разряда 1/16 градуса, что и корректируется соответственно.

XOR
Offline
Зарегистрирован: 25.04.2015

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

VK
Offline
Зарегистрирован: 19.11.2016

Неужели все так сложно даже для профи? Думал что все просто... 

 

VK
Offline
Зарегистрирован: 19.11.2016

XOR пишет:

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

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

2026446
Offline
Зарегистрирован: 13.01.2017

Столкнулся с такой же проблемой. Повезло быстро решить. В папке с библиотекой OLED I2C есть файл DefaultFonts.c открываем его с помощью блокнота и видим что в команде MegaNumbers нет символа минус а вот в команде BigNumbers есть. Меняем в коде везде где встречается Mega (3раза) меняем на Big. Все работает. Но шрифт теперь занимает не весь экран что не очень эстетически.