Всё по DS18(B/S)20.

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Re: Всё по DS18(B/S)20.

Сообщение ibiza11 »

shads писал(а):Если что глянь как я сделал...
http://asis-kbr.ru/forum/viewtopic.php?f=11&t=160
Прошу прощения, что вмешиваюсь. Посмотрел Ваш проект термометра. У Вас в ds18b20.h все в куче, по правилам файл .h не должен содержать реализации функций и объявление переменных.
Если этот ds18b20.h будет добавлен в несколько модулей - при компиляции появится ошибка.
Ставим плюсы: )
Реклама
WoodCat
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Ср дек 04, 2013 03:35:21
Откуда: Москва

Re: Всё по DS18(B/S)20.

Сообщение WoodCat »

Возникли сложности при обработке температуры с ds18b20 в модели протеуса, подскажите плз, может кто сталкивался.
Эффект проявляется при отрицательных температурах с долями градуса.
Допустим, на датчике стоит -1, тогда младший бит приходящий с датчика 1111 0000, все верно. Выставляю на датчике температуру -1.1, младший бит становится 1110 1111, дробная часть (правая половина байта) правильная, но при этом изменяется и значение целой части температуры в левой половине байта, после пересчета получится уже не 1 а 2.
Точно так же и с другими температурами, если стоит любое целое значение, -5, -10, какое угодно, все верно. Но добавляем любое значение в десятые и значение самой температуры увеличивается на 1. Это баг протеуса? Или фича, смысла которой я не понял?
Реклама
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Re: Всё по DS18(B/S)20.

Сообщение a_skr »

Все правильно. Цена младшего разряда = 1/16 градуса. Т.е. с датчика получаете результат в градусах, умноженный на 16.
-1.1 * 16 = -17.6, дробная часть откидывается.

-17 в двоичном виде = 1111 1111 1110 1111 (16 бит)

Для проверки: -17 / 16 = -1.0625
Конечно, учитываем ошибки округления, т.к. -1.1 точно передать не получится, следующее значение будет -1,125 (1111 1111 1110 1110).

Никакие единицы градусов не теряются и не прибавляются.
WoodCat
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Ср дек 04, 2013 03:35:21
Откуда: Москва

Re: Всё по DS18(B/S)20.

Сообщение WoodCat »

Вроде бы все логично.
Но в таком случае, это означает что все выложенные в сети алгоритмы пересчета значений 18b20 страдают этим косяком и все реализованные на их основе термометры при отрицательной температуре и не круглых ее значениях врут на градус вниз?

Алгоритмов я нашел много, на разных языках и для разных платформ, везде они одинаковые:
1. Читаем младший и старший байты, допустим пусть они будут байт1 и байт2
2. четыре младших бита байта1 - значение десятых долей, выносятся в отдельную переменную
3. четыре старших бита байта2 - признак отрицательной температуры, он тоже выносится отдельно
4. оставшиеся значения объединяются в один байт, младшие биты байта2 становятся старшими битами итоговой переменной, старшие биты байта1 младшими ее битами
5. в случае если температура отрицательна, итоговая переменная инвертируется и к ней прибавляется единица.

Или я чего-то не понимаю?
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Re: Всё по DS18(B/S)20.

Сообщение uldemir »

Не понимаете. Это - стандартное представление чисел со знаком. И если не выдумывать отсебятину, то всё работает совершенно верно. Для инвертирования знака числа надо выполнить инверсию всех бит числа и прибавить единицу к младшему разряду. Для проверки можете провести проверку для 0:

0000 0000 0000
инвертируем:
1111 1111 1111
прибавляем 1:
0000 0000 0000

Как видите ноль нулём и остался.

Еще пример - температура "минус 1/16 градуса":
1111 1111 1111
инвертируем:
0000 0000 0000
прибавляем 1:
0000 0000 0001 - получили +1/16
Реклама
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Всё по DS18(B/S)20.

Сообщение Леонид Иванович »

WoodCat писал(а):все выложенные в сети алгоритмы пересчета значений 18b20 страдают этим косяком


А какая задача? Получить представление температуры в десятых градуса?

Код: Выделить всё

  uint8_t tl = OwpRead();
  uint8_t th = OwpRead();
  int16_t temp = 10 * (tl | (th << 8)) / 16;
Реклама
WoodCat
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Ср дек 04, 2013 03:35:21
Откуда: Москва

Re: Всё по DS18(B/S)20.

Сообщение WoodCat »

uldemir писал(а):Не понимаете. Это - стандартное представление чисел со знаком. И если не выдумывать отсебятину, то всё работает совершенно верно.


Вот с этим я как раз не спорю, меня смущает не то что 1+1=2 а реализация найденных мной алгоритмов :)
triest
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Вт апр 09, 2013 20:43:04

Re: Всё по DS18(B/S)20.

Сообщение triest »

Есть код на асме, в Proteus работает превосходно. А в железе не хочет. Подключаю как с паразитным питанием.
В протеусе работает нормально, а STK500 выдает зашкал.
Частота в протеусе 4Мгц, у стк500 3,68 (для прошивки пересчитал).
В чем проблема не понимаю
Вложения
пример.rar
(18.01 КБ) 191 скачивание
WoodCat
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Ср дек 04, 2013 03:35:21
Откуда: Москва

Re: Всё по DS18(B/S)20.

Сообщение WoodCat »

А если в протеусе поставить 3,68 - работает?
Я на своем небогатом опыте уже успел столкнуться с тем что 1-wire порой бывает критична к задержкам.

PS Жаль не 3,62, для круглости :beer:
triest
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Вт апр 09, 2013 20:43:04

Re: Всё по DS18(B/S)20.

Сообщение triest »

WoodCat писал(а):А если в протеусе поставить 3,68 - работает?
Я на своем небогатом опыте уже успел столкнуться с тем что 1-wire порой бывает критична к задержкам.

PS Жаль не 3,62, для круглости :beer:

Не выставить. Только 2 и 4мГц. :(
WoodCat
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Ср дек 04, 2013 03:35:21
Откуда: Москва

Re: Всё по DS18(B/S)20.

Сообщение WoodCat »

Жаль. Перед тем как писать, специально попробовал на Pic, позволяет и 3.62 и 3.68.
А STM не пробовал, мал еще, не дорос :oops:
triest
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Вт апр 09, 2013 20:43:04

Re: Всё по DS18(B/S)20.

Сообщение triest »

WoodCat писал(а):Жаль. Перед тем как писать, специально попробовал на Pic, позволяет и 3.62 и 3.68.
А STM не пробовал, мал еще, не дорос :oops:

Все заработало. Над было во фьюзах 2 мГц выставить.
Аватара пользователя
Freerider
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Вс сен 06, 2009 20:17:20

Re: Всё по DS18(B/S)20.

Сообщение Freerider »

Изучаю датчик ds18b20 не получается команда копировать из озу в пзу 0x48.Вот програмка.
OWI_DetectPresence(BUS);//959 мкс
OWI_SendByte(OWI_ROM_SKIP, BUS);// 576 мкс команда 0xcc только для 1 датчика
// пропуск rom
OWI_SendByte(DS18B20_WRITE_SCRATCHPAD ,BUS);//3334 мкс
OWI_SendByte(27 ,BUS);//3334 мкс Отсылаем TH
OWI_SendByte(25 ,BUS);//3334 мкс TL
OWI_SendByte(127 ,BUS);//3334 мкс байт конфигурации
OWI_SendByte(DS18B20_COPY_SCRATCHPAD,BUS); // Вот и сама команда 0x48

Теперь считываем из ПЗУ в ОЗУ Командой 0xB8
OWI_DetectPresence(BUS);//959 мкс
OWI_SendByte(OWI_ROM_SKIP, BUS);
OWI_SendByte(DS18B20_RECALL_E, BUS);// Команда 0xB8
while (!OWI_ReadBit(BUS)); //ждем пока перезапишет

while(1){

/*подаем сигнал сброса
команду пропуска ROM
команду - чтение внутренней памяти
затем считываем внутреннюю память датчика в массив*/
OWI_DetectPresence(BUS);
OWI_SendByte(OWI_ROM_SKIP, BUS);
OWI_SendByte(DS18B20_READ_SCRATCHPAD, BUS);
for(char z=0;z<10;z++)
{
scratchpad[z] = OWI_ReceiveByte(BUS);
};
};
При этом в массив scratchpad записывается в байт TH=0 TL=0 и байт конф.=95 .Это то что у меня было в самом датчике изначально.
Все проганяю с в AVR Studio с помощью Jtag-Ice на atmege 16
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Re: Всё по DS18(B/S)20.

Сообщение uldemir »

Изучайте внимательно диаграммы. Откуда контроллер знает, что "вот и сама команда", что это команда??????????

Freerider писал(а):OWI_DetectPresence(BUS);//959 мкс
OWI_SendByte(OWI_ROM_SKIP, BUS);// 576 мкс команда 0xcc только для 1 датчика
// пропуск rom
OWI_SendByte(DS18B20_WRITE_SCRATCHPAD ,BUS);//3334 мкс
OWI_SendByte(27 ,BUS);//3334 мкс Отсылаем TH
OWI_SendByte(25 ,BUS);//3334 мкс TL
OWI_SendByte(127 ,BUS);//3334 мкс байт конфигурации

--- тут надо вставить снова сброс шины и команды выбора устройства
OWI_DetectPresence(BUS);//959 мкс
OWI_SendByte(OWI_ROM_SKIP, BUS);// 576 мкс команда 0xcc только для 1 датчика
// пропуск rom
OWI_SendByte(DS18B20_COPY_SCRATCHPAD,BUS); // Вот и сама команда 0x48
Ну и не забудьте правильно дождаться выполнения этой команды (или читая статус при нормальном питании, или устанавливая strong pullup выдерживать определенное время указанное в даташите)
Аватара пользователя
Freerider
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Вс сен 06, 2009 20:17:20

Re: Всё по DS18(B/S)20.

Сообщение Freerider »

Да заработало поставил в програмке
OWI_SendByte(DS18B20_WRITE_SCRATCHPAD ,BUS);//3334 мкс
OWI_SendByte(27 ,BUS);//3334 мкс
OWI_SendByte(25 ,BUS);//3334 мкс
OWI_SendByte(127 ,BUS);//3334 мкс


OWI_DetectPresence(BUS);//959 мкс
OWI_SendByte(OWI_ROM_SKIP, BUS);
OWI_SendByte(DS18B20_COPY_SCRATCHPAD, BUS);

Но самое интересное это я щас начал писать в IARe ,а до этого использовал cvavr так вот там в библиотеке есть функция инициализации этого датчика где отстутствует повторный сигнал сброса и пропуска Rom вот функция сия
unsigned char ds18b20_init(unsigned char *addr,signed char temp_low,signed char temp_high,
unsigned char resolution)
{
if (ds18b20_select(addr)==0) return 0;
resolution=(resolution<<5) | 0x1f;
w1_write(0x4e);
w1_write(temp_high);
w1_write(temp_low);
w1_write(resolution);
if (ds18b20_read_spd(addr)==0) return 0;
if ((__ds18b20_scratch_pad.temp_low!=temp_low) ||
(__ds18b20_scratch_pad.temp_high!=temp_high) ||
(__ds18b20_scratch_pad.conf_register!=resolution)) return 0;
if (ds18b20_select(addr)==0) return 0;
w1_write(0x48);
delay_ms(15);
return w1_init();
}
Аватара пользователя
uldemir
Друг Кота
Сообщения: 7359
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Re: Всё по DS18(B/S)20.

Сообщение uldemir »

Не знаю, что там у них за функции, я предпочитаю разбираться с низким уровнем. Поэтому 13-14 станицы даташита в руки и изучать диаграммы. Любое обращение к устройству 1-wire начинается со сброса шины, затем выбора устройства: read-rom, match-rom или skip-rom (с соответсвующими сопутствующими действиями), и даём команду с необходимыми аргументами. После чего датчик больше ничего не воспринимает, пока снова не произойдёт сброс шины и команда выбора датчика не укажет пальцем, что это к нему относится. Всё остальное - игнорируется.
kk042fjv
Грызет канифоль
Сообщения: 261
Зарегистрирован: Ср авг 01, 2012 10:45:42

Re: Всё по DS18(B/S)20.

Сообщение kk042fjv »

Добрый день!
Подскажите почему периодически на ЖК высвечивается температура на втором датчике -9999?

Код: Выделить всё

sprintf(lcd_buf, "%.1f\xdfC", ds18b20_temperature(&ds18b20_rom_codes[0][0]));
lcd_gotoxy(0,0);
lcd_puts(lcd_buf);
       
                      sprintf(lcd_buf, "%.1f\xdfC", ds18b20_temperature(&ds18b20_rom_codes[1][0]));
                      lcd_gotoxy(0,1);
                      lcd_puts(lcd_buf);
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Re: Всё по DS18(B/S)20.

Сообщение uk8amk »

Для CVAVR это значит, что глючит сенсор или ошибка на шине.
Может быть следствием:
*плохого контакта
*длинного или неудачно выбранного кабеля
*неправильной последовательности команд обращения к датчику
*невыдерживания временных интервалов
и т.д.
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Re: Всё по DS18(B/S)20.

Сообщение Gudd-Head »

Кто-нибудь работал с сабжем или другим 1-Wire с тактовой МК 128 кГц (собака)?
1 такт получается 7.8 мкс, а в даташитах рисуют что хорошо бы считать данные до 15 мкс...
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
sanyo.95
Нашел транзистор. Понюхал.
Сообщения: 170
Зарегистрирован: Вс мар 30, 2014 21:41:24
Откуда: Украина

Re: Всё по DS18(B/S)20.

Сообщение sanyo.95 »

Здравствуйте. Извините если данный вопрос уже обсуждался. Пишу типа термостат: Atmega8, ds18b20. Я новичок и довольно долго мучился чтобы заставить программу хоть как-то работать. Проблема заключается в том что периодически на индикаторе появляется число 83, пока на индикаторе 83 на PORTC.5 - единица, потом опять показывает норм. температуру, PORTC.5=0 и опять 83..... Точность нужна до 1 градуса. Еще очень плохо производить настройку, а конкретно добавлять или отнимать temper_down, temper_up - после нажатия на кнопку изменения на индикатор доходят как то долго, хотя переключение между режимами происходит мгновенно.
Исходник:
Спойлер

Код: Выделить всё

#include <mega8.h>
#include <delay.h>
#include <1wire.h>
#include <ds18b20.h>
static flash unsigned char display[]=   // масив для индикатора
 {
  (~0b11000000), // 0
  (~0b11111001), // 1
  (~0b10100100), // 2
  (~0b10110000), // 3
  (~0b10011001), // 4
  (~0b10010010), // 5
  (~0b10000010), // 6
  (~0b11111000), // 7
  (~0b10000000), // 8
  (~0b10010000)  // 9
 };
int temper,temper_down,temper_up,temp[2],temp_down[2],temp_up[2];
char i=0,rezhim=0;     
bit butt1,butt2,butt3; // биты для кнопок
//////////////////ФУНКЦИЯ ДЕЛЕНИЯ ТЕМПЕРАТУРЫ////////////
void del_temp()
 {  
  temper=ds18b20_temperature(0);  
  temp[0]= temper/10;           // реальная температура  
  temp[1]= temper%10;  
  temp_down[0]= temper_down/10; // нижний порог
  temp_down[1]= temper_down%10;
  temp_up[0]= temper_up/10;     // верхний порог
  temp_up[1]= temper_up%10;
  delay_ms(1500);  
 } 
////////////// ОПРОС КНОПОК ///////////////
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
TCNT1H=0x00;
TCNT1L=0x00;
 if(PINB.4==0&&butt1==0)
  {
  rezhim++;
  butt1=1;
   if(rezhim>=3) rezhim=0;
  }
  if(PINB.4==1) butt1=0;
  
 if(rezhim==0) PORTC.3=1;  // РЕАЛЬНАЯ ТЕМПЕРАТУРА //
 else PORTC.3=0;
 
 if(rezhim==1)             // НИЖНИЙ ПОРОГ //
 { 
  PORTC.2=1;               
  if(PINB.2==0&&butt2==0)
  {
   temper_down++;
   butt2=1; 
  }
  if(PINB.2==1) butt2=0;
  if(PINB.3==0&&butt3==0)
  {
   temper_down--;
   butt3=1;
  }
  if(PINB.3==1) butt3=0;
 }
 else PORTC.2=0;           
 if(rezhim==2)             // ВЕРХНИЙ ПОРОГ //
  {
   PORTC.4=1;              
  if(PINB.2==0&&butt2==0)
   {
   temper_up++;
   butt2=1; 
   }
  if(PINB.2==1) butt2=0;
  if(PINB.3==0&&butt3==0)
   {
   temper_up--;
   butt3=1;
   }
  if(PINB.3==1) butt3=0;
  }
  else PORTC.4=0;
}    
/////////ДИНАМИЧЕСКАЯ ИНДИКАЦИЯ////////////
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
PORTC &= ~(1<<i);         
i++;
if(i>=2) i=0;
 if(rezhim==0)
 {                                     
 PORTD=display[temp[i]];      
 PORTC|=(1<<i);
 }
 if(rezhim==1)
 {
 PORTD=display[temp_down[i]];      
 PORTC|=(1<<i);
 }
 if(rezhim==2)
 {
 PORTD=display[temp_up[i]];      
 PORTC|=(1<<i);
 }             
}

void main(void)
{ 
PORTB=0x1C;
DDRB=0x00; 
PORTC=0x00;
DDRC=0x1F; 
PORTD=0x00;
DDRD=0x7F;
TCCR1A=0x00;
TCCR1B=0x05;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x4E;
OCR1BH=0x00;
OCR1BL=0x00;
// TC0
TCCR0=0x03; 
TCNT0=0x00;
TIMSK=0x11;
w1_init();
#asm("sei")
while (1)
      {
       del_temp();    // вызов функции деления 
       if(temper<=temper_down) PORTC.5=1; // условия управления нагрузкой
       if(temper>=temper_up) PORTC.5=0;                          
      };
}
Буду очень благодарен если будут еще какие то замечания по коду, хочется писать максимально "правильно".
Последний раз редактировалось Gudd-Head Пт сен 26, 2014 08:47:25, всего редактировалось 2 раза.
Причина: Нарушение п.2.5 Правил Форума
Ответить

Вернуться в «Периферия»