// Подключение необходимых библиотек #include // Для работы с шиной 1-Wire #include // Для I2C коммуникации #include // Для работы с датчиками температуры DS18B20 #include // Библиотека OLED-дисплея iarduino_OLED_txt myOLED(0x78); // Создание объекта дисплея (адрес 0x78) extern const uint8_t MediumFont[]; // Подключение шрифта // Определение пинов #define ONE_WIRE_BUS 10 // Пин для подключения датчиков температуры #define RESET_PIN 7 // Пин для сброса нумерации #define MANUAL_MODE_PIN 9 // Пин для активации ручного режима // Инициализация объектов для работы с датчиками OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); // Константы и глобальные переменные const float TEMP_THRESHOLD = 27.0; // Порог температуры для автоматической нумерации DeviceAddress tempSensors[24]; // Массив для хранения адресов датчиков int totalSensors = 0; // Общее количество найденных датчиков int numberedSensors = 0; // Количество пронумерованных датчиков bool isNumbered[24] = {false}; // Флаги нумерации для каждого датчика // Прототипы функций void updateDisplay(String line1 = "", String line2 = "", String line3 = ""); void writeStoredNumber16(DeviceAddress addr, uint16_t number); /* Запись 16-битного числа в память датчика */ void writeStoredNumber16(DeviceAddress addr, uint16_t number) { // Разделение числа на два байта uint8_t lowByte = (number >> 8) & 0xFF; // Старший байт uint8_t highByte = number & 0xFF; // Младший байт // Использование функций установки алармов для записи данных sensors.setHighAlarmTemp(addr, highByte); sensors.setLowAlarmTemp(addr, lowByte); sensors.saveScratchPad(addr); // Сохранение изменений } /* Сброс всех назначенных номеров */ void resetAllNumbers() { for (int i = 0; i < totalSensors; i++) { if (isNumbered[i]) { writeStoredNumber16(tempSensors[i], 0); // Запись нуля isNumbered[i] = false; } } numberedSensors = 0; Serial.println("All numbers reset!"); updateDisplay("Reset complete!", "", ""); } /* Вывод адреса датчика в serial port */ void printAddress(DeviceAddress addr) { for (uint8_t i = 0; i < 8; i++) { if (addr[i] < 16) Serial.print("0"); Serial.print(addr[i], HEX); // Вывод в HEX-формате } } /* Обновление информации на OLED-дисплее */ void updateDisplay(String line1, String line2, String line3) { myOLED.clrScr(); // Вывод трех строк пользовательского текста if (line1 != "") myOLED.print(line1, 0, 0); if (line2 != "") myOLED.print(line2, 0, 1); if (line3 != "") myOLED.print(line3, 0, 2); // Статусная информация (всегда отображается) myOLED.print("Total: " + String(totalSensors), 0, 3); myOLED.print("Active: " + String(numberedSensors), 0, 4); } /* Режим ручного назначения номера */ void manualMode() { if (totalSensors == 0) { Serial.println("No sensors found for manual mode!"); updateDisplay("No sensors!", "", ""); return; } Serial.println("\nManual mode activated!"); updateDisplay("Manual mode", "Enter number:", "0-65535"); while (!Serial.available()); // Ожидание ввода пользователя String input = Serial.readStringUntil('\n'); uint16_t number = input.toInt(); // Проверка допустимости значения if (number > 65535) { Serial.println("Error: Number too large! Max is 65535"); updateDisplay("Error:", "Number too large!", "Max 65535"); delay(2000); return; } // Получение адреса последнего датчика DeviceAddress lastSensor; memcpy(lastSensor, tempSensors[totalSensors - 1], sizeof(DeviceAddress)); // Вывод информации о назначении Serial.print("Setting number "); Serial.print(number); Serial.print(" (0x"); Serial.print(number, HEX); Serial.print(") to sensor: "); printAddress(lastSensor); Serial.println(); // Запись номера в датчик writeStoredNumber16(lastSensor, number); // Обновление счетчиков if (!isNumbered[totalSensors - 1]) { numberedSensors++; isNumbered[totalSensors - 1] = true; } updateDisplay("Assigned:", String(number), "to last sensor"); Serial.println("Manual mode completed!"); delay(2000); } /* Инициализация системы */ void setup() { Serial.begin(9600); myOLED.begin(); // Инициализация дисплея myOLED.setFont(SmallFontRus); // Установка шрифта // Настройка пинов pinMode(RESET_PIN, INPUT); pinMode(MANUAL_MODE_PIN, INPUT_PULLUP); Serial.println("System started"); updateDisplay("System started", "", ""); sensors.begin(); // Старт работы с датчиками totalSensors = sensors.getDeviceCount(); // Поиск датчиков Serial.print("Found sensors: "); Serial.println(totalSensors); updateDisplay("Found:", String(totalSensors) + " sensors", ""); delay(1000); // Вывод адресов всех найденных датчиков for (int i = 0; i < totalSensors; i++) { if (sensors.getAddress(tempSensors[i], i)) { Serial.print("Sensor "); Serial.print(i + 1); Serial.print(": "); printAddress(tempSensors[i]); Serial.println(); } } updateDisplay("Ready", "", ""); } /* Основной цикл программы */ void loop() { myOLED.invScr(); // Инверсия экрана для визуальной индикации работы // Проверка активации ручного режима if (digitalRead(MANUAL_MODE_PIN) == HIGH) { delay(50); // Защита от дребезга if (digitalRead(MANUAL_MODE_PIN) == HIGH) { manualMode(); delay(1000); return; } } // Проверка кнопки сброса if (digitalRead(RESET_PIN)) { updateDisplay("Resetting...", "", ""); resetAllNumbers(); delay(1000); return; } // Основная логика работы: опрос датчиков sensors.requestTemperatures(); // Проверка температуры каждого датчика for (int i = 0; i < totalSensors; i++) { float temp = sensors.getTempC(tempSensors[i]); // Если температура выше порога и датчик еще не нумерован if (temp != DEVICE_DISCONNECTED_C && temp > TEMP_THRESHOLD && !isNumbered[i]) { numberedSensors++; writeStoredNumber16(tempSensors[i], numberedSensors); isNumbered[i] = true; Serial.print("Sensor "); printAddress(tempSensors[i]); Serial.print(" got #"); Serial.println(numberedSensors); updateDisplay("Assigned #" + String(numberedSensors), "", ""); delay(500); } } delay(1000); // Пауза между измерениями }