Guest User

управление котельной V3.5

a guest
May 17th, 2018
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 43.12 KB | None | 0 0
  1. #include <SPI.h>
  2. #include <SD.h>
  3. #include <EEPROM.h>
  4. #include <OneWire.h>
  5. #include <iarduino_RTC.h>                                     // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени.
  6.  
  7. #define SD_SS_pin 10                                          // подключаем SD карту на 10-й pin. Может быть придётся поменять потом.
  8. #define num_byte_setup 20                                     // количество переменных тип long для считывания с SD-карты (сами переменные тоже надо определить !)
  9. #define block_1_EEPROM 0                                      // начальный адрес блока переменных в EEPROM (num_byte_setup Х 4 = 80 байт)
  10. #define block_2_EEPROM num_byte_setup*4+10                    // начальный адрес блока адресов термосенсоров в EEPROM (num_byte_setup Х 4 +10 = 90 )
  11.  
  12. #define addr_max_boiler block_1_EEPROM + 0                    // адрес ячейки памяти EEPROM, откуда брать значение переменной "T_max_boiler" - максимальная температура до которой нагреваем бойлер пелетным котлом
  13. #define addr_min_boiler block_1_EEPROM + 4                    // адрес "T_min_boiler" - минимальная температура при которой пытаемся запустить пелетный котёл при отсутствии других источников тепла
  14.  
  15. #define addr_tank_up block_1_EEPROM + 8                       // адрес T_tank_up - максимальная температура в верхней части теплоаккумулятора при которой считаем его "заряженным"
  16. #define addr_tank_med block_1_EEPROM + 12                     // адрес T_tank_med - максимальная температура в средней части теплоаккумулятора при которой прекращаем нагрев
  17. #define addr_tank_down block_1_EEPROM + 16                    // адрес T_tank_down - максимальная температура в нижней части теплоаккумулятора при которой устраиваем "тревогу".
  18. #define num_sensors 5                                         // общее количество термодатчиков в системе
  19.  
  20. OneWire  ds(9);                                               // если потребуется вторая шина 1-Wire, то придётся удвоить часть кода
  21. iarduino_RTC time(RTC_DS1302, 6, 7, 8);                       // Объявляем объект time для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT
  22.  
  23.  
  24. // -------блок глобальных переменных----------------
  25. boolean _F_SD_exist = 0;                                      // флаг наличия SD-карты в ридере
  26. int TEMPERATURE[num_sensors] = {0};                           // массив для показаний термодатчиков
  27. String last_time_T = "";                                      // текстовое значение времени, когда крайний раз производилось измерение температуры
  28. //--------------------------------------------------
  29.  
  30.  
  31. //------------- запись логов на SD-карту-----------------------
  32. boolean LOG_data(boolean autoLOG, String filename, String filedata) {                        // функция имеет два режима: автоматическое логирование autoLOG=true и вывод в файл принятых параметров.
  33.  
  34.   boolean _W1_errors = true;                                                                 // признак ошибки записи на SD-карту
  35.   boolean _W2_errors = true;                                                                 // признак ошибки записи на SD-карту
  36.  
  37.   if (autoLOG) {                                                                             // если установлен autoLOG
  38.     String filename = "/LOG/" + String(time.gettime("ymd"));                                 // имя директории - "год.месяц.день" в директории \LOG
  39.     String filedata = "";                                                                    // в данном случае нам монопенисуально, что пришло в параметрах функции
  40.     if (!SD.exists(filename)) {                                                              // если ещё не создан каталог \LOG\текущая дата
  41.       SD.mkdir(filename);                                                                    // создаём каталог \LOG\текущая дата
  42.     }
  43.     filename = filename + '/' ;                                                              // для сохранения данных в директории \LOG\текущая дата\
  44.                                                                                
  45.     for (byte c = 0; c < num_sensors - 1 ; c++) {                                            // чтобы убрать последнюю запятую, только для красоты
  46.       filedata = filedata + String(TEMPERATURE[c] / 100.00) + ", ";                          // формируем строку для записи в файл (все сенсоры температуры)
  47.     }
  48.     File LOGfile =  SD.open(filename + "all_sens.log", FILE_WRITE);                          // файл сохранения данных "все термосенсоры одним файлом" в директории \LOG\текущая дата
  49.     unsigned long curent_size = LOGfile.size();                                              // размер файла до записи в него
  50.     LOGfile.println(last_time_T + filedata + String(TEMPERATURE[num_sensors - 1] / 100.00)); // доделываем строку для записи в файл
  51.     unsigned long new_size = LOGfile.size();                                                 // размер файла после записи в него
  52.     LOGfile.close();                                                                         // закрываем файл
  53.     if (new_size > curent_size) _W1_errors = _W1_errors & false;                               // если размер файла не увеличился, то всё плохо
  54.     filedata = " ";                                                                          // очищаем переменные для следующего этапа
  55.  
  56.     for (byte c = 0; c < num_sensors; c++) {                                                 // цикл перебора всех термосенсоров в системе
  57.  
  58.       filename = filename ;                                   // к сожалению, ограничение на имя файла 8.3
  59.       if (!SD.exists(filename + "tsens_" + String(c) + ".log")) {                                                            // если такой файл создается в первый раз, то пишем в него приветственную речь
  60.         for (byte x = 0; x < 8; x++) {                                                       // цикл считывания из EEPROM адреса текущего термосенсора
  61.           filedata = filedata + String(EEPROM.read(block_2_EEPROM + (c * 9) + x )) + " ";    // считываем из EEPROM отдельные байты и формируем имя файла
  62.         }
  63.         File LOGfile =  SD.open(filename + "tsens_" + String(c) + ".log", FILE_WRITE);       // открываем файл для записи
  64.         LOGfile.print(F("Measurement results for the sensor : "));                           // пишем в него "приветственную речь"
  65.         LOGfile.println(filedata);                                                           // указываем адрес термосенсора, для которого создан этот файл
  66.         LOGfile.close();                                                                     // закрываем файл
  67.       }
  68.       filedata = last_time_T + String(TEMPERATURE[c] / 100.00);                              // стандартная запись в файл : время,данные
  69.       File LOGfile =  SD.open(filename + "tsens_" + String(c) + ".log", FILE_WRITE);         // открываем файл для записи. Такое усложнение для предотвращения дробления записи при перемене даты
  70.       curent_size = LOGfile.size();                                                          // размер файла до записи в него
  71.       LOGfile.println(filedata);                                                             // стандартная запись в файл
  72.       new_size = LOGfile.size();                                                             // размер файла после записи в него
  73.       LOGfile.close();                                                                       // закрываем файл
  74.       if (new_size > curent_size) _W2_errors = _W2_errors & false;                             // если размер файла не увеличился, хоть один раз, то всё плохо.
  75.       filedata = "";                                                                         // очищаем переменные для следующего этапа
  76.     }
  77.     filename = "";                                                                           // очищаем переменные для следующего этапа
  78.   }
  79.  
  80.   if (!autoLOG) {                                                                          // это для "ручного режима" записи LOG-файла
  81.     if (!SD.exists(filename)) {                                                            // если файл с таким именем ещё не был создан
  82.  
  83.       File LOGfile =  SD.open(filename, FILE_WRITE);                                       // то открываем новый файл
  84.       LOGfile.print(F("Time and date when LOGfile was started: "));                        // пишем в него небольшую заметку.
  85.       LOGfile.println(time.gettime("d-m-Y, H:i:s, D"));                                    // пишем в файл новое установленное время и дату
  86.       LOGfile.close();                                                                     // закрываем файл
  87.       Serial.println(F("logfile 1"));                                                      // временный тестовый вывод
  88.     }
  89.     File LOGfile =  SD.open(filename, FILE_WRITE);                                         // если файл с таким именем уже был создан
  90.     LOGfile.println(filedata);                                                             // пишем в него то, что пришло в параметрах функции
  91.     LOGfile.close();                                                                       // закрываем файл
  92.     Serial.println(F("logfile 0"));                                                        // временный тестовый вывод
  93.  
  94.   }
  95.  
  96.   Serial.println(F("end procedure loging"));                                               // временный тестовый вывод
  97.   return (_W1_errors || _W2_errors);                                                       // возвращаем признак ошибки записи в любом из блоков
  98. }
  99.  
  100. //------------------конец процедуры-----------------------------
  101.  
  102. void setup() {
  103.  
  104.   Serial.begin(115200);
  105.   time.begin();                                               // Инициируем работу с модулем RTC DS1302.
  106.   time.period (30);                                           // Указываем обращаться к модулю RTC не чаще, чем один раз в полчаса, в этом промежутке значения вычисляются в библиотеке
  107.  
  108.  
  109.   pinMode(SD_SS_pin, OUTPUT);                                 // выход SS для SD-карты.
  110.  
  111.   byte addr[9] = {0};                                         // массив для адреса сенсора и его назначения
  112.   long bufer_config[num_byte_setup] = {0};                    // временный массив считанных с SD-карты настроек. допустимы переменные размером до 4 байта
  113.   File configFile;                                            // переменная файла
  114.   boolean _F_begin = 0;                                       // флаг начала обработки данных в файле
  115.   String read_symbol = "";                                    // строка для формирования числового значения из символов в тексте
  116.   byte count_symbol = 0;                                      // счётчик цикла формирования строки String read_symbol
  117.   byte temp_val = 0;                                          // временная переменная чтения байт из файла
  118.   int address = block_1_EEPROM;                               // устанавливаем начало блока для записи в EEPROM переменных из default.cfg
  119.  
  120.   //----------------- инициализация SD-карты------------------------
  121.   if (SD.begin(SD_SS_pin)) {                                  // проверяем, есть ли SD-карта в ридере
  122.     _F_SD_exist = 1;                                          // SD-карта присутствует, будем её использовать.
  123.     //if (!SD.exists("LOG")) {
  124.     //   SD.mkdir("LOG");
  125.     // }
  126.     //-------------------- установка точного времени-----------------------------------
  127.     if (SD.exists("settime.txt")) {                           // если на SD-карте присутствует файл \settime.txt
  128.       configFile = SD.open("settime.txt");                    // открываем файл
  129.       read_symbol = "";                                       // строка для формирования числового значения из символов в тексте
  130.       count_symbol = 0;                                       // счётчик цикла формирования строки String read_symbol
  131.       temp_val = 0;                                           // временная переменная чтения байт из файла
  132.       int a[7] = {0};                                         // массив для значений устанавливаемого времени
  133.  
  134.       while (configFile.available()) {                        // пока файл не кончился, читаем
  135.         temp_val = configFile.read();                         // присваиваем считанный из файла байт переменной temp_val
  136.  
  137.         if (temp_val == 0x29) {                               // если найдено ASCII значение ')' закрывающая скобка
  138.           a[count_symbol] = read_symbol.toInt();              // преобразуем сформированную символьную строку в "цифровое" значение
  139.           read_symbol = "";                                   // очищаем строку
  140.           time.settime(a[0], a[1], a[2], a[3], a[4], a[5], a[6]); // Записываем время в модуль: 0 сек, 51 мин, 21 час, 27, октября, 2015 года, вторник.
  141.           count_symbol = 0;                                   // подготовка для следующей группы адресов
  142.         }
  143.  
  144.         if (temp_val == 0x2C) {                               // если найдено ASCII значение ','
  145.           a[count_symbol] = read_symbol.toInt();              // преобразуем сформированную символьную строку в "цифровое" значение
  146.           read_symbol = "";                                   // очищаем строку для формирования числового значения из символов в тексте
  147.           count_symbol++;                                     // переходим к следующему элементу
  148.         }
  149.         if (temp_val == 0x30) read_symbol = read_symbol + "0";// если найдено ASCII значение '0', то добавляем в строку символ "0"
  150.         if (temp_val == 0x31) read_symbol = read_symbol + "1";// если найдено ASCII значение '1', то добавляем в строку символ "1"
  151.         if (temp_val == 0x32) read_symbol = read_symbol + "2";// если найдено ASCII значение '2', то добавляем в строку символ "2"
  152.         if (temp_val == 0x33) read_symbol = read_symbol + "3";// если найдено ASCII значение '3', то добавляем в строку символ "3"
  153.         if (temp_val == 0x34) read_symbol = read_symbol + "4";// если найдено ASCII значение '4', то добавляем в строку символ "4"
  154.         if (temp_val == 0x35) read_symbol = read_symbol + "5";// если найдено ASCII значение '5', то добавляем в строку символ "5"
  155.         if (temp_val == 0x36) read_symbol = read_symbol + "6";// если найдено ASCII значение '6', то добавляем в строку символ "6"
  156.         if (temp_val == 0x37) read_symbol = read_symbol + "7";// если найдено ASCII значение '7', то добавляем в строку символ "7"
  157.         if (temp_val == 0x38) read_symbol = read_symbol + "8";// если найдено ASCII значение '8', то добавляем в строку символ "8"
  158.         if (temp_val == 0x39) read_symbol = read_symbol + "9";// если найдено ASCII значение '9', то добавляем в строку символ "9"
  159.       }
  160.       SD.remove("settime.txt");                               // удаляем файл \settime.txt
  161.       configFile = SD.open("settime.ok", FILE_WRITE);         // делаем метку на флешке, что данные успешно считаны. Создаём файл \SETTIME.OK
  162.       configFile.println(time.gettime("d-m-Y, H:i:s, D"));    // пишем в файл новое установленное время и дату
  163.       configFile.println(F("Time & Date was setup Ок"));      // пишем в файл \SETTIME.OK небольшую заметку.
  164.       configFile.println(F("To set the clock, you must delete the file \SETTIME.OK from the SD card and create the file \settime.txt"));  // Для повторной установки часов необходимо удалить c SD-карты файл \SETTIME.OK и создать файл \settime.txt
  165.       configFile.println(F("(СЕКУНДЫ,МИНУТЫ,ЧАСЫ,ДЕНЬ,МЕСЯЦ,ГОД,ДЕНЬ_НЕДЕЛИ)"));
  166.       configFile.close();                                     // закрываем файл
  167.       Serial.println(F("Time & Date was setup Ок"));          // временный тестовый вывод
  168.     }
  169.  
  170.     //-------- запись и чтение настроек системы ----------
  171.     if (SD.exists("default.cfg") && !(SD.exists("default.ok"))) { // если на SD-карте присутствует файл настроек и он ещё не был загружен
  172.       configFile = SD.open("default.cfg");                    // открываем файл default.cfg для чтения
  173.       while (configFile.available()) {                        // пока файл не кончился, читаем
  174.         temp_val = configFile.read();                         // присваиваем считанный файл переменной temp_val
  175.  
  176.         if (temp_val == 0x29 && _F_begin == 1) {              // ищем закрывающую скобку, конец цикла формирования массива
  177.           _F_begin = 0;                                       // флаг окончания обработки данных в файле
  178.           bufer_config[count_symbol] = read_symbol.toInt();   // преобразуем ранее сформированную символьную строку в "цифровое" значение
  179.           read_symbol = "";                                   // очищаем строку для формирования числового значения из символов в тексте
  180.           configFile.close();                                 // закрываем файл. Парсинг закончен.
  181.           //--------------- запись данных в EEPROM -----------------
  182.           for (int x = 0; x < num_byte_setup; x++) {          // перебираем последовательно все элементы временного массива
  183.             EEPROM.put(address, bufer_config[x]);             // делим long на 4 byte и пишем их в ячейки энергонезависимой памяти
  184.             address = address + 4;                            // выбираем следующую группу из четырёх ячеек
  185.           }
  186.         }
  187.  
  188.         if (temp_val == 0x2C && _F_begin == 1) {              // если найдено ASCII значение ',' в течении цикла импорта данных, ограниченного символами '('  ')'
  189.           bufer_config[count_symbol] = read_symbol.toInt();   // преобразуем сформированную символьную строку в "цифровое" значение
  190.           read_symbol = "";                                   // очищаем строку для формирования числового значения из символов в тексте
  191.           count_symbol++;                                     // переходим к следующему элементу временного массива считанных с SD-карты настроек
  192.         }
  193.  
  194.         if (temp_val == 0x28 && _F_begin == 0) _F_begin = 1;  // ищем открывающую скобку, начало цикла формирования массива. Устанавливаем флаг начала обработки данных в файле
  195.  
  196.         if (temp_val == 0x30 && _F_begin == 1) read_symbol = read_symbol + "0"; // если найдено ASCII значение '0', то добавляем в строку символ "0"
  197.         if (temp_val == 0x31 && _F_begin == 1) read_symbol = read_symbol + "1"; // если найдено ASCII значение '1', то добавляем в строку символ "1"
  198.         if (temp_val == 0x32 && _F_begin == 1) read_symbol = read_symbol + "2"; // если найдено ASCII значение '2', то добавляем в строку символ "2"
  199.         if (temp_val == 0x33 && _F_begin == 1) read_symbol = read_symbol + "3"; // если найдено ASCII значение '3', то добавляем в строку символ "3"
  200.         if (temp_val == 0x34 && _F_begin == 1) read_symbol = read_symbol + "4"; // если найдено ASCII значение '4', то добавляем в строку символ "4"
  201.         if (temp_val == 0x35 && _F_begin == 1) read_symbol = read_symbol + "5"; // если найдено ASCII значение '5', то добавляем в строку символ "5"
  202.         if (temp_val == 0x36 && _F_begin == 1) read_symbol = read_symbol + "6"; // если найдено ASCII значение '6', то добавляем в строку символ "6"
  203.         if (temp_val == 0x37 && _F_begin == 1) read_symbol = read_symbol + "7"; // если найдено ASCII значение '7', то добавляем в строку символ "7"
  204.         if (temp_val == 0x38 && _F_begin == 1) read_symbol = read_symbol + "8"; // если найдено ASCII значение '8', то добавляем в строку символ "8"
  205.         if (temp_val == 0x39 && _F_begin == 1) read_symbol = read_symbol + "9"; // если найдено ASCII значение '9', то добавляем в строку символ "9"
  206.       }
  207.       configFile = SD.open("default.ok", FILE_WRITE);              // делаем метку на флешке, что данные успешно считаны.
  208.       configFile.println(F("Data from \DEFAULT.CFG was read succes\r\nDelete this file for update EEPROM again")); // пишем в файл default.ok небольшую заметку-инструкцию. Для повторной записи в EEPROM необходимо удалить c SD-карты файл default.ok
  209.       configFile.close();                                          // закрываем файл
  210.       Serial.println(F("default.cgf was import succes"));
  211.     }
  212.     //----------------считываем адреса всех датчиков и сохраняем их в файл--------------
  213.     if (!SD.exists("config.ini")) {                                // если на SD-карте отсутствует файл конфигурации термосенсоров создадим его.
  214.       configFile = SD.open("config.ini", FILE_WRITE);              // сохраним все адреса сенсоров в файл для привязки сенсоров
  215.       ds.reset_search();                                           // сброс счётчика адресов 1-Wire
  216.       while (ds.search(addr)) {                                    // цикл, пока не найдены все сенсоры в системе
  217.         for ( byte i = 0; i < 8; i++) {                            // перебираем элементы массива адреса сенсора
  218.           configFile.print(addr[i], DEC);                          // пишем в файл информацию о сенсоре в десятичном формате, HEX сложнее парсить.
  219.           configFile.print(" ");                                   // пишем в файл разделитель байт.
  220.         }
  221.         configFile.print("x,\r\n");                                // символ 'x' необходимо заменить в файле /CONFIG.INI на номер сенсора в схеме
  222.       }
  223.       configFile.close();                                          // закрываем файл, когда обнаружены все сенсоры на шине 1-Wire
  224.       configFile = SD.open("config.ok", FILE_WRITE);               // создаём файл-подтверждение, что запись прошла успешно
  225.       configFile.println(F("List sensors was writen to \CONFIG.INI\n\rFor next step - edit \CONFIG.INI and delete this file \CONFIG.OK"));
  226.       configFile.close();                                          // закрываем файл
  227.       Serial.println(F("config.ini was writen Ок"));               // временный тестовый вывод
  228.     }
  229.     //---создали файл с номерами датчиков, следующим шагом надо назначить их соответствие------------
  230.     if (SD.exists("config.ini") && !(SD.exists("config.ok"))) {    // если на SD-карте присутствует файл конфигурации термосенсоров и нет файла \CONFIG.OK то парсим \CONFIG.INI
  231.       configFile = SD.open("config.ini");                          // открываем файл для чтения
  232.       address = block_2_EEPROM;                                    // устанавливаем начало блока для записи в EEPROM адресов сенсоров
  233.       read_symbol = "";                                            // строка для формирования числового значения из символов в тексте
  234.       count_symbol = 0;                                            // счётчик цикла формирования строки String read_symbol
  235.       temp_val = 0;                                                // временная переменная чтения байт из файла
  236.  
  237.       while (configFile.available()) {                             // пока файл не кончился, читаем
  238.         temp_val = configFile.read();                              // присваиваем считанный из файла символ переменной temp_val
  239.  
  240.         if (temp_val == 0x2C) {                                    // если найдено ASCII значение ','
  241.           addr[count_symbol] = read_symbol.toInt();                // преобразуем сформированную символьную строку в "цифровое" значение
  242.           read_symbol = "";                                        // очищаем строку
  243.  
  244.           for (int x = 0; x < 9; x++) {                            // перебираем последовательно все элементы временного массива
  245.             EEPROM.update((addr[8] * 9) + address + x, addr[x]);   // и пишем их в ячейки энергонезависимой памяти
  246.           }
  247.           //   address = address + 9;                                 // выбираем следующую группу из девяти ячеек
  248.           count_symbol = 0;                                        // подготовка для следующей группы адресов
  249.         }
  250.  
  251.         if (temp_val == 0x20) {                                    // если найдено ASCII значение ' '
  252.           addr[count_symbol] = read_symbol.toInt();                // преобразуем сформированную символьную строку в "цифровое" значение
  253.  
  254.           read_symbol = "";                                        // очищаем строку для формирования числового значения из символов в тексте
  255.           count_symbol++;                                          // переходим к следующему элементу
  256.         }
  257.         if (temp_val == 0x30) read_symbol = read_symbol + "0";     // если найдено ASCII значение '0', то добавляем в строку символ "0"
  258.         if (temp_val == 0x31) read_symbol = read_symbol + "1";     // если найдено ASCII значение '1', то добавляем в строку символ "1"
  259.         if (temp_val == 0x32) read_symbol = read_symbol + "2";     // если найдено ASCII значение '2', то добавляем в строку символ "2"
  260.         if (temp_val == 0x33) read_symbol = read_symbol + "3";     // если найдено ASCII значение '3', то добавляем в строку символ "3"
  261.         if (temp_val == 0x34) read_symbol = read_symbol + "4";     // если найдено ASCII значение '4', то добавляем в строку символ "4"
  262.         if (temp_val == 0x35) read_symbol = read_symbol + "5";     // если найдено ASCII значение '5', то добавляем в строку символ "5"
  263.         if (temp_val == 0x36) read_symbol = read_symbol + "6";     // если найдено ASCII значение '6', то добавляем в строку символ "6"
  264.         if (temp_val == 0x37) read_symbol = read_symbol + "7";     // если найдено ASCII значение '7', то добавляем в строку символ "7"
  265.         if (temp_val == 0x38) read_symbol = read_symbol + "8";     // если найдено ASCII значение '8', то добавляем в строку символ "8"
  266.         if (temp_val == 0x39) read_symbol = read_symbol + "9";     // если найдено ASCII значение '9', то добавляем в строку символ "9"
  267.  
  268.       }
  269.       configFile = SD.open("config.ok", FILE_WRITE);               // делаем метку на флешке, что данные успешно считаны.
  270.       configFile.println(F("config.ini was import succes. Update EEPROM succes.\n\rDelete this file for update EEPROM again")); // пишем в файл setup.ok небольшую заметку-инструкцию. Для повторной записи в EEPROM необходимо удалить c SD-карты файл setup.ok
  271.       configFile.close();                                          // закрываем файл
  272.       Serial.println(F("config.ini was import Ок"));               // временный тестовый вывод
  273.     }
  274.   }
  275.   else {
  276.     _F_SD_exist = 0;                                               // нет SD-карты, будем дальше работать без неё.
  277.   }
  278.  
  279.  
  280.  
  281. }                                                                  // конец инициализации
  282.  
  283. boolean T_measuring () {                                           // функция считывания показаний датчиков температуры
  284.   boolean _T_errors = false;                                       // Флаг ошибки при преобразовании температуры
  285.   byte type_s;                                                     // тип термосенсора, если будет замена на другой тип во время эксплуатации
  286.   byte data[12];                                                   // массив для хранения "сырых" данных от текущего термосенсора
  287.   byte addr[8];                                                    // массив для хранения адреса текущего термосенсора
  288.  
  289.   ds.reset();                                                      // начало обмена данными на шине 1-Wire
  290.   ds.skip();                                                       // следующая команда применяется для всех термосенсоров
  291.   ds.write(0x44);                                                  // начать конвертацию данных в значение температуры
  292.   last_time_T = String(time.gettime("H:i:s, "));                   // время последнего сеанса измерения температуры
  293.   delay(150);                                                      // 150 миллисекунд на конвертацию. надо уточнить по даташиту
  294.  
  295.   for (byte i = 0; i < num_sensors; i++) {                         // цикл перебора все термосенсоров в системе
  296.     for (byte x = 0; x < 8; x++) {                                 // цикл считывания из EEPROM адреса текущего термосенсора
  297.       addr[x] =  EEPROM.read(block_2_EEPROM + (i * 9) + x );       // считываем из EEPROM отдельные байты и заносим в массив
  298.     }
  299.  
  300.     if (OneWire::crc8(addr, 7) != addr[7]) {                       // проверяем контрольную сумму считанных из EEPROM байт адреса
  301.       _T_errors = true;                                            // если произошла ошибка при считывании, то устанавливаем флаг ошибки и продолжаем дальше
  302.       if (_F_SD_exist) {                                           // Если SD-карта доступна, то создаём файл с сообщением об ошибке
  303.         File configFile = SD.open("system.err", FILE_WRITE);       // делаем метку на флешке, что данные считаны с ошибкой.
  304.         configFile.print(F("Thermosensor "));                      // пишем в файл system.err сообщение об ошибке
  305.         configFile.print(i);                                       // номер термосенсора по схеме
  306.         configFile.println(F(" CRC is not valid during reading addr from EEPROM !"));
  307.         configFile.close();                                        // закрываем файл
  308.       }
  309.     }
  310.  
  311.     switch (addr[0]) {                                             // первый байт адреса термосенсора указывает на тип сенсора
  312.       case 0x10:                                                   // Chip = DS18S20 или старый тип DS1820
  313.         type_s = 1;                                                // устанавливаем признак типа термосенсора
  314.         break;
  315.       case 0x28:                                                   // Chip = DS18B20
  316.         type_s = 0;                                                // устанавливаем признак типа термосенсора
  317.         break;
  318.       case 0x22:                                                   // Chip = DS1822
  319.         type_s = 0;                                                // устанавливаем признак типа термосенсора
  320.         break;
  321.       default:                                                     // если не удалось идентифицировать термосенсор
  322.         _T_errors = true;                                          // ошибка при редактировании адреса в файле \CONFIG.INI, или ошибка чтения данных из EEPROM
  323.         if (_F_SD_exist) {                                         // Если SD-карта доступна, то создаём файл с сообщением об ошибке
  324.           File configFile = SD.open("system.err", FILE_WRITE);     // делаем метку на флешке, что произлошла ошибка при работе с термосенсором "i".
  325.           configFile.print("Thermosensor ");                       // пишем в файл system.err сообщение об ошибке
  326.           configFile.print(i);                                     // номер термосенсора по схеме
  327.           configFile.println(F(" error when editing the address in the file \CONFIG.INI, or the error reading data from the EEPROM."));
  328.           configFile.close();                                      // закрываем файл
  329.         }
  330.     }
  331.  
  332.     ds.reset();                                                    // начало обмена данными на шине 1-Wire
  333.     ds.select(addr);                                               // адрес текущего термосенсора
  334.     ds.write(0xBE);                                                // начать чтение данных с термосенсора
  335.  
  336.     for (byte j = 0; j < 9; j++) {                                 // нам надо получить 9 байт от термосенсора
  337.       data[j] = ds.read();                                         // массив для "сырых" данных
  338.     }
  339.  
  340.     int16_t raw = (data[1] << 8) | data[0];                        // 16-бит переменная из 2х8
  341.     if (type_s) {                                                  // от типа зависит способ преобразования. Если Chip = DS18S20 или старый DS1820
  342.       raw = raw << 3;                                              // то он имеет 9 бит разрешающую способность
  343.       if (data[7] == 0x10) {                                       // "остаток счёта" может дать нам дополнительно 12 бит разрешающую способность
  344.         raw = (raw & 0xFFF0) + 12 - data[6];
  345.       }
  346.     }
  347.     else {                                                         // если Chip = DS18B20 или Chip = DS1822. обычно установлена 12 бит разрешающая способность, время преобразования 750 ms при "паразитном" питании
  348.       byte cfg = (data[4] & 0x60);                                 // проверяем, естановлен ли бит низкой разрешающей способности
  349.       if (cfg == 0x00) raw = raw & ~7;                             // 9 бит разрешающая способность, время преобразования 93.75 ms
  350.       else if (cfg == 0x20) raw = raw & ~3;                        // 10 бит разрешающая способность, время преобразования 187.5 ms
  351.       else if (cfg == 0x40) raw = raw & ~1;                        // 11 бит разрешающая способность, время преобразования 375 ms
  352.     }
  353.     TEMPERATURE[i] = int(((float)raw / 16.0) * 100);               // массив для измеренных значений температуры всеми термосенсорами
  354.   }
  355.   return _T_errors;                                                // возвращаем флаг о наличии или отсутствии ошибок при работе модуля
  356. }
  357.  
  358.  
  359.  
  360. void loop() {
  361.  
  362.   boolean test = T_measuring();                                    // делаем "снимок" температуры
  363.   Serial.print("_T_errors = ");
  364.   Serial.println(test);                                            // временный тестовый вывод сообщения о наличии ошибок
  365.  
  366.   //----------формируем блок данных для записи на карту ----------
  367.  
  368.   if (_F_SD_exist) {                                               // если присутствует SD-карта
  369.     boolean test1 = LOG_data(1, "00", "00");                       // автоматическое логирование показаний сенсоров температуры
  370.  
  371.     Serial.print("_W_errors = ");
  372.     Serial.println(test1);                                         // временный тестовый вывод сообщения о наличии ошибок
  373.   }
  374.  
  375.  
  376.   delay (10000);                                                   // период опроса сенсоров 10 секунд
  377. }
Advertisement
Add Comment
Please, Sign In to add comment