Получение от датчика DS18B20 точности в 0.1 градус.
Здраствуйте! На радиотехничиских форумах я встречал много вопросов о том как заставить датчик DS18B20 выдавать температуру с точностью в 0.1 градус. Предлагаю вашему вниманию пример термометра который позволяет показывать эту точность. Если немного посидеть над исходником можно еще и сделать терморегулятор, ну а пока схема и исходник:)
Нужно еще в параметрах датчика изменить шаг увеличения температуры с 1, на 0.1
Исходник:
#include <mega8.h> // 1 Wire Bus functions #asm .equ __w1_port=0x15 ;PORTC .equ __w1_bit=0 #endasm #include <1wire.h> // DS1820 Temperature Sensor functions #include <ds18b20.h> #include <delay.h> // maximum number of DS1820 devices // connected to the 1 Wire bus #define MAX_DS18B20 8 // number of DS1820 devices // connected to the 1 Wire bus unsigned char ds18b20_devices; // DS1820 devices ROM code storage area, // 9 bytes are used for each device // (see the w1_search function description in the help) unsigned char ds18b20_rom_codes[MAX_DS18B20][9];
// Declare your global variables here float temper; int temper_int,temper_fl,min=0; unsigned long int temper_t; char lcd_buffer[33];
void temperature(void) // функция по работе с термо-датчиком { temper=ds18b20_temperature(&ds18b20_rom_codes[0][0]); temper_int=temper; if(temper_int>1000) // при отрицательной температуре { temper_fl=(temper-temper_int)*10; temper_t=(long)temper_int*10; temper_t=temper_t+temper_fl; temper_int=40960-temper_t; min=1; }else // при положительной { min=0; temper_fl=(temper-temper_int)*10; temper_int=(temper_int*10)+temper_fl; } }
void main(void) { // Determine the number of DS1820 devices // connected to the 1 Wire bus ds18b20_devices=w1_search(0xf0,ds18b20_rom_codes); ds18b20_init(0,-35,35,DS18B20_12BIT_RES); // переключения термометра в 12 битный режим // LCD module initialization lcd_init(16); while (1) { // Place your code here delay_ms(500); temperature(); // вызываем функцию температуры lcd_clear(); // очищаем LCD if(min==1) { sprintf(lcd_buffer,"t=-%i.%d\xdfC",temper_int/10,temper_int%10); //вывод отрицательной температуры }else { sprintf(lcd_buffer,"t=+%i.%d\xdfC",temper_int/10,temper_int%10); // вывод положительной } lcd_puts(lcd_buffer); // вывод на дисплей }; }
Можно улучшить точность датчика, но только на определенном диапазоне ...как в данной статье http://www.adventx.com.ua/automation/article/ds18b20_precision/
Можно улучшить точность датчика, но только на определенном диапазоне ...как данной статье http://www.adventx.com.ua/automation/article/ds18b20_precision/
Драсте. Нельзя сделать точность 0.1 градус, потому как заявленная точность производителя этого датчика 0.5 градуса в диапазоне -10+85, за пределами этого диапазона еще хуже. А вот дискретность можно увеличить за счет увеличения разрешения конвертации, но увеличивается время конвертации. Максимальная дискретность 0.0625 при 12-битном разрешении. Так что не путайте понятия.
Здесь неправильно написано для отрицательной температуры. Я сделал так
....... // Declare your global variables here float temper; int temper_int,temper_fl,min=0; unsigned long int temper_t;
void temperature(void) // функция по работе с термо-датчиком { temper=ds18b20_temperature(&ds18b20_rom_codes[0][0]); temper_int=temper; // отбор целой части от температуры if(temper<0) // при отрицательной температуре { temper_fl=(temper-temper_int-0.0625)*10; // дробная часть temper_int=-((temper_int*10)+temper_fl); // температура*10 min=1; // минус }else // при положительной { temper_fl=(temper-temper_int)*10; // дробная часть temper_int=(temper_int*10)+temper_fl;// температура*10 min=0; // плюс }
} void main(void) { // Determine the number of DS1820 devices // connected to the 1 Wire bus ds18b20_devices=w1_search(0xf0,ds18b20_rom_codes); ds18b20_init(0,-35,35,DS18B20_12BIT_RES); // переключения термометра в 12 битный режим
LcdInit(); // LCD module initialization
while (ds18b20_devices>0 ) { // Place your code here delay_ms(500); temperature(); // вызываем функцию температуры LcdClear(); // очищаем LCD if(min==1) // если минус { sprintf(lcd_buf,"-%u.%u\x80C",temper_int/10,temper_int%10); //вывод отрицательной температуры }else { sprintf(lcd_buf,"+%i.%d\x80C",temper_int/10,temper_int%10); // вывод положительной } LcdStringBold(1,2);// вывод на 3310Lcd ...... На Протеусе все нормально показывает.
А можно было сделать так????????? long int temp; temp=(ds18b20_temperature(&rom_code[i][0]))*10; //читаем температуру с выбранного датчика и умножаем на 10 if (temp>10000){ //если датчик выдаёт больше 10000 temp=40960-temp; //отнимаем от данных 40960 temp=-temp; //и ставим знак "минус" }
lcd_clear(); //чистим дисплей перед выводом sprintf(lcd_buffer,"t=%i.%u\xdfC",temp/10,(temp)%10); //пишем масив для экрана температуру lcd_puts(lcd_buffer); //выводим масив на LCD delay_ms(100);
Приветствую, есть вопрос, как ведет себя данный термометр "в железе"? При симуляции в протеусе отрицательная температура отображается с "минусом" как перед целой частью, так и перед дробной. http://sinerson.narod.ru/proteus_temp.JPG