Easyelectronics.ru

Электроника для всех
Текущее время: 23 авг 2017, 20:54

Часовой пояс: UTC + 5 часов



    • JLCPCB for PCB Prototyping: 10 шт. 2-слоя 100*100mm 2$(около 140rub), изготовление за 24 часа.
    • Создание принципиальных схем и проектирование печатных плат
    • Крупнейший китайский онлайн магазин радиодеталей. Скидка 50%
    • Просмотр GERBER файлов

Начать новую тему Ответить на тему  [ Сообщений: 45 ]  На страницу Пред.  1, 2
Автор Сообщение
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 11 авг 2017, 03:17 
Только пришел

Зарегистрирован: 11 авг 2017, 02:54
Сообщения: 10
raznodel писал(а):
vbogom писал(а):
Держите...
Вложение:
1-Wire.zip

Сейчас используется, 411 чип. Для добавления другого чипа отредактируйте файл onewire.h по аналогии (уже добавлены три серии чипов). В main пример для себя, но сам по себе довольно понятный.

Спасибо! Очень помогло!

От себя пять копеек - есть два термодатчика, при этом их обнаруживает по два раза каждый.
Сейчас разбираюсь, как понял проблема что CurrentNode при выполнении первого прохода NextSearchROM не инициализированна.
В результате:
1. StartSearchROM находит 1й темродатчик, выставляет LastNode.
2. NextSearchROM находит 2й, LastNode=CurrentNode (обычно это 0).
3. NextSearchROM ищет дальше, и находит 1й термодатчик снова. Но CurrentNode уже не ноль.
4. NextSearchROM ищет дальше, и находит 2й термодатчик снова.
5. Останов.
Как решу отпишу!



Реши так:
NextSearchROM
1. CurrentNode = 0;
2.
if (CurrentNode == 0) {
StatusSearch = 2;
}

PS странные термодатчики - после 75 градусов зависают наглухо, пока не остудишь не работают.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 12 авг 2017, 20:57 
Только пришел

Зарегистрирован: 11 авг 2017, 02:54
Сообщения: 10
raznodel писал(а):
PS странные термодатчики - после 75 градусов зависают наглухо, пока не остудишь не работают.


У датчиков частота уплывает из за температуры, в итоге подтяжка 1-wire по 0лю больше 30 микросекунд.

Продолжаю повествование:
Проблема в том что UART слишком умный, он генерирует HAL_USART_ERROR_NE Noise error в связи с тем что термодатчик отпускает шину в тот момент когда uart замеряет очередной бит.
При этом попасть на ошибку шума можно не сразу а в процессе нагрева например (частота термодатчика плавает с температурой).
Щас решаю как лечить:
1. либо как то отучить uart проверять шум (самое лучшее),
2. либо как то сбрасывать ошибку uart.

Решил первым способом __HAL_UART_DISABLE_IT(huart, UART_IT_ERR); все ок!


Последний раз редактировалось raznodel 12 авг 2017, 23:09, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 12 авг 2017, 22:54 
Старожил

Зарегистрирован: 11 сен 2012, 11:19
Сообщения: 4063
raznodel, единственное верное решение не юзать либы уверововших в калокуб, да и калокуб не юзать...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 12 авг 2017, 23:11 
Только пришел

Зарегистрирован: 11 авг 2017, 02:54
Сообщения: 10
dosikus_2 писал(а):
raznodel, единственное верное решение не юзать либы уверововших в калокуб, да и калокуб не юзать...

Может, но это не этот случай. Здесь поулчилось все как надо.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 00:37 
Свой человек

Зарегистрирован: 14 сен 2015, 08:50
Сообщения: 178
Откуда: Россия, Ростов-на-Дону
raznodel писал(а):
vbogom писал(а):
Держите...
Вложение:
1-Wire.zip

Сейчас используется, 411 чип. Для добавления другого чипа отредактируйте файл onewire.h по аналогии (уже добавлены три серии чипов). В main пример для себя, но сам по себе довольно понятный.

Спасибо! Очень помогло!

От себя пять копеек - есть два термодатчика, при этом их обнаруживает по два раза каждый.
Сейчас разбираюсь, как понял проблема что CurrentNode при выполнении первого прохода NextSearchROM не инициализированна.
В результате:
1. StartSearchROM находит 1й темродатчик, выставляет LastNode.
2. NextSearchROM находит 2й, LastNode=CurrentNode (обычно это 0).
3. NextSearchROM ищет дальше, и находит 1й термодатчик снова. Но CurrentNode уже не ноль.
4. NextSearchROM ищет дальше, и находит 2й термодатчик снова.
5. Останов.
Как решу отпишу!

StartSearchROM и NextSearchROM это "внутренние" (их нет в файле OneWire.h) функции и они не предназначены для непосредственно их использования в программе. Необходимо пользоваться FindRomDeviceWire или FindFamilyRomDeviceWire. Поэтому CurrentNode и не надо инициировать она проходит инициализацию в StartSearchROM, которая вызывается функцией GeneralisationFindRomDeviceWire.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 00:42 
Свой человек

Зарегистрирован: 14 сен 2015, 08:50
Сообщения: 178
Откуда: Россия, Ростов-на-Дону
raznodel писал(а):
PS странные термодатчики - после 75 градусов зависают наглухо, пока не остудишь не работают.


На таких температурах не проверял.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 01:17 
Только пришел

Зарегистрирован: 11 авг 2017, 02:54
Сообщения: 10
vbogom писал(а):
StartSearchROM и NextSearchROM это "внутренние" (их нет в файле OneWire.h) функции и они не предназначены для непосредственно их использования в программе. Необходимо пользоваться FindRomDeviceWire или FindFamilyRomDeviceWire. Поэтому CurrentNode и не надо инициировать она проходит инициализацию в StartSearchROM, которая вызывается функцией GeneralisationFindRomDeviceWire.



FindFamilyRomDeviceWire ее и вызываю, все как в примере испольщования:
CurrentNode не инициализируется в StartSearchROM, только LastNode.
Код:
uint8_t StartSearchROM(HAL_Wire *Wire, uint8_t Consider, uint8_t Mode,
                       uint8_t *Addr) //Начитаем искать ROM. Mode - режим поиска
                                      //(SEARCH_ROM или ALARM_SEARCH). Addr -
//адрес очередного устройства. Возвращает
// 0xFF если утройство найдено и 0x0 - если
//нет.
{
    uint8_t res = 0;
    uint8_t tmp;
    if (!SendWireReset(Wire))
        goto exit; //Если ни одно устройство не ответило, то и искать бесполезно
    uint8_t i;
    for (i = 0; i < 8; i++) //Обнуляем адрес
        Addr[i] = 0;
    SendWireByte(Wire, Mode); //Посылаем команду поиска
    uint8_t CurrBit;
    Wire->USART->Init.BaudRate = 115200;
    HAL_HalfDuplex_Init(Wire->USART);
    __HAL_UART_DISABLE_IT(Wire->USART, UART_IT_ERR);
    i = 0;
    if (Consider) //Если требуется искать адреса устройств определенного
                  //семейства
    {
        Addr[0] = LastAddr[0]; //Первый байт нам известен
        for (; i < 8; i++)     //Все равно необходимо пройти всю цепочку бит адреса
        {
            CurrBit = ReadWireBit2(Wire); //Читаем бит и комплементарный бит
            tmp = (LastAddr[i / 8] >> (i % 8)) &
                  1;                //Значение бита адреса в i-ой позииции семейства
            SendWireBit(Wire, tmp); //Отсылаем бит семейства
        }
    }
    for (; i < 64; i++) //Продолжаем читать оставшиеся биты (если Сonsider не
    //равен нулю, то счет начинается с восьми)
    {
        CurrBit = ReadWireBit2(Wire); //Читаем бит и комплементарный бит
        switch (CurrBit) {
        case 3: //Если оба бита равны 1, то устройств на шине нет, или сбой шины
            goto exit;
        case 0: //Если оба бита равны 0 - коллизия
            LastNode = i;
        default:
            SendWireBit(Wire,
                        CurrBit >> 1); //Отсылаем полученный бит устройствам
            Addr[i / 8] |= (CurrBit >> 1)
                           << (i % 8); //Запоминаем полученый бит адреса
        }
    }
    for (i = 0; i < 8;
         i++) //Если удалось прочитать все 64 бита, то сохраняем найденный адрес
        LastAddr[i] = Addr[i];
    res = CheckCRCWire((uint8_t *)Addr, 8); //Проверяем CRC адреса

exit:
    Wire->USART->Init.BaudRate = 9600;
    HAL_HalfDuplex_Init(Wire->USART);
    __HAL_UART_DISABLE_IT(Wire->USART, UART_IT_ERR);
    return res; //Возвращаем результат поиска
}


Для решения переписал NextSearchROM:
Цитата:
uint8_t NextSearchROM(HAL_Wire *Wire, uint8_t Consider, uint8_t Mode,
uint8_t *Addr) //Продолжаем искать ROM. Mode - режим
//поиска (SEARCH_ROM или ALARM_SEARCH).
// Addr - адрес очередного устройства.
//Возвращает 0xFF если утройство найдено и
// 0x0 - если нет.
{
uint8_t res = 0;
uint8_t tmp = 0;
if (!SendWireReset(Wire))
goto exit; //Если ни одно устройство не ответило, то и искать бесполезно
uint8_t i;
for (i = 0; i < 8; i++) //Обнуляем адрес
Addr[i] = 0;
SendWireByte(Wire, Mode); //Посылаем команду поиска
uint8_t CurrBit;
Wire->USART->Init.BaudRate = 115200;
HAL_HalfDuplex_Init(Wire->USART);
__HAL_UART_DISABLE_IT(Wire->USART, UART_IT_ERR);
i = 0;
CurrentNode = 0;
if (Consider) //Если требуется искать адреса устройств определенного
//семейства
{
Addr[0] = LastAddr[0]; //Первый байт нам известен
for (; i < 8; i++) //Все равно необходимо пройти всю цепочку бит адреса
{
CurrBit = ReadWireBit2(Wire); //Читаем бит и комплементарный бит
tmp = (LastAddr[i / 8] >> (i % 8)) &
1; //Значение бита адреса в i-ой позииции семейства
SendWireBit(Wire, tmp); //Отсылаем бит семейства
}
}
for (; i < 64; i++) //Продолжаем читать оставшиеся биты (если Сonsider не
//равен нулю, то счет начинается с восьми)
{
CurrBit = ReadWireBit2(Wire); //Читаем бит и комплементарный бит
if (i < LastNode) //Повторяем уже пройденный путь
{
if (CurrBit == 0) //Если коллизия
{
tmp = (LastAddr[i / 8] >> (i % 8)) & 1; //Значение бита адреса в
// i-ой позииции прошлого
//устройства
SendWireBit(Wire,
tmp); //Отсылаем бит, полученный при поиске ROM
//прошлого устройства
if (tmp == 0)
CurrentNode = i; //Последний найденный узел, в котором
//"свернули в ноль"
Addr[i / 8] |=
tmp << (i % 8); //Запоминаем бит, полученный при поиске
// ROM прошлого устройства
} else {
SendWireBit(Wire,
CurrBit >> 1); //Отсылаем полученный бит устройствам
Addr[i / 8] |= (CurrBit >> 1)
<< (i % 8); //Запоминаем полученый бит адреса
}
continue;
}
switch (CurrBit) {
case 3: //Если оба бита равны 1, то устройств на шине нет, или сбой шины
goto exit;
case 0: //Если оба бита равны 0 - коллизия
if (i == LastNode) {
SendWireBit(Wire, 1); //Идем на другую ветку
Addr[i / 8] |= 1 << (i % 8); //Запоминаем полученый бит адреса
continue;
}
CurrentNode =
i; //Последний найденный узел, в котором "свернули в ноль"
default:
SendWireBit(Wire,
CurrBit >> 1); //Отсылаем полученный бит устройствам
Addr[i / 8] |= (CurrBit >> 1)
<< (i % 8); //Запоминаем полученый бит адреса
}
}
LastNode = CurrentNode; //Запоминаем найденный узел для следующей итерации
tmp = 0;
for (i = 0; i < 8;
i++) //Если удалось прочитать все 64 бита, то сохраняем найденный адрес
{
if (LastAddr[i] == Addr[i])
tmp++; //Подсчитываем сколько байт текущего адреса совпало с прошлым
LastAddr[i] = Addr[i];
}
if (tmp == 8) //Если все байты адреса совпали, то поиск завершен
{
StatusSearch = 2;
} else {
res = CheckCRCWire((uint8_t *)Addr, 8); //Проверяем CRC адреса
}
if (CurrentNode == 0) { // Если 0 - значит нет коллизий, больше искать нечего
StatusSearch = 2;
}

exit:
Wire->USART->Init.BaudRate = 9600;
HAL_HalfDuplex_Init(Wire->USART);
__HAL_UART_DISABLE_IT(Wire->USART, UART_IT_ERR);
return res; //Возвращаем результат поиска
}



Для высоких температур добавил фикс:
__HAL_UART_DISABLE_IT(Wire->USART, UART_IT_ERR);
после каждого вызова
HAL_HalfDuplex_Init(Wire->USART);

Теперь если uart читает значение в момент когда датчик отпускает шину прерывание с ошибкой Noze не генерируется, все работает дальше.

Вам еще раз спасибо за код, буду рад если мои фиксы вам пригодятся!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 01:54 
Свой человек

Зарегистрирован: 14 сен 2015, 08:50
Сообщения: 178
Откуда: Россия, Ростов-на-Дону
raznodel писал(а):

FindFamilyRomDeviceWire ее и вызываю, все как в примере испольщования:
CurrentNode не инициализируется в StartSearchROM, только LastNode.


Странно... C CurrenetNode всё в порядке, она всё равно сначала инициализируется и лишь затем используется. Задваивания происходить не должно, т.к. в функции NextSearchROM проверяется повторность нахождения адреса:
Код:
if (tmp==8)                      //Если все байты адреса совпали, то поиск завершен
   {
      StatusSearch=2;
   }else   res=CheckCRCWire((uint8_t*)Addr, 8);   //Проверяем CRC адреса

Т.е. функция NextSearchROM должна возвращать в этом случае 0x0, что и говорит о том, что в данном случае ничего не найдено.

А за поправку для высоких температур спасибо!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 04:01 
Только пришел

Зарегистрирован: 11 авг 2017, 02:54
Сообщения: 10
vbogom писал(а):
raznodel писал(а):

FindFamilyRomDeviceWire ее и вызываю, все как в примере испольщования:
CurrentNode не инициализируется в StartSearchROM, только LastNode.


Странно... C CurrenetNode всё в порядке, она всё равно сначала инициализируется и лишь затем используется. Задваивания происходить не должно, т.к. в функции NextSearchROM проверяется повторность нахождения адреса:
Код:
if (tmp==8)                      //Если все байты адреса совпали, то поиск завершен
   {
      StatusSearch=2;
   }else   res=CheckCRCWire((uint8_t*)Addr, 8);   //Проверяем CRC адреса

Т.е. функция NextSearchROM должна возвращать в этом случае 0x0, что и говорит о том, что в данном случае ничего не найдено.

А за поправку для высоких температур спасибо!


Щас прикинем (ситуация два теомродатчика):
1. StartSearchROM в конце работы: определен LastNode, не определен CurrentNode, первый ТД найден.
2. NextSearchROM в конце работы: LastNode = CurrentNode, который не определен, т.к. первый ТД считан в StartSearchROM, а теперь читаем второй, коллизия будет в известном на месте по LastNode, в связи с этим мы:
Код:
       
      │    case 0: //Если оба бита равны 0 - коллизия                                                                                                                                                                                           
      │   │   if (i == LastNode) {                                                                                                                                                                                                             
      │   │   │   SendWireBit(Wire, 1); //Идем на другую ветку                                                                                                                                                                                 
      │   │   │   Addr[i / 8] |= 1 << (i % 8); //Запоминаем полученый бит адреса                                                                                                                                                               
      │   │   │   continue;                                                                                                                                                                                                                   
      │   │   }
      │   │   CurrentNode =                                                                                                                                                                                                                   
      │   │   │   i; //Последний найденный узел, в котором "свернули в ноль" 

не омечаем коллизию в CurrentNode, а больше коллизий не будет - ТД то два.
При этом мы не можем остановиться нужно вызвать еще раз NextSearchROM который увидит совпадение и остановит поиск, но!
3. Итак NextSearchROM Начинает работать с последним адресом и непределенным LastNode, и в итоге снова считает первый ТД (LastNode у меня всегда был равен нулую).
4. Следующий NextSearchROM считывает 2й тд.
5. И только следующий NextSearchROM все застопорит ибо CurrentNode уже заполнен верно.

Итого датчики считанны дважды каждый.

Для температуры киньте ТД в кипяток, может проявиться ошибка, а может и нет - у каждого ТД частота плывет немножко по своему.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 11:33 
Свой человек

Зарегистрирован: 14 сен 2015, 08:50
Сообщения: 178
Откуда: Россия, Ростов-на-Дону
raznodel писал(а):
1. StartSearchROM в конце работы: определен LastNode, не определен CurrentNode, первый ТД найден.
2. NextSearchROM в конце работы: LastNode = CurrentNode, который не определен, т.к. первый ТД считан в StartSearchROM, а теперь читаем второй, коллизия будет в известном на месте по LastNode, в связи с этим мы:
не омечаем коллизию в CurrentNode, а больше коллизий не будет - ТД то два.

Неверно:
Пункт 1: всё согласен.
Пункт 2: В конце работы LastNode = CurrentNode, но он уже определен.
Код:
   for(; i<64; i++)//Продолжаем читать оставшиеся биты (если Сonsider не равен нулю, то счет начинается с восьми)
   {
      CurrBit=ReadWireBit2(Wire);   //Читаем бит и комплементарный бит
      if (i<LastNode)//Повторяем уже пройденный путь
      {
         if (CurrBit==0)//Если коллизия
         {
            tmp=(LastAddr[i/8]>>(i%8))&1;//Значение бита адреса в i-ой позииции прошлого устройства
            SendWireBit(Wire,tmp);    //Отсылаем бит, полученный при поиске ROM прошлого устройства
            if (tmp==0) CurrentNode=i;//Последний найденный узел, в котором "свернули в ноль"
            Addr[i/8]|=tmp<<(i%8);//Запоминаем бит, полученный при поиске ROM прошлого устройства
         }else
         {
            SendWireBit(Wire,CurrBit>>1);    //Отсылаем полученный бит устройствам
            Addr[i/8]|=(CurrBit>>1)<<(i%8);   //Запоминаем полученый бит адреса
         }
         continue;
      }
      switch (CurrBit)
      {
         case 3:                              //Если оба бита равны 1, то устройств на шине нет, или сбой шины
            goto exit;
         case 0:                              //Если оба бита равны 0 - коллизия
            if (i==LastNode)
            {
               SendWireBit(Wire,1);   //Идем на другую ветку
               Addr[i/8]|=1<<(i%8);   //Запоминаем полученый бит адреса
               continue;
            }
            CurrentNode=i;//Последний найденный узел, в котором "свернули в ноль"
         default:
            SendWireBit(Wire,CurrBit>>1);    //Отсылаем полученный бит устройствам
            Addr[i/8]|=(CurrBit>>1)<<(i%8);   //Запоминаем полученый бит адреса
      }      
   }

Да, необходимо еще раз вызывать NextSearchROM чтобы он "застопорил" поиск, но при этом он возвращает 0, что говорит о том, что в данной итерации ничего нового не найдено.
Смотрим описание:
//Поиск адресов устройств. Family - семейство устройств (первый байт ROM`а). Mode - режим поиска (SEARCH_ROM или ALARM_SEARCH). Addr - адрес очередного устройства. Возвращает 0xFF если утройство найдено и 0x0 - если нет.

И их вызов в программе я реализую следующим образом (пример ROM поиска датчиков температуры с алармом):
Код:
while (FindFamilyRomDeviceWire(&Wire,0x28, ALARM_SEARCH/*SEARCH_ROM*/, (uint8_t*)AddrU))


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 14:39 
Только пришел

Зарегистрирован: 11 авг 2017, 02:54
Сообщения: 10
vbogom писал(а):
raznodel писал(а):
1. StartSearchROM в конце работы: определен LastNode, не определен CurrentNode, первый ТД найден.
2. NextSearchROM в конце работы: LastNode = CurrentNode, который не определен, т.к. первый ТД считан в StartSearchROM, а теперь читаем второй, коллизия будет в известном на месте по LastNode, в связи с этим мы:
не омечаем коллизию в CurrentNode, а больше коллизий не будет - ТД то два.

Неверно:
Пункт 1: всё согласен.
Пункт 2: В конце работы LastNode = CurrentNode, но он уже определен.
Код:
   for(; i<64; i++)//Продолжаем читать оставшиеся биты (если Сonsider не равен нулю, то счет начинается с восьми)
   {
      CurrBit=ReadWireBit2(Wire);   //Читаем бит и комплементарный бит
      if (i<LastNode)//Повторяем уже пройденный путь
      {
         if (CurrBit==0)//Если коллизия
         {
            tmp=(LastAddr[i/8]>>(i%8))&1;//Значение бита адреса в i-ой позииции прошлого устройства
            SendWireBit(Wire,tmp);    //Отсылаем бит, полученный при поиске ROM прошлого устройства
            if (tmp==0) CurrentNode=i;//Последний найденный узел, в котором "свернули в ноль"
            Addr[i/8]|=tmp<<(i%8);//Запоминаем бит, полученный при поиске ROM прошлого устройства
         }else
         {
            SendWireBit(Wire,CurrBit>>1);    //Отсылаем полученный бит устройствам
            Addr[i/8]|=(CurrBit>>1)<<(i%8);   //Запоминаем полученый бит адреса
         }
         continue;
      }
      switch (CurrBit)
      {
         case 3:                              //Если оба бита равны 1, то устройств на шине нет, или сбой шины
            goto exit;
         case 0:                              //Если оба бита равны 0 - коллизия
            if (i==LastNode)
            {
               SendWireBit(Wire,1);   //Идем на другую ветку
               Addr[i/8]|=1<<(i%8);   //Запоминаем полученый бит адреса
               continue;
            }
            CurrentNode=i;//Последний найденный узел, в котором "свернули в ноль"
         default:
            SendWireBit(Wire,CurrBit>>1);    //Отсылаем полученный бит устройствам
            Addr[i/8]|=(CurrBit>>1)<<(i%8);   //Запоминаем полученый бит адреса
      }      
   }

Да, необходимо еще раз вызывать NextSearchROM чтобы он "застопорил" поиск, но при этом он возвращает 0, что говорит о том, что в данной итерации ничего нового не найдено.
Смотрим описание:
//Поиск адресов устройств. Family - семейство устройств (первый байт ROM`а). Mode - режим поиска (SEARCH_ROM или ALARM_SEARCH). Addr - адрес очередного устройства. Возвращает 0xFF если утройство найдено и 0x0 - если нет.

И их вызов в программе я реализую следующим образом (пример ROM поиска датчиков температуры с алармом):
Код:
while (FindFamilyRomDeviceWire(&Wire,0x28, ALARM_SEARCH/*SEARCH_ROM*/, (uint8_t*)AddrU))


Пункт 2, в каком месте опеделяется CurrentNode?
Там два потенциальных места:
Первое:
Код:
         if (CurrBit==0)//Если коллизия
         {
            tmp=(LastAddr[i/8]>>(i%8))&1;//Значение бита адреса в i-ой позииции прошлого устройства
            SendWireBit(Wire,tmp);    //Отсылаем бит, полученный при поиске ROM прошлого устройства
            if (tmp==0) CurrentNode=i;//Последний найденный узел, в котором "свернули в ноль"


Здесь не определиться, ибо ТД два и коллизи до LastNode не произойдет.
Второе:
Код:
         case 0:                              //Если оба бита равны 0 - коллизия
            if (i==LastNode)
            {
               SendWireBit(Wire,1);   //Идем на другую ветку
               Addr[i/8]|=1<<(i%8);   //Запоминаем полученый бит адреса
               continue;
            }
            CurrentNode=i;//Последний найденный узел, в котором "свернули в ноль"

Вот здесь какраз и будет коллизия что и в прошлый раз, мы ее обработаем, перйедем на другую ветвь дерева, и вызовем continue так и не дойдя до CurrentNode=i;.
Далее коллизий не будет, т.к. первый ТД перестанет анонсировать свой ID после данного шага.
Вроде как то так.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 14:49 
Старожил

Зарегистрирован: 16 ноя 2012, 07:47
Сообщения: 2283
raznodel писал(а):
PS странные термодатчики - после 75 градусов зависают наглухо, пока не остудишь не работают.

У себя с таким столкнулся. На UART+DMA, на одной шине висит 5 датчиков DS18B20, T0-92, питание НЕ паразитное. 4 работают корректно до 100°, а один отваливается как у вас, после 70°. Точнее не отваливался, а у него сильно плавало время измерений (более 750 мс), а у меня было сделано не по опросу линии, а просто задержка 850 мс. Но мог и показать температуру 25°, при том, что у него должно быть под 78°. Причем до этого работал некоторое время. Разница лишь в том, что 4 работающие от проверенного поставщика, а 5-й у меня валялся несколько лет, заказанный когда-то с Китая. Первые 4 показывали температуру +- 0,1 градуса(от друг друга), а зачастую и все одно и тоже, а 5-й врал +-2 градуса. В принципе укладывался в погрешность, заявленную производителем, но все равно, какой-то левый. Поменял на новый, все отлично заработало.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 14:55 
Только пришел

Зарегистрирован: 11 авг 2017, 02:54
Сообщения: 10
Hold писал(а):
raznodel писал(а):
PS странные термодатчики - после 75 градусов зависают наглухо, пока не остудишь не работают.

У себя с таким столкнулся. На UART+DMA, на одной шине висит 5 датчиков DS18B20, T0-92, питание НЕ паразитное. 4 работают корректно до 100°, а один отваливается как у вас, после 70°. Точнее не отваливался, а у него сильно плавало время измерений (более 750 мс), а у меня было сделано не по опросу линии, а просто задержка 850 мс. Но мог и показать температуру 25°, при том, что у него должно быть под 78°. Причем до этого работал некоторое время. Разница лишь в том, что 4 работающие от проверенного поставщика, а 5-й у меня валялся несколько лет, заказанный когда-то с Китая. Первые 4 показывали температуру +- 0,1 градуса(от друг друга), а зачастую и все одно и тоже, а 5-й врал +-2 градуса. В принципе укладывался в погрешность, заявленную производителем, но все равно, какой-то левый. Поменял на новый, все отлично заработало.

Уже пофикшено, ТД в порядке, чуть выше описанно))


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 15:16 
Свой человек

Зарегистрирован: 14 сен 2015, 08:50
Сообщения: 178
Откуда: Россия, Ростов-на-Дону
raznodel писал(а):
vbogom писал(а):
raznodel писал(а):
1. StartSearchROM в конце работы: определен LastNode, не определен CurrentNode, первый ТД найден.
2. NextSearchROM в конце работы: LastNode = CurrentNode, который не определен, т.к. первый ТД считан в StartSearchROM, а теперь читаем второй, коллизия будет в известном на месте по LastNode, в связи с этим мы:
не омечаем коллизию в CurrentNode, а больше коллизий не будет - ТД то два.

Неверно:
Пункт 1: всё согласен.
Пункт 2: В конце работы LastNode = CurrentNode, но он уже определен.
Код:
   for(; i<64; i++)//Продолжаем читать оставшиеся биты (если Сonsider не равен нулю, то счет начинается с восьми)
   {
      CurrBit=ReadWireBit2(Wire);   //Читаем бит и комплементарный бит
      if (i<LastNode)//Повторяем уже пройденный путь
      {
         if (CurrBit==0)//Если коллизия
         {
            tmp=(LastAddr[i/8]>>(i%8))&1;//Значение бита адреса в i-ой позииции прошлого устройства
            SendWireBit(Wire,tmp);    //Отсылаем бит, полученный при поиске ROM прошлого устройства
            if (tmp==0) CurrentNode=i;//Последний найденный узел, в котором "свернули в ноль"
            Addr[i/8]|=tmp<<(i%8);//Запоминаем бит, полученный при поиске ROM прошлого устройства
         }else
         {
            SendWireBit(Wire,CurrBit>>1);    //Отсылаем полученный бит устройствам
            Addr[i/8]|=(CurrBit>>1)<<(i%8);   //Запоминаем полученый бит адреса
         }
         continue;
      }
      switch (CurrBit)
      {
         case 3:                              //Если оба бита равны 1, то устройств на шине нет, или сбой шины
            goto exit;
         case 0:                              //Если оба бита равны 0 - коллизия
            if (i==LastNode)
            {
               SendWireBit(Wire,1);   //Идем на другую ветку
               Addr[i/8]|=1<<(i%8);   //Запоминаем полученый бит адреса
               continue;
            }
            CurrentNode=i;//Последний найденный узел, в котором "свернули в ноль"
         default:
            SendWireBit(Wire,CurrBit>>1);    //Отсылаем полученный бит устройствам
            Addr[i/8]|=(CurrBit>>1)<<(i%8);   //Запоминаем полученый бит адреса
      }      
   }

Да, необходимо еще раз вызывать NextSearchROM чтобы он "застопорил" поиск, но при этом он возвращает 0, что говорит о том, что в данной итерации ничего нового не найдено.
Смотрим описание:
//Поиск адресов устройств. Family - семейство устройств (первый байт ROM`а). Mode - режим поиска (SEARCH_ROM или ALARM_SEARCH). Addr - адрес очередного устройства. Возвращает 0xFF если утройство найдено и 0x0 - если нет.

И их вызов в программе я реализую следующим образом (пример ROM поиска датчиков температуры с алармом):
Код:
while (FindFamilyRomDeviceWire(&Wire,0x28, ALARM_SEARCH/*SEARCH_ROM*/, (uint8_t*)AddrU))


Пункт 2, в каком месте опеделяется CurrentNode?
Там два потенциальных места:
Первое:
Код:
         if (CurrBit==0)//Если коллизия
         {
            tmp=(LastAddr[i/8]>>(i%8))&1;//Значение бита адреса в i-ой позииции прошлого устройства
            SendWireBit(Wire,tmp);    //Отсылаем бит, полученный при поиске ROM прошлого устройства
            if (tmp==0) CurrentNode=i;//Последний найденный узел, в котором "свернули в ноль"


Здесь не определиться, ибо ТД два и коллизи до LastNode не произойдет.
Второе:
Код:
         case 0:                              //Если оба бита равны 0 - коллизия
            if (i==LastNode)
            {
               SendWireBit(Wire,1);   //Идем на другую ветку
               Addr[i/8]|=1<<(i%8);   //Запоминаем полученый бит адреса
               continue;
            }
            CurrentNode=i;//Последний найденный узел, в котором "свернули в ноль"

Вот здесь какраз и будет коллизия что и в прошлый раз, мы ее обработаем, перйедем на другую ветвь дерева, и вызовем continue так и не дойдя до CurrentNode=i;.
Далее коллизий не будет, т.к. первый ТД перестанет анонсировать свой ID после данного шага.
Вроде как то так.


Смотрим еще раз:
В первом случае (при проверке уже пройденного пути):
Код:
if (i<LastNode)//Повторяем уже пройденный путь
      {
         if (CurrBit==0)//Если коллизия
         {
            tmp=(LastAddr[i/8]>>(i%8))&1;//Значение бита адреса в i-ой позииции прошлого устройства
            SendWireBit(Wire,tmp);    //Отсылаем бит, полученный при поиске ROM прошлого устройства
            if (tmp==0) CurrentNode=i;//Последний найденный узел, в котором "свернули в ноль"
            Addr[i/8]|=tmp<<(i%8);//Запоминаем бит, полученный при поиске ROM прошлого устройства
         }else
         {
            SendWireBit(Wire,CurrBit>>1);    //Отсылаем полученный бит устройствам
            Addr[i/8]|=(CurrBit>>1)<<(i%8);   //Запоминаем полученый бит адреса
         }
         continue;
      }

т.е. если коллизия была, то CurrentNode=i;

Второй случай (новая ветка):
Код:
switch (CurrBit)
      {
         case 3:                              //Если оба бита равны 1, то устройств на шине нет, или сбой шины
            goto exit;
         case 0:                              //Если оба бита равны 0 - коллизия
            if (i==LastNode)
            {
               SendWireBit(Wire,1);   //Идем на другую ветку
               Addr[i/8]|=1<<(i%8);   //Запоминаем полученый бит адреса
               continue;
            }
            CurrentNode=i;//Последний найденный узел, в котором "свернули в ноль"
         default:
            SendWireBit(Wire,CurrBit>>1);    //Отсылаем полученный бит устройствам
            Addr[i/8]|=(CurrBit>>1)<<(i%8);   //Запоминаем полученый бит адреса
      }      

при case 3: ничего инициализировать не надо, т.к. искать нечего. По default также ничего инициализировать не надо. А по case 0 инициализация проходит.
Когда датчиков более одного, то первая коллизия инициализируется в StartSearchROM, только инициализируем сразу LastNode, т.к. CurrentNode нам и не нужна, т.к. мы ищем сам факт наличия развилки.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 15:39 
Только пришел

Зарегистрирован: 11 авг 2017, 02:54
Сообщения: 10
Чето я туплю.
В первом случае до LastNode коллизии не будет, т.к. ТД два, и них коллизия по биту LastNode, до него коллизий не будет.
Во втором случае мы подошли к коллизии и идем в ветку case 0:
При этом коллизия у нас в том же бите т.е. i==LastNode а значит до CurrentNode=i; мы не дойдем, а вылетим по continue.
Далее в ветке case 0: мы не попадем, т.к. один ТД перестанет далее анонсировать свой ID.
Итог CurrentNode не опеределен.
LastNode= CurrentNode - не определено, рандомно.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 16:12 
Свой человек

Зарегистрирован: 14 сен 2015, 08:50
Сообщения: 178
Откуда: Россия, Ростов-на-Дону
raznodel писал(а):
Чето я туплю.
В первом случае до LastNode коллизии не будет, т.к. ТД два, и них коллизия по биту LastNode, до него коллизий не будет.
Во втором случае мы подошли к коллизии и идем в ветку case 0:
При этом коллизия у нас в том же бите т.е. i==LastNode а значит до CurrentNode=i; мы не дойдем, а вылетим по continue.
Далее в ветке case 0: мы не попадем, т.к. один ТД перестанет далее анонсировать свой ID.
Итог CurrentNode не опеределен.
LastNode= CurrentNode - не определено, рандомно.

Согласен ошибка.
Думаю (проверить сейчас не могу) необходимо сделать следующие изменения в коде:
В StartSearchROM добавить CurrentNode=i;:
Show

А в NextSearchROM: if (LastNode==CurrentNode) StatusSearch=2;
Show


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 16:28 
Только пришел

Зарегистрирован: 11 авг 2017, 02:54
Сообщения: 10
vbogom писал(а):
raznodel писал(а):
Чето я туплю.
В первом случае до LastNode коллизии не будет, т.к. ТД два, и них коллизия по биту LastNode, до него коллизий не будет.
Во втором случае мы подошли к коллизии и идем в ветку case 0:
При этом коллизия у нас в том же бите т.е. i==LastNode а значит до CurrentNode=i; мы не дойдем, а вылетим по continue.
Далее в ветке case 0: мы не попадем, т.к. один ТД перестанет далее анонсировать свой ID.
Итог CurrentNode не опеределен.
LastNode= CurrentNode - не определено, рандомно.

Согласен ошибка.
Думаю (проверить сейчас не могу) необходимо сделать следующие изменения в коде:
В StartSearchROM добавить CurrentNode=i;:
Show

А в NextSearchROM: if (LastNode==CurrentNode) StatusSearch=2;
Show

Тоже вариант. Я в начале NextSearchROM присваиваю CurrentNode = 255; в конце проверяю if (CurrentNode == 255) { // Если 0 - значит нет коллизий, больше искать нечего
│ StatusSearch = 2;
}
В принципе одно и тоже, если что еще заметим думаю стоит сюда отписывать, так сказать кооперция!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 16:37 
Свой человек

Зарегистрирован: 14 сен 2015, 08:50
Сообщения: 178
Откуда: Россия, Ростов-на-Дону
raznodel писал(а):
Тоже вариант. Я в начале NextSearchROM присваиваю CurrentNode = 255; в конце проверяю if (CurrentNode == 255) { // Если 0 - значит нет коллизий, больше искать нечего
│ StatusSearch = 2;
}
В принципе одно и тоже, если что еще заметим думаю стоит сюда отписывать, так сказать кооперция!

Спасибо за выловленную ошибку! Я проверял 1, 3 и 5 датчиках, а на двух нет. На одном, правда, проверял с отключенной опцией #define __SEARCHROM__. И у меня ошибка не вылезала.

Предложенные мною исправления проверяли?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 16:59 
Свой человек

Зарегистрирован: 14 сен 2015, 08:50
Сообщения: 178
Откуда: Россия, Ростов-на-Дону
vbogom писал(а):
Предложенные мною исправления проверяли?

Функцию StartSearchROM необходимо ещё модифицировать (случай с одним датчиком):
Show

Проверте, пожалуйста, а то у меня сейчас к железу нет доступа.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Onewire правильно ли понимаю.
СообщениеДобавлено: 13 авг 2017, 17:34 
Свой человек

Зарегистрирован: 14 сен 2015, 08:50
Сообщения: 178
Откуда: Россия, Ростов-на-Дону
Выкладываю исправленную библиотеку (ещё окончательно не проверена) с поправками от raznodel.
Вложение:
Комментарий к файлу: Версия библиотеки OneWire - 1.2.1
1-Wire1.7z [17.04 Кб]
Скачиваний: 7


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 45 ]  На страницу Пред.  1, 2

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB