реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> DS18b20 и Atmega128
SortoVaritu
сообщение Nov 7 2010, 01:41
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 44
Регистрация: 4-11-10
Пользователь №: 60 647



Использую в своем девайсе датчики DS18b20.
Подключаю их на Atmega128. Столкнулся с проблемой
3 датчика работаю нормально но если подключить четвертый то все становитсяя наперекосяк.
Процессор каждый раз видит как будто на шине датчиков не 4 а 10 или 14 или 30. Каждый раз поразному.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 7 2010, 09:28
Сообщение #2


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Прекрасно изложена суть проблемы - без подробностей...
Какая схема включения?
Как инициализируете контроллер?
Как работаете с датчиком?
Как питаете всё хозяйство?


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
SortoVaritu
сообщение Nov 7 2010, 09:43
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 44
Регистрация: 4-11-10
Пользователь №: 60 647



Цитата(demiurg_spb @ Nov 7 2010, 12:28) *
Прекрасно изложена суть проблемы - без подробностей...
Какая схема включения?
Как инициализируете контроллер?
Как работаете с датчиком?
Как питаете всё хозяйство?



Схема включения очень проста. Питание берется +5В то же что и питание контроллера
на шину данных вешается подтягивающий резистор 4,7 КОм.

Для работы с датчиком использую готовый модуль
Код
#include "iom128.h"
#include "inavr.h"
#include "stdio.h"
#include "stdlib.h"
#include "stdint.h"
#include "string.h"
#include "ds18b20.h"
#include "stdint.h"
#include "timersw.h"



void DelayMs(uint8_t ms)            // Ждать ms    милисекунд
{
uint8_t    i;                        // рабочий регистр
for(i=ms;i>0;i--)
  __delay_cycles(1000000/TCLK);        // Задержка 1мс
}


void Delay01(uint16_t s01)            // Ждать s01*0.1 секунд
{
uint8_t    i;                        // рабочий регистр
for(i=s01;i>0;i--) DelayMs(100);
}


uint8_t    OW_crc8(uint8_t seed, uint8_t inData)
{
    uint8_t    bitsLeft;
    uint8_t    temp;

    for    (bitsLeft =    8; bitsLeft    > 0; bitsLeft--)
    {
        temp = ((seed ^    inData)    & 0x01);
        if (temp ==    0) seed >>= 1;
        else
        {
            seed ^=    0x18;
            seed >>= 1;
            seed |=    0x80;
        }
        inData >>= 1;
    }
    return seed;
}

//Сброс    шины 1-wire
uint8_t    OW_reset(void)
{
  uint8_t answer;
  
  OW_PORT_SET;                                    // Обеспечить питанием для двух проводного варианта
  OW_DDR_SET;                                    // На вывод
  DelayMs(10);                                    // 10 ms
  
  OW_PORT_CLR;                                    // Reset
  __delay_cycles(510000/TCLK);                    // 510 us

  OW_DDR_CLR;                                    // Освободить шину
  OW_PORT_SET;                                    // Подпорка
   __delay_cycles(50000/TCLK);                    // ~50us

  answer = ((OW_PIN & (1<<OW_DQ))!=0);
  __delay_cycles(430000/TCLK);                     // ~420us для завершения цикла
  OW_DDR_SET;                                    // На вывод
  return (answer);                                // 0-есть устройства, 1-нет устройств
}

//Запись бита
void OW_write_bit(uint8_t bit)
{
  OW_DDR_SET;                                    // Порт на вывод
  OW_PORT_CLR;                                    // Начало вывода бита
  __delay_cycles(2000/TCLK);                    // 2us
  
  if(bit) OW_DDR_CLR;                            // Если "1", то освободить шину
  __delay_cycles(62000/TCLK);                    // +62us
  OW_DDR_CLR;
  OW_PORT_SET;                                    // Завершить цикл
}

//Чтение бита
uint8_t OW_read_bit(void)
{
  uint8_t result;
  
  OW_DDR_SET;                                    // Порт на вывод
  OW_PORT_CLR;                                    // Начало чтения бита
  __delay_cycles(2000/TCLK);                    // 2us
  
  OW_DDR_CLR;                                    // Освободить шину
  OW_PORT_SET;                                    // Подпереть
  __delay_cycles(13000/TCLK);                    // +13us

  result = ((OW_PIN & (1<<OW_DQ))!=0);             // прочитать
  __delay_cycles(43000/TCLK);                    // +45us завершить операцию

  return result;
}

//Запись байта
void OW_write_byte(uint8_t command)
{
    for    (uint8_t i = 0;    i <    8; i++)
     {
         OW_write_bit(command &    0x01);            // передаём бит
         command >>= 1;                            // сдвигаем к следующему
     }
}

//Чтение байта
uint8_t    OW_read_byte(void)
{
  uint8_t    i;
  uint8_t    value =    0;

  for(i    = 0; i < 8;    i++)
    value    |= OW_read_bit() << i;                // читаем один бит и записываем    его    в разряд i

  return(value);
}

//Запуск конвертации температуры (для одного датчика на шине)
void convert_temp_short(void)
{
    OW_reset();
    OW_write_byte(SKIP_ROM);                    //    skip ROM command (0xCC)
    OW_write_byte(CONVERT_T);                    // convert T (0x44)
}

//Чтение температуры
int16_t    read_scratchpad(uint8_t tip)
{
uint8_t    scratchpad[8];
uint8_t    crc    = 0;

OW_write_byte(READ_SCRATCHPAD);                // читаем scratchpad 0xBE
for    (uint8_t c1    = 0; c1    < 8; c1++)
{
    scratchpad[c1] = OW_read_byte();            // Принять данные с    1 Wire шины
    crc    =  OW_crc8(crc, scratchpad[c1]);        // Посчитать CRC8  для 1 Wire шины
}
crc=OW_crc8(crc, OW_read_byte());
OW_reset();
if (crc == 0)                                    // Проверить CRC8  для 1 Wire шины
{
   if(tip==DS18B20TIP)

      //return ((scratchpad[1] << 4) | (scratchpad[0] >> 4));
return ((scratchpad[1] <<8) | (scratchpad[0] ));
   else
     return ((scratchpad[1] & 0x80) |    (scratchpad[0] >> 1));
}
else return ( ERROR_CRC);                        // Message -80
}

//Чтение температуры (для одного датчика на шине)
int16_t    read_temp_short(void)
{
    OW_reset();
    OW_write_byte(SKIP_ROM);                    // пропусь ROM
    return (read_scratchpad(DS18B20TIP));        // Чтение температуры
}

//Выбор датчика
void MatchRom(uint8_t numb_dev)
{
uint8_t    crc,*addr;
    
crc = 0;                                        // предустановка crc
OW_reset();
OW_write_byte(MATCH_ROM);                        //    match ROM команда (0x55)
// Указатель на начало ROM области данного устройства
for(addr=OW_Rom_Device+numb_dev*7;addr<OW_Rom_Device+numb_dev*7+7;addr++)
{
    OW_write_byte(*addr);                        // вывести байт ROM
    crc = OW_crc8(crc,*addr);                    // посчитать CRC
}
OW_write_byte(crc);                            // вывести байт crc
}

//Запуск конвертации температуры (для конкретного датчика на шине)
void convert_temp(uint8_t numb_dev)
{
MatchRom(numb_dev);                            // match ROM команда
OW_write_byte(CONVERT_T);                        // convert T (0x44)
OW_PORT_SET;                                    // Обеспечить питанием для двух проводного варианта
OW_DDR_SET;                                    // На вывод
}

//Чтение температуры (для конкретного датчика на шине)
int16_t    read_temp(uint8_t numb_dev)
{
    MatchRom(numb_dev);                            // match ROM команда
    return (read_scratchpad(*(OW_Rom_Device+numb_dev*7)));
}


uint8_t lastDiscrep;                             // last discrepancy
uint8_t *CurrentAddr;


// NEXT
// Эта функция ищет следующее устройство на 1- проводной шине. Если
// нет больше устройств  на 1- проводной шине, тогда возвращается FALSE.
//
uint8_t Next(void)
{
uint8_t crc;                                    // CRC
uint8_t m = 1;                                    // битовый индекс
uint8_t n = 0;                                    // байтовый индекс
uint8_t k = 1;                                    // битовая маска
uint8_t discrepMarker = 0;                        // "маркер несоответствия" или "развилка" на дереве устройств
uint8_t g;                                        // Рабочий/Выходной бит

crc = 0;                                        // предустановка crc
if(OW_reset()||(lastDiscrep==100))                // Нет устройств (нет ответа) или все устройства перебраны, то выход FALSE
{
   lastDiscrep = 0;                                // Начало поиска
   return FALSE;
}
OW_write_byte(SEARCH_ROM);                        // передать команду SearchROM
do                                                // для всех восьми байтов
{
   g = OW_read_bit() << 1;                        // ответ на "0"
   g |= OW_read_bit();                            // и на дополнение
   if(g ==3) break;                                // нет устройств - завершить
   else
   {
     if(g>0)                                    // все связанные устройства отвечают на 0 или 1 (нет перекрёстка)
       g = g>>1;                                // битовая величина записи для поиска (идём по ветке)
     else    
     {                                            // Два устр-ва ответило на разные биты -- перекрёсток
                                                // если этот перекрёсток - перед последним
                                                // перекрёстком на предшествующем NEXT, тогда выберите
                                                // такой же бит как и в прошлый раз
       if(m<lastDiscrep) g = (((*(CurrentAddr+n))&k)>0);
       else    g = (m==lastDiscrep);                // если равен последнему отклику ==1
        if (g==0) discrepMarker = m;            // Выбрать новый перекрёсток
     }
     if(g==1)    (*(CurrentAddr+n)) |= k;        // перепешите бит в ROM[n] с маской k      
     else        (*(CurrentAddr+n)) &= ~k;      
     OW_write_bit(g);                            // вывести
     m++;                                        // следующий бит
     k = k<<1;                                    // сдвинуть маску
     if(k==0)                                    // если маска переполнилась, то - следующий байт ROM
     {                                            // байт n и инициализация маски
       crc = OW_crc8(crc, *(CurrentAddr+n));    // посчитать CRC
       n++; k++;
     }
   }
}while(n<8);                                    // цикл через все байты ROM 0-7

if(m<65||crc){                                 // если поиск был неудачным, тогда
   lastDiscrep=0;                                // очистка last discrepancy
   return FALSE;
}  
else
{
   lastDiscrep = discrepMarker;                    // поиск был удачным, так что установлено lastDiscrep,
   if(lastDiscrep==0) lastDiscrep=100;            // Если перекрёсток был последним, то установить признак выхода в след. NEXT
   else
   {
      CurrentAddr +=7;                            // Следующий адрес
      malloc(7);                                // Зарезервировать память под ROM
   }    
   return TRUE;                                    // указывает что поиск - не завершен пока,
}                                                // некоторые устройства остаются
}


uint8_t OW_cnt_device(void)
{
uint8_t    Cnt_Device;                                // Число устройств на шине

if(!OW_reset())                                // Начинается когда импульс присутствия обнаружен
{
   lastDiscrep = 0;                                // восстановите последнее несоответствие rom поиска глобальное
   Cnt_Device=0;
   OW_Rom_Device=CurrentAddr=malloc(8);            // Зарезервировать память под ROM
   while (Next())                                // Продолжить пока все дополнительные устройства не будут обнаружены
   {
     Cnt_Device++;
   }
}  return(3);
}





в теле программы вызываю процедуру поиска датчиков
Код
OW_cnt_device(void)


и вот она мне ка раз и возвращает количество датчиков большое.
Пробовал симулировать в Протеусе - все то же самое
Go to the top of the page
 
+Quote Post
xemul
сообщение Nov 7 2010, 10:03
Сообщение #4



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Вы резервируете память malloc(8) только под один слэйв.

UPD: разглядел.
Код
      CurrentAddr +=7;                            // Следующий адрес
      malloc(7);                                // Зарезервировать память под ROM

Предпочитаете грабли с тщательно отполированными ручками?

А скорее всего на 4-ом слэйве при malloc() просто наезжаете на стэк.
Go to the top of the page
 
+Quote Post
Dx!
сообщение Nov 7 2010, 10:16
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 108
Регистрация: 6-02-09
Из: Новочеркасск
Пользователь №: 44 469



А что мешает работать прямо по адресам и не использовать неработающую функцию поиска?

Сообщение отредактировал Dx! - Nov 7 2010, 10:23
Go to the top of the page
 
+Quote Post
domowoj
сообщение Nov 7 2010, 10:38
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1 548
Регистрация: 20-12-07
Из: г.Новосибирск
Пользователь №: 33 486



Цитата(SortoVaritu @ Nov 7 2010, 15:43) *
в теле программы вызываю процедуру поиска датчиков
Код
OW_cnt_device(void)


и вот она мне как раз и возвращает количество датчиков большое.
Пробовал симулировать в Протеусе - все то же самое

Вот мне всегда было не понятна сама суть команды "поиск ROM"(F0h),
ну определил я кол-во датчиков, ну знаю темпеатуру каждого,
НО где какой датчик-то неизвесно.
Проще знать идентификационный номер каждого датчика и место его расположения и
обращаться к каждому датчику индивидуально командой(55h).



--------------------
И на камнях растут деревья!
Go to the top of the page
 
+Quote Post
Dx!
сообщение Nov 7 2010, 10:45
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 108
Регистрация: 6-02-09
Из: Новочеркасск
Пользователь №: 44 469



И ещё - а какие адреса у "призраков"? Это может помочь найти грабли - один фиг вам нужно эти адреса запоминать, как заметили выше.
Я эти датчики опрашивал по одному через SKIP ROM для определения адреса.

Если геморрой с адресами не нужен, и датчиков не много - можно их по одному повесить, каждый на свою шину.

Сообщение отредактировал Dx! - Nov 7 2010, 11:57
Go to the top of the page
 
+Quote Post
SortoVaritu
сообщение Nov 7 2010, 11:17
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 44
Регистрация: 4-11-10
Пользователь №: 60 647



Цитата(Dx! @ Nov 7 2010, 13:16) *
А что мешает работать прямо по адресам и не использовать неработающую функцию поиска?

Для этого нужно в коде программы прописать эти датчики.
Использую я 4 датчика. И получиться что если датчик сдохнет то нужно перепрошивать проц.

Цитата(xemul @ Nov 7 2010, 13:03) *
Вы резервируете память malloc(8) только под один слэйв.

UPD: разглядел.
Код
      CurrentAddr +=7;                            // Следующий адрес
      malloc(7);                                // Зарезервировать память под ROM

Предпочитаете грабли с тщательно отполированными ручками?

А скорее всего на 4-ом слэйве при malloc() просто наезжаете на стэк.


Код
      malloc(7);                                // Зарезервировать память под ROM

[/code]

но функция next вызывается несколько раз и каждый раз когда найдено новое устройство резервируется память

А почему я должен наехать на Стэк. Я HEAP большой делаю
Go to the top of the page
 
+Quote Post
xemul
сообщение Nov 7 2010, 11:51
Сообщение #9



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(SortoVaritu @ Nov 7 2010, 14:17) *
Использую я 4 датчика. И получиться что если датчик сдохнет то нужно перепрошивать проц.

Вам просто намекают, что после обнаружения датчиков нужно еще выполнить и их привязку в пространстве. (возможно, Вы уже решили эту задачу)
Цитата
но функция next вызывается несколько раз и каждый раз когда найдено новое устройство резервируется память

Я заметил, но чуть позже.
Цитата
А почему я должен наехать на Стэк. Я HEAP большой делаю

Ну если есть такая уверенность, то остаются расползающиеся фронты при увеличении ёмкости на шине, не укладывающиеся в заданные тайминги.
Go to the top of the page
 
+Quote Post
SortoVaritu
сообщение Nov 7 2010, 12:37
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 44
Регистрация: 4-11-10
Пользователь №: 60 647



Цитата(xemul @ Nov 7 2010, 14:51) *
Вам просто намекают, что после обнаружения датчиков нужно еще выполнить и их привязку в пространстве. (возможно, Вы уже решили эту задачу)

Я заметил, но чуть позже.

Ну если есть такая уверенность, то остаются расползающиеся фронты при увеличении ёмкости на шине, не укладывающиеся в заданные тайминги.


Вот этого я и опасаюсь - физики процесса.
Хотя думаю, что в самом деле для моей конструкции будет лучше обращаться непосредственно по имени к датчику и не делать поиска.

Go to the top of the page
 
+Quote Post
Dx!
сообщение Nov 7 2010, 13:33
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 108
Регистрация: 6-02-09
Из: Новочеркасск
Пользователь №: 44 469



Цитата(SortoVaritu @ Nov 7 2010, 16:37) *
Хотя думаю, что в самом деле для моей конструкции будет лучше обращаться непосредственно по имени к датчику и не делать поиска.

Или выделить четыре ножки а не одну, если предполагается замена.
Go to the top of the page
 
+Quote Post
SortoVaritu
сообщение Nov 7 2010, 22:20
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 44
Регистрация: 4-11-10
Пользователь №: 60 647



Сделал все без поиска. Но все равно 2 датчика работают нормально, как только вешаю еще 2 сразу зависает проц.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th June 2025 - 21:03
Рейтинг@Mail.ru


Страница сгенерированна за 0.01496 секунд с 7
ELECTRONIX ©2004-2016