Скетч Arduino с огромным числом датчиков DS18B20. TEST!!!

Использование системы в различных ситуациях, вопросы программирования сценариев.

Модератор: immortal

tsember
Сообщения: 52
Зарегистрирован: Ср фев 04, 2015 12:28 am
Благодарил (а): 54 раза
Поблагодарили: 6 раз

Re: Скетч Arduino с огромным числом датчиков DS18B20. TEST!!

Сообщение tsember » Вт мар 31, 2015 7:21 pm

Lordserdjo писал(а):спасибо большое, буду изучать. Ощущаю что надо закупаться книгами по С++. С точки разбора можно понять, а что бы написать такое пока для меня и думаю для многих просто космос.
Поверьте мне на слово. Месяц назад, когда я забрал посылку с ардуино из почты, в СИ я был полный ноль. Минус даже, можно сказать. Вообще программирование у меня - только школьный курс.
Все находил в интернете.

Для себя сделал небольшой вывод:
Чтобы написать работоспособную программу, нужно в первую очередь: четко понимать, что ты хочешь, и как это можно реализовать. Представить в уме (или зарисовать) блок схему будущей программы, какой шаг за каким должен выполняться, нужно представлять результат работы. А уж только потом начинать что либо писать, и не важно, Си это или Паскаль.
Regard, Peter
tsember
Сообщения: 52
Зарегистрирован: Ср фев 04, 2015 12:28 am
Благодарил (а): 54 раза
Поблагодарили: 6 раз

Re: Скетч Arduino с огромным числом датчиков DS18B20. TEST!!

Сообщение tsember » Чт апр 02, 2015 11:12 pm

СпойлерПоказать

Код: Выделить всё


/**
* Универсальный контроллер сбора данных на базе Arduino (к проекту http://smartliving.ru/)
* Platform: Arduino UNO R3 + EthernetShield W5100
* IDE: Arduino 1.6.1
* Автор: Петр Цембер. На форуме tsember. 2015. город Сыктывкар.
**/

// ----==== ПОДКЛЮЧЕНИЕ БИБЛИОТЕК ====----
  #include <Ethernet.h>                                // (Ethernet Shield)
  #include <SPI.h>                                     // (Для работы с устройствами по протоколу SPI, например с Ethernet Shield)
  #include <Arduino.h>                                 // (Основная библиотека Arduino)
  #include <OneWire.h>                                 // (Шина 1-wire)
  #include <DallasTemperature.h>                       // (Датчик температуры DS18B20)


// ----==== НАСТРОЙКИ СЕТИ ====----
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xE4, 0xDE, 0x35 }; // MAC-адрес контроллера Arduino
  byte ip[] = { 192, 168, 1, 15 };                     // ip-адрес контроллера Arduino
  byte subnet[] = { 255, 255, 255, 0 };                // Маска подсети
  byte gateway[] = { 192, 168, 1, 250 };               // ip-адрес основного шлюза
  byte dns_server[] = { 192, 168, 1, 250 };            // ip-адрес DNS-сервера
  byte rserver[] = { 192, 168, 1, 123 };               // ip-адрес сервера MajorDoMo
  char buf[100];                                       // Переменная для хранения GET запроса
  char ipbuff[16];                                     // Переменная для IP адреса
  EthernetClient rclient;


// ----==== НАСТРОЙКИ ПОДКЛЮЧЕННЫХ УСТРОЙСТВ ====----
// Вход, на котором находится шина 1-wire с датчиками DS18S20
  #define ONE_WIRE_BUS 2                               // нога 2



// ----==== НАСТРОЙКИ ПЕРЕМЕННЫХ И МАССИВОВ ДАННЫХ ====----
  float current_temp1;                                 // Задаем переменную, в которой будем хранить текущую температуру
  float delta_temp = 0.2;                              // Дельта температур, при превышении которой следует отправлять данные на сервер МЖД
  long requestMillis;                                  // Задаем переменную времени последней передачи данных на сервер
  long interval = 18000000;                            // Задаем максимальный интервал между передачами данных на сервер
  byte numberOfDevices;                                // Количество датчиков DS18B20 на шине 1-wire (Обновляется автоматически)
  DeviceAddress Termometers;                           // Массив с датчиками
  // Размер следующих массивов - предполагаемое максимальное количество датчиков DS18B20.
  // По умолчанию - 30. Нужно больше?! Увеличиваете числа и перезаливаете скетч
  byte na[30];                                         // Массив с порядковыми номерами датчиков температуры DS18B20
  String aa[30];                                       // Массив с HEX-адресами датчиков температуры DS18B20
  float ta[30];                                        // Массив с последней отправленной температурой датчиков DS18B20


// Инициализация веб-сервера на 80 порту, а так же шины 1-wire и датчиков температуры DS18B20
  OneWire oneWire(ONE_WIRE_BUS);
  DallasTemperature sensors(&oneWire);


// ---=== ПОИСК ДАТЧИКОВ ТЕМПЕРАТУРЫ DS18B20 НА ШИНЕ 1-WIRE ===---
void TempSensorSearch()
{
  sensors.begin();                                   // Инициализация датчиков DS18B20
  sensors.requestTemperatures();                     // Перед каждым получением температуры надо ее запросить
  sensors.setResolution(Termometers, 12);            // Установка чувствительности на 12 бит 
//   Serial.print("Vsego datchikov: ");
   numberOfDevices = sensors.getDeviceCount(); 
//   Serial.println(numberOfDevices);                  // вывод на экран общего количества найденых датчиков
   
  for(byte i=0;i<numberOfDevices; i++) {            // цикл для записи в массивы данных
     if(sensors.getAddress(Termometers, i))          // если адрес датчика под индексом i определен, то:
      {        
      String aba[8];                                 // Создаем массив с байтами адреса 
       for (int i=0; i<8; i++)                        // цикл получения бит адреса
        { 
          if (Termometers[i] < 16) { aba[i] = "0"+String(Termometers[i],HEX); } //если бит меньше 16, то дописываем в начале 0, так же конвертируем в шеснадцатиричный код
          else {aba[i] = String(Termometers[i],HEX);}// в противном случае просто конвертируем в 16ричный код и записываем байт в массив
        }
      aa[i] = aba[0]+aba[1]+aba[2]+aba[3]+aba[4]+aba[5]+aba[6]+aba[7]; // Записываем полный адрес в массив адресов aa[], в ячейку i.      
//    Serial.print("Sensor "); Serial.print(i, DEC); Serial.print(" with address: "); // Датчик под номером i с адресом:
  //  Serial.println(aa[i]);                           // Выводим на экран i ячейку с 16-ричным адресом устройства  
       }
     }
}  
 
 
// ---=== ПОЛУЧЕНИЕ И ОБРАБОТКА ТЕМПЕРАТУРЫ ===---
void TempSensorSend()
{ for(byte i=0;i<numberOfDevices; i++)    {          // цикл для получения, обработки, округления и отправки температуры каждого датчика DS18B20
    int str_len = aa[i].length() + 1; char char_array[str_len]; aa[i].toCharArray(char_array, str_len);      // Конвертируем строку с адресом в массив символов
    float tempC = sensors.getTempCByIndex(i); // Получим температуру от датчика (или ошибку)
    
      // Устройство отдало реальное значение температуры (или осталось старое)
      // Округление полученной температуры до десятых
      // Пример: 23.899 => 238.99 => 239.49 => 239 => 23.9) // При округлении изменился первый разряд, после запятой. Правило работает.
       tempC = sensors.getTempCByIndex(i) * 10;
       tempC = tempC + 0.5;
       tempC = (int)tempC;
       tempC =  tempC / 10;
    float delta = fabsf(ta[i]-tempC);                // Выделяем дельту температуры, между текущей и в последний раз отправленной темп.
    if (tempC < -70) { Serial.print("Temp sensor "); Serial.print(i); Serial.println(" is disconnected");}
    else if (tempC == 0) {Serial.print("Temp sensor "); Serial.print(i); Serial.println(" is disconnected");}
    else if ((delta > delta_temp)                    // Если разница между прошлым и текущим значением темп. больше обозначенной дельты и дельта не более 70...
    || ((millis() - requestMillis) > interval))      // Если последняя передача данных на сервер была более 30 минут назад (например температура не менялась)...
     {  
     int temp1 = (tempC - (int)tempC) * 10;          // выделяем дробную часть

     sprintf(buf, "GET /objects/?object=%s&op=m&m=tempChanged&t=%0d.%d", char_array, (int)tempC, abs(temp1)); // Формируем GET запрос
      sendHTTPRequest();                             // И передаем на сервер
      requestMillis = millis();                      // Засекаем время последней передачи данных на сервер
      ta[i]=tempC;                                   // Задаем текущую температуру предыщущей.
     }
    }
}



// ---=== ФУНКЦИЯ ОТПРАВКИ ДАННЫХ (HTTP-ЗАПРОСА) НА СЕРВЕР MAJORDOMO ===---
void sendHTTPRequest() 
{ Serial.println (buf);
/*  if (rclient.connect(rserver, 80)) 
  { 
   Serial.println("OK"); 
   Serial.println(buf);                                 // Вывод на экран сгенерированного GET запроса
   rclient.print(buf);
   rclient.println(" HTTP/1.0");
   rclient.print("Host: ");
   sprintf(ipbuff, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
   rclient.println(ipbuff);                             // ip адрес нашего контроллера в текстовом виде
   rclient.print("Content-Type: text/html\n");
   rclient.println("Connection: close\n");
   \(10);
   rclient.stop();
  } else 
  { Serial.println("FAILED SENDING"); } */
}


// ---=== ФУНКЦИЯ НАСТРОЙКИ ===---
void setup()
  {
  Serial.begin(9600);                                   // Инициализируем Serial (монитор последовательного порта)
  Serial.println("Start");
  Ethernet.begin(mac, ip, dns_server, gateway, subnet); // Инициализируем Ethernet Shield/
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  }


// ---=== ЦИКЛИЧЕСКАЯ ФУНКЦИЯ ===---
void loop() {

  TempSensorSearch();
  TempSensorSend();
}

 
Немножко изменил код.
Обратно убрал проверку на отключение датчика. Объясняю. Так как поиск датчиков на шине повторяется циклически, вначале каждого цикла void loop, соответственно если датчик отключился, он просто удалится из массива с адресами датчиков. Выявить это просто! Не будут передаваться данные на сервер по этому датчику. Делаем вывод, что датчик отключился.
Так же, не знаю, по каким причинам, но иногда передается значение -127 с копейками градусов, так же бывает передается 0 градусов. Сделал проверку на эти показания, если температура равна 0, или температура ниже -70 градусов, игнорируем показания, в сериал монитор выводим сообщение об ошибке, ничего не отправляем на сервер.

Спасибо
zelevova
Сообщения: 291
Зарегистрирован: Вт ноя 18, 2014 11:43 pm
Откуда: Краснодарский край
Благодарил (а): 32 раза
Поблагодарили: 68 раз

Re: Скетч Arduino с огромным числом датчиков DS18B20. TEST!!

Сообщение zelevova » Пт апр 03, 2015 12:14 pm

А если температура действительно 0? Например уличный термометр.
Majordomo (GitHub) на cubietruck + MegaD + 1-wire
CONNECT: http://connect.smartliving.ru/profile/311
tsember
Сообщения: 52
Зарегистрирован: Ср фев 04, 2015 12:28 am
Благодарил (а): 54 раза
Поблагодарили: 6 раз

Re: Скетч Arduino с огромным числом датчиков DS18B20. TEST!!

Сообщение tsember » Пт апр 03, 2015 11:30 pm

zelevova писал(а):А если температура действительно 0? Например уличный термометр.
Я думаю, не проблема, если будет -0,2 или +0,1 градус. Не критично.

Так же мне прислали ПМ:
СпойлерПоказать
Видел ваш скетч, но что то не компилируется....в разных версиях ардуины разные ошибки....
Не могли бы вы для новичка показать пример скетча для одного датчика температуры DS18B20 и самое главное как в системе MD получать с него показания?
У меня ардуина + шилд W5100, система есть и на хостинге и на компе под виндой
Отвечаю:
Здравствуйте. Объясняю вкратце, как все это работает:
Датчик температуры подключается к ардуине. Ардуина получает температуру, ее каким то образом обрабатывает (в моем случае, округляет до десятых).
Далее, сравнивает текущуу температуру по каким то условиям (например, у меня отправляет только в том случае, если температура не ровна нулю, больше -80 градусов, и если дельта между старой и новой температурой больше, чем 0,3 градуса). Если эти условия выполняются, то формируется GET запрос, который отправляется на сервер с МЖД.
Мажор, в свою очередь принимает данные, и присваивает свойству объекта (который прописан в гет запросе) значение (которое между прочим тоже в гет запросе)

Скетч проверялся на разных компиляторах, на разных ПК. Везде компилируется.
Проверьте наличие библиотек (которые должны подключаться, см.начало скетча)
Аватара пользователя
savenko_egor
Сообщения: 705
Зарегистрирован: Вс авг 03, 2014 8:17 pm
Откуда: Украина, Запорожье
Благодарил (а): 108 раз
Поблагодарили: 147 раз
Контактная информация:

Re: Скетч Arduino с огромным числом датчиков DS18B20. TEST!!

Сообщение savenko_egor » Сб апр 04, 2015 9:20 am

tsember писал(а): Так же, не знаю, по каким причинам, но иногда передается значение -127 с копейками градусов, так же бывает передается 0 градусов. Сделал проверку на эти показания, если температура равна 0, или температура ниже -70 градусов, игнорируем показания, в сериал монитор выводим сообщение об ошибке, ничего не отправляем на сервер.
Тоже такое бывало, делал перепроверку, то есть запрашивал значение по новой. Ещё может быть причина в количестве запросов к датчику. Для себя писал что бы каждую секунду, датчик обновлял значение, после этого выявил что проблема именно в этом и начал запрашивать значения 1 раз в 10 минут. В случае если это обычный уличный или комнатный датчик, то обновление в 10 минут не особо критично.
tsember
Сообщения: 52
Зарегистрирован: Ср фев 04, 2015 12:28 am
Благодарил (а): 54 раза
Поблагодарили: 6 раз

Re: Скетч Arduino с огромным числом датчиков DS18B20. TEST!!

Сообщение tsember » Сб апр 04, 2015 1:32 pm

warik писал(а):
tsember писал(а):В случае если это обычный уличный или комнатный датчик, то обновление в 10 минут не особо критично.
В дальнейшем буду делать высокоточный термостат для регулировки температуры. Поэтому 10 минут в некоторых случаях будет достаточно долго.
В моем случае идет не опрос датчиков веб переменными (Кстати, Сергей сказал, что это не самый удобный и быстрый способ), а ардуино сама посылает данные об температуре, если они не изменились.
Аватара пользователя
savenko_egor
Сообщения: 705
Зарегистрирован: Вс авг 03, 2014 8:17 pm
Откуда: Украина, Запорожье
Благодарил (а): 108 раз
Поблагодарили: 147 раз
Контактная информация:

Re: Скетч Arduino с огромным числом датчиков DS18B20. TEST!!

Сообщение savenko_egor » Сб апр 04, 2015 2:50 pm

Всё верно. У меня так же было. Сама Ардуинка шлёт данные. И вот как раз я чуть-чуть ограничил время. Где-то слышал что это может быть из-за длины линии до датчика. Так же есть ИМХО что это из-за питания. У меня была проблема с датчиками движения. Почему-то он не хотел нормально работать, посоветовали подключить отдельное питание для него. То есть что бы он был запитан не от Ардуино, а отдельным БП. Может и в этом случае так же попробовать?
tsember
Сообщения: 52
Зарегистрирован: Ср фев 04, 2015 12:28 am
Благодарил (а): 54 раза
Поблагодарили: 6 раз

Re: Скетч Arduino с огромным числом датчиков DS18B20. TEST!!

Сообщение tsember » Сб апр 04, 2015 3:26 pm

warik писал(а):посоветовали подключить отдельное питание для него. То есть что бы он был запитан не от Ардуино, а отдельным БП. Может и в этом случае так же попробовать?
На китайских сайтах полно блоков питаний для датчиков и шин 1-wire.
tsember
Сообщения: 52
Зарегистрирован: Ср фев 04, 2015 12:28 am
Благодарил (а): 54 раза
Поблагодарили: 6 раз

Re: Скетч Arduino с огромным числом датчиков DS18B20. TEST!!

Сообщение tsember » Сб апр 04, 2015 11:28 pm

Код: Выделить всё

/**
* Универсальный контроллер сбора данных на базе Arduino (к проекту http://smartliving.ru/)
* Platform: Arduino UNO R3 + EthernetShield W5100
* IDE: Arduino 1.6.1
* Автор: Петр Цембер. На форуме tsember. 2015. город Сыктывкар.
**/

// ----==== ПОДКЛЮЧЕНИЕ БИБЛИОТЕК ====----
  #include <Ethernet.h>                                // (Ethernet Shield)
  #include <SPI.h>                                     // (Для работы с устройствами по протоколу SPI, например с Ethernet Shield)
  #include <Arduino.h>                                 // (Основная библиотека Arduino)
  #include <OneWire.h>                                 // (Шина 1-wire)
  #include <DallasTemperature.h>                       // (Датчик температуры DS18B20)


// ----==== НАСТРОЙКИ СЕТИ ====----
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xE4, 0xDE, 0x35 }; // MAC-адрес контроллера Arduino
  byte ip[] = { 192, 168, 1, 15 };                     // ip-адрес контроллера Arduino
  byte subnet[] = { 255, 255, 255, 0 };                // Маска подсети
  byte gateway[] = { 192, 168, 1, 250 };               // ip-адрес основного шлюза
  byte dns_server[] = { 192, 168, 1, 250 };            // ip-адрес DNS-сервера
  byte rserver[] = { 192, 168, 1, 123 };               // ip-адрес сервера MajorDoMo
  char buf[100];                                       // Переменная для хранения GET запроса
  char ipbuff[16];                                     // Переменная для IP адреса
  EthernetClient rclient;


// ----==== НАСТРОЙКИ ПОДКЛЮЧЕННЫХ УСТРОЙСТВ ====----
// Вход, на котором находится шина 1-wire с датчиками DS18S20
  #define ONE_WIRE_BUS 2                               // нога 2



// ----==== НАСТРОЙКИ ПЕРЕМЕННЫХ И МАССИВОВ ДАННЫХ ====----
  float current_temp1;                                 // Задаем переменную, в которой будем хранить текущую температуру
  float delta_temp = 0.2;                              // Дельта температур, при превышении которой следует отправлять данные на сервер МЖД
  long requestMillis;                                  // Задаем переменную времени последней передачи данных на сервер
  long interval = 18000000;                            // Задаем максимальный интервал между передачами данных на сервер
  byte numberOfDevices;                                // Количество датчиков DS18B20 на шине 1-wire (Обновляется автоматически)
  DeviceAddress Termometers;                           // Массив с датчиками
  // Размер следующих массивов - предполагаемое максимальное количество датчиков DS18B20.
  // По умолчанию - 30. Нужно больше?! Увеличиваете числа и перезаливаете скетч
  byte na[30];                                         // Массив с порядковыми номерами датчиков температуры DS18B20
  String aa[30];                                       // Массив с HEX-адресами датчиков температуры DS18B20
  float ta[30];                                        // Массив с последней отправленной температурой датчиков DS18B20


// Инициализация веб-сервера на 80 порту, а так же шины 1-wire и датчиков температуры DS18B20
  OneWire oneWire(ONE_WIRE_BUS);
  DallasTemperature sensors(&oneWire);


// ---=== ПОИСК ДАТЧИКОВ ТЕМПЕРАТУРЫ DS18B20 НА ШИНЕ 1-WIRE ===---
void TempSensorSearch()
{
  sensors.begin();                                   // Инициализация датчиков DS18B20
  sensors.setResolution(Termometers, 12);            // Установка чувствительности на 12 бит 

  Serial.print("Vsego datchikov: ");
   numberOfDevices = sensors.getDeviceCount(); 
   Serial.println(numberOfDevices);                  // вывод на экран общего количества найденых датчиков
   
  for(byte i=0;i<numberOfDevices; i++) {             // цикл для записи в массивы данных
     if(sensors.getAddress(Termometers, i))          // если адрес датчика под индексом i определен, то:
      {        
      String aba[8];                                 // Создаем массив с байтами адреса 
       for (int i=0; i<8; i++)                       // цикл получения бит адреса
        { 
          if (Termometers[i] < 16) { aba[i] = "0"+String(Termometers[i],HEX); } //если бит меньше 16, то дописываем в начале 0, так же конвертируем в шеснадцатиричный код
          else {aba[i] = String(Termometers[i],HEX);}// в противном случае просто конвертируем в 16ричный код и записываем байт в массив
        }
      aa[i] = aba[0]+aba[1]+aba[2]+aba[3]+aba[4]+aba[5]+aba[6]+aba[7]; // Записываем полный адрес в массив адресов aa[], в ячейку i.      
    Serial.print("Sensor "); Serial.print(i, DEC); Serial.print(" with address: "); // Датчик под номером i с адресом:
    Serial.print(aa[i]);                           // Выводим на экран i ячейку с 16-ричным адресом устройства  
    Serial.print(", tempC = "); Serial.println(sensors.getTempCByIndex(i));
       }
     }
}  
 
 
// ---=== ПОЛУЧЕНИЕ И ОБРАБОТКА ТЕМПЕРАТУРЫ ===---
void TempSensorSend()
{ sensors.requestTemperatures();                     // Перед каждым получением температуры надо ее запросить
  delay(760);                                        // Задержка в 750 мс (для обработки 12 битной чувствительности) + запас 10 мс
  for(byte i=0;i<numberOfDevices; i++)    {          // цикл для получения, обработки, округления и отправки температуры каждого датчика DS18B20
    int str_len = aa[i].length() + 1; char char_array[str_len]; aa[i].toCharArray(char_array, str_len);      // Конвертируем строку с адресом в массив символов
    float tempC = sensors.getTempCByIndex(i); // Получим температуру от датчика (или ошибку)
    
      // Устройство отдало реальное значение температуры (или осталось старое)
      // Округление полученной температуры до десятых
      // Пример: 23.899 => 238.99 => 239.49 => 239 => 23.9) // При округлении изменился первый разряд, после запятой. Правило работает.
       tempC = sensors.getTempCByIndex(i) * 10;
       tempC = tempC + 0.5;
       tempC = (int)tempC;
       tempC =  tempC / 10;
    float delta = fabsf(ta[i]-tempC);                // Выделяем дельту температуры, между текущей и в последний раз отправленной темп.
//    if (tempC < -70) { Serial.print("Temp sensor "); Serial.print(i); Serial.println(" is disconnected");}
//    else if (tempC == 0) {Serial.print("Temp sensor "); Serial.print(i); Serial.println(" is disconnected");}
//    else 
if ((delta > delta_temp)                    // Если разница между прошлым и текущим значением темп. больше обозначенной дельты и дельта не более 70...
    || ((millis() - requestMillis) > interval))      // Если последняя передача данных на сервер была более 30 минут назад (например температура не менялась)...
     {  
     int temp1 = (tempC - (int)tempC) * 10;          // выделяем дробную часть

     sprintf(buf, "GET /objects/?object=%s&op=m&m=tempChanged&t=%0d.%d", char_array, (int)tempC, abs(temp1)); // Формируем GET запрос
      sendHTTPRequest();                             // И передаем на сервер
      requestMillis = millis();                      // Засекаем время последней передачи данных на сервер
      ta[i]=tempC;                                   // Задаем текущую температуру предыщущей.
     }
    }
}



// ---=== ФУНКЦИЯ ОТПРАВКИ ДАННЫХ (HTTP-ЗАПРОСА) НА СЕРВЕР MAJORDOMO ===---
void sendHTTPRequest() 
{ Serial.println (buf);
/*  if (rclient.connect(rserver, 80)) 
  { 
   Serial.println("OK"); 
   Serial.println(buf);                                 // Вывод на экран сгенерированного GET запроса
   rclient.print(buf);
   rclient.println(" HTTP/1.0");
   rclient.print("Host: ");
   sprintf(ipbuff, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
   rclient.println(ipbuff);                             // ip адрес нашего контроллера в текстовом виде
   rclient.print("Content-Type: text/html\n");
   rclient.println("Connection: close\n");
   \(10);
   rclient.stop();
  } else 
  { Serial.println("FAILED SENDING"); } */
}


// ---=== ФУНКЦИЯ НАСТРОЙКИ ===---
void setup()
  {
  Serial.begin(9600);                                   // Инициализируем Serial (монитор последовательного порта)
  Serial.println("Start");
  Ethernet.begin(mac, ip, dns_server, gateway, subnet); // Инициализируем Ethernet Shield/
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  
  TempSensorSearch();                                   // Запуск процедуры поиска датчиков на шине 1-wire
  }


// ---=== ЦИКЛИЧЕСКАЯ ФУНКЦИЯ ===---
void loop() {


  TempSensorSend();
} 
Несколько подправил скетч.
Вынес поиск датчиков с loop`a в setup.
Не вижу смысла постоянно держать ардуино в поискать датчиков на шине. Один раз в начале работы платы сканировали шину, и все. Если добавили датчик, просто нажали резет ардуины или перезапустили питание, и все.
Так же добавить задержку между запросом температуры и и ее получением в 760 милисекунд (750 мс - максимальное время перекодирования температуры в 12 битный формат + 10мс запас).

По поводу ошибок -127.9 градусов, 0 градусов и +85 градусов = все это ошибки чтения данных с датчиков.
Я думал, почему у меня посреди ночи ошибки эти случаются?! Оказывается мой кот с красным огонечком играется по ночам, платка то на усб шнурке со стола свисает, вот он ее и колотит. Заодно и провода задевает. Спрятал плату, дальше буду наблюдать. Спасибо
karlismoto
Сообщения: 39
Зарегистрирован: Чт окт 16, 2014 11:12 pm
Благодарил (а): 5 раз
Поблагодарили: 0
Контактная информация:

Re: Скетч Arduino с огромным числом датчиков DS18B20. TEST!!

Сообщение karlismoto » Вс апр 05, 2015 10:14 pm

Вот мой последний экспериментальный вариант. 18b20 пять штук + DH11 на контроллер Arduino UNO. Все прекрасно работает с MD.
спасибо за идеи!






/*
При изменении значения датчика, контроллер отправляет по ethernet-сети HTTP-запрос на сервер,
где установлена система MajorDoMo.
*/

#include <SPI.h>
#include <Ethernet.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "DHT.h"

// -------------------------------
// NETS
byte mac[] = {0x00,0x2A,0xF6,0x12,0x68,0xAE};
byte ip[] = {192,168,0,5};
byte subnet[] = {255,255,255,0};
byte gateway[] = {192,168,0,1};
byte dns_server[] = {192,168,0,1};
byte remoteIP[] = {192,168,0,2};
int remotePort=80;
EthernetClient EK; // objekts

// -------------------------------
// SENSORI
// DallasTemperature
#define ONE_WIRE_BUS 2 // Digital 2 pin Arduino (куда подключен выход с шины датчиков DS18X20
#define TEMPERATURE_PRECISION 9
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DT(&oneWire); // objekts
// Настройка датчиков температуры (адреса удобно определять программой из примера DallasTemperature/Mulriple)
//Device 0 Address: 1060CF59010800E3 // piemers
//DeviceAddress Termometer1 = {0x28, 0xD6, 0xA6, 0x3D, 0x06, 0x00, 0x00, 0xC3}; // Ariela sens
//DeviceAddress Termometer2 = {0x28, 0x1F, 0x46, 0x3F, 0x06, 0x00, 0x00, 0x17}; // Ariela sens
DeviceAddress Termometers; // Для поиска

int numberOfDevices; // OneWire
String aa[30]; // Массив с HEX-адресами датчиков температуры DS18B20
float tempC;
//int old_temperature1=0;
//int old_temperature2=0;

// DHT
#define DHTPIN 3 // what pin we're connected to
#define DHTTYPE DHT11 // DHT 11
DHT dht(DHTPIN, DHTTYPE);

//
char buf[80];
char ipbuff[16];
char ripbuff[16];

// taimeris
unsigned long tPrev;
unsigned long tInterval = 60000;

// Setup
void setup()
{
// SERIAL
Serial.begin(9600); // Скорость консольного порта 115200 (пригодится для отладки)
//
Serial.println("[SETUP]");
Serial.println();
Serial.println("Temperaturas tiek nolasitas x1/60sek");

// ETHERNET
Serial.println("Ethernet:");
Ethernet.begin(mac, ip, dns_server, gateway, subnet);
// give the ethernet module time to boot up:
//delay(2000);
for (int i=0; i<4; i++)
{
Serial.print(".");
delay(500);
}
/*
if (Ethernet.begin(mac) == 0)
{
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
// try to congifure using IP address instead of DHCP:

Ethernet.begin(mac, ip, dns_server, gateway, subnet);
}
*/
Serial.print(" IP = ");
Serial.println(Ethernet.localIP());
Serial.println();

// DallasTemperature

feja_mekletIerices();

Serial.println();

// DHT
dht.begin();

//
Serial.println("[AIZIET]");
Serial.println();
}

// AIZIET
void loop()
{
// DT
unsigned long tNow = millis();

if (tNow - tPrev > tInterval)
{
tPrev = tNow;

// requestTemperatures
DT.requestTemperatures(); // Перед каждым получением температуры надо ее запросить

int valid_sensor=0; // !?

delay(1000);

for(int i=0; i < numberOfDevices; i++)
{
// // TEMP SENSOR 1
float current_temp;

// getTempC / getTempCByIndex
//tempC = DT.getTempC(Termometer1); // Получим температуру от датчика (или ошибку)
tempC = DT.getTempCByIndex(i); // Получим температуру от датчика (или ошибку)

//
if (tempC == DEVICE_DISCONNECTED_C)
{
// Устройство отсоеденнено
Serial.println("Termometer1 is DEVICE_DISCONNECTED_C");
// TODO Послать бы на сервер сигнал о том, что датчит не отвечает
}
else
{
// Устройство отдало реальное значение температуры (или осталось старое)
current_temp = tempC; // получаем температуру

// Tn=n.n
Serial.print("T #"); Serial.print(i); Serial.print(" = "); Serial.print(current_temp); Serial.println("C");

//if ((old_temperature1!=(int)current_temp) && (current_temp<79) && (current_temp>5))
if (1==1)
{
int temp1 = (current_temp - (int)current_temp) * 100; // выделяем дробную часть

//sprintf(buf, "GET /objects/?object=objGKTS&op=m&m=tempChanged&t=%0d.%d", (int)current_temp, abs(temp1));

//sprintf(buf, "GET /objects/?object=sensorKotel&op=m&m=tempChanged&t=%0d.%d", (int)current_temp, abs(temp1));
//sprintf(buf, "GET /_arduCl/index.php?object=sensorKotel&op=m&m=tempChanged&t=%0d.%d", (int)current_temp, abs(temp1));

// v2
int str_len = aa.length() + 1; char char_array[str_len]; aa.toCharArray(char_array, str_len); // Конвертируем строку с адресом в массив символов

sprintf(buf, "GET /objects/?object=%s&op=m&m=tempChanged&t=%0d.%d", char_array, (int)current_temp, abs(temp1)); // Формируем GET запрос

Serial.println(buf);

feja_httpRequest();
}

//old_temperature1=(int)current_temp;
}
// end TEMP SENSOR 1

}

/* // TEMP SENSOR 2
float current_temp2=0;
tempC = DT.getTempC(Termometer2); // Получим температуру от датчика (или ошибку)

//
if (tempC == DEVICE_DISCONNECTED_C)
{
// Устройство отсоеденнено
Serial.println("Termometer2 is DEVICE_DISCONNECTED_C");
// TODO Послать бы на сервер сигнал о том, что датчит не отвечает
}
else
{
// Устройство отдало реальное значение температуры (или осталось старое)
current_temp2 = tempC; // получаем температуру

Serial.print("T2=");
Serial.println(current_temp2);

//if ((old_temperature2!=(int)current_temp2) && (current_temp2<79) && (current_temp2>5))
if ((current_temp2<79) && (current_temp2>5))
{
int temp2 = (current_temp2 - (int)current_temp2) * 100; // выделяем дробную часть
sprintf(buf, "GET /objects/?object=objTS2&op=m&m=tempChanged&t=%0d.%d", (int)current_temp2, abs(temp2));
feja_httpRequest();
}

//
old_temperature2=(int)current_temp2;
}
*/

// DHT
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
float t = dht.readTemperature();

// check if returns are valid, if they are NaN (not a number) then something went wrong!
if (isnan(t) || isnan(h))
{
Serial.println("Failed to read from DHT");
}
else
{
Serial.print("Humidity: ");
Serial.print(h);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print(t);
Serial.println(" *C");

int h2 = (h - (int)h) * 100; // выделяем дробную часть
sprintf(buf, "GET /objects/?object=DHT1_h&op=m&m=humChanged&h=%0d.%d", (int)h, abs(h2));
feja_httpRequest();
int t2 = (t - (int)t) * 100; // выделяем дробную часть
sprintf(buf, "GET /objects/?object=DHT1_t&op=m&m=tempChanged&t=%0d.%d", (int)t, abs(t2));
feja_httpRequest();
}
// end DHT
}
}

//
void feja_mekletIerices()
{
// begin
DT.begin(); // initialise bus 1-wire (temp. sensori)

// setResolution 9, 10, 11, 12 bit
DT.setResolution(TEMPERATURE_PRECISION); // visiem
//DT.setResolution(Termometer1, TEMPERATURE_PRECISION); // vienam no

Serial.println("DallasTemperature:");

// getDeviceCount
numberOfDevices = DT.getDeviceCount();
Serial.print("Deveju skaits = "); Serial.println(numberOfDevices, DEC);

// isParasitePowerMode
Serial.print("ParasitePowerMode = ");
if (DT.isParasitePowerMode()) {
Serial.println("ON");
}
else {
Serial.println("OFF");
}

// requestTemperatures
DT.requestTemperatures();

Serial.println("DallasTemperature -> meklejam ierices:");

for(int i=0; i < numberOfDevices; i++)
{
// getAddress
if(DT.getAddress(Termometers, i))
{
// v1
//Serial.print("Sensors "); Serial.print(i, DEC); Serial.print(" / Adr = ");

// v2
String aba[8]; // Создаем массив с байтами адреса

for (uint8_t i=0; i<8; i++)
{
//если бит меньше 16, то дописываем в начале 0, так же конвертируем в шеснадцатиричный код
if (Termometers<16)
{
//Serial.print("0");
aba = "0"+String(Termometers, HEX);
}
else // в противном случае просто конвертируем в 16ричный код и записываем байт в массив
{
aba = String(Termometers, HEX);
}
//Serial.print(Termometers, HEX);
}

aa = aba[0]+aba[1]+aba[2]+aba[3]+aba[4]+aba[5]+aba[6]+aba[7]; // Записываем полный адрес в массив адресов aa[], в ячейку i.

//
Serial.print("Sensors #"); Serial.print(i, DEC); Serial.print(" Adr = "); Serial.print(aa); // Выводим на экран i ячейку с 16-ричным адресом устройства

// v1
// getResolution
Serial.print(" / Resolution = "); Serial.print(DT.getResolution(Termometers), DEC); Serial.print(" / TempC = ");

// getTempC
//float tempC = DT.getTempC(Termometers);
Serial.print(DT.getTempC(Termometers)); Serial.println("C");
}
else
{
Serial.print("NOT FOUND");
}
}
}

//
void feja_httpRequest()
{
Serial.print("Ethernet -> Savienojamies ar ");
sprintf(ripbuff, "%u.%u.%u.%u", remoteIP[0], remoteIP[1], remoteIP[2], remoteIP[3]);
Serial.print(ripbuff);
Serial.print(":");
Serial.print(remotePort);
// if there's a successful connection:
if (EK.connect(remoteIP, remotePort))
{
Serial.print(" :) ");
//Serial.print("httpRequest: ");
Serial.println(buf);
//Serial.println();

// send the HTTP request:
// piemers EK.println("GET /_arduCl/index.php?t1 HTTP/1.1"); // wamp
// piemers EK.println("Host: 192.168.2.102");

// GET
EK.print(buf);
EK.println(" HTTP/1.1");
// Host
EK.print("Host: ");
sprintf(ipbuff, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
EK.println(ipbuff); // ip адрес нашего контроллера в текстовом виде
// ...
EK.println("User-Agent: arduino-ethernet"); // Arduine Repeating Web client
EK.println("Content-Type: text/html"); //EK.print("Content-Type: text/html\n");
EK.println("Connection: close"); //EK.println("Connection: close\n");
EK.println();
//
delay(2000); // no D18B20v1 + D18B20v2
EK.stop(); // no D18B20v1 + D18B20v2
}
else
{
// if you couldn't make a connection:
Serial.println(" :(");
EK.stop(); // Arduine Repeating Web client
}

}
Windows7 + MajorDoMo.
HP laptop, MegaD modules, Arduino Megas, DS18B20, DHT-11 and other sensors.
DSC Alarm + envisalink 3
Connect
Ответить