Почистил скетч примера работы с DS18B20 из библы OneWire..

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

AlexZR пишет:

упростил до минимума, наверное, работает )))

#include <OneWire.h>
OneWire ds(4);
int16_t temperature;
unsigned long lastUpdateTime;
unsigned long timing;

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

void loop() {
  if (millis() - timing > 2000) {
    timing = millis();
    detectTemperature();
    Serial.println(temperature);
  }
}

int detectTemperature() {
  byte data[2];
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);
  if (millis() - lastUpdateTime > 1500) {
    lastUpdateTime = millis();
    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);
    data[0] = ds.read();
    data[1] = ds.read();
    temperature = (data[1] << 8) + data[0]; temperature = temperature >> 4;
  }
}

не, посмотри как у деда, сначала читаем а потом сразу же запрос

Green
Offline
Зарегистрирован: 01.10.2015

DetSimen пишет:

-NMi- пишет:

Дет, црц - это заибок, а есть ли там фича, шо даччик апосля ресета или инита ответил на шину?

Столь далеко мои компетенции не простираюца. 


Вы что, прикалываетесь?) Любой обмен начинается с ресет, на который ус-во должно ответить presence. Вот и проверяйте, а не однажды при старте.)

AlexZR
Offline
Зарегистрирован: 08.02.2016

может кто подскажет, а как этот код заставить работать и в Proteus ?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexZR пишет:

может кто подскажет, а как этот код заставить работать и в Proteus ?

Чёт Вы всю тему жалуетесь на протеус, неужели до сих пор не разобрались?

Там в свойствах датчика есть временной интервал. И интервал этот не имеет никакого отношения к такому же интервалу, заданному в OneWire. Поставьте такой, как в OneWire и всё заработает.

AlexZR
Offline
Зарегистрирован: 08.02.2016

ЕвгенийП пишет:
Чёт Вы всю тему жалуетесь на протеус, неужели до сих пор не разобрались?

не жалуюсь, а всего лишь прошу совета!

Green
Offline
Зарегистрирован: 01.10.2015

А у нас уже давно не Страна Советов.)

Green
Offline
Зарегистрирован: 01.10.2015

Та что ж вы такой обидчивый! Там же смайлик.

AlexZR
Offline
Зарегистрирован: 08.02.2016

Green пишет:
Та что ж вы такой обидчивый! Там же смайлик.

извините!

Green
Offline
Зарегистрирован: 01.10.2015

Не стОит.)
Вспомнилось. Как то после очередного коммунистического субботника сидим мы в кабаке (известно же чем эти субботники заканчиваются). И тут товарищ предлагает послушать его стихи. Ну, валяй. И вдруг.
"Обрушился на наше поколение... социализм предельно развитой..." Мы сразу тише, тише, тише...)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, чё, разобрались? Заработало в протеусе?

AlexZR
Offline
Зарегистрирован: 08.02.2016

ЕвгенийП пишет:
Ну, чё, разобрались? Заработало в протеусе?

нет, пока не получается (((

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, смотрите какое время в OneWire и поставьте такое же в протеусе. Всё всегда работало.

AlexZR
Offline
Зарегистрирован: 08.02.2016

ЕвгенийП пишет:
Ну, смотрите какое время в OneWire и поставьте такое же в протеусе. Всё всегда работало.

меняю, но эффекта нет, что то не так видно делаю..

 

Green
Offline
Зарегистрирован: 01.10.2015

Там в свойствах ещё другие времена есть. Time Reset Low и пр.

AlexZR
Offline
Зарегистрирован: 08.02.2016

Green пишет:
Там в свойствах ещё другие времена есть. Time Reset Low и пр.

да, менял везде, чувствую где то какой то подвох, а где, не могу понять (((

Green
Offline
Зарегистрирован: 01.10.2015

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

AlexZR
Offline
Зарегистрирован: 08.02.2016

встал, но мне это ничего не дает )))

AlexZR
Offline
Зарегистрирован: 08.02.2016

в протеусе работает этот код, но он не работает в ESP32, ругается на библиотеку MsTimer2.h, пытался без с нее, сделать таймер на millis, не получилось (((

#include <MsTimer2.h>
#include <OneWire.h>
OneWire sensDs (2);

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

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

void setup() {
  MsTimer2::set(2, timerInterrupt); // задаем период прерывания по таймеру 2 мс
  MsTimer2::start();               // разрешаем прерывание по таймеру
  Serial.begin(57600); // инициализируем порт, скорость 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;
 
      Serial.println(temperature);   
    }
  } 
}

//--- обработчик прерывания 2 мс
void  timerInterrupt() {
  // управление датчиком 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();  // чтение памяти датчика    
}

 

Green
Offline
Зарегистрирован: 01.10.2015

На reset отвечает, обмен есть. Я бы зациклил reset и какую-нибудь SKIP_ROM. И сравнил бы времена...
Так а зачем вы тогда рабочую в Протеусе проверяете? Тоже прикалываетесь? Я пас.(

AlexZR
Offline
Зарегистрирован: 08.02.2016

Green пишет:
Так а зачем вы тогда рабочую в Протеусе проверяете? Тоже прикалываетесь? Я пас.(

это другая прошивка, не работает на esp32, а мне нужна простая прошивка, без проверок, без наворотов, температура в целых числах, но что бы она работала в ардуине, есп32 и протеусе...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вот Вам рабочие значения. С такими, вроде, работает, как видите.

b707
Offline
Зарегистрирован: 26.05.2017

AlexZR пишет:

в протеусе работает этот код, но он не работает в ESP32, ругается на библиотеку MsTimer2.h, пытался без с нее, сделать таймер на millis, не получилось (((
 

зачем весь этот ужас аж с пятнадцатью! событиями по таймеру? - вы ветку с начала не читали? - события только два - сначала запрашиваем данные, потом по миллис отмеряем 750-1000 мс и получаем температуру. ВСЕ

Код элементарнейший и работает на любом МК, где есть реализация OneWire

и вообще, последние 3 страницы - какой-то невероятный бред. Вам дали готовый код в сообщении #282. Все, что от вас требовалось - правильно вставить его в программу. Что вы тут обсуждаете пятый день?

Мне кажется, Ваша проблема в том, что Вы - а) нифига не понимаете и, к сожалению б) не хотите учиться. Вам "некогда разбираться с этим долбаным датчиком", вы хотели по-быстрому - а по факту ваш быстрый путь буксует который день.  Значительно правильнее было бы сесть и спокойно разобраться с протоколом, потратили бы один вечер и решили проблему

AlexZR
Offline
Зарегистрирован: 08.02.2016

ЕвгенийП пишет:
Вот Вам рабочие значения. С такими, вроде, работает, как видите.

все! с вашими значениями и у меня заработало! спасибо!

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

Как сделать попроще три датчика на три вывода. Код набросал, работает, но хотелось бы еще упростить.

float getTemp3() {int ii; ii = 0;  label: wdt_reset(); //Serial.println(ci);
if (ii < 6)  {   // если неудачно то делаем 6 попыток
  byte data[12];   //
  byte addr[8];
    if ( !ds3.search(addr)) {
    Serial.println F("No more addresses."); wdt_reset(); 
    //Serial.println(addr[8]);
    ds3.reset_search();
    delay(250); wdt_reset();
     ++ii; goto label;
  }

 if (OneWire::crc8(addr, 7) != addr[7]) {  //проверка массива адреса на срц
      Serial.println F("CRC is not valid!");
      ++ii; goto label; wdt_reset();
  }
  
  ds3.search(addr); // 
  ds3.reset_search();
  ds3.reset();
  ds3.select(addr);
  ds3.write(0x44);
  delay(1000); wdt_reset();
  ds3.reset();
  ds3.select(addr);
  ds3.write(0xBE);
  for (int i = 0; i < 9; i++) data[i] = ds3.read();

  if (OneWire::crc8(data, 8) != data[8]) { // проверка црц считанной температуры.
      Serial.println F("Data CRC is not valid!"); wdt_reset(); 
      ++ii; goto label;
  }
   
  int raw = (data[1] << 8) | data[0]; // Переводим в температуру
  if (data[7] == 0x10) raw = (raw & 0xFFF0) + 12 - data[6];
  return raw / 16.0; wdt_reset();
 }
}

Выше код на третий датчик, тоесть :

OneWire  ds1(15); // 15 (A1) вход датчика 18b20 один шт.
OneWire  ds2(17); // 17 (A3) вход датчика 18b20 один шт.
OneWire  ds3(18); // 18 (A4) вход датчика 18b20 один шт.

как бы извернуться, и  не три раза повторять float getTemp3()  float getTemp2()  float getTemp1()

а написать один для всех датчиков? Но именно по тому пути, который я выбрал. Код выше - полностью рабочий.

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

Чтобы указать в итоге как то так:

float getTemp(ds1)

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, добавьте в параметры функции ссылку на объект датчика, например

OneWire & ds

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

Или я чего-то не понял?

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

да, таки получилось. Спасибо  за наводку. Почитал что такое указатели и ссылки, и заработало. Оказалось еще проще чем я думал.

Теперь хочу сделать еще варинт - один пин  на десять датчиков, хранение  номера каждого датчика в епром с последовательным чтением этих номеров из епром. Но наверное не в эту тему писать.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Удалось кому-нибудь получать температуру с этого датчика (только чтение) быстрее 10 миллисекунд?

Интервал между запросами не важен

Green
Offline
Зарегистрирован: 01.10.2015

8 мс за 1 проход обычно. За несколько итого меньше.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Green пишет:

8 мс за 1 проход обычно. За несколько итого меньше.

у меня в районе 14 получается, долго, нужно как можно быстрее, лучше 1мс было бы то, что надо

Green
Offline
Зарегистрирован: 01.10.2015

Минимум 850мкс, если растянуть. Примерно так:
 

void Ds18b20Exe() {
  static uint16_t state;
  static uint16_t timer;
  static uint16_t temp;
  
  if (timer) 
    --timer;
  else
    switch (state) {
      case 0:
        if (!ds_reset())
          break;
        next(state);
        
        ds_byte(SKIP_ROM);
        next(state);
        
        ds_byte(READ_SCRATCHPAD);
        next(state);
        
        temp = ds_byte(0xff);
        next(state);
        
        temp |= ds_byte(0xff)<<8;
        temperature = ds2cels(temp);
        next(state);
        
        if (!ds_reset()) {
          state = 0;
          break;
        }
        next(state);
        
        ds_byte(SKIP_ROM);
        next(state);
        
        ds_byte(CONVERT_T);
        timer = ms2sys(CONVERTION_TIME);
        state = 0;
        break;
    }    
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

Функция Назначение Расчетное время Измеренное время
reset() Инициализация обмена 960 мкс 966 мкс
write() Запись байта 480 - 960 мкс 548 мкс
read() Чтение байта 480 - 960 мкс 522 мкс
read_bytes() Чтение блока байтов (9байтов) 4320 - 8640 мкс 4700 мкс
crc8 Вычисление контрольной суммы - 7,3 мкс

 

rkit
Offline
Зарегистрирован: 23.11.2016

Нарисуй на таймере с прерываниями. Будет меньше 1 мс процессорного времени легко.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

rkit пишет:

Нарисуй на таймере с прерываниями. Будет меньше 1 мс процессорного времени легко.

я ненастоящий сталевар

d00m
Offline
Зарегистрирован: 21.02.2013

интересный момент -  код автора из самого первого сообщения, выводит разные данные на разных MCU, если адрес термосенсора НЕ правильный, то есть на шине нет сенсора с таким адресом.

например на Arduino based - выводит  "-0.06" 

а на другом MCU - Cubecell AB01/02 на базе другого чипа - выводит "4095.94"

никак не пойму, почему так..