ds18b20+st7735+blynk

Roma_40

New member
Господа, подскажите.
Нужно, что бы показания с 2-х датчиков ds18b20 выводились на дисплей с точностью до одного знака после запятой.
методом тыка собрал следующий скетч:

#include <Wire.h> // include Wire library (required for I2C devices)
#include <Adafruit_GFX.h> // include Adafruit graphics library
#include <Adafruit_ST7735.h> // include Adafruit ST7735 TFT library
//#include <Adafruit_BME280.h> // include Adafruit BME280 sensor library


// ST7735 TFT module connections
#define TFT_RST -1 // TFT RST pin is connected to NodeMCU reset pin
#define TFT_CS D8 // TFT CS pin is connected to NodeMCU pin D8 (GPIO15)
#define TFT_DC D4 // TFT DC pin is connected to NodeMCU pin D4 (GPIO2)
// initialize ST7735 TFT library with hardware SPI module
// SCK (CLK) ---> NodeMCU pin D5 (GPIO14)
// MOSI(DIN) ---> NodeMCU pin D7 (GPIO13)
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

/* ESP & Blynk */
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#define BLYNK_PRINT Serial

/* Blynk credentials */
char auth[] = "G-dy-92lhAjxqaFzEl6s5OjoFSMaW0CW";

/* WiFi credentials */
char ssid[] = "Keenetic Giga II";
char pass[] = "waFpmReW";

/* TIMER */
//#include <SimpleTimer.h>
SimpleTimer timer;

/* DS18B20 Temperature Sensor */
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 5 // DS18B20 подключаем на D1 на плате
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
float temp_0;
float temp_1;

void setup()
{
Serial.begin(115200);
Blynk.begin(auth, ssid, pass);
DS18B20.begin();
timer.setInterval(1000L, getSendData);
Serial.println(" ");
Serial.println("Testing Dual Sensor data");
//void setup(void)
{
tft.initR(INITR_BLACKTAB); // initialize a ST7735S chip, black tab
tft.fillScreen(ST7735_BLACK); // fill screen with black color
tft.drawFastHLine(0, 10, tft.width(), ST7735_WHITE); // draw horizontal white line at position (0, 15)

tft.setTextColor(ST7735_WHITE, ST7735_BLACK); // set text color to white and black background
tft.setTextSize(1); // text size = 1
tft.setCursor(44, 0); // move cursor to position (40, 0) pixel
tft.print("KOLONNA");

tft.setTextColor(ST7735_GREEN, ST7735_BLACK); // set text color to green and black background
tft.setCursor(8, 20); // move cursor to position (8, 20) pixel
tft.print("TEMPERATURA =");

tft.fillTriangle(4, 60, 10, 41, 16, 60, ST77XX_RED); // print Triangle up symbol
tft.fillTriangle(4, 71, 10, 90, 16, 71, ST77XX_BLUE); // print Triangle down symbol


}
}



void loop()
{
timer.run(); // Initiates SimpleTimer
Blynk.run();

{
tft.setTextSize(3);
tft.setCursor(20, 40);
tft.setTextColor(ST7735_YELLOW, ST7735_BLACK); // set text color to yellow and black background
if(temp_0 < 0) // if temperature < 0
tft.printf( "-%02u.%01u", (int)abs(temp_0), (int)(abs(temp_0) * 10) % 10 );
else // temperature >= 0
tft.printf( " %02u.%01u", (int)temp_0, (int)(temp_0 * 10) % 10 );

tft.setCursor(20, 70);
tft.setTextColor(ST7735_YELLOW, ST7735_BLACK); // set text color to yellow and black background
if(temp_1 < 0) // if temperature < 0
tft.printf( "-%02u.%01u", (int)abs(temp_1), (int)(abs(temp_1) * 10) % 10 );
else // temperature >= 0
tft.printf( " %02u.%01u", (int)temp_1, (int)(temp_1 * 10) % 10 );

tft.drawCircle(120, 42, 2, ST7735_CYAN); // print degree symbol ( ° )
tft.drawCircle(120, 72, 2, ST7735_CYAN); // print degree symbol ( ° )


delay(1000); // wait a second
}
}

/***************************************************
* Send Sensor data to Blynk
**************************************************/
void getSendData()
{
DS18B20.requestTemperatures();
temp_0 = DS18B20.getTempCByIndex(0); // Sensor 0 показания для датчика 1 в цельсиях
temp_1 = DS18B20.getTempCByIndex(1); // Sensor 0 показания для датчика 2 в цельсиях

//Serial.print(" Temp_0-");
//Serial.print(temp_0 );
//Serial.print(" Temp_1-");
//Serial.print(temp_1 );

Blynk.virtualWrite(10, temp_0); //вывод данных на виртуальный пин V10
Blynk.virtualWrite(11, temp_1); //вывод данных навиртуальный пин V11
}

Вроде как все работает.
Но обнаружил проблему. Знак после запятой меняется с интервалом не "0.1", а "0,3". Т.е. показывает значение 24.0, следующее становится 23.7 или 24.3
 

pvvx

Активный участник сообщества
DS18B20 Datasheet: ±0.5°C Accuracy from -10°C to +85°C
1610241750631.png
От минимума (-55С) до максимума (+125С) при 9 битах выходит (55+125)/(2pow9) = 0.3515625 С
Но реальность хуже, т.к. минималка в кодах у него 0xFC90, а максимум 0x07D0. Т.е. -880..2000 при 16 битах в передаваемых данных. Эти значения надо сдвинуть на 4 бита и получаем единицы градусов. А 12 бит от 16-ти и есть максимальный шаг оцифровки у данного датчика и равен +-1 С :)
 

Roma_40

New member
т.е. простыми словами виновник DS18B20, а не код? И для DS18B20 показывать значения с шагом 0,5 это норма? а с шагом 0.3515625 это идеал? :oops:
 

CodeNameHawk

Moderator
Команда форума
т.е. простыми словами виновник DS18B20, а не код?
Виновник тот, кто не хочет читать datasheet DS18B20.
+-0.5 градуса этого точность в диапазоне -10°C to +85°C , а выдавать он может с дискретностью
The resolution of the temperature sensor is user-configurable to 9, 10, 11, or 12 bits, corresponding to increments of 0.5°C, 0.25°C, 0.125°C, and 0.0625°C, respectively.

Посмотрите библиотеку dallas

там есть
// set global resolution to 9, 10, 11, or 12 bits
void setResolution(uint8_t);

В железе, изменение температуры на 0.1 градаса, датчик отрабатывает надежно.
 
Последнее редактирование:

Roma_40

New member
CodeNameHawk, я просто немного далек от этих умных фраз :)
Но направление ясно, буду пробовать исправлять код. Спасибо.

Но если кто-то подскажет, что и чем нужно заменить, буду благодарен))
 

CodeNameHawk

Moderator
Команда форума
Но если кто-то подскажет, что и чем нужно заменить, буду благодарен))
Чем вас не устраивает готовая библиотека с рабочими примерами?

Если нужна помощь, то выкиньте из кода все что не относится к измерению температуры и покажите что выводится в сериал при измерении, а потом добавив в setup функцию setResolution(12);
 

Roma_40

New member
загрузил скетч из "Примеры>DallasTemperature>Multiple"

Device Address: 282C9556B5013C31 Temp C: 24.81
Device Address: 28737A79A200036F Temp C: 24.00
Requesting temperatures...DONE
Device Address: 282C9556B5013C31 Temp C: 24.81
Device Address: 28737A79A200036F Temp C: 24.00
Requesting temperatures...DONE
Device Address: 282C9556B5013C31 Temp C: 24.81
Device Address: 28737A79A200036F Temp C: 24.00
Requesting temperatures...DONE
Device Address: 282C9556B5013C31 Temp C: 24.88
Device Address: 28737A79A200036F Temp C: 24.00
Requesting temperatures...DONE
Device Address: 282C9556B5013C31 Temp C: 24.88
Device Address: 28737A79A200036F Temp C: 24.00
Requesting temperatures...DONE
Device Address: 282C9556B5013C31 Temp C: 24.88
Device Address: 28737A79A200036F Temp C: 24.00
Requesting temperatures...DONE
Device Address: 282C9556B5013C31 Temp C: 24.94
Device Address: 28737A79A200036F Temp C: 24.00
 

Roma_40

New member
интересно конечно, но пока пробовал изменить свой скетч (менял и загружал), так же загружал скетч из "Примеры>DallasTemperature>Multiple"...
сейчас мой стандартный скетч, показывает изменения с таким же интервалом как и под спойлером
 

Roma_40

New member
CodeNameHawk , по коду подскажите?
сейчас отображение так и идет с интервалом 0.1, но я так понимаю это случайность😏
 

CodeNameHawk

Moderator
Команда форума
@CodeNameHawk , по коду подскажите?
сейчас отображение так и идет с интервалом 0.1, но я так понимаю это случайность
Случайности не случайны.
Читайте внимательно
Если нужна помощь, то выкиньте из кода все что не относится к измерению температуры и покажите что выводится в сериал при измерении, а потом добавив в setup функцию setResolution(12);
те. должны быть два скетча и два вывода в сериал, тут понятно?

Посмотрите на функцию getResolution.
 
Последнее редактирование:

Roma_40

New member
/* DS18B20 Temperature Sensor */
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 5 // DS18B20 подключаем на D1 на плате
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
float temp_1;
float temp_2;

void setup()
{
Serial.begin(115200);
DS18B20.begin();
}

void loop()
{
DS18B20.requestTemperatures();
temp_1 = DS18B20.getTempCByIndex(0); // Sensor 0 показания для датчика 1 в цельсиях
temp_2 = DS18B20.getTempCByIndex(1); // Sensor 1 показания для датчика 2 в цельсиях

Serial.print(" Temp_1-");
Serial.print(temp_1 );
Serial.print(" Temp_2-");
Serial.println(temp_2 );
}
Temp_1-23.63 Temp_2-22.88
Temp_1-23.69 Temp_2-22.88
Temp_1-23.69 Temp_2-22.88
Temp_1-23.69 Temp_2-22.88
Temp_1-23.69 Temp_2-22.88
Temp_1-23.69 Temp_2-22.88
Temp_1-23.69 Temp_2-22.88
Temp_1-23.75 Temp_2-22.88
Temp_1-23.81 Temp_2-22.88
Temp_1-23.81 Temp_2-22.88
Temp_1-23.81 Temp_2-22.88
Temp_1-23.81 Temp_2-22.88
Temp_1-23.88 Temp_2-22.88
Temp_1-23.94 Temp_2-22.88
Temp_1-24.00 Temp_2-22.94
Temp_1-24.00 Temp_2-22.88
Temp_1-24.06 Temp_2-22.94
Temp_1-24.13 Temp_2-22.88


/* DS18B20 Temperature Sensor */
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 5 // DS18B20 подключаем на D1 на плате
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
float temp_1;
float temp_2;

void setup()
{
Serial.begin(115200);
DS18B20.begin();
DS18B20.setResolution(12);
}

void loop()
{
DS18B20.requestTemperatures();
temp_1 = DS18B20.getTempCByIndex(0); // Sensor 0 показания для датчика 1 в цельсиях
temp_2 = DS18B20.getTempCByIndex(1); // Sensor 1 показания для датчика 2 в цельсиях

Serial.print(" Temp_1-");
Serial.print(temp_1 );
Serial.print(" Temp_2-");
Serial.println(temp_2 );
}
Temp_1-24.06 Temp_2-23.25
Temp_1-24.06 Temp_2-23.25
Temp_1-24.06 Temp_2-23.25
Temp_1-24.06 Temp_2-23.25
Temp_1-24.06 Temp_2-23.25
Temp_1-24.06 Temp_2-23.25
Temp_1-24.13 Temp_2-23.25
Temp_1-24.19 Temp_2-23.25
Temp_1-24.19 Temp_2-23.25
Temp_1-24.19 Temp_2-23.25
Temp_1-24.25 Temp_2-23.25
Temp_1-24.25 Temp_2-23.25
Temp_1-24.25 Temp_2-23.25
Temp_1-24.31 Temp_2-23.25
Temp_1-24.31 Temp_2-23.25
Temp_1-24.31 Temp_2-23.25
Temp_1-24.38 Temp_2-23.25
Temp_1-24.44 Temp_2-23.25
Temp_1-24.44 Temp_2-23.25
Temp_1-24.50 Temp_2-23.25
Temp_1-24.56 Temp_2-23.25

надеюсь setResolution поставил верно
 

CodeNameHawk

Moderator
Команда форума
надеюсь setResolution поставил верно
Ну вот похоже у вас все работает как надо, видны изменения на 0.0625 градуса.
Учтите только, что requestTemperatures для 12 битного режима, продолжается почти секунду, поэтому результат надо читать после задержки. Самое тупое решение просто вставить delay(1000); Правильное на первом проходе цикла задать requestTemperatures , а через секунду (и нафига так часто?) проверяя millis() прочитать температуры и снова дать команду на измерение температор, ну и все по новой.

Две цифры после запятой "плохо" воспринимаются, преобразовать в текст с одной цифрой можно так
Код:
char temp1_s[7];
dtostrf(temp_1 , 0, 1, temp1_s);
Или просто округлить, если это надо.

Вставьте эти строки в первый скетч и покажите результат.
Код:
char temp1_s[7];
char temp2_s[7];
void loop()
{
DS18B20.requestTemperatures();
delay(1000);
Serial.println(DS18B20.getResolution());

temp_1 = DS18B20.getTempCByIndex(0); // Sensor 0 показания для датчика 1 в цельсиях
temp_2 = DS18B20.getTempCByIndex(1); // Sensor 1 показания для датчика 2 в цельсиях 
dtostrf(temp_1 , 0, 1, temp1_s);
Serial.println(temp1_s);
dtostrf(temp_1 , 0, 1, temp2_s);
Serial.println(temp2_s);
 

Roma_40

New member
Вставьте эти строки в первый скетч и покажите результат.
/* DS18B20 Temperature Sensor */
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 5 // DS18B20 подключаем на D1 на плате
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
float temp_1;
float temp_2;
char temp1_s[7];
char temp2_s[7];

void setup()
{
Serial.begin(115200);
DS18B20.begin();
}

void loop()
{
DS18B20.requestTemperatures();
delay(2000);
Serial.println(DS18B20.getResolution());

temp_1 = DS18B20.getTempCByIndex(0); // Sensor 0 показания для датчика 1 в цельсиях
temp_2 = DS18B20.getTempCByIndex(1); // Sensor 1 показания для датчика 2 в цельсиях
dtostrf(temp_1 , 0, 1, temp1_s);
Serial.println(temp1_s);
dtostrf(temp_1 , 0, 1, temp2_s);
Serial.println(temp2_s);
}
2.6
22.6
12
22.6
22.6
12
22.6
22.6
12
22.6
22.6
12
22.5
22.5
12
22.6
22.6
12
22.5
22.5
12
22.6
22.6
12
22.6
22.6
12
22.6
22.6
12
22.8
22.8
12
23.0
23.0
12
23.3
23.3
12
23.6
23.6
12
23.9
23.9
12
24.2
24.2
12
24.5
24.5
12
24.8
24.8
12
25.0
25.0
12
25.3
25.3
12
25.4
25.4
12
25.5
25.5
12
25.6
25.6
12
25.6
25.6
12
25.7
25.7
12
25.7
25.7
12
25.8
25.8
12
25.8
25.8

Показывает один результат. Я всегда грею только первый датчик.

Про 1 секунду - в исходном скетче на Blynk стоит "timer.setInterval(1000L, getSendData)", а т.к. я не знаю зависят ли они друг от друга поэтому и здесь оставил так, хотя можно и 2

про char почитал, но ничего не понял))
 

CodeNameHawk

Moderator
Команда форума
сейчас отображение так и идет с интервалом 0.1, но я так понимаю это случайность
Ответ на ваш вопрос, это не случайность, датчик помнит с каким разрешением ему работать.
dtostrf(temp_1 , 0, 1, temp2_s); Serial.println(temp2_s);
Можете и сами поправить немного подумав, по аналогии с
dtostrf(temp_1 , 0, 1, temp1_s); Serial.println(temp1_s);
 

nikolz

Well-known member
Ну вот похоже у вас все работает как надо, видны изменения на 0.0625 градуса.
Учтите только, что requestTemperatures для 12 битного режима, продолжается почти секунду, поэтому результат надо читать после задержки. Самое тупое решение просто вставить delay(1000); Правильное на первом проходе цикла задать requestTemperatures , а через секунду (и нафига так часто?) проверяя millis() прочитать температуры и снова дать команду на измерение температор, ну и все по новой.

Две цифры после запятой "плохо" воспринимаются, преобразовать в текст с одной цифрой можно так
Код:
char temp1_s[7];
dtostrf(temp_1 , 0, 1, temp1_s);
Или просто округлить, если это надо.

Вставьте эти строки в первый скетч и покажите результат.
Код:
char temp1_s[7];
char temp2_s[7];
void loop()
{
DS18B20.requestTemperatures();
delay(1000);
Serial.println(DS18B20.getResolution());

temp_1 = DS18B20.getTempCByIndex(0); // Sensor 0 показания для датчика 1 в цельсиях
temp_2 = DS18B20.getTempCByIndex(1); // Sensor 1 показания для датчика 2 в цельсиях
dtostrf(temp_1 , 0, 1, temp1_s);
Serial.println(temp1_s);
dtostrf(temp_1 , 0, 1, temp2_s);
Serial.println(temp2_s);
чтобы не ставить задержку в 1 секунду, читать надо по готовности данных. В результате время преобразования будет менее 0.7 сек.
--------------
Как вариант можно выдать сигнал на преобразование и отправить ESP спать на 1 секунду
потом проснуться считать данный отправить и снова запустить преобразование и послать ESP спать
В результате потребление в таком режиме работы при скорости 1 отсчет в секунду будет раз в 5 меньше.
-----------------
а еще можно запускать преобразование температуры до включения Wifi и включать wifi после чтения данных с датчика
 

pvvx

Активный участник сообщества
В результате потребление в таком режиме работы при скорости 1 отсчет в секунду будет раз в 5 меньше.
Всё "можно", но где-же взять то те варианты и о чем вы пишите про "можно"? :)
Да и в этом нет никакого смыслу - DS18B20 не годится для автономных устройств, т.к. жрет при измерении и считывании больше чем простой чип BLE. Как говорят - "не в коня корм".
 

nikolz

Well-known member
Всё "можно", но где-же взять то те варианты и о чем вы пишите про "можно"? :)
Да и в этом нет никакого смыслу - DS18B20 не годится для автономных устройств, т.к. жрет при измерении и считывании больше чем простой чип BLE. Как говорят - "не в коня корм".
каждому -свое.
Вам интересно на аппаратуре за 1000 баксов делать сложный софт никому не нужных автономных BLE глушилок
А кому-то надо реальное устройство за 5 баксов для управления домиком в деревне. Да и софт в этом случае до безобразие простой.
---------------
А вот какой смысл в том, что Вы написав сложную прошивку для BLE экономите 2 доллара в год. Только Вам и понятно.
-------------
Специально для Вас поясняю -МОЖНО -это означает что я так делал и все работает, а нужно или нет решает каждый сам
 

nikolz

Well-known member
информация к размышлению.
В действительности для измерения температуры в реальных домашних устройствах и технологиях нет надобности
ни в DS18B20
ни в 24 битных АЦП
ни вообще в каких либо АЦП достаточно термистора.
Использовать BLE или WIFI - это дело вкуса.
Разница в результатах будет лишь в затраченных средствах на реализацию,
ну и в наличии желания у pvvx осчастливить человечество.
 

Roma_40

New member
CodeNameHawk, а почему по последнему вашему скетчу , датчики показывают одни и те же показания?
Про "dtostrf" все понятно))
У меня почему то новая оказия, при загрузке моего исходного скетча, второй датчик показывает -127. Хотя при загрузке других скетчей, в serial выводятся нормальные показания обоих датчиков :oops:
 
Сверху Снизу