Подключение нескольких DS18b20 на одну шину и на разные выводы

sadman41
Offline
Зарегистрирован: 19.10.2016

Так надо в функцию передавать не номер датчика, а адрес, в виде uint8_t*

В принципе можно вообще вместо строки 44 влепить 104-106 без всякой функции.

Для усиления эффекта есть такое: Skip ROM (0xCC) followed by a convert T (0x44) would instruct all networked devices that have a Convert T command to perform a temperature conversion. Т.е. даем команду на массовую конвертацию, ждем один период конверсии и читаем подряд все датчики.

Гриша
Offline
Зарегистрирован: 27.04.2014

sadman41 пишет:

Для усиления эффекта есть такое: Skip ROM (0xCC) followed by a convert T (0x44).... Т.е. даем команду на массовую конвертацию, ждем один период конверсии и читаем подряд все датчики.

вот спасибо!!! а меня смутило выражение "data collision will occur on the bus as
multiple slaves transmit simultaneously" я и не проникся всей сутью.

исправлено, дополнено к посту 50, НОВЫЙ РАБОЧИЙ КОД ( с заготовками)

//100% рабочий алгоритм
// одновременный старт на конвертацию всех датчиков

#include <OneWire.h>
OneWire  ds(A0);  // линия 1-Wire будет на этом пине

byte ndT = 9;     // сколько датчиков подключили

// список адресов моих датчиков для теста
byte DeviceAddres[9][8]={                        // ...а датчиков у мня 7 штук в наличии
  {0x28, 0xB2, 0x29, 0xD7, 0x8, 0x0, 0x0, 0xDE}, // датчик с нулевым адресом, 1й
  {0x28, 0x96, 0x66, 0xFA, 0x8, 0x0, 0x0, 0xDF}, // адрес 1,  2й  второй по порядку
  {0x28, 0x3F, 0x43, 0xD6, 0x8, 0x0, 0x0, 0x5D}, // 3й
  {0x28,  0xD, 0xFD, 0xD7, 0x8, 0x0, 0x0, 0xBC}, // 4й
  {0x28, 0x28, 0x88, 0xD6, 0x8, 0x0, 0x0, 0xD1}, // 5й
  {0x28, 0xF1, 0xD0, 0xFA, 0x8, 0x0, 0x0, 0xD7}, // 6й - нет такого у меня, просто для теста кода
  {0x28, 0x2B, 0xB7, 0xF7, 0x8, 0x0, 0x0, 0x9C}, // 7й
  {0x28, 0xF1, 0xD0, 0xF7, 0x8, 0x0, 0x0, 0xD7}, // 8й
  {0x28, 0xF1, 0xF1, 0xF1, 0x8, 0x0, 0x0, 0xD7}, // 9й - нет такого у меня, просто для теста кода
};

byte CheckDevicePresent[9]= {0, 0, 0, 0, 0, 0, 0, 0, 0}; // заняли место в памяти под проверку датчиков и переменные
byte data[12];                                           // переменная для данных из датчика
int SignBit;           // знак температуры
int Tc_100;            // умножено на 100 целочисленное значение температуры, т.е. запятая "подвинута >>" на 2 знака
byte conversion_T = 0; // разнести по времени обращение и прием данных из датчика

void setup(void) 
{
  Serial.begin(9600);
}


void loop() 
{

  for (byte i = 0; i < ndT; i++) // чИпЯтаем шапку таблЫцЫ
  {
                 Serial.print( "Device №" );
                 Serial.print( i );
                 Serial.print( "   " );
  }
                 Serial.println( " " );

    start_conversion_T ();
    
//  for (byte i = 0; i < ndT; i++) // проверяем все датчикии, запускаем АЦП
//  {
//     start_conversion_T (i);
//  }


   delay (1000); // задержка на конвертацию
 if (conversion_T == 1) // задержка на конвертацию
 {
    conversion_T = 2; // место для нормального кода без delay
  }
   
 if (conversion_T == 2)  // если груши уже поспели - собираем урожай
 {
  for (byte i = 0; i < ndT; i++) // получаем и печатаем результаты
  {

       GETTEMP (i); // получаем температуру


  if (CheckDevicePresent[i] != 0)   //если датчик не нашли
  {Serial.print( "   NC        " );}
  else
  {
  if (SignBit) {Serial.print( "  -" );}
  else         {Serial.print( "   " );}
  Serial.print( Tc_100 );
  Serial.print( "      " ); 
  }}}

      conversion_T = 0; // прочитали все датчики можно заново запрашивать 


                Serial.println( " " ); 
                Serial.print( "   " ); 
               for (byte i = 0; i < ndT; i++) // печатаем для самоконтроля
                {
                 Serial.print( CheckDevicePresent[i] , DEC );
                 Serial.print( "            " );
                }
                Serial.println( " " );

                 Serial.println( " " );
                 Serial.println( " " );
                 Serial.println( " " );

   delay (30000); // задержка на конвертацию !!!!!! :))))))))))))))

} // конец loop




void start_conversion_T () 
{
  if (conversion_T == 0)
  {
  ds.reset();
  ds.write(0xCC);      // обращение ко всем DS18x20
  ds.write(0x44, 1);   // Запускаем конвертацию (получение температуры)
  conversion_T = 1;     // запустили конвертацию 
  }
}


void GETTEMP (byte No)
{
  
  ds.reset();
  ds.select(DeviceAddres[No]);
  ds.write(0xBE);    // Считываем ОЗУ датчика  

  for (byte i = 0; i < 9; i++)    // Обрабатываем 9 байт
  {     data[i] = ds.read();   }

  if (data[4] == 255) // проверяем CRC 8 или CONFIG 4 если его нет, нет датчика = 255 (0xFF)
                      // в конфиге бит 1 всегда 0, а CRC может быть 255
  {
      CheckDevicePresent[No]= 1; // пишем, что датчика нет
     return;
  } 
      CheckDevicePresent[No]= 0; // пишем, что датчик есть  

  // Высчитываем температуру :)

  int TReading;
  TReading = (data[1] << 8) + data[0]; // собираем в кучку оба байта
  
   SignBit = TReading & 0x8000;      // Проверяем дубак там или нет
   if (SignBit)                      // Если на улице дубак :)
   { TReading = (TReading ^ 0xffff) + 1;  }

// Tc_100 - это температура из датчика формата int со сдвинутой запятой на 2 знака 
   Tc_100 = (6 * TReading) + TReading / 4;     // Умножаем на (100 * 0.0625) или 6.25
                                               // т.е. убираем 4 лишних бита
}






////старая версия запроса на преобразование по адресам
//void start_conversion_T (byte No) 
//{
//
//  ds.reset();
//  ds.select(DeviceAddres[No]);
//  ds.write(0xBE);    // Считываем ОЗУ датчика  
//
//  for (byte i = 0; i < 9; i++)    // читаем в байты, 9 байт ОЗУ датчика
//  {     data[i] = ds.read();   }
//
//  if (data[4] == 255) // проверяем CRC 8 или CONFIG 4 если его нет, нет датчика = 255 (0xFF)
//                      // в конфиге бит 1 всегда 0, а CRC может быть 255
//  {
//      CheckDevicePresent[No]= 1; // пишем, что датчика нет
//     return;
//  } 
//
//  CheckDevicePresent[No]= 0;  // датчик есть
//  ds.reset();
//  ds.select(DeviceAddres[No]);
//  ds.write(0x44, 1);   // Запускаем конвертацию (получение температуры)
//}

Может я еще чего проглядел, ну чтоб не читать 9 байт, а потом проверять четвертый на присутствие датчика?!?!?????????

sadman41
Offline
Зарегистрирован: 19.10.2016

 

В любом случае вы должны "читать" с шины ответ после отсылки команды конкретному датчику на возврат значения. Если уж по взрослому, то нужно прочитать весь Scratchpad и сверить CRC. Только тогда будет понятно - датчик ответил или на шине фигня творится.  А прерываться на 4-м байте или нет - это вопрос веры. Особой оптимизации с этого не получить, думаю.

Гриша
Offline
Зарегистрирован: 27.04.2014

sadman41 пишет:

В любом случае вы должны "читать" с шины ответ после отсылки команды конкретному датчику на возврат значения. Если уж по взрослому, то нужно прочитать весь Scratchpad и сверить CRC. Только тогда будет понятно - датчик ответил или на шине фигня творится.  А прерываться на 4-м байте или нет - это вопрос веры. Особой оптимизации с этого не получить, думаю.

Вы 100% правы, но я искал или пытался нати байт ответа на запрос по адресум (вместо 9-ти). Придумал самый простой и быстрый вариант (признак). Для серьезной ситемы с критичным отношением к температуре, безусловно, необходимо пересчитывать полином под CRC и потом сверять. В примитивных системах, полагаю, этого кода хватит. Да и работает он не в пример быстрее и весит крохи.

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Ну, сколько вы там сэкономите... 20мс на датчике? У вас вся экономия в воздух уходит на строках 053 и 093. А надежность снижается.

Впрочем, система ваша - чего тут лезть с советами...

Гриша
Offline
Зарегистрирован: 27.04.2014

sadman41 пишет:

Ну, сколько вы там сэкономите... 20мс на датчике? У вас вся экономия в воздух уходит на строках 053 и 093. А надежность снижается.

Впрочем, система ваша - чего тут лезть с советами...

вне системы можно строки с delay оставить, а вот в конкретной системе все переводится на таймер с флагами. Я для этого разнес запрос и опрос, чтобы в промежутке кучу всего можно было сделать.

по поводу лезть с советами - я бы не постил эти вопросы, если бы советы мне были не нужны. Впрочем, большую часть ответа я получил в поста 51, за что огромное спасибо.

bwn
Offline
Зарегистрирован: 25.08.2014

Гриша, а чем эта тема плоха? CRC и прочее без проблем добавить, если бобик при деле ниже там  на миллисе есть.

Гриша
Offline
Зарегистрирован: 27.04.2014

bwn пишет:

Гриша, а чем эта тема плоха? CRC и прочее без проблем добавить, если бобик при деле ниже там  на миллисе есть.

уверен, что ничем, лопатил то, что имею. Об этой теме не знал, как и о многих других. Спасибо за ссылку, почитаю.

Ursinoid
Offline
Зарегистрирован: 04.03.2018

Здравствуйте. Сразу скажу я не программист, мне это просто интересно для реализации моей задумки. Подскажите как перекомпилировать адрес датчика температуры из вида: 28FFC850B3170108, в вид: 0x28, 0x1D, 0x39, 0x31, 0x2, 0x0, 0x0, 0xF0, для вставки в код скетча. 

sadman41
Offline
Зарегистрирован: 19.10.2016

Пишете адрес в строчку, через каждые два символа ставите запятую, перед ними - 0x.

Ursinoid
Offline
Зарегистрирован: 04.03.2018

Благодарю за ответ! А то я уже пытался это сделать с помощью калькулятора винды, не получилось:))

ELITE
ELITE аватар
Offline
Зарегистрирован: 11.01.2018
delay (30000); // задержка на конвертацию !!!!!! :))))))))))))))

если не критично для разового вывода ложных значений при включении то нафик не нужна задержка, а просто надо порядок последовательности поменять)

вначале получать данныее, а потом обновлять их, и всё по таймеру раз в секунду например

 

 cMs = millis(); //текущее время - у меня много раз запрашивается
 /******************** опрос датчиков Т *********************/
  if ( pMs5 + 1000UL <= cMs ){   pMs5 = cMs;        //этот код повторяться каждые 1 сек
  ter1 = (int)ds.getTempCByIndex(0);  // в переменную int8_t (-127+127) читаю и пишу целую часть показаний температуры
  ds.requestTemperatures(); // а тут даю команду на обновление данных в датчике

  }

вот кусок кода - собственно к моменту нового запроса, у датчика уже будут свежие АКТУАЛЬНЫЕ данные и никаких делеев )

Logik
Offline
Зарегистрирован: 05.08.2014

Дак все прогрессивное человечество так и творит. При старте ставим флаг  - НИЧИТАЙ, а в лупе, когда пора температуру обновлять, проверяем флаг НИЧИТАЙ и если установлен, то сбрасываем его, иначе читаем и обрабатываем температуру. Далее по любому запускаем преобразование (т.е. то что у Вас названо "обновляем"). Так по кругу. Флаг защищает от "разового вывода ложных значений". А время на преобразование выделяется за счет периода опроса. Правда значение температуры каждый раз немного "устаревшее", но при медленном её изменении и небольшом периоде это не существенно. Ниче не мешает так и кучу датчиков опрашивать.

bwn
Offline
Зарегистрирован: 25.08.2014

Ну да, а учитывая, что с последнего сообщения, прошло чуть больше года.............

Green
Онлайн
Зарегистрирован: 01.10.2015

Главное что бы доходило. Неважно через сколько.)

123ksn
Offline
Зарегистрирован: 24.11.2014

ELITE пишет:

delay (30000); // задержка на конвертацию !!!!!! :))))))))))))))

Знать бы еще откуда эта строка скопирована. 

Гриша
Offline
Зарегистрирован: 27.04.2014

123ksn пишет:

ELITE пишет:

delay (30000); // задержка на конвертацию !!!!!! :))))))))))))))

Знать бы еще откуда эта строка скопирована. 

пост 52 строка 93 :)))))))))))