Урок 26. Подключение термодатчиков DS18B20 к Ардуино. Библиотека OneWire. Точный Ардуино термометр-регистратор.

Ардуино термометр на DS18B20

В уроке узнаем, как подключать к плате Ардуино датчик температуры DS18B20, как управлять им с помощью библиотеки OneWire, разработаем точный термометр.

Предыдущий урок     Список уроков     Следующий урок

DS18B20 это интегральный датчик температуры с цифровым последовательным интерфейсом 1-Wire. Датчик с уникальными параметрами и функциональными возможностями. Я написал статью о нем.  Сейчас я подчеркну особенности этого устройства, благодаря которым он получил такое широкое распространение. Датчику DS18B20 свойственны:

  • Высокая точностью измерения, погрешность не превышает 0,5 °C. Датчик откалиброван при изготовлении, дополнительной калибровки не требует.
  • Разрешающая способность задается программно и достигает 0,0625 °C при максимальном разрешении 12 бит.
  • Широкий диапазон измерения температуры -55 … + 125 °C.
  • Датчик осуществляет преобразование температуры в цифровой код, т.е. дополнительного АЦП не требует.
  • Передача информации осуществляется по последовательному протоколу 1-Wire, требуется только три провода для подключения термодатчика к микроконтроллеру.
  • Поддерживает режим ”паразитного питания”, в котором датчик получает питание от линии связи. В этом режиме для подключения устройства к микроконтроллеру достаточно двух проводной линии связи.
  • На одну линию связи может быть включено несколько датчиков.

 

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

Подключение датчика DS18B20 к микроконтроллеру.

Самый распространенный вариант исполнения DS18B20 в корпусе TO-92.

DS18B20

Выводы на схемах подключения указаны для такого варианта. Существуют две стандартные схемы подключения DS18B20 к микроконтроллеру.

Схема питания с внешним источником.

Схема подключения DS18B20

Все просто: земля, питание, сигнал данных. Подтягивающий резистор строго необходим и устанавливается вблизи вывода микроконтроллера.

Схема в режиме ”паразитного питания” позволяет подключить термодатчик к микроконтроллеру всего двумя проводами, что особенно важно при размещении датчика на значительном расстоянии от контроллера.

Схема подключения DS18B20

В этом режиме сигнал шины данных заряжает внутренний конденсатор датчика и за счет энергии на нем происходит питание устройства при низком уровне на шине. У режима ”паразитного питания ” много особенностей. Можно почитать по ссылке. Сейчас скажу главное, что в этом режиме не гарантируется работа датчика при температуре свыше 100 °C. Надо использовать схему с внешним питанием.

Для такого случая я использую следующую схему.

Схема подключения DS18B20

Датчик работает в режиме внешнего питания, которое запасается через диод на дополнительном конденсаторе. В моих устройствах схема работает без проблем, но я не уверен, что такой вариант поддерживает библиотека OneWire. Я использовал эту схему только на PIC контроллерах с собственной библиотекой.

 

Обмен информацией с термодатчиком по шине интерфейса 1-Wire.

Если кто-то желает узнать подробную информацию по этому вопросу я опять дам ссылку на статью о DS18B20. Сейчас я перечислю необходимые нам операции работы с устройством:

  • Инициализация – последовательность импульсов, с которых начинается любая операция на шине.
  • Запись байта – передача байта данных в устройство DS18B20.
  • Чтение байта – прием данных из устройства DS18B20.

Этих трех операций достаточно для работы с термодатчиком, все они поддерживаются библиотекой OneWire.

Библиотека Ардуино OneWire для работы с интерфейсом 1-Wire.

Загрузить последнюю версию библиотеки OneWire  можно по этой ссылке. Как установить ее можно посмотреть в уроке 9.

Нас интересуют следующие методы.

OneWire( uint8_t pin);

Конструктор, Pin – номер вывода, к которому подключен датчик.

OneWire sensDs (14);  // датчик подключен к выводу 14

uint8_t reset(void);

Инициализация операции на шине. С этой команды должна начинаться любая операция обмена данными. Возвращает:

  • 1 – если устройство подключено к шине (был ответный импульс присутствия);
  • 0 – если устройство отсутствует на шине (ответного импульса не было).

void write(uint8_t v, uint8_t power = 0);

Запись байта. Передает байт в устройство на шине.

  • v – байт;
  • power – признак выбора режима питания;
    • power=0 – питание от внешнего источника
    • power=1 – “паразитное” питание.

uint8_t read(void);

Чтение байта – принимает байт, переданный устройством. Возвращает значение принятого байта.

Этих команд вполне достаточно, чтобы работать с датчиком DS18B20. Можно добавить методы записи и чтения блоков байтов и функцию вычисления контрольной суммы.

void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0);

Запись блока байтов.

  • buf – указатель на массив;
  • count – число байтов;
  • power – признак выбора режима питания.

void read_bytes(uint8_t *buf, uint16_t count);

Чтение блока байтов.

  • buf – указатель на массив;
  • count – число байтов.

static uint8_t crc8(const uint8_t *addr, uint8_t len);

Функция вычисления 8ми разрядной контрольной суммы.

  • addr - указатель на массив данных;
  • len – число байтов.

Возвращает вычисленную сумму.

 

Последовательность операций работы с DS18B20.

Я приведу и объясню самую простую последовательность команд. Для измерения температуры необходимо выполнить следующую последовательность действий:

  • sensDs.reset() - Инициализация. Выполняет сброс шины, готовит ее для выполнения новой операции.
  • sensDs.write(0xCC, power) – Команда пропуск ROM. У нас только один датчик на шине. Поэтому нет необходимости в поиске устройства с нужным адресом. Мы эту операцию пропускаем.
  • sensDs.write(0x44, power) - Команда инициирует измерение температуры.
  • Пауза 1 сек. Ожидание на время, необходимое для выполнения датчиком преобразования температуры. Это время зависит от выбранной разрешающей способности датчика. Мы используем максимальное разрешение 12 бит.  Это разрешение установлено в датчике по умолчанию. Время преобразования для него – 750 мс. Если необходима другая разрешающая способность, то ее необходимо задать дополнительными командами.
  • sensDs. reset() - Инициализация. Мы собираемся выполнить новую операцию на шине 1-Wire.
  • sensDs.write(0xCC, power) – Команда пропуск ROM.
  • sensDs.write(0xBE, power) – Команда чтения памяти датчика. Команда используется для чтения всех 9ти байтов памяти DS18B20.
Байт 0 Температура мл. байт
Байт 1 Температура ст. байт
Байт 2 Th регистр порога сигнализации
Байт 3 Tl регистр порога сигнализации
Байт 4 Регистр конфигурации
Байт 5 Зарезервирован
Байт 6 Зарезервирован
Байт 7 Зарезервирован
Байт 8 Циклический код CRC
  • read_bytes(buf, 9) - Чтение 9ти байтов данных.
  • crc8(addr, 8) - Вычисление контрольного кода данных.
  • Сравнение контрольного кода с принятым.

После этой последовательности операций значение температуры содержится в первых двух байтах массива из принятых 9ти байтов.

Формат данных

Отрицательная температура записывается в дополнительном коде.

Таблица соответствия кодов температуре

Младший разряд имеет вес 0,0625 °C.

Проект Ардуино термометра с использованием датчика DS18B20.

Создадим термометр с функциями, аналогичными устройствам из урока 24 и урока 25. Использование термодатчика DS18B20 позволяет добиться:

  • высокой точности измерения  0,5 °C;
  • высокой разрешающей способности 0,0625 °C:
  • диапазон измерения составляет -55 … +125 °C.

Схема термометра с датчиком DS18B20.

Схема Ардуино термометра на DS18B20

Led индикатор подключен по привычной схеме из предыдущих уроков. Есть два варианта подключения термодатчика: с внешним питанием и ”паразитным питанием.”

На моем макете устройство выглядит так.

Макет Ардуино термометра на DS18B20

Резидентная программа Ардуино термометра.

Структура и большая часть программы из предыдущих уроков 24 и 25. Последовательность операций для DS18B20 подробно описаны выше. Поэтому я сразу приведу скетч программы.

// термометр, датчик DS18B20
#include <MsTimer2.h>
#include <Led4Digits.h>
#include <OneWire.h>

#define POWER_MODE  0 // режим питания, 0 - внешнее, 1 - паразитное

// тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
Led4Digits disp(1, 5,4,3,2, 6,7,8,9,10,11,12,13);

OneWire sensDs (14);  // датчик подключен к выводу 14

byte bufData[9];  // буфер данных
float temperature;  // измеренная температура

void setup() {
  MsTimer2::set(2, timerInterrupt); // задаем период прерывания по таймеру 2 мс
  MsTimer2::start();               // разрешаем прерывание по таймеру
  Serial.begin(9600); // инициализируем порт, скорость 9600 
}

void loop() { 

  sensDs.reset();  // сброс шины
  sensDs.write(0xCC, POWER_MODE); // пропуск ROM
  sensDs.write(0x44, POWER_MODE); // инициализация измерения
  delay(900);  // пауза 0,9 сек
  sensDs.reset();  // сброс шины
  sensDs.write(0xCC, POWER_MODE); // пропуск ROM 
  sensDs.write(0xBE, POWER_MODE); // команда чтения памяти датчика 
  sensDs.read_bytes(bufData, 9);  // чтение памяти датчика, 9 байтов

  if ( OneWire::crc8(bufData, 8) == bufData[8] ) {  // проверка CRC
    // данные правильные
    temperature=  (float)((int)bufData[0] | (((int)bufData[1]) << 8)) * 0.0625 + 0.03125;
 
    // вывод измеренной температуры на индикаторы
    if (temperature >= 0) {
      // температура положительная
      disp.print((int)(temperature * 10.), 4, 1);        
    }
    else {
      // температура отрицательная
      disp.print((int)(temperature * -1 * 10.), 3, 1);        
      disp.digit[3]= 0x40;  // отображается минус
    }
    disp.digit[1] |= 0x80;  // зажечь точку второго разряда                
       
    // передача температуры на компьютер
    Serial.println(temperature);   
  }
  else { 
    // ошибка CRC, отображается ----
      disp.digit[0]= 0x40;
      disp.digit[1]= 0x40;
      disp.digit[2]= 0x40;
      disp.digit[3]= 0x40;        
  }   
}

//-------------------------------------- обработчик прерывания 2 мс
void  timerInterrupt() {
  disp.regen(); // регенерация индикатора
}

Загрузить скетч можно по этой ссылке:

Зарегистрируйтесь и оплатитеВсего 60 руб. в месяц за доступ ко всем ресурсам сайта!

Программа использует библиотеки OneWire, MsTimer2 и Led4Digits.

Не забудьте выбрать в программе режим питания датчика:

#define POWER_MODE  0 // режим питания, 0 - внешнее, 1 – паразитное

 

Программа верхнего уровня для Ардуино термометра-регистратора.

С этим устройством работает программа Thermometer из урока 24. В уроке можно загрузить программу, получить информацию по установке и применению программы.

Программа Ардуино термометра на DS18B20

Регистратор Ардуино термометра на DS18B20

Реализация измерения температуры параллельным процессом.

В проекте термометра управление термодатчиком DS18B20 происходит в основном цикле программы. Задержка 0,9 секунд реализована функцией delay(). Программа на это время зависает и никаких других действий производить не может. Хорошо, что нам в термометре больше ничего делать не надо. А если у нас сложная программа с множеством других задач.

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

// термометр, датчик DS18B20
#include <MsTimer2.h>
#include <Led4Digits.h>
#include <OneWire.h>

#define POWER_MODE  0 // режим питания, 0 - внешнее, 1 - паразитное
#define MEASURE_PERIOD 500  // время измерения, * 2 мс

// тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
Led4Digits disp(1, 5,4,3,2, 6,7,8,9,10,11,12,13);

OneWire sensDs (14);  // датчик подключен к выводу 14

int timeCount;     // счетчик времени измерения
boolean flagSensReady;  // признак готовности данных с датчика
byte bufData[9];  // буфер данных
float temperature;  // измеренная температура

void setup() {
  MsTimer2::set(2, timerInterrupt); // задаем период прерывания по таймеру 2 мс
  MsTimer2::start();               // разрешаем прерывание по таймеру
  Serial.begin(9600); // инициализируем порт, скорость 9600 
}

void loop() { 

  if ( flagSensReady == true ) {
    flagSensReady= false;
    // данные готовы

   if ( OneWire::crc8(bufData, 8) == bufData[8] ) {  // проверка CRC
      // данные правильные
      temperature=  (float)((int)bufData[0] | (((int)bufData[1]) << 8)) * 0.0625 + 0.03125;
 
      // вывод измеренной температуры на индикаторы
      if (temperature >= 0) {
        // температура положительная
        disp.print((int)(temperature * 10.), 4, 1);        
      }
      else {
        // температура отрицательная
        disp.print((int)(temperature * -1 * 10.), 3, 1);        
        disp.digit[3]= 0x40;  // отображается минус
      }
      disp.digit[1] |= 0x80;  // зажечь точку второго разряда                
       
      // передача температуры на компьютер
      Serial.println(temperature);   
    }
    else { 
      // ошибка CRC, отображается ----
        disp.digit[0]= 0x40;
        disp.digit[1]= 0x40;
        disp.digit[2]= 0x40;
        disp.digit[3]= 0x40;        
    }   
  } 
}

//-------------------------------------- обработчик прерывания 2 мс
void  timerInterrupt() {
  disp.regen(); // регенерация индикатора

  // управление датчиком DS18B20 паралллельным процессом
  timeCount++; if ( timeCount >= MEASURE_PERIOD ) { timeCount=0; flagSensReady=true; }
 
  if (timeCount == 0) sensDs.reset();  // сброс шины  
  if (timeCount == 1) sensDs.write(0xCC, POWER_MODE); // пропуск ROM
  if (timeCount == 2) sensDs.write(0x44, POWER_MODE); // инициализация измерения

  if (timeCount == 480) sensDs.reset();  // сброс шины
  if (timeCount == 481) sensDs.write(0xCC, POWER_MODE); // пропуск ROM 
  if (timeCount == 482) sensDs.write(0xBE, POWER_MODE); // команда чтения памяти датчика 
   
  if (timeCount == 483 ) bufData[0]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 484 ) bufData[1]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 485 ) bufData[2]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 486 ) bufData[3]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 487 ) bufData[4]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 488 ) bufData[5]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 489 ) bufData[6]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 490 ) bufData[7]= sensDs.read();  // чтение памяти датчика
  if (timeCount == 491 ) bufData[8]= sensDs.read();  // чтение памяти датчика    
}

После получения данных с датчика DS18B20 формируется признак о готовности данных и в основном асинхронном процессе они могут быть использованы.

В обработчике прерываний все операции с датчиком выполняются по принципу - одна операция с байтом за один цикл прерывания.  Во время паузы 0,9 сек, вообще ничего не делается. Так что в основном цикле может выполняться другая задача без значительной задержки.

 

В следующем уроке планирую рассказать об измерении температуры в системе Ардуино с помощью термопар. Будет рабочий проект Ардуино термометра для высоких температур.

 

Предыдущий урок     Список уроков     Следующий урок

2

Автор публикации

не в сети 15 часов

Эдуард

280
Комментарии: 1936Публикации: 197Регистрация: 13-12-2015

104 комментария на «Урок 26. Подключение термодатчиков DS18B20 к Ардуино. Библиотека OneWire. Точный Ардуино термометр-регистратор.»

  1. спасибо за материал, очень доходчиво. планируется ли продолжение с подключением других устройств 1-wire, например ds2450, ds2406

    0
    • Спасибо, приятно слышать. На счет подключения других датчиков 1-wire пока не знаю. Сейчас в планах много других интересных тем, которые я еще не рассматривал.

      0
  2. Скажите пожалуйста, что надо изменить в программе чтоб изменить на датчик ds1820? у меня температура при домашней 24,33 показывает 2,33

    0
    • Я боюсь ошибиться, но различие этих датчиков в разрешающей способности. У DS1820 это 0,5 C.
      Попробуйте строчку
      temperature= (float)((int)bufData[0] | (((int)bufData[1]) < < 8)) * 0.0625 + 0.03125; заменить на temperature= (float)((int)bufData[0] | (((int)bufData[1]) << 8)) * 0.5 + 0.25;

      0
  3. Получилось! Спасибо!
    если я пишу так
    temperature= (float)((int)bufData[0] | (((int)bufData[1]) << 8)) * 0.5 + 0.5;
    то температура меньше на 1 градус от другого термометра на ds18b20.

    0
    • Рад, что помог.
      Надо писать:
      temperature= (float)((int)bufData[0] | (((int)bufData[1]) < < 8)) * 0.5 + 0.25; + 0.25 - это округление половины значащего разряда.

      0
  4. Спасибо автору!
    Вместо резистора 4,7 кОм (у кого нет),
    использовал подтягивающий резистор A2 (15)
    digitalWrite(15, HIGH),
    Соединяем 14 и 15 (A0 и A1)… Работает!

    1
  5. Спасибо за полезную статью.
    Подскажите, можно упростить код, если не нужны значения температуры после запятой? (нужны только целые значения температуры).

    0
    • Только целое значение температуры можно вывести так. Блок
      // вывод измеренной температуры на индикаторы
      if (temperature >= 0) {
      // температура положительная
      disp.print((int)(temperature * 10.), 4, 1);
      }
      else {
      // температура отрицательная
      disp.print((int)(temperature * -1 * 10.), 3, 1);
      disp.digit[3]= 0x40; // отображается минус
      }
      disp.digit[1] |= 0x80; // зажечь точку второго разряда

      заменить на блок

      // вывод измеренной температуры на индикаторы
      if (temperature >= 0) {
      // температура положительная
      disp.print((int)(temperature + 0.5), 4, 1);
      }
      else {
      // температура отрицательная
      disp.print((int)(temperature * -1. + 0.5), 3, 1);
      disp.digit[3]= 0x40; // отображается минус
      }

      0
      • Я может не совсем правильно выразил свой вопрос.
        Мне на дисплей не нужно выводить показания.
        Мне просто достаточно точности в один градус.
        Я хотел спросить, можно ли изменить код в Вашем последнем примере, что бы датчик передавал температуру с разрешением 0,5 градуса.
        В Вашей статье про датчик написано «Основная функция DS18B20 – преобразование температуры датчика в цифровой код. Разрешение преобразования задается 9, 10, 11 или 12 бит. Это соответствует разрешающей способность — 0,5 (1/2) °C, 0,25 (1/4) °C, 0,125 (1/8) °C и 0,0625 (1/16) °C. При включении питания, состояние регистра конфигурации устанавливается на разрешение 12 бит.»

        Хотелось бы упростить свою программу
        // два датчика DS18B20
        #include
        #include

        #define POWER_MODE 0 // режим питания, 0 — внешнее, 1 — паразитное
        #define MEASURE_PERIOD 1000 // время измерения, * 2 мс

        OneWire sensOut (4); // датчик внешний подключен к выводу 4
        OneWire sensIn (5); // датчик внутренний подключен к выводу 5
        int timeCount; // счетчик времени измерения
        boolean flagSensReady; // признак готовности данных с датчика
        byte bufDataOut[9]; // буфер данных снаружи
        byte bufDataIn[9]; // буфер данных внутри
        float temperatureOut; // измеренная температура снаружи
        float temperatureIn; // измеренная температура внутри
        void setup() {
        MsTimer2::set(2, timerInterrupt); // задаем период прерывания по таймеру 2 мс
        MsTimer2::start(); // разрешаем прерывание по таймеру
        Serial.begin(9600); // инициализируем порт, скорость 9600
        }

        void loop() {

        if ( flagSensReady == true ) {
        flagSensReady= false;
        // данные готовы

        if ( OneWire::crc8(bufDataOut, 8) == bufDataOut[8] ) { // проверка CRC
        // данные правильные
        temperatureOut
        = (float)((int)bufDataOut[0] | (((int)bufDataOut[1]) << 8)) * 0.0625 + 0.03125;

        // передача температуры на компьютер
        Serial.println(temperatureOut);
        }
        if ( OneWire::crc8(bufDataIn, 8) == bufDataIn[8] ) { // проверка CRC
        // данные правильные
        temperatureIn
        = (float)((int)bufDataIn[0] | (((int)bufDataIn[1]) <= MEASURE_PERIOD ) { timeCount=0; flagSensReady=true; }

        if (timeCount == 0) sensOut.reset(); // сброс шины
        if (timeCount == 1) sensOut.write(0xCC, POWER_MODE); // пропуск ROM
        if (timeCount == 2) sensOut.write(0x44, POWER_MODE); // инициализация измерения

        if (timeCount == 480) sensOut.reset(); // сброс шины
        if (timeCount == 481) sensOut.write(0xCC, POWER_MODE); // пропуск ROM
        if (timeCount == 482) sensOut.write(0xBE, POWER_MODE); // команда чтения памяти датчика

        if (timeCount == 483 ) bufDataOut[0]= sensOut.read(); // чтение памяти датчика
        if (timeCount == 484 ) bufDataOut[1]= sensOut.read(); // чтение памяти датчика
        if (timeCount == 485 ) bufDataOut[2]= sensOut.read(); // чтение памяти датчика
        if (timeCount == 486 ) bufDataOut[3]= sensOut.read(); // чтение памяти датчика
        if (timeCount == 487 ) bufDataOut[4]= sensOut.read(); // чтение памяти датчика
        if (timeCount == 488 ) bufDataOut[5]= sensOut.read(); // чтение памяти датчика
        if (timeCount == 489 ) bufDataOut[6]= sensOut.read(); // чтение памяти датчика
        if (timeCount == 490 ) bufDataOut[7]= sensOut.read(); // чтение памяти датчика
        if (timeCount == 491 ) bufDataOut[8]= sensOut.read(); // чтение памяти датчика

        if (timeCount == 500) sensIn.reset(); // сброс шины
        if (timeCount == 501) sensIn.write(0xCC, POWER_MODE); // пропуск ROM
        if (timeCount == 502) sensIn.write(0x44, POWER_MODE); // инициализация измерения

        if (timeCount == 980) sensIn.reset(); // сброс шины
        if (timeCount == 981) sensIn.write(0xCC, POWER_MODE); // пропуск ROM
        if (timeCount == 982) sensIn.write(0xBE, POWER_MODE); // команда чтения памяти датчика

        if (timeCount == 983 ) bufDataIn[0]= sensIn.read(); // чтение памяти датчика
        if (timeCount == 984 ) bufDataIn[1]= sensIn.read(); // чтение памяти датчика
        if (timeCount == 985 ) bufDataIn[2]= sensIn.read(); // чтение памяти датчика
        if (timeCount == 986 ) bufDataIn[3]= sensIn.read(); // чтение памяти датчика
        if (timeCount == 987 ) bufDataIn[4]= sensIn.read(); // чтение памяти датчика
        if (timeCount == 988 ) bufDataIn[5]= sensIn.read(); // чтение памяти датчика
        if (timeCount == 989 ) bufDataIn[6]= sensIn.read(); // чтение памяти датчика
        if (timeCount == 990 ) bufDataIn[7]= sensIn.read(); // чтение памяти датчика
        if (timeCount == 991 ) bufDataIn[8]= sensIn.read(); // чтение памяти датчика
        }

        0
        • Для этого надо запрограммировать регистр конфигурации датчика. Я не помню, как это делается. Надо разбираться. У меня на сайте есть статья с форматами регистров. Не проще оставить все как есть. Так даже команд меньше. Что Вы сэкономите? Только время измерения.

          0
  6. Вопрос от начинающего.
    Не компилируется строка:
    MsTimer2::set(2,timerInterrupt); // задаем период прерывания по таймеру 2 мс

    выдаётся сообщение:
    exit status 1
    ‘timerInterrupt’ was not declared in this scope

    Если её комментировать, то компилируется нормально.
    В чём может быть причина?

    0
  7. Попробовал обе версии из статьи и скачанный скетч. Не компилируется. Библиотека MsTimer2.h установлена.
    Как я понимаю, таймер нужен только для индикации.
    Индикация мне не нужна, Если я закомментирую строки с обращениями к таймеру, всё остальное должно работать (измерение и передача в комп). Если нет то вместо него можно попробовать вставить delay? Вообще нужно раз в несколько минут измерять температуру и по запросу отправлять SMS, AT-командами через модем.

    0
  8. Скажите пожалуйста, что надо изменить в программе, если к шине подключено 2 датчика DS18B20 (как прописать адрес датчика) ?

    0
    • Это достаточно сложная последовательность операций. Я сейчас не помню. Может проще 2 линии связи использовать.

      0
  9. Вопрос от начинающего.
    Пробовал примеры из разных уроков, результат тот же.
    Библиотека MsTimer2 установлена.
    Не компилируется строка:
    MsTimer2::set(2,timerInterrupt);

    Arduino: 1.6.13 (Windows 8.1), Плата:»Arduino/Genuino Uno»

    G:\РђСЂРґСѓРёРЅРѕ\DS18B20_РђСЂРґСѓРёРЅРѕ\DS18B20_Ard\DS18B20_Ard.ino: In function ‘void setup()’:

    DS18B20_Ard:17: error: ‘timerInterupt’ was not declared in this scope

    exit status 1
    ‘timerInterupt’ was not declared in this scope

    Если её закомментировать, то компилируется нормально.
    Следующая за ней строка:
    MsTimer2::start();
    компилируется нормально.

    0
    • Даже не знаю, что сказать. У меня компилируется нормально.
      Сообщение ‘timerInterupt’ was not declared in this scope означает, что переменная или функция не объявлены. Попробуйте изменить имя функции обработчика прерывания. Может при копировании что-то у Вас портится. Напишите имя функции заново.
      Не понятно, почему у Вас в сообщении timerInterupt с одной буквой r. Проверьте внимательно. В программе везде timerInterrupt.

      0
  10. Всё получилось.
    Проект по умолчанию сохранялся в папке документы, путь к которой содержал русские буквы.
    Сохранил в корень диска С папка «12345» и компиляция прошла успешно.
    Спасибо за внимание к начинающим.

    0
  11. Здравствуйте! У меня не отображается цифра ноль на лед индикации с общим анодом, а другие все цифры отображаются. Собирал на индикации с общим катодом все нормально отображается. Подскажите, пожалуйста с чем это может быть связано?

    0
    • А что отображается вместо 0? Цифра 0 не отображается в любом месте? У меня все индикаторы с общим анодом. Наверное, аппаратная ошибка.

      0
      • У меня не отображается ноль при переходе с плюсовой температуры на минусовую и обратно. Пример: +3, +2, +1, , -1, -2. Т.е. вообще не загарается индикация. А для цифр +10, +20, -10, -20 и.т. д. нули нормально загараются.

        0
        • А еще точнее. Должно выводиться 0.2 а выводится _._, т.е. только точка? И только для индикаторов с общим анодом?

          0
  12. Подскажите пожалуйста, при компиляции выдает ошибку на библиотеку Led4Digits:
    This report would have more information with
    «Show verbose output during compilation»
    enabled in File > Preferences.
    Arduino: 1.0.6 (Windows XP), Board: «Arduino Uno»
    In file included from Led4Digits.cpp:12:
    Led4Digits.h:40: error: a brace-enclosed initializer is not allowed here before ‘{‘ token
    Led4Digits.h:57: error: ISO C++ forbids initialization of member ‘_segCod’
    Led4Digits.h:57: error: making ‘_segCod’ static
    Led4Digits.h:57: error: invalid in-class initialization of static data member of non-integral type ‘const byte [16]’
    Led4Digits.cpp: In member function ‘void Led4Digits::tetradToSegCod(byte, byte)’:
    Led4Digits.cpp:88: error: ‘_segCod’ was not declared in this scope
    Что делать?

    0
    • Даже не знаю. Впервые такое случилось. Попробуйте в новый пустой скетч добавьте библиотеку. Будет ошибка?

      #include
      void setup() {
      }

      void loop() {
      }

      0

  13. Открыл новый скетч , добавил библиотеку:
    #include
    void setup(){}
    void loop(){}
    Выдал ошибку:
    This report would have more information with
    «Show verbose output during compilation»
    enabled in File > Preferences.
    Arduino: 1.0.6 (Windows XP), Board: «Arduino Uno»
    In file included from sketch_jan05a.ino:3:
    C:\Program Files\arduino-1.0.6\libraries\Led4Digits/Led4Digits.h:40: error: a brace-enclosed initializer is not allowed here before ‘{‘ token
    C:\Program Files\arduino-1.0.6\libraries\Led4Digits/Led4Digits.h:57: error: ISO C++ forbids initialization of member ‘_segCod’
    C:\Program Files\arduino-1.0.6\libraries\Led4Digits/Led4Digits.h:57: error: making ‘_segCod’ static
    C:\Program Files\arduino-1.0.6\libraries\Led4Digits/Led4Digits.h:57: error: invalid in-class initialization of static data member of non-integral type ‘const int [16]’
    Может у меня ARDUINO IDE 1.0.6 -как бы под устарела?

    0
  14. Обновил IDE до 1.6.13, скомпилировал скетч .Теперь другая ошибка:
    Arduino: 1.6.13 (Windows XP), Плата:»Arduino/Genuino Uno»

    C:\Documents and Settings\Олег\РњРѕРё документы\Arduino\РјРѕРё sketch\led_4digits\led_4digits.ino: In function ‘void setup()’:

    led_4digits:20: error: ‘timerInterrupt’ was not declared in this scope

    exit status 1
    ‘timerInterrupt’ was not declared in this scope

    Этот отчёт будет иметь больше информации с
    включенной опцией Файл -> Настройки ->
    «Показать подробный вывод во время компиляции»

    0
    • Такая ошибка у кого-то была. Если я правильно помню, то он разместил скетч программы в папке названной русскими символами. Проверьте, что название всех каталогов только латинскими символами.

      0
  15. Убрал «русские» папки и все равно ошибка:

    Arduino: 1.6.13 (Windows XP), Плата:»Arduino/Genuino Uno»

    libraries\Led4Digits\Led4Digits.cpp.o (symbol from plugin): In function `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’:

    (.text+0x0): multiple definition of `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’

    sketch\Led4Digits.cpp.o (symbol from plugin):(.text+0x0): first defined here

    libraries\Led4Digits\Led4Digits.cpp.o (symbol from plugin): In function `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’:

    (.text+0x0): multiple definition of `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’

    sketch\Led4Digits.cpp.o (symbol from plugin):(.text+0x0): first defined here

    libraries\Led4Digits\Led4Digits.cpp.o (symbol from plugin): In function `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’:

    (.text+0x0): multiple definition of `Led4Digits::regen()’

    sketch\Led4Digits.cpp.o (symbol from plugin):(.text+0x0): first defined here

    libraries\Led4Digits\Led4Digits.cpp.o (symbol from plugin): In function `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’:

    (.text+0x0): multiple definition of `Led4Digits::tetradToSegCod(unsigned char, unsigned char)’

    sketch\Led4Digits.cpp.o (symbol from plugin):(.text+0x0): first defined here

    libraries\Led4Digits\Led4Digits.cpp.o (symbol from plugin): In function `Led4Digits::Led4Digits(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)’:

    (.text+0x0): multiple definition of `Led4Digits::print(unsigned int, unsigned char, unsigned char)’

    sketch\Led4Digits.cpp.o (symbol from plugin):(.text+0x0): first defined here

    collect2.exe: error: ld returned 1 exit status

    exit status 1
    Ошибка компиляции для платы Arduino/Genuino Uno.

    Уже мозг кипит.

    0
    • Какая-то грубая ошибка. Попробуйте заново. Удалите библиотеку. Убедитесь, что она исчезла из списка в Arduino IDE. В папке с проектами создайте папку libraries. Скопируйте туда папку Led4Digits с файлами библиотеки. Запустите Arduino IDE, убедитесь, что библиотека появилась в списке. Затем в новый пустой файл включите библиотеку через Arduino IDE и скомпилируйте. У всех работает. Попробуйте с другой библиотекой, например, LedDigitsKeys.h

      0
  16. Эдуард, точка и значения после запятой выводятся именно цифра ноль не выводятся, пример: .2, .4,- .5. У меня подозрение на датчик температуры, а чтоб проверить пока нет запасной. Хотя на индикации с общим катодом работало все идеально. Буду разбираться.

    0
    • Так программа и должна работать. Там установлен признак гашения не знащащих нулей. Посмотрите в уроке 20.
      •blank – признак гашения незначащих разрядов. blank=0 означает, что число должно отображаться со всеми нулями. Число ”7” будет выглядеть “0007”. При blank, отличном от 0 незначащие нули будут гаситься.
      Можете отключить гашение
      disp.print((int)(temperature * 10.), 4, 0);

      Но, тогда температура будет отображаться в виде 00.2

      0
  17. Эдуард, Благодарю за помощь!
    Все сделал, работает так, как я хотел. А кому интересно (для начинающих!):
    if (temperature >= 0) {
    // температура положительная
    disp.digit[3]= 0x00; // гасим знак минус
    disp.print((int)(temperature * 10.), 3, 0);
    if (temperature — 10)
    {disp.digit[2]= 0x00; // гасим ненужные
    disp.print((int)(temperature * — 1 * 10.), 2, 0); // разряды
    }
    }

    disp.digit[0] = 0x63; // отображаем знак градуса

    Здесь гасятся не нужные разряды и не будет отображаться типа 09, 08, … -03, -05. И вместо цифр после запятой будет отображаться знак градуса.

    0
  18. В предыдущей почему- то не правильно отобразилось программа, еще раз пробую отправить
    if (temperature >= 0) {
    // температура положительная
    disp.digit[3]= 0x00;
    disp.print((int)(temperature * 10.), 3, 0);
    if (temperature — 10)
    {disp.digit[2]= 0x00;
    disp.print((int)(temperature * — 1 * 10.), 2, 0);
    }
    }
    //disp.digit[1] |= 0x80; // зажечь точку второго разряда
    disp.digit[0] = 0x63; // отображаем знак градуса

    0
  19. Здесь тоже вырезалось часть текста программы из середины. Но, думаю кому интересно разберутся.

    0
  20. Эдуард, по Вашему совету сделал следующее:
    1. удалил библиотеку;
    2.создал папку «libraries» в папке «may sketch», распаковал туда «Led4Digits.rar», но она нигде не появилась;
    3.удалил «libraries» из «may sketch»;
    4.добавил библиотеку «Led4Digits.h» как обычно, она появилась в основной «libraries»;
    5.открыл пустой скетч, подключил библиотеку «Led4Digits.h» , скомпилировал— о чудо , все получилось.
    6. «на радостях» компилирую полный скетч—- ошибка:
    Arduino: 1.6.13 (Windows XP), Плата:»Arduino/Genuino Uno»

    collect2.exe: error: ld returned 5 exit status

    exit status 1
    Ошибка компиляции для платы Arduino/Genuino Uno.

    Этот отчёт будет иметь больше информации с
    включенной опцией Файл -> Настройки ->
    «Показать подробный вывод во время компиляции»
    Взрыв мозга!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    0
    • Олег, а у вас Windows XP?
      В интернете полно обсуждения этой ошибки. Наберите в поисковом запросе Яндекса: ардуино collect2.exe error ld returned 5 exit status.

      0
  21. Да, Windows XP. «Погуглил» : предлагали поменять файл LD на на такой же, но из старой версии ( у меня осталась 1.0.6). Ничего не вышло. Снёс версию 1.6.13. У меня был архив версии 1.6.1 (в прошлом году скачал , а почему не установил — не помню).
    Установил 1.6.1 подсунул файл LD, и вуаля—все срослось .
    Эдуард спасибо что удили время.

    0
  22. Здравствуйте, Эдуард.
    Обращаюсь к вам как с специалисту, так как в микроэлектронике соображаю снова и всего пару дней.
    Год назад я сделал температурный контроль теплиц в шестью датчиками DS18B20 и общей длиной провода в 235 метров. Плата Arduino UNO через библиотеки Даллас и 1-wire исправно выдавала температуры всех датчиков на экран компьютера.
    Ртутные градусники , установленные физически в этих же местах теплиц подтверждали реальное отсутствие погрешностей и система ни разу не дала сбой.
    К сожалению, я почти позабыл, как именно я это сделал и почему система работала целый год, пока меня не попросили наворотить её побогаче, да пожирнее…
    Добавив ещё пару таких же датчиков и метров 5 точно такого же провода (кспвг 4х0,2) система работала ещё пару дней на восьми датчиках пока я не добавил в плату двух релейный блок повесив его по доброте душевной на тот же пин питания 5в платы Arduino UNO, на котором висит вся сеть…
    Короче, плата начала видеть верхние сектора подпространства, призраков, фей и попросила звонить «03».
    Я вкратце опишу схему сети до потустороннего вмешательства:
    К каждому датчику DS18S20 во влагозащищённом корпусе на конце провода длиной около метра (на этом проводе датчик продаётся) припаяно сопротивление 4,7 К, которое находится в непосредственной близости к месту подсоединения к линии обычными колодками под отвёртку.
    Сеть собрана по схеме «Карусель».
    Длина первой линии с одним датчиком на конце до точки слияния со второй линией — 30 метров. Длина второй линии до точки слияния с первой — 85 метров. Дальше 5 метров вместе до точки слияния с третьей линией.
    На второй линии стоят два датчика. Один на конце, второй в 40 метрах от конца
    На третьей линии длиной 120м, стоят три датчика. До ближайшего 50м, до следующего 80 и конечный.
    Чтобы схема «Карусель» заработала, необходимо запитать плату не только от USB, но и от внешнего источника и ни в коем случае нельзя ставить сопротивление рядом с платой Arduino UNO.
    Ближайшее подтягивающее сопротивление 4,7К находится на расстоянии 35 метров!
    В моём случае для дополнительного питания платы используется трансформатор 5В на 100 мА.
    Сеть начинается одним проводом кспвг 4х0,2 (во всей сети из него используются только три отдельных жилы), затем разделена физически сначала на две линии (если мы «идём» от платы) с примерно одинаковым «весом» для уравновешивания.
    В моём случае это 120 метров против 115-ти.
    Линия в 120 метров не будет работать без линии в 115 метров, так как она «тащит» вольтаж, необходимый для того, чтобы параллельная «река» тока, после развилки, достигла самого дальнего датчика.
    В свою очередь, линия в 115 метров так же оснащена «корягой» в виде ближайшего к плате датчика, который подтягивает вольтаж первым в сети сопротивлением, находящимся на расстоянии 35 метров от платы.
    Расстояния до девайсов линии с «корягой» такие: (35м+45м/85м)
    У третьей, «простой» линии: (50м/80м/120м)
    Понимаю, как «страшно» всё это звучит на языке чайника Гарри, но поверьте, я вычитал как «ЭТО» сделать именно в интернете и помню, что для схемы «Бурлаки на линии» советовалось выбрать провод именно сечением 0,2 а не 0,5 мм кв.
    Я понимаю, что увеличив количество датчиков до восьми, нужно было бы перепаять сопротивления на поменьше, но я не смог найти следов Творца, научившего меня фокусам. 🙁
    Дело в том, что сейчас заказчик попросил меня не только добавить два датчика, но и переставить имена датчиков на экране компьютера и, по ходу, подсоединить три сирены, которые бы будили кочегара, где бы он не прилёг поспать.
    Но мне уже не до сирены…
    Вот этот скетч (из-за того, что он больше предыдущего) уже забирает питание с платы на питание самой платы на время обработки более сложной задачи и напряжение на концах сети еле-еле хватает:
    [quote]
    #include 
    #include 

    #define ONE_WIRE_BUS 10
    #define TEMPERATURE_PRECISION 9

    [color=#CC6600]OneWire[/color] oneWire(ONE_WIRE_BUS);

    [color=#CC6600]DallasTemperature[/color] sensors(&oneWire);
      
    [color=#CC6600]DeviceAddress[/color] Thermometer1 = {
      0x28, 0xA3, 0xF0, 0xA8, 0x04, 0x00, 0x00, 0x96 };
    [color=#CC6600]DeviceAddress[/color] Thermometer2 = {
      0x28, 0x74, 0x31, 0x55, 0x05, 0x00, 0x00, 0x7F };
    [color=#CC6600]DeviceAddress[/color] Thermometer3 = {
      0x28, 0xBE, 0xD6, 0x67, 0x05, 0x00, 0x00, 0xEB };
    [color=#CC6600]DeviceAddress[/color] Thermometer4 = {
      0x28, 0x63, 0x6C, 0x55, 0x05, 0x00, 0x00, 0xD8 };
    [color=#CC6600]DeviceAddress[/color] Thermometer5 = {
      0x28, 0x11, 0x8A, 0x54, 0x05, 0x00, 0x00, 0xE7 };
    [color=#CC6600]DeviceAddress[/color] Thermometer6 = {
      0x28, 0xE2, 0x58, 0x54, 0x05, 0x00, 0x00, 0x11 };
    [color=#CC6600]DeviceAddress[/color] Thermometer7 = {
      0x28, 0xEF, 0x1A, 0x55, 0x05, 0x00, 0x00, 0xBE };
    [color=#CC6600]DeviceAddress[/color] Thermometer8 = {
      0x28, 0x44, 0xFF, 0x5A, 0x05, 0x00, 0x00, 0x88 };

    [color=#CC6600]void[/color] [color=#CC6600][b]setup[/b][/color]()
    {
      sensors.[color=#CC6600]begin[/color]();
      
      sensors.[color=#CC6600]setResolution[/color](Thermometer1, 10);
      sensors.[color=#CC6600]setResolution[/color](Thermometer2, 10);
      sensors.[color=#CC6600]setResolution[/color](Thermometer3, 10);
      sensors.[color=#CC6600]setResolution[/color](Thermometer4, 10);
      sensors.[color=#CC6600]setResolution[/color](Thermometer5, 10);
      sensors.[color=#CC6600]setResolution[/color](Thermometer6, 10);
      sensors.[color=#CC6600]setResolution[/color](Thermometer7, 10);
      sensors.[color=#CC6600]setResolution[/color](Thermometer8, 10);
      
      [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]begin[/color](9600);
    }
     
    [color=#CC6600]void[/color] printTemperature([color=#CC6600]DeviceAddress[/color] deviceAddress) {
      [color=#CC6600]float[/color] tempC = sensors.[color=#CC6600]getTempC[/color](deviceAddress);
      [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color](tempC);
    }
    [color=#CC6600]void[/color] [color=#CC6600][b]loop[/b][/color]() {
     
      sensors.[color=#CC6600]requestTemperatures[/color]();
      [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]»Sens1 «[/color]);
      printTemperature(Thermometer1); 
      [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]»Sens2 «[/color]);
      printTemperature(Thermometer2);    
      [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]»Sens3 «[/color]);
      printTemperature(Thermometer3); 
      [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]»Sens4 «[/color]);
      printTemperature(Thermometer4);   
      [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]»Sens5 «[/color]);
      printTemperature(Thermometer5);
      [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]»Sens6 «[/color]);
      printTemperature(Thermometer6);  
      [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]»Big «[/color]);
      printTemperature(Thermometer7);
      [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]»Small «[/color]);
      printTemperature(Thermometer8);
    }
     

    [/quote]
    После замены погибшей платы и записи нового скетча систему приходится запускать в следующем порядке:
    1. Подключаем плату в USB порт компьютера.
    2. Запускаем программу Arduino 1.0.6 \\плата тут же начинает опрос датчиков, но ей не хватает силёнок.
    3. Включаем внешнее питание на плату. \\спустя несколько секунд монитор порта начинает выдавать цифры.
    А мне нужно дописать ещё и скетч на релюшки и подключить их…
    Не могли бы Вы подсказать:
    -Как вычислить сопротивление, которое нужно перепаять на каждом датчике, чтобы питание до датчиков доходило легче?
    До вмешательства был не важен порядок включения, контроль температуры вёлся платой постоянно от включенного в сеть транса, а USB разъём, готовый к включению в комп, валялся на столе.

    0
    • Станислав, здравствуйте!
      Может Вы откроете тему на форуме сайта и скопируете туда ваш вопрос. Там есть раздел форума датчики температуры.
      Во первых проще будет обсуждать.
      Во вторых кто-нибудь поделится своим опытом.
      Если по каким-либо причинам Вы не желаете общаться на форуме, то сообщите мне. Я напишу ответ на сайте.

      0
      • Эдуард, спасибо за отзывчивость. К сожалению у меня не постоянный доступ к интернету для общения на форуме. Приблизительный ответ я уже нашёл «здесь» http://microkontroller.ru/praktikum-mikrokontrollershhika/datchik-temperaturyi-ds18b20-podklyuchenie-programmirovanie/ : «Сопротивление может быть от 5,1 до 1 кОм». Придётся паять два варианта, на 1 кОм или на 2,2… Так будет быстрее, чем толочь воду в ступе.

        0
    • Станислав!
      Думаю у вас проблема с питанием.
      Попробуйте подключить параллельно к реле по диоду.

      0
    • а нафига козе баян?
      Насколько я понимаю, при использовании библиотеки DallasTemperature, не нужно проверять ответ. Тревога срабатывает на обрыв любого из проводов благодаря функции hasAlarm (куда и включено в том числе и отсутствие ответа от датчика)
      В реальности всё работает отлично )))
      Мне пришлось запитать отдельно положительные провода сети на датчики от блока питания 5В 500мА и соединить минус от блока питания и с сетью и с пином GRD arduino uno.
      Вот рабочий скетч, при котором сирена срабатывает и на отсутствие сигнала от одного их датчиков и на вытаскивание вручную из пина МК любого из трёх проводов идущих к датчикам

      #include
      #include

      #define ONE_WIRE_BUS 10
      #define TEMPERATURE_PRECISION 9

      OneWire oneWire(ONE_WIRE_BUS);

      DallasTemperature sensors(&oneWire);

      DeviceAddress Thermometer1 = {
      0x28, 0xA3, 0xF0, 0xA8, 0x04, 0x00, 0x00, 0x96 };
      DeviceAddress Thermometer2 = {
      0x28, 0x74, 0x31, 0x55, 0x05, 0x00, 0x00, 0x7F };
      DeviceAddress Thermometer3 = {
      0x28, 0xBE, 0xD6, 0x67, 0x05, 0x00, 0x00, 0xEB };
      DeviceAddress Thermometer4 = {
      0x28, 0x63, 0x6C, 0x55, 0x05, 0x00, 0x00, 0xD8 };
      DeviceAddress Thermometer5 = {
      0x28, 0x11, 0x8A, 0x54, 0x05, 0x00, 0x00, 0xE7 };
      DeviceAddress Thermometer6 = {
      0x28, 0xE2, 0x58, 0x54, 0x05, 0x00, 0x00, 0x11 };
      DeviceAddress Thermometer7 = {
      0x28, 0xEF, 0x1A, 0x55, 0x05, 0x00, 0x00, 0xBE };
      DeviceAddress Thermometer8 = {
      0x28, 0x44, 0xFF, 0x5A, 0x05, 0x00, 0x00, 0x88 };
      float tempC;

      void setup(void)
      {
      char alarmTemp;
      Serial.begin(9600);
      sensors.begin();

      Serial.println(«Setting alarm temps…»);
      sensors.setHighAlarmTemp(Thermometer1, 25);
      sensors.setLowAlarmTemp(Thermometer1, -2);
      sensors.setHighAlarmTemp(Thermometer2, 25);
      sensors.setLowAlarmTemp(Thermometer2, -2);
      sensors.setHighAlarmTemp(Thermometer3, 25);
      sensors.setLowAlarmTemp(Thermometer3, -2);
      sensors.setHighAlarmTemp(Thermometer4, 25);
      sensors.setLowAlarmTemp(Thermometer4, -2);
      sensors.setHighAlarmTemp(Thermometer5, 25);
      sensors.setLowAlarmTemp(Thermometer5, -2);
      sensors.setHighAlarmTemp(Thermometer6, 25);
      sensors.setLowAlarmTemp(Thermometer6, -2);
      sensors.setHighAlarmTemp(Thermometer7, 95);
      sensors.setLowAlarmTemp(Thermometer7, -50);
      sensors.setHighAlarmTemp(Thermometer8, 95);
      sensors.setLowAlarmTemp(Thermometer8, -50);
      alarmTemp = sensors.getHighAlarmTemp(Thermometer1);
      Serial.print(«High Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getLowAlarmTemp(Thermometer1);
      Serial.print(«Low Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getHighAlarmTemp(Thermometer2);
      Serial.print(«High Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getLowAlarmTemp(Thermometer2);
      Serial.print(«Low Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getHighAlarmTemp(Thermometer3);
      Serial.print(«High Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getLowAlarmTemp(Thermometer3);
      Serial.print(«Low Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getHighAlarmTemp(Thermometer4);
      Serial.print(«High Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getLowAlarmTemp(Thermometer4);
      Serial.print(«Low Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getHighAlarmTemp(Thermometer5);
      Serial.print(«High Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getLowAlarmTemp(Thermometer5);
      Serial.print(«Low Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getHighAlarmTemp(Thermometer6);
      Serial.print(«High Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getLowAlarmTemp(Thermometer6);
      Serial.print(«Low Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getHighAlarmTemp(Thermometer7);
      Serial.print(«High Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getLowAlarmTemp(Thermometer7);
      Serial.print(«Low Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getHighAlarmTemp(Thermometer8);
      Serial.print(«High Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      alarmTemp = sensors.getLowAlarmTemp(Thermometer8);
      Serial.print(«Low Alarm is set to «);
      Serial.print(alarmTemp, DEC);
      Serial.println(» C»);
      }

      void CheckAlarm(DeviceAddress fThermometer){
      if (sensors.hasAlarm (fThermometer))
      {
      Serial.println(«—————-Alarm—————«);
      pinMode(4, OUTPUT);
      digitalWrite(4, LOW); // turn the rele on
      delay(1000); // wait for a second
      digitalWrite(4, HIGH); // turn the rele off
      delay(1000);
      }
      }

      void loop(void)
      {
      sensors.requestTemperaturesByAddress(Thermometer1);
      Serial.print(«Big Teplitsa «);
      Serial.println(sensors.getTempC(Thermometer1));
      CheckAlarm(Thermometer1);

      sensors.requestTemperaturesByAddress(Thermometer2);
      Serial.print(«New Naves «);
      Serial.println(sensors.getTempC(Thermometer2));
      CheckAlarm(Thermometer2);

      sensors.requestTemperaturesByAddress(Thermometer3);
      Serial.print(«Low New Naves «);
      Serial.println(sensors.getTempC(Thermometer3));
      CheckAlarm(Thermometer3);

      sensors.requestTemperaturesByAddress(Thermometer4);
      Serial.print(«Metall «);
      Serial.println(sensors.getTempC(Thermometer4));
      CheckAlarm(Thermometer4);

      sensors.requestTemperaturesByAddress(Thermometer5);
      Serial.print(«Old Naves «);
      Serial.println(sensors.getTempC(Thermometer5));
      CheckAlarm(Thermometer5);

      sensors.requestTemperaturesByAddress(Thermometer6);
      Serial.print(«Carnation «);
      Serial.println(sensors.getTempC(Thermometer6));
      CheckAlarm(Thermometer6);

      sensors.requestTemperaturesByAddress(Thermometer7);
      Serial.print(«Small Kotel «);
      Serial.println(sensors.getTempC(Thermometer7));
      CheckAlarm(Thermometer7);

      sensors.requestTemperaturesByAddress(Thermometer8);
      Serial.print(«Big Kotel «);
      Serial.println(sensors.getTempC(Thermometer8));
      CheckAlarm(Thermometer8);
      Serial.println(» «);
      Serial.println(» «);
      }

      Единственный косяк… 🙁
      При выключении света или открытии монитора порта происходит автоматическая перезагрузка arduino, которая зависает от сигналов, идущих с датчиков, висящих на отдельном питании и ардуинка не воспринимает команду с компьютера до тех пор, пока не «мигнёшь» отдельным питанием.
      Пришлось сделать отдельный выключатель для того, чтобы производить запуск системы.
      Клиент морщиться… )))
      Но это уже другая проблема )))

      0
  23. Почему-то при копировании скетча поле добавления библиотек получилось пустым…
    #include
    #include

    0
    • блин, туплю… тревога срабатывает на вытаскивание любого из ДВУХ проводов, идущих к датчикам. (я же запитал датчики отдельно, но и до этого проверял работу, когда были подключены три провода к ардуино без доппитания) если длина проводов не была бы четверть километра, то не понадобилось бы отдельного питания.
      В данный момент питание контроллера и сирен идёт от бесперебойника, а питание сети датчиков от электросети.
      Сделано это для того, чтобы при исчезновении питания в городской электросети функция hasAlarm смогла обнаружить отсутствие сигнала от датчиков и подать сигнал тревоги, обозначающий не обрыв провода, а отключение света.

      0
  24. Здравствуйте.
    В sketch с задержкой 0,9с данный считываются сразу:
    sensDs.read_bytes(bufData, 9); // чтение памяти датчика, 9 байтов.
    Во втором с прерываниями 9 байт считываются побайтно через 2мс, это связано с низкой скоростью передачи?

    0
    • Здравствуйте! Во втором скетче чтение датчика реализовано параллельным процессом. Время между чтением байтов предназначено для выполнения программы основного процесса в цикле loop. Обработка прерывания не должна на долго задерживать выполнение программы.

      0
  25. Эдуард, Ваши уроки помогли разобраться мне во многих непонятных момента, но кое-что озадачило.
    Поставлена задача, для реализации которой необходимо 4 датчика DS18B20 (температура в помещении, на улице, и температура воды на выходе котла и в обратке). Повесил датчики на 1 шину и стал обращаться к ним по адресам.
    Из статьи «Время выполнения функций библиотеки OneWire» у меня получилось:
    — инициализация измерений 2135мкс,
    — время чтения данных с ОДНОГО датчика 3565мкс.
    Так же из Вашей статьи по времени выполнения некоторых функций библиотеки LiquidCrystal.h (напр. ispl.clear(); и displ.home();) составляет 2280мкс.
    Я так понимаю было бы логично время по таймеру обработки прерываний в 2 мс увеличить, например, до 4 мс, как считаете?

    0
    • Возможно. Все зависит от структуры программы. Обратите внимание, что программа измерения времени выполнения программных блоков правильно измеряет время до 4 мс.

      0
    • извиняюсь, сильно ошибся со временем:
      инициализация — 2133мкс
      обращение к конкретному датчику — 5253мкс
      чтение сразу всех 9 байт данных — 5022мкс

      0
  26. здравствуйте. скажите почему выходит ошибка.
    Arduino: 1.8.3 Hourly Build 2017/05/23 05:33 (Windows 10), Плата:»Arduino/Genuino Uno»

    F:\АРДУИНО\arduino-nightly\arduino-builder -dump-prefs -logger=machine -hardware F:\АРДУИНО\arduino-nightly\hardware -tools F:\АРДУИНО\arduino-nightly\tools-builder -tools F:\АРДУИНО\arduino-nightly\hardware\tools\avr -built-in-libraries F:\АРДУИНО\arduino-nightly\libraries -libraries C:\Users\саша\Documents\Arduino\libraries -fqbn=arduino:avr:uno -ide-version=10803 -build-path C:\Users\7E6B~1\AppData\Local\Temp\arduino_build_706345 -warnings=more -build-cache C:\Users\7E6B~1\AppData\Local\Temp\arduino_cache_464322 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=F:\АРДУИНО\arduino-nightly\hardware\tools\avr -prefs=runtime.tools.avrdude.path=F:\АРДУИНО\arduino-nightly\hardware\tools\avr -prefs=runtime.tools.arduinoOTA.path=F:\АРДУИНО\arduino-nightly\hardware\tools\avr -verbose C:\Users\7E6B~1\AppData\Local\Temp\arduino_modified_sketch_760195\sketch_may25f.ino
    flag provided but not defined: -build-cache
    Usage of F:\АРДУР?РќРћ\arduino-nightly\arduino-builder:
    -build-options-file string
    Instead of specifying —hardware, —tools etc every time, you can load all such options from a file
    -build-path string
    build path
    -built-in-libraries value
    Specify a built-in ‘libraries’ folder. These are low priority libraries. Can be added multiple times for specifying multiple built-in ‘libraries’ folders
    -compile
    compiles the given sketch
    -core-api-version string
    version of core APIs (used to populate ARDUINO #define) (default «10600»)
    -debug-level int
    Turns on debugging messages. The higher, the chattier (default 5)
    -dump-prefs
    dumps build properties used when compiling
    -fqbn string
    fully qualified board name
    -hardware value
    Specify a ‘hardware’ folder. Can be added multiple times for specifying multiple ‘hardware’ folders
    -ide-version string
    [deprecated] use ‘core-api-version’ instead (default «10600»)
    -libraries value
    Specify a ‘libraries’ folder. Can be added multiple times for specifying multiple ‘libraries’ folders
    -logger string
    Sets type of logger. Available values are ‘human’, ‘machine’ (default «human»)
    -prefs value
    Specify a custom preference. Can be added multiple times for specifying multiple custom preferences
    -preprocess
    preprocess the given sketch
    -quiet
    if ‘true’ doesn’t print any warnings or progress or whatever
    -tools value
    Specify a ‘tools’ folder. Can be added multiple times for specifying multiple ‘tools’ folders
    -verbose
    if ‘true’ prints lots of stuff
    -version
    prints version and exits
    -vid-pid string
    specify to use vid/pid specific build properties, as defined in boards.txt
    -warnings string
    Sets warnings level. Available values are ‘none’, ‘default’, ‘more’ and ‘all’
    F:\АРДУИНО\arduino-nightly\arduino-builder возвратил 2

    Ошибка компиляции для платы Arduino/Genuino Uno.

    0
  27. http://arduino-ua.com/art24-vintajnii-barometr решил совместить с Вашим проектом
    // термометр, датчик DS18B20
    #include
    #include
    #include

    #include //Библиотека для датчика давления
    #define POWER_MODE 0 // режим питания, 0 — внешнее, 1 — паразитное
    #define MEASURE_PERIOD 500 // время измерения, * 2 мс
    Adafruit_BMP085 press_data; //переменная для работы с датчиком

    byte mA = 3;
    float Pmm; //для хранения показаний давления
    // тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
    Led4Digits disp(1, 5,4,16,2, 6,7,8,9,10,11,12,13);

    OneWire sensDs (15); // датчик подключен к выводу 14

    int timeCount; // счетчик времени измерения
    boolean flagSensReady; // признак готовности данных с датчика
    byte bufData[9]; // буфер данных
    float temperature; // измеренная температурания

    void setup()

    {
    MsTimer2::set(2, timerInterrupt); // задаем период прерывания по таймеру 2 мс
    MsTimer2::start(); // разрешаем прерывание по таймеру
    Serial.begin(9600); //инициализируем последовательный порт

    press_data.begin(); //подключаемся к датчику

    press_data.begin();

    pinMode(mA, OUTPUT);

    }

    void loop(){

    {

    Pmm=press_data.readPressure()/133.322; //читаем и пересчитываем давление

    //выводим в порт

    Serial.print(» P= «);

    Serial.println(Pmm);

    delay(1000); //ждем 1 секунду

    Pmm=map(Pmm, 700, 800, 0, 255);

    analogWrite(mA, Pmm);

    }
    {

    if ( flagSensReady == true ) {
    flagSensReady= false;
    // данные готовы

    if ( OneWire::crc8(bufData, 8) == bufData[8] ) { // проверка CRC
    // данные правильные
    temperature= (float)((int)bufData[0] | (((int)bufData[1]) <= 0) {
    // температура положительная
    disp.print((int)(temperature * 10.), 4, 1);
    }
    else {
    // температура отрицательная
    disp.print((int)(temperature * -1 * 10.), 3, 1);
    disp.digit[3]= 0x40; // отображается минус
    }
    disp.digit[1] |= 0x80; // зажечь точку второго разряда

    // передача температуры на компьютер
    Serial.println(temperature);
    }
    else {
    // ошибка CRC, отображается —-
    disp.digit[0]= 0x40;
    disp.digit[1]= 0x40;
    disp.digit[2]= 0x40;
    disp.digit[3]= 0x40;
    }
    }
    }
    }
    //————————————— обработчик прерывания 2 мс
    void timerInterrupt() {
    disp.regen(); // регенерация индикатора

    // управление датчиком DS18B20 паралллельным процессом
    timeCount++; if ( timeCount >= MEASURE_PERIOD ) { timeCount=0; flagSensReady=true; }

    if (timeCount == 0) sensDs.reset(); // сброс шины
    if (timeCount == 1) sensDs.write(0xCC, POWER_MODE); // пропуск ROM
    if (timeCount == 2) sensDs.write(0x44, POWER_MODE); // инициализация измерения

    if (timeCount == 480) sensDs.reset(); // сброс шины
    if (timeCount == 481) sensDs.write(0xCC, POWER_MODE); // пропуск ROM
    if (timeCount == 482) sensDs.write(0xBE, POWER_MODE); // команда чтения памяти датчика

    if (timeCount == 483 ) bufData[0]= sensDs.read(); // чтение памяти датчика
    if (timeCount == 484 ) bufData[1]= sensDs.read(); // чтение памяти датчика
    if (timeCount == 485 ) bufData[2]= sensDs.read(); // чтение памяти датчика
    if (timeCount == 486 ) bufData[3]= sensDs.read(); // чтение памяти датчика
    if (timeCount == 487 ) bufData[4]= sensDs.read(); // чтение памяти датчика
    if (timeCount == 488 ) bufData[5]= sensDs.read(); // чтение памяти датчика
    if (timeCount == 489 ) bufData[6]= sensDs.read(); // чтение памяти датчика
    if (timeCount == 490 ) bufData[7]= sensDs.read(); // чтение памяти датчика
    if (timeCount == 491 ) bufData[8]= sensDs.read(); // чтение памяти датчика
    }
    Барометр не работает. Может подскажете выход. Мой второй проект на ардуино. Спасибо.

    0
    • Здравствуйте!
      Такие объемные вопросы лучше обсуждать на форуме сайта, просто удобнее.
      Что касается отладки программы. Я бы посоветовал следующее.
      Определить, что мешает нормальной работе барометра. Убрать из программы обработку датчика температуры, затем индикатор и прерывание. Скорее всего нормальная работа функции press_data.readPressure нарушается довольно длинными вызовами функций чтения DS18B20.
      Если это так, то надо изменить структуру программы. В прерывании от таймера оставить только регенерацию LED индикаторов. А в основном цикле выполнять синхронно запуск измерения DS18B20, затем чтение барометра, пауза для завершения преобразования DS18B20 и чтение DS18B20.
      Сделать это можно асинхронно по отношению к прерываниям (с помощью delay) или синхронно, как это сделано в контроллере элемента Пельтье (урок 38). Начните с простого варианта.

      0
  28. Доброго дня. Решить повторить данный урок и столкнулся с проблемой. у меня макетка с Атмегай 16, кварц 16М, все как по схеме у УНО/НАНО. залит через УСБАСП загрузчик ардуино. заливаю скетч. ничего не происходит. выношу функцию disp.regen(); в loop() — тогда начинают показываться данные с датчика. Не работает функция таймера. через Ардуино ИДЕ обновил версию библиотеки MsTimer2. теперь при компиляции ругается на :
    Arduino\libraries\MsTimer2\MsTimer2.cpp:149:2: error: #error Unsupported CPU type
    куда копать чтоб заработал вызов функции по таймеру.
    аналогичная ошибка с библиотекой FlexiTimer2,

    0
    • Здравствуйте!
      Я не знаю. Покопайте в интернете. Попробуйте использовать для прерываний по таймеру библиотеку TimerOne.h. Она описывается в уроке 29.

      0
  29. Посибо, буду пробовать! пока сделал так:

    void setup() {
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    }

    SIGNAL(TIMER0_COMPA_vect) {disp.regen();}
    Отлично работает.

    0
  30. Добрый день!
    Наткнулся на Ваш урок. Все в порядке, компилируется, работает.
    Только не совсем понятна эта строка:
    temperature= (float)((int)bufData[0] | (((int)bufData[1]) << 8)) * 0.0625 + 0.03125;

    В даташите на датчик температуры нет ничего про эти + 0.03125, они точно лишние!
    И еще момент. Данная строка преобразования справедлива только если датчик настроен на 12 битное разрешение и Ваш код не проверяет текущие настройки датчика.

    0
    • Здравствуйте!
      В принципе + 0.03125 особого значения в данном случае не имеет. Это округление, прибавление половины младшего значащего разряда.
      На счет конфигурации датчика вы правы. Я показал самый простой вариант работы с датчиком. При другой разрешающей способности все будет работать, только точность измерения будет хуже.

      0
      • Здравствуйте!
        Эти + 0.03125 как раз имеют значение и влияют на итоговый результат. У вас в описании есть таблица соответствия температуры и hex. И если подставить hex коды в вашу программу, то значения температуры будут отличаться от табличных. Отличаться как раз на эти + 0.03125

        0
        • Здравствуйте!
          Представьте, что вы водите целую часть чисел 9,2 и 9,9. Понятно, что в первом случае вы должны отображать 9, в во втором 10. Но если вы выводите формально, без округления, то в обоих случаях будет 9. Принцип округления — прибавление половины младшего значащего разряда. В приведенном мною примере это +0,5. Получается 9,7 и 10,4, и при формальном выводе 9 и 10.

          0
  31. Здравствуйте! интересует информация о возможности подключения этого датчика к Arduino m0 (ATSAMD21G18). библиотеку OneWire она не поддерживает. как можно обойти данную ситуацию?

    0
  32. Эдуард, здравствуйте! Есть три датчика в 2-х проводном варианте. Подключаю к ардуино про мини 328 5v. Два работают, третий уже нет. Насколько я понимаю, третьему не хватает питания. Подскажите, пожалуйста, можно ли решить вопрос с подключением без замены датчиков на трехпроводные?

    0
  33. Эдуард, подскажите плиз, почему во втором варианте программы ( с параллельным процессом) нужно считывать каждый байт отдельно? Почему нельзя было как в первом варианте —
    sensDs.read_bytes(bufData, 9); // чтение памяти датчика, 9 байтов
    ?

    0
    • Здравствуйте!
      Чтение данных блоком занимает больше времени и подвешивает программу в обработчике прерывания. Смысл в том, чтобы длительную операцию чтения данных размазать во времени и выполнить незаметно для основной программы.

      0
  34. А понятно, спасибо за пояснение. А такой вопрос — не могли бы вы сделать урок как использовать несколько этих датчиков с адресацией. Я правильно понимаю что их можно несколько штук повесить на одну линию? И логично было бы наверное при этом использовать паразитное питание. Задачка выглядит интересной и весьма не простой…

    0
    • Здравствуйте!
      Я представил самый простой способ чтения датчика. Уроки только начинались. Я подумаю. Если будет время, то попробую сделать это.

      0
  35. Здравствуйте!

    У меня выражение

    temperature= (float)((int)bufData[0] | (((int)bufData[1]) << 8))

    корректно работает только при положительной температуре, при отрицательной переменная temperature содержит число 4xxx, такое ощущение что инвертирование происходит неверно.

    0
      • Приветствую!

        такая конструкция тоже не работает, а вот из примеров к библиотеки OneWire работает с отрицательной температурой верно

        int16_t raw = ((bufData[1] << 8) | bufData[0]) ;
        temperature = (float) raw * 0.0625 + + 0.03125;

        0
      • Приветствую!

        В итоге методом тыка, нашёл вариант работающей конструкции работающей с отрицательной температурой

        temperature = (int16_t)(bufData[0] | (bufData[1] << 8)) * 0.0625

        Видимо, просто (int) не переводит дополнительный код в прямой, а (int16_t) это делает.

        И без (float) работает корректно, не знаю правильно ли это и зачем использовать (float) в данном случае, ведь точность после запятой не нужна, там итак целое число после преобразования. Я прав?

        Одного я не могу понять, элемент массива bufData[] byte = 8 bit при сдвиге влево должно быть "0000 0000", почему получается "1111 1111 0000 0000", при сдвиге без разницы в каком типе переменной происходит сдвиг и разрядность увеличивается по необходимости?

        0
        • Так…сам себе отвечу по поводу (float) перед выражением.

          Если в выражение множители будут все целочисленные, то хоть переменная будет иметь тип float результат будет целочисленный

          float i = 13 / 2; i будет равняться 6

          Если в выражении хоть один из множителей будет float то и результат будет float

          float i = 13 / 2.0; i будет равняться 6,5

          так вот (float) гарантированно делает явное преобразование переменной в тип с плавающей запятой и тогда результат будет float

          На пальцах:

          temperature = (int16_t)(bufData[0] | (bufData[1] << 8)) / 16; // делить на 16 это тоже самое что умножать на 0.0625

          Результат будет целое число, точнее будет отсечена дробная часть хоть переменная temperature имеет тип float

          А вот если преобразовать хоть одну переменную во float:

          temperature = (float)(int16_t)(bufData[0] | (bufData[1] << 8)) / 16;

          или

          temperature = (int16_t)(bufData[0] | (bufData[1] << 8)) / (float) 16

          то результат получим float с дробной частью.

          ещё в каком-то из Си есть правило int * float = int поэтому Эдуард как опытный программист привёл все переменные к одному типу.

          Осталось разобраться со сдвигом 🙂

          0
          • Здравствуйте!
            Скорее корректный вариант следующий:
            temperature= ((float)((int)((unsigned int)bufData[0] | (((unsigned int)bufData[1]) < < 8)))) * 0.0625 + 0.03125; Но я на отрицательных температурах не проверял.

            0
  36. Приветствую. Это код написан для Uno. Подскажите, этот код должен работать без корректировки для Nano типа плат ? Схема собрана как в уроке.

    0
    • Здравствуйте!
      Да, конечно. Все должно работать на Nano.
      Там ошибка с вычислением отрицательных температур. Посмотрите в самом конце комментариев. Я не успел заменить в скетче.

      0
  37. Эдуард! ДД! В формуле вычисления температуры добавляется половина младшего разряда (temperature= (float)((int)bufData[0] | (((int)bufData[1]) << 8)) * 0.0625 + 0.03125;). В половине источников это так, в другой опущено. Просьба поясните.

    0
    • Здравствуйте!
      Это округление. Т.е. прибавление половины незначащего разряда.
      Представьте себе измеритель, который измеряет с дискретностью одна десятая, а отображает с дискретностью единицы. И он выводит значение просто отбрасывая дробные. Допустим он измерил 5,8, отбросил дробную часть и получилось 5. А если прибавить половину незначащего разряда, то будет 5,8 + 0,5 = 6,3. Выводится 6. Что ближе к измеренному значению? При измеренном 5,4 будет 5,4 + 0, 5 = 5,9, отображается 5.

      0
  38. AlxNovo и Эдуарду. Противооблединительная система. Температура скачет вокруг нуля. Греющий кабель и утеплитель. Большая опасность возгорания. Решил, что нужна фильтрация температуры до регулятора. Те суммировать N измерений в 16-ти разрядном виде,
    (int)bufData[0] | (((int)bufData[1]) << 8), (а затем разделить на N).
    Но почитав посты AlxNovo, понял что вылезут подводные камни из-за доп.вида отрицательных тем-р. А система живет около нуля, А это значит часть в прямом коде , часть в дополнительном.
    AlxNovo Вы уже прочувствовали эту проблему, подскажите пути решения. (достаточно будет в фильтре суммировать после этого Вашего преобразования:
    (int16_t)(bufData[0] | (bufData[1] << 8) ?)
    С уважением

    0
    • Здравствуйте!
      Думаю, получить значение температуры правильнее будет так
      (int16_t)((uint16_t)bufData[0] | ((uint16_t)bufData[1] < < 8)) Можно суммировать значения температуры в беззнаковом формате (uint16_t), а потом преобразовать в знаковый. Числа представленные в дополнительном коде вычтутся автоматически.

      0
  39. Кстати вариант Эдуарда, то же прекрасно работает.
    temperature= ((float)((int)((unsigned int)bufData[0] | (((unsigned int)bufData[1]) < < 8)))) * 0.0625 + 0.03125;

    0
  40. temperature= (float)((int)bufData[0] | (((int)bufData[1]) << 8)) * 0.0625 + 0.03125;
    Эдуард, здравствуйте!
    Зачем нужна корректировка + 0.03125 в размере половины веса самого младшего разряда?

    0
      • Я так понял, что такая корректировка должна учитывать особенности вывода на дисплей, ну, или дальнейшей работы с полученным значением, и округляться должна по известному правилу, 0.5 и выше — в большую сторону, меньше 0.5 — в меньшую сторону. Каким образом округляется результат в DS18B20 — не ясно, вещь-то очень умная, и скорее всего округляет она в нужную сторону. То есть выдаёт результат в виде, максимально приближенном к реальной величине температуры. Вносить корректировку в показания прибора, наверное, неправильно.

        0

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Нажимая кнопку "Отправить" Вы даёте свое согласие на обработку введенной персональной информации в соответствии с Федеральным Законом №152-ФЗ от 27.07.2006 "О персональных данных".