3 датчика DS18B20+Arduino

memfise
Offline
Зарегистрирован: 30.06.2012

 Здравствуйте. У меня такой вопрос (прошу прощения если вопрос уже звучал на данном форуме, но, к сожалению, я не нашел на него ответа...):
- итак, имеется сама arduino, 3 датчика температуры DS18B20 (подключены параллельно). Температуру я с них вытаскиваю нормально, а вот конкретно с 1 или со 2 по запросу не могу узнать как это реализовать. Знаю что необходимо отправить запрос SEARCH ROM, но куда в коде это вставить? Вариант со считыванием адресов по одному и записью их в скетч не подходит. Код прилагаю.

#include <OneWire.h>

OneWire ds (10); // все OneWire устройства на pin 10
int led_pin=13; // определили pin 13 для светодиода
byte done[8];

void setup  (void) {
  Serial.begin  (9600);
  pinMode(led_pin, OUTPUT);
}

void loop (void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;

  if  (ds.search  (addr)!=1) {
    ds.reset_search  ();
    delay  (250);
    return;
  }
  ds.reset  ();
  ds.select  (addr);

  //Serial.print  ((addr)[8]);
  //Serial.print  (" ");

  ds.write  (0x44,1); // start conversion, with parasite power on at the end

  delay  (1000); // maybe 750ms is enough, maybe not
  // we might do a ds.depower  () here, but the reset will take care of it.

  present = ds.reset  ();
  ds.select  (addr);
  ds.write  (0xBE); // Read Scratchpad

  for  (i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read ();
  }

  // convert the data to actual temperature
  unsigned int raw =  (data[1] << 8) | data[0];
  if  (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if  (data[7] == 0x10) {
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } 
  else {
    byte cfg =  (data[4] & 0x60);
    if  (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms
    else if  (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if  (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
  }

  celsius =  (float)raw / 16.0;
  //Serial.print  ("Temperature = ");
  Serial.println  (celsius);
  //Serial.print  (" ");
  Serial.flush(); //очищаем значения порта
}

 

memfise
Offline
Зарегистрирован: 30.06.2012

 Небольшое уточнение: все датчики подключены как уже сказано параллельно к 10 pin arduino для экономии. Позже планирую подключить 2х датчик DH11. С количеством пока не определился. Сейчас задача сводиться к тому, чтобы при выводе температуры отображалась информация типа: температура1 - 25.02 температура2 - 28.05 ....и т.д.

leshak
Offline
Зарегистрирован: 29.09.2011

 >если вопрос уже звучал на данном форуме

Вы правы - звучал. http://arduino.ru/forum/programmirovanie/onewire-vyvesti-adres-dlya-dalneishego-dlya-pryamoi-indeksatsii

Но и ваш скетч должен работать. Собственно говоря строчка 20 - что как ни поиск следующего девайса на шине? Сами же сказали "нужен search". ну дык это он и есть :)  (вообщем при каждом проходе loop, оно должно следующий датчик смотреть, если больше не нашло - опять начинать с первого).

memfise
Offline
Зарегистрирован: 30.06.2012

  мой скетч работает, он показывает температуру со всех датчиков, при необходимости выводит все адреса, но не может определить и вывести температуру с определенного. Спасибо за пример, его я еще не видел, но в нем по-моему (не так давно занимаюсь программированием МК) другой алгоритм поиска, который я пока не понимаю.

leshak
Offline
Зарегистрирован: 29.09.2011

 >другой алгоритм поиска, который я пока не понимаю.

Нет. Там другая библиотека. Вернее "еще одна". Специально для этих датчиков температур. Но внутри себя они использует ту же самую OneWire библиотеку. Это просто удобная обертка над OneWire для данного конкретного случая (ну что-бы не нужно было помнить коды комманд и т.п.).  Так что "механизм работы" у этих примеров - один и тот же. 

OneWire - универсальная. С ее помощью можно работать с любым устройсвом (вкиснув в его даташит), а DallasTemperatureControl - частный случай  для DS18B20

>необходимости выводит все адреса

> вывести температуру с определенного

Я, видимо, не совсем понимаю в чем проблема. Что вы понимаете под "определенный"? 

По идее каждый адресс и позволяет обращатся к определенному датчику. Это есть его "определение".

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

memfise
Offline
Зарегистрирован: 30.06.2012

для данной системы датчиков разработан (пока минимальный функционал) сайт с базой данных. Счиитывая температуру, как сейчас (т.е. температура валиться подряд неизвестно от какого из датчиков) проблема состоит в том, что при записи температуры в БД нельзя определить откуда она взята, а в моем алгоритме (взят с какогото примера) нет возможности: посчитать датчии, определить сколько их на шине (актуально при увеличении их количества). Вместе с тем я хочу реализовать запро-ответ....например хочу узнать температуру 2 или 3 датчика, но пока не соображу как это сделать. Приведенный вами пример, к сожалению, у меня не работает, а ответа в интернете я, пока, нигде не нахожу. Буду признателен за помощь, для меня алгоритм (библиотека не принципаальна)

leshak
Offline
Зарегистрирован: 29.09.2011

 >что при записи температуры в БД нельзя определить откуда она взята

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

Насколько я понимаю закоменченные строки 28,29  и была попытка сделать это. Правда корявая. Скорее нужно что-типа

Serial.println("----------");
Serial.print("Addr:");
for(byte i=0;i<8;i++)Serial.print(addr[i],HEX);
Serial.println();

>нет возможности: посчитать датчии, определить сколько их на шине

Почему нет возможности? Что мешает setup() вызвать  что-то типа while(ds.search (addr) )sensorCounter++

Загляните в файлик OneWire.h, почитайте что делают и что возвращают функции. В частности функция search

// Look for the next device. Returns 1 if a new address has been
    // returned. A zero might mean that the bus is shorted, there are
    // no devices, or you have already retrieved all of them.  It
    // might be a good idea to check the CRC to make sure you didn't
    // get garbage.  The order is deterministic. You will always get
    // the same devices in the same order.
    uint8_t search(uint8_t *newAddr); 

> Приведенный вами пример, к сожалению, у меня не работает,

Ну видимо сожаление не слишком большое, раз попыток решить проблему не предпринимается.

>а ответа в интернете я, пока, нигде не нахожу

Ну так "точного решения" вашей задачи вы и не найдете. Есть, конечно, вероятность что кто-то делал что-то "в точности то же что и вы", но шансы такое найти... . Реализовывать свою логику "запрос-ответ" прийдется самому. В инете нет скетчей на все случая жизни :) 

А "в общем" в инете (и в примерах/документации) все описанно. Как опрашивать датчики, как работать с serail портом. А вот "как соеденить" все это - это уже забота автора скетча. Если с этим большие проблемы, то может стоит какую-нибудь книжечку по программированию почитать (или хотя-бы раздел http://arduino.ru/Reference прочитать/освоится). Потому, несмотря на маркетинг, для исползования арудуины "немного программинга" все равно нужно освобить (хотя бы разобратся с переменными, и управляющими операторами).

 

memfise
Offline
Зарегистрирован: 30.06.2012

 видими придется и адрес датчика определять.

>Насколько я понимаю закоменченные строки 28,29 и была попытка сделать это. Правда корявая. Скорее нужно что-типа

это  остатки кода в котром пробовал считать количество устройств. За предложенный вариант благодарен, но он у меня есть (я пока его убрал).

uint8_t OneWire::search(uint8_t *newAddr)
 данная функция, как я смог понять ищет новые устройства на шине (команда 0xf0), если находит то возвращает 1 и адрес устройства. 

посчитать количество устройств можно так (взято из библиотеки DallasTemperature):

  Serial.print(sensors.getDeviceCount(), DEC);

 

 

prometheus
Offline
Зарегистрирован: 31.05.2011

Скачайте библиотеку DallasTemperature

И далее получение температуры с конкретного датчика выглядит так:

tempS1 = sensors.getTempC(sensor_1);
tempS2 = sensors.getTempC(sensor_2);
tempS3 = sensors.getTempC(sensor_3);

где DeviceAddress sensor_1, sensor_2, sensor_3;

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

memfise
Offline
Зарегистрирован: 30.06.2012

 спасибо, кое что уже получилось с использованием данной библиотеки.

YuraSh
Offline
Зарегистрирован: 18.01.2013

Простите за нубский вопрос. При использовании библиотеки DallasTemperature как нумеруются датчики? Самый ближний будет первый, дальше второй и т.д. Или надо как то самому привязывать номер датчика к индивидуальному 64 адресу датчика? Тогда как это лучше сделать физически. Подключать по одному и запоминать/записывать их адрес???

memfise
Offline
Зарегистрирован: 30.06.2012

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

YuraSh
Offline
Зарегистрирован: 18.01.2013

Значит пишем простой скетч, который считывает адрес датчика. По очереди подключаем по одному датчики, читаем их адреса, как то их помечаем (???). Впаиваем так как нам надо в шину, прописываем в рабочем скетче какому дачику какой номер присвоить и только тогда наслаждаемся работой. Я правильно понял???

Муторненько получается. А датчиков будет более 20.

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

YuraSh пишет:

По очереди подключаем по одному датчики, читаем их адреса, как то их помечаем (???).

Зачем так сложно? :) Монтируем датчики, включаем в скетче опрос с выводом в сериал-консоль  номера и температуры и по очереди греем датчик  так, чтобы его данные отличались от соседних... Для 20 датчиков - 20 минут с подходом и отходом от каждого датчика.

Borland
Offline
Зарегистрирован: 17.05.2012

Думал об этом.

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

 

YuraSh
Offline
Зарегистрирован: 18.01.2013

Поделитесь! Плиззз! И желательно более детально!

Borland
Offline
Зарегистрирован: 17.05.2012

я по мере сил и времени пытаюсь сделать чтото вроде кситала

Сигнализация + управление температурой в доме , плюс поставил себе задачу чтобы была возможность установить и прописать все датчики без использования монитора: 4 кнопки 7 диодов

 

Смысл в следующем

В сетапе:

В озу формируется структура для термометров аналогичная эпромовской Thermometer

typedef struct {
int Valid;
DeviceAddress Address;
char Type;    // 4 types of Devices
              //  B - Simple, Inside the Body only for statistics and report
	      //  S - Simple, Ordinary only for statistics and report
	      //  R - Full Rele controled with High Low limits
              //  O - Can be Overrided with sms command R1111 from phone;
float Temp;
int LowLimit;
int HighLimit;
unsigned char ReleNumber;
float CurrentTemp;
} Term;
Так же она хранится ( или на начальном этапе не хранится в эпроме) 

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

код буквально такой

  numberOfsensors=sensors.getDeviceCount();
  CleanTempSensors();
 for(i=0,k=0;i<numberOfsensors;i++) {
   digitalWrite(GREEN1,HIGH); 
   if (!sensors.getAddress(Addr, i)) SayOkISee(3,RED4);    
   j=SearchEprom(Addr); 
   TotalSensors=Parameters.SensorsWritten+k;
   if(j--) GetDeviceFromEprom(j,&Thermometer[j]);
   else {
      SayOkISee(4,RED4); // Sensor not found in Eprom
      Serial.print("Sensor not Found in Eprom");
      memcpy(Thermometer[Parameters.SensorsWritten+k].Address,Addr,sizeof(Addr));
      Thermometer[Parameters.SensorsWritten+k].Type='D';
      Thermometer[Parameters.SensorsWritten+k].Valid=0x55AA;
      k++;
      
      //Thermometer(CountEpromSensors();
   }
 крявенький, планирую улучшить но тарахтит

в результате получается  в озу получается структура заполненая из eprom, каждый рекорд  определяется полем Valid

если 55ff то все отлично датчик есть

теперь в loop на кнопке ( ну в режиме супервизора естественно и прочее) есть функция

SetupSensors

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

  CleanTempSensors();
// Clean all devices;
  while (numberOfsensors!=1 ) {
      if (digitalRead(BUT4)) return;
      sensors.begin();
      numberOfsensors=sensors.getDeviceCount();
        for(i=0;i<numberOfsensors;i++) {
           digitalWrite(GREEN1+i,HIGH); 
           delay(100);
           digitalWrite(GREEN1+i,LOW);
         }
  }

тоесть она в начале требует отключить все датчики кроме корпусного

потом на его пишет в эпром

 Serial.print (" Adding Shell Device");
  Thermometer[0].Valid=0x55AA;
  Thermometer[0].Type='B';
  Thermometer[0].LowLimit=-20;
  Thermometer[0].HighLimit=+35;
  AddDeviceToEprom(0,&Thermometer[0]);
 Serial.print("Addres from Body Sensor:");
  PrintAddress(Thermometer[0].Address);
  Parameters.SensorsWritten=1;
  AddSystemParameters(&Parameters);

Последняя строка - количество записаных датчиков

Потом идет цикл, функция требует либо добавить датчик, либо нажать кнопку ESC

она достаточна громоздка, в связи с устаноками для датчиков лимитов температур и прочего но если интерес то кину.

смысл в том что в цикле опрашивается количество текущих датчиков и при добавлении нового в онлайне

определяется его адрес и в случае если такого нет в текущем рекорде структуры Thermometr ОЗУ( Он может быть гдето ниже в структуре, но раз он попался скажем вторым в этой функции)  то  структура Thermometr заполняется на один рекорд. и пишется в эпром

датчик становится с адресом и с номером рекорда структуры

пришлось это делать изза двух причин:

1) при добавлении нового датчика он просто не всегда становится последним

2) Не хотелось хардкодить адрес корпусного датчика - вдруг сгорит

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

У тебя есть только номер датчика и присущие ему свойства (корпусной,релейный, статистический и тд)

и дальше ты уже знаешь какой конкретно у тебя датчик за что отвечает

У кситала в корпусе стоит DHT11 , они этим не стали заморачиваться :)

 

 

Borland
Offline
Зарегистрирован: 17.05.2012

Была мысль сделать как советует Andrey_Y_Ostanov , все было бы проще, но тогда нужен хотябы экран, или Уповать на то что ты сделал самый горячий датчик (Зажигалкой?) Летом датчик может нагрется до 60 на солнце.

YuraSh
Offline
Зарегистрирован: 18.01.2013

А если не заморачиваться и каждый датчик прицепить на отдельный пин? (Заказал мегу, там пинов хватит, правда кабелей будет поболее). Или там тоже надо будет обращаться по адресу?

leshak
Offline
Зарегистрирован: 29.09.2011

Десятки кабелей только затем что-бы не выяснять у кого какой адресс?

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

Можно даже не в кноечную систему, а звять дуину отдельную и к ней подключить/посмотреть. Сделать себе как-бы "тестер проверялку адреса".

Да и сами датчики можно изначально не припаивать, а какой-то разъем предусмотреть (тем более все-ко бывает, может потребуется замена в будущем). Вынул датчик, подключил его к "тестовому оборудованию" - посмотрел адресс.

Или можно "инвертировать". Вначале все подключить, получить полный список адресов, а потом отключать по одному и смотреть "какой адресс исчез".

YuraSh
Offline
Зарегистрирован: 18.01.2013

Но есть и плюс. При замене датчика не надо менять прошивку. А кабеля у меня ну максимум 3м, а многие и того меньше.

kristow
kristow аватар
Offline
Зарегистрирован: 08.08.2013

leshak пишет:

Serial.println("----------");
Serial.print("Addr:");
for(byte i=0;i<8;i++)Serial.print(addr[i],HEX);
Serial.println();

Подскажите пожалуйста, как присвоить переменной то что выдает Serial.print(addr[i],HEX)?

Пробовал вот так:

 

for(byte i=0;i<8;i++)Serial.print(addr[i],HEX);
adress = (addr[i],HEX)
Serial.println();

У меня тоже подключено несколько датчиков, я хочу по адресу датчика распределять ответы...

if (adress == '28190C040074') {
    Serial.print  ("Temperature №1 = ");
    Serial.println  (celsius);
  }
  if (adress == '28564C04003A') {
    Serial.print  ("Temperature №2 = ");
    Serial.println  (celsius);
  }

 

 

maksim
Offline
Зарегистрирован: 12.02.2012

addr[] это и есть переменная, а точнее массив переменных, почитайте массив (array).

kristow
kristow аватар
Offline
Зарегистрирован: 08.08.2013

Спасибо, я это читал...

Как создавать массив я знаю, я не пойму почему не получается присвоить переменной adress полученный массив, который выводится в COM порт.

Если не сложно подскажите синтаксис...

пробовал и вот так:

for(byte i=0;i<8;i++)adress=(addr[i],HEX);
Serial.print(adress);
Serial.println();

 

 

maksim
Offline
Зарегистрирован: 12.02.2012

Потому что у вас address не является массивом это раз и два нельзя просто так присвоить массив массиву. Почему нельзя в один пустой стакан налить 8 стаканов воды?
И почему нельзя одной рукой разом перелить 8 стаканов с водой в 8 пустых стаканов? 

Присвоить массив массиву можно например функцией memcpy(array_1, array_2, len).

Сравнивать массивы можно например функцией memcmp(array_1, array_2, len).

byte address_1[] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
byte address_2[] = {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};

.......
             
  if (!memcmp(address_1, addr, 8)) {
    Serial.print  ("Temperature №1 = ");
    Serial.println  (celsius);
  }
  if (!memcmp(address_2, addr, 8)) {
    Serial.print  ("Temperature №2 = ");
    Serial.println  (celsius);
  }

 

leshak
Offline
Зарегистрирован: 29.09.2011

kristow пишет:

 

пробовал и вот так:

for(byte i=0;i<8;i++)adress=(addr[i],HEX);
Serial.print(adress);
Serial.println();

 

Ну наверное, потому что нужно понять что сами переменные не имеют "системы исчисления". Цифры в переменных (и элементах массива) хранятся как "абстрактные". Представте себе коробку с яблоками. В ней лежит сколько-то яблок. Когда вас просят на бумажке написать "сколько там яблок", то это уже ваше дело, как писателя, напишите вы десятчиной цифрой 4, римской IV или двоичной B100. Ни коробка, ни яблоки от этого не изменятся. Если вам скажут "положи в ту коробку столько же яблок сколько лежит в это" (это и есть присвоение переменной) - то "римскую IV" не будете туда ложить. Вы будете ложить яблоки :)

Так и тут - переменная "коробка". В которой лежит какое значение числа, но нет инфрмации о его "формате". Это для людей. Поэтому выражение вида (addr[i],HEX) - не имеет смысла.

А вот для print - уже имеет. Это как раз "писатель". Поэтому ему важно знать "в какой системе исчисления вывести эту переменную ЧЕЛОВЕКУ".

for(byte i=0;i<8;i++)adress=addr[i];
Serial.print(adress,HEX);
Serial.println();

 

Но.... скорее все вы хотели вывести все значения массива addr, а не только последнее, поэтому вам нужно почитать {} (фигурные скобки) | Аппаратная платформа Arduino  и Оператор For | Аппаратная платформа Arduino

и правильно добавить фигурные скобки. что-бы Serial.print-ты тоже выполнялись в цикле, а не после него. Что-бы вывели каждый элемент.

kristow
kristow аватар
Offline
Зарегистрирован: 08.08.2013

Оператор for и фигурные скобки знакомы :)

Я понял что при каждом цикле for строка дописывается в COM порту Serial.print(addr[i],HEX)... Отсюда я получаю в терминале (Addr:28190C040074). Хочу вот этот полученный ответ "28190C040074" присваивать переменной, чтобы переменная имела вид: adress = '28190C040074' Возможно как-то реализовать?

Либо может есть более простой путь решения задачи? нужно читать адрес датчика, и по условию совпадения записанного адреса датчика вписывать его значения температуры...

maksim
Offline
Зарегистрирован: 12.02.2012

kristow пишет:

Либо может есть более простой путь решения задачи? нужно читать адрес датчика, и по условию совпадения записанного адреса датчика вписывать его значения температуры...

Сообщение #24 перечитайте.

leshak
Offline
Зарегистрирован: 29.09.2011

kristow пишет:

Оператор for и фигурные скобки знакомы :)

Ну либо плохо знакомы, либо.... вы ввели в заблуждение что такое у вас переменная adress? Это массив? Это одна цифра адреса?

Если это "одна цифра", то не имеет смысла Serial.print(adress), так как принт не умеет выводить массивы.

Если это "массив", то почему вы пытались делать adress=addr[i]?  То есть получали элемент массива и пытались присвоить его массиву?  Тогда уже нужно было address[i]=addr[i]. Каждый элемент копировать отдельно (либо как вам показал Максим, через memcpy копировать сразу весь массив, без всяких циклов). Вообщем явно, как советовали выше - еще раз почитать про массивы.

Вообщем

1. Вы не показали что такое adress
2. Из дальнешего кода следует что это "одна цифра адреса"
3. Из ваших слов следуют что это "адресс целиком", то есть "массив".

Так что:

a. Определитесь что же именно вам нужно
б. Все-таки еще раз перечитайте соотвествующие разделы документации, что-бы выражать кодом свою мысль, а не подбирать-угадывать "как  заработает"
в. В коде показывайте и объявления переменных. Тип переменных является очень важной инфой. Влияющией и на то как компилятор будет собирать прошивку и на самоу логику исполнения прошивки (поэтому про типы - тоже желательно почитать, что-бы в будущем не "лепить на обум", скажем int, там где хватило-бы byte").

 

kristow
kristow аватар
Offline
Зарегистрирован: 08.08.2013

Я пробовал сделать так как Вы писали "Maksim" в 24 сообщении...

Но условие не сработало... Поэтому и пытаюсь решить другими путями...

Может я не верно прописал переменные? В терминале я получаю адреса датчиков в виде: 28190C040074 и 28564C04003A.

я создал переменные вот такие: 

byte  address_1[] = {0x28, 0x19, 0x0C, 0x04, 0x00, 0x74};
byte  address_2[] = {0x28, 0x56, 0x4C, 0x04, 0x00, 0x3A};

if (!memcmp(address_1, addr, 8)) {
    // 28190C040074
    Serial.print  ("Temperature №1 = ");
    Serial.println  (celsius);
  }
  if (!memcmp(address_2, addr, 8)) {
    // 28564C04003A
    Serial.print  ("Temperature №2 = ");
    Serial.println  (celsius);
  }

Но не работает...

 

maksim
Offline
Зарегистрирован: 12.02.2012

Не работает, потому что вы что не так делаете.

leshak
Offline
Зарегистрирован: 29.09.2011

>Но не работает...

А какая у вас длина (размер) address_1 и adress_2? И addr?

А сколько байт вы сравниваете функцией memcmp?

Функция memcmp - вглядываемся в третий параметр.

maksim
Offline
Зарегистрирован: 12.02.2012

Кстати, да. У меня массивы в примерах какой длинны??? А у вас?

И с какого вдруг 64-битный номер датчика у вас поместился в 6-ти байтах???

leshak
Offline
Зарегистрирован: 29.09.2011

maksim пишет:

Не работает, потому что вы что не так делаете.

Перевод: не предполагайте наличие телепатов. ваш монитор никто не видит. старайтесь описывать "как именно не работает" (можно еще добавлять и "что ожидали" - тут тоже не всегда очевидно).

maksim
Offline
Зарегистрирован: 12.02.2012

Номер для начала по нормальному прочитайте

  for(byte i = 0; i < 8; i++)
  {
    Serial.print("0x");
    if(addr[i] < 0x10) Serial.print("0");
    Serial.print(addr[i], HEX);
    if(i == 7) Serial.println();
    else Serial.print(", ");
  }

Прямо из монитора копируете его.

kristow
kristow аватар
Offline
Зарегистрирован: 08.08.2013

Ясна, вот скетч:

#include <OneWire.h>
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius;
OneWire ds (10); // все OneWire устройства на pin 10
int led_pin=13; // определили pin 13 для светодиода
byte done[8];

void setup  (void) {
  Serial.begin  (9600);
  pinMode(led_pin, OUTPUT);
}

void reeds (void) {


  if  (ds.search  (addr)!=1) {
    ds.reset_search  ();
    delay  (250);
    return;
  }
  ds.reset  ();
  ds.select  (addr);

  Serial.println("----------");
  Serial.print("Addr:");
  for(byte i=0;i<8;i++)Serial.print(addr[i],HEX);
  Serial.println();

  ds.write  (0x44,1); // start conversion, with parasite power on at the end

  delay  (1000); // maybe 750ms is enough, maybe not
  // we might do a ds.depower  () here, but the reset will take care of it.

  present = ds.reset  ();
  ds.select  (addr);
  ds.write  (0xBE); // Read Scratchpad

  for  (i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read ();
  }

  // convert the data to actual temperature
  unsigned int raw =  (data[1] << 8) | data[0];
  if  (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if  (data[7] == 0x10) {
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } 
  else {
    byte cfg =  (data[4] & 0x60);
    if  (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms
    else if  (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if  (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
  }

  celsius =  (float)raw / 16.0;
  Serial.print  ("Temperature = ");
  Serial.println  (celsius);
  Serial.print  (" ");
  Serial.flush(); //очищаем значения порта
  
}

void loop (void) {
  reeds();
  if (!memcmp(address_1, addr, 6)) {
    Serial.print  ("Temperature №1 = ");
    Serial.println  (celsius);
  }
  if (!memcmp(address_2, addr, 6)) {
    Serial.print  ("Temperature №2 = ");
    Serial.println  (celsius);
  }
}

Вот логи из COM порта:

----------
Addr:28190C040074
Temperature = 28.12
 ----------
Addr:28190C040074
Temperature = 28.06
 ----------
Addr:28190C040074
Temperature = 28.12
 ----------
Addr:28190C040074
Temperature = 28.12
 ----------
Addr:28190C040074
Temperature = 28.12
 ----------
Addr:28190C040074
Temperature = 28.06
 ----------
Addr:28190C040074
Temperature = 28.06
 ----------

Хочу сделать чтобы в добавок выводилось Temperature №1 = 28.06 для датчика №1 с адресом 28190C040074

Приблизительно вот так:

----------
Addr:28190C040074
Temperature = 28.12
Temperature № 1= 28.12
 ----------
Addr:28190C040074
Temperature = 28.06
Temperature № 1= 28.06
 ----------
Addr:28190C040074
Temperature = 28.12
Temperature № 1= 28.12
 

Сейчас подключил один датчик, чтобы случайно не запутаться...

Я понял что мой массив сейчас не верно указан... Подскажите как правильно переводить...
maksim
Offline
Зарегистрирован: 12.02.2012
#include <OneWire.h>
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius;
byte  address_1[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
byte  address_2[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

OneWire ds (10); // все OneWire устройства на pin 10
int led_pin=13; // определили pin 13 для светодиода
byte done[8];

void setup() {
  Serial.begin  (9600);
  pinMode(led_pin, OUTPUT);
}

void reeds()
{
  if(ds.search(addr) != 1) 
  {
    ds.reset_search();
    delay(250);
    return;
  }
  ds.reset();
  ds.select(addr);

  Serial.println("----------");
  Serial.print("Addr: ");
  for(byte i = 0; i < 8; i++)
  {
    Serial.print("0x");
    if(addr[i] < 0x10) Serial.print("0");
    Serial.print(addr[i], HEX);
    if(i == 7) Serial.println();
    else Serial.print(", ");
  }

  ds.write(0x44, 1); // start conversion, with parasite power on at the end

  delay(1000); // maybe 750ms is enough, maybe not
  // we might do a ds.depower  () here, but the reset will take care of it.

  present = ds.reset  ();
  ds.select(addr);
  ds.write(0xBE); // Read Scratchpad

  for(i = 0; i < 9; i++) data[i] = ds.read ();

  // convert the data to actual temperature
  unsigned int raw =  (data[1] << 8) | data[0];
  if(type_s) 
  {
    raw = raw << 3; // 9 bit resolution default
    if(data[7] == 0x10) raw = (raw & 0xFFF0) + 12 - data[6];
  } 
  else 
  {
    byte cfg = data[4] & 0x60;
    if(cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms
    else if(cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if(cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
  }

  celsius = (float)raw / 16.0;
  Serial.print("Temperature = ");
  Serial.println(celsius);
  Serial.print(" ");
  Serial.flush(); //очищаем значения порта

}

void loop () 
{
  reeds();
  if (!memcmp(address_1, addr, 8)) 
  { // (address == '28190C040074')
    Serial.print  ("Temperature №1 = ");
    Serial.println  (celsius);
  }
  if (!memcmp(address_2, addr, 8)) 
  { //(address == '28564C04003A')
    Serial.print  ("Temperature №2 = ");
    Serial.println  (celsius);
  }
}

только номера поменяйте на те что прочтутся.

kristow
kristow аватар
Offline
Зарегистрирован: 08.08.2013

Спасибо Максим за пост #34.

Скопировал я адрес датчика, в логах появилась нужнаю строка! Отлично! Но не пойму почему в логе задублированы строка Temperature_1 = 27.81, хотя по коду она должна один раз прописаться при одном цикле...

----------
Addr:0x28, 0x19, 0x00, 0xC0, 0x04, 0x00, 0x00, 0x74
Temperature = 27.81
 Temperature_1 = 27.81
Temperature_1 = 27.81
----------
Addr:0x28, 0x19, 0x00, 0xC0, 0x04, 0x00, 0x00, 0x74
Temperature = 27.81
 Temperature_1 = 27.81
Temperature_1 = 27.81

 

leshak
Offline
Зарегистрирован: 29.09.2011

kristow пишет:

В терминале я получаю адреса датчиков в виде: 28190C040074 

Значит неправильно получаете :(

Поленились сделать разделители между цифрами. У вас пропали "лидирующе нули". Если код был "02 08 ...." у вас вывеслось "2 8...." (нули впереди числа не дописываются). А так как пробел межу цифрами вы не выводите, то вы увидиле "28". И все у вас "два байта" превратиль в один :(

#define ADDR_LEN 8 // длина "правильно" адреса
byte address_1[ADDR_LEN] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; // укажим длину в явном виде, что-бы компилятор ругался на ошибочный адресс
byte address_2[ADDR_LEN] = {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};

byte someAddr1[ADDR_LEN] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1};


void setup(){
  Serial.begin(9600);
  
  Serial.print("Addr1=");
  printlnAddr(address_1);
  
  Serial.print("Addr2=");
  printlnAddr(address_2);
  
  printlnAddrForCopyPaste("someAddr1",address_1);
  printlnAddrForCopyPaste("someAddr2",address_2);
  
}

void loop(){
}

void printlnAddr(byte pAddress[]){
  for(byte i=0;i<ADDR_LEN;i++){
    Serial.print(pAddress[i],HEX);
    Serial.print(i==ADDR_LEN-1?"\r\n":"-"); // выводим разделитель "-" или перевод строки для последнего числа
  }
}

void printlnAddrForCopyPaste(char* varName,byte pAddress[]){ // выводит адрес готовым для вставки в код
  Serial.print("byte "); Serial.print(varName); Serial.print("[ADDR_LEN] = {");

  for(byte i=0;i<ADDR_LEN;i++){
      Serial.print("0x");
      if(pAddress[i]<0x10)Serial.print("0"); // для малых цифр впереди ноль дописываем. чисто "для красоты".
      Serial.print(pAddress[i],HEX);
      Serial.print(i==ADDR_LEN-1?"};\r\n":", "); 
  }
}

Выводит:

 

Addr1=1-1-1-1-1-1-1-1
Addr2=2-2-2-2-2-2-2-2
byte someAddr1[ADDR_LEN] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
byte someAddr2[ADDR_LEN] = {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};

 

maksim
Offline
Зарегистрирован: 12.02.2012
void reeds()
{
  for(byte i = 0; i < 8; i++) addr[i] = 0;
  if(ds.search(addr) != 1) 
  {
    ds.reset_search();
    delay(250);
    return;
  }

Адрес надо обнулять иначе при отсутствии следующего адреса при поиске датчиков адрес остается прежним и условие выполняется повторно.

leshak
Offline
Зарегистрирован: 29.09.2011

kristow пишет:

Спасибо Максим за пост #34.

Скопировал я адрес датчика, в логах появилась нужнаю строка! Отлично! Но не пойму почему в логе задублированы строка Temperature_1 = 27.81, хотя по коду она должна один раз прописаться при одном цикле...

Возможно еще оптому что руками перенабирали текст Максима. И очепятались. У него в годе строки "Temperature_1" - вообще нет.

kristow
kristow аватар
Offline
Зарегистрирован: 08.08.2013

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

Не пойму почему так происходит? то есть при выполнении простого условия выполняется два раза его содержание...

if (!memcmp(address_1, addr, 8)) {
    // 28190C040074
    Serial.print  ("Temperature_1 = ");
    Serial.println  (celsius);
  }

Выдает в логах:

----------
Addr:0x28, 0x19, 0x00, 0xC0, 0x04, 0x00, 0x00, 0x74
Temperature = 27.75
Temperature_1 = 27.75
Temperature_1 = 27.75
----------
Addr:0x28, 0x19, 0x00, 0xC0, 0x04, 0x00, 0x00, 0x74
Temperature = 27.75
Temperature_1 = 27.75
Temperature_1 = 27.75

Пробовал вставить delay, ничего не изменилось...

Код для поиска ошибок:

#include <OneWire.h>
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius;
byte  address_1[] = {0x28, 0x19, 0x00, 0xC0, 0x04, 0x00, 0x00, 0x74};
byte  address_2[] = {0x28, 0x56, 0x4C, 0x04, 0x00, 0x3A};


OneWire ds (10); // все OneWire устройства на pin 10
int led_pin=13; // определили pin 13 для светодиода
byte done[8];

void setup  (void) {
  Serial.begin  (9600);
  pinMode(led_pin, OUTPUT);
}

void reeds (void) {


  if  (ds.search  (addr)!=1) {
    ds.reset_search  ();
    delay  (250);
    return;
  }
  ds.reset  ();
  ds.select  (addr);

  Serial.println("----------");
  Serial.print("Addr:");
  for(byte i = 0; i < 8; i++)
{
  Serial.print("0x");
  if(addr[i] < 0x10) Serial.print("0");
  Serial.print(addr[i], HEX);
  if(i == 7) Serial.println();
  else Serial.print(", ");
}

  ds.write  (0x44,1); // start conversion, with parasite power on at the end

  delay  (1000); // maybe 750ms is enough, maybe not
  // we might do a ds.depower  () here, but the reset will take care of it.

  present = ds.reset  ();
  ds.select  (addr);
  ds.write  (0xBE); // Read Scratchpad

  for  (i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read ();
  }

  // convert the data to actual temperature
  unsigned int raw =  (data[1] << 8) | data[0];
  if  (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if  (data[7] == 0x10) {
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } 
  else {
    byte cfg =  (data[4] & 0x60);
    if  (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms
    else if  (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if  (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
  }

  celsius =  (float)raw / 16.0;
  Serial.print  ("Temperature = ");
  Serial.println  (celsius);
  Serial.flush(); //очищаем значения порта
  
}

void loop (void) {
  reeds();
  if (!memcmp(address_1, addr, 8)) {
    // 28190C040074
    Serial.print  ("Temperature_1 = ");
    Serial.println  (celsius);
  }
  if (!memcmp(address_2, addr, 8)) {
    // 28564C04003A
    Serial.print  ("Temperature_2 = ");
    Serial.println  (celsius);
  }
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

kristow пишет:

 

if (!memcmp(address_1, addr, 8)) {
    // 28190C040074
    Serial.print  ("Temperature_1 = ");
    Serial.println  (celsius);
  }

 

Опять "кусок кода", который показался вам важным... проблема-то может быть и ниже :) Что у вас там в print написанно во втором условии?

kristow
kristow аватар
Offline
Зарегистрирован: 08.08.2013

Для поиска ошибок подключил второй датчик, и странно то что по второму датчику дублирования нет...

Вот логи из COM порта:

----------
Addr:0x28, 0x19, 0x00, 0xC0, 0x04, 0x00, 0x00, 0x74
Temperature = 30.50
Temperature_1 = 30.50
Temperature_1 = 30.50
----------
Addr:0x28, 0x56, 0x04, 0xC0, 0x04, 0x00, 0x00, 0x3A
Temperature = 32.06
Temperature_2 = 32.06
----------
Addr:0x28, 0x19, 0x00, 0xC0, 0x04, 0x00, 0x00, 0x74
Temperature = 30.69
Temperature_1 = 30.69
Temperature_1 = 30.69
----------
Addr:0x28, 0x56, 0x04, 0xC0, 0x04, 0x00, 0x00, 0x3A
Temperature = 32.06
Temperature_2 = 32.06
----------
Addr:0x28, 0x19, 0x00, 0xC0, 0x04, 0x00, 0x00, 0x74
Temperature = 30.81
Temperature_1 = 30.81
Temperature_1 = 30.81

 

maksim
Offline
Зарегистрирован: 12.02.2012

kristow пишет:

Не пойму почему так происходит? то есть при выполнении простого условия выполняется два раза его содержание...

 #39

kristow
kristow аватар
Offline
Зарегистрирован: 08.08.2013

Увидел 39 пост. добавил в код эту строку....

Ничего не изменилось... Так и осталось дублирование Температуры 1, а температура 2 не дублируется...

maksim
Offline
Зарегистрирован: 12.02.2012

А если так?

void reeds()
{
  if(ds.search(addr) != 1) 
  {   
    ds.reset_search();
    delay(250);
    for(byte i = 0; i < 8; i++) addr[i] = 0;
    return;
  }

 

leshak
Offline
Зарегистрирован: 29.09.2011

Попробуйте вот это

 for(byte i = 0; i < 8; i++) addr[i] = 0;

Вставить, между

delay  (250);
return;

 

maksim
Offline
Зарегистрирован: 12.02.2012

Почти одновременно )

kristow
kristow аватар
Offline
Зарегистрирован: 08.08.2013

Спасибо большое за супер помощь leshak и maksim!

Получил ожидаемый результат! 

EvgenKir
Offline
Зарегистрирован: 17.09.2013

У меня такой вопрос, я хочу сделать опрос по датчикам, а потом к примеру через время 5-10 секунд сделать следующий опрос. Но я никак не могу понять, в какую часть кода мне вписат ьвременную задержку для следующего опроса



#include <OneWire.h>
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius;
  byte  address_1[8] = {0x28, 0xA0, 0x21, 0x33, 0x04, 0x00, 0x00, 0x29};
  byte  address_2[8] = {0x28, 0x08, 0x22, 0x33, 0x04, 0x00, 0x00, 0x9A};
  byte  address_3[8] = {0x28, 0x29, 0x41, 0x33, 0x04, 0x00, 0x00, 0x44};
  byte  address_4[8] = {0x28, 0x05, 0x12, 0x33, 0x04, 0x00, 0x00, 0x54};


OneWire ds (30); // все OneWire устройства на pin 10
int led_pin=13; // определили pin 13 для светодиода
byte done[8];

void setup() {
  Serial.begin  (9600);
  pinMode(led_pin, OUTPUT);
}

void reeds()
{
  if(ds.search(addr) != 1) 
  {
    ds.reset_search();
    delay(250);
    for(byte i = 0; i < 8; i++) addr[i] = 0;
    return;
  }
  ds.reset();
  ds.select(addr);

  Serial.println("----------");
  Serial.print("Addr: ");
  for(byte i = 0; i < 8; i++)
  {
   Serial.print("0x");
   if(addr[i] < 0x10) Serial.print("0");
    Serial.print(addr[i], HEX);
    if(i == 7) Serial.println();
    else Serial.print(", ");
  }

  ds.write(0x44, 1); // start conversion, with parasite power on at the end

  delay(750); // maybe 750ms is enough, maybe not
  // we might do a ds.depower  () here, but the reset will take care of it.

  present = ds.reset  ();
  ds.select(addr);
  ds.write(0xBE); // Read Scratchpad

  for(i = 0; i < 9; i++) data[i] = ds.read ();

  // convert the data to actual temperature
  unsigned int raw =  (data[1] << 8) | data[0];
  if(type_s) 
  {
    raw = raw << 3; // 9 bit resolution default
    if(data[7] == 0x10) raw = (raw & 0xFFF0) + 12 - data[6];
  } 
  else 
  {
    byte cfg = data[4] & 0x60;
    if(cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms
    else if(cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if(cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
  }

  celsius = (float)raw / 16.0;
  //Serial.print("Temperature = ");
  //Serial.println(celsius);
  //Serial.print(" ");
  Serial.flush(); //очищаем значения порта

}

  void loop () 
{
  reeds();
  if (!memcmp(address_1, addr, 8)) 
  { // (address == '28190C040074')
    Serial.print  ("T1 = ");
    Serial.println  (celsius);
  }
  if (!memcmp(address_2, addr, 8)) 
  { //(address == '28564C04003A')
    Serial.print  ("T2 = ");
    Serial.println  (celsius);
  }
  if (!memcmp(address_3, addr, 8)) 
  { //(address == '28564C04003A')
    Serial.print  ("T3 = ");
    Serial.println  (celsius);
  }
  if (!memcmp(address_4, addr, 8)) 
  { //(address == '28564C04003A')
    Serial.print  ("T4 = ");
    Serial.println  (celsius);
    
  }

}