#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
#define DHTPIN 3
#define DHTTYPE DHT22
#define BUTTON_PIN A3
const int sensorPin = A2;
const int temperaturePin = A1;
DHT dht(DHTPIN, DHTTYPE);
bool lastButtonState = HIGH;
int displayMode = 0;
bool buttonPressed = false;
const float BETA = 3950; // Коэффициент B терморезистора
const float Gamma = 0.7; // Параметр для расчёта освещённости
const float RL10 = 50; // Сопротивление при 10 люкс (кОм)
// Глобальные переменные для хранения текущих данных датчиков
float currentT = 1.0;
float currentH = 1.0;
float currentLux = 1.0;
float currentCelsius = 1.0;
float currentH_old = 1.0;
float currentT_old = 1.0;
float currentLux_old = 1.0;
float currentCelsius_old = 1.0;
void setup() {
Serial.begin(9600);
lcd.begin(20, 4);
lcd.clear();
lcd.backlight();
dht.begin();
pinMode(BUTTON_PIN, INPUT_PULLUP);
// 1. Даём АЦП стабилизироваться
delay(500);
// 2. Первое грубое считывание (прогрев АЦП)
readAllSensors();
// 3. Пауза для успокоения сигналов
delay(200);
// Однократное считывание датчиков при старте
readAllSensors();
int ntcValue = analogRead(temperaturePin) - 8;
Serial.print(ntcValue);
currentCelsius = 1 / (log(1 / (1023. / ntcValue - 1)) / BETA + 1.0 / 298.15) - 273.15;
Serial.println("demo");
Serial.print(currentCelsius);
// Вывод всех датчиков на дисплей при старте
displayData(0, currentT, currentH, currentLux, currentCelsius);
// Отправка в Serial при старте
sendToSerial(0, currentT, currentH, currentLux, currentCelsius);
}
void loop() {
bool currentButtonState = digitalRead(BUTTON_PIN);
// Считываем все датчики один раз за цикл
readAllSensors();
// Проверяем, изменилось ли хотя бы одно значение
if (currentH != currentH_old ||
currentT != currentT_old ||
currentCelsius != currentCelsius_old ||
currentLux != currentLux_old) {
displayData(displayMode, currentT, currentH, currentLux, currentCelsius);
sendToSerial(displayMode, currentT, currentH, currentLux, currentCelsius);
// Обновляем «старые» значения
currentH_old = currentH;
currentT_old = currentT;
currentLux_old = currentLux;
currentCelsius_old = currentCelsius;
}
// Обработка нажатия кнопки
if (lastButtonState == HIGH && currentButtonState == LOW) {
buttonPressed = true;
displayMode++;
if (displayMode > 5) displayMode = 0;
}
if (buttonPressed) {
// Пересчитываем датчики при нажатии кнопки
readAllSensors();
displayData(displayMode, currentT, currentH, currentLux, currentCelsius);
sendToSerial(displayMode, currentT, currentH, currentLux, currentCelsius);
buttonPressed = false;
delay(30); // Антидребезг
}
lastButtonState = currentButtonState;
}
// Функция для единовременного считывания всех датчиков
void readAllSensors() {
// 1. Датчик освещённости (LDR)
int ldrValue = analogRead(sensorPin);
float ldrVoltage = ldrValue / 1023.0 * 5.0;
float ldrResistance = 10000.0 * ldrVoltage / (5.0 - ldrVoltage); // R_upper = 10 кОм
currentLux = pow(RL10 * 1e3 * pow(10, Gamma) / ldrResistance, (1.0 / Gamma));
// 2. Датчик температуры NTC
int ntcValue = analogRead(temperaturePin);
Serial.print("Проверка датчика");
Serial.print(ntcValue);
float ntcVoltage = ntcValue / 1023.0 * 5.0; // Напряжение на аналоговом пине
// Рассчитываем сопротивление NTC
// Если NTC внизу (к GND), а верхний резистор 10 кОм:
float R_ntc = 10000.0 * ntcVoltage / (5.0 - ntcVoltage);
// Защита от некорректных значений
if (R_ntc <= 0 || isnan(R_ntc)) {
currentCelsius = 0.0; // или другое значение по умолчанию
return;
}
// Формула Стейнхарта‑Харта (корректная версия)
float logR = log(R_ntc); // натуральный логарифм
float T_Kelvin = 1.0 / (
(1.0 / 298.15) +
(1.0 / BETA) * (logR - log(10000.0)) // log(10кОм) — опорное сопротивление
);
currentCelsius = T_Kelvin - 273.15;
// Ограничиваем диапазон (опционально)
if (currentCelsius < -50 || currentCelsius > 150) {
currentCelsius = 0.0; // ошибка измерения
}
// 3. Датчик DHT22 (температура и влажность)
currentH = dht.readHumidity();
currentT = dht.readTemperature();
// Защита от NaN (DHT может возвращать ошибки)
if (isnan(currentH)) currentH = 0.0;
if (isnan(currentT)) currentT = 0.0;
}
void displayData(int mode, float t, float h, float lux, float celsius) {
char tempStr[8];
dtostrf(t, 5, 1, tempStr); // 1 знак после запятой
char celsiusStr[8];
dtostrf(celsius, 5, 1, celsiusStr);
char humStr[8];
dtostrf(h, 5, 1, humStr);
lcd.clear();
switch (mode) {
case 0:
lcd.setCursor(0, 0); lcd.print("Temp_DHT: "); lcd.print(tempStr); lcd.print(" "); lcd.write(byte(223)); lcd.print("C");
lcd.setCursor(0, 1); lcd.print("Humidity: "); lcd.print(humStr); lcd.print(" %");
lcd.setCursor(0, 2); lcd.print("LDR: "); lcd.print(lux, 0); lcd.print(" lux");
lcd.setCursor(0, 3); lcd.print("Temp_NTC: "); lcd.print(celsiusStr); lcd.print(" "); lcd.write(byte(223)); lcd.print("C");
break;
case 1:
lcd.setCursor(0, 0); lcd.print("Temp_DHT: "); lcd.print(tempStr); lcd.print(" "); lcd.write(byte(223)); lcd.print("C");
break;
case 2:
lcd.setCursor(0, 0); lcd.print("Humidity: "); lcd.print(humStr); lcd.print(" %");
break;
case 3:
lcd.setCursor(0, 0); lcd.print("LDR: "); lcd.print(lux, 0); lcd.print(" lux");
break;
case 4:
lcd.setCursor(0, 0); lcd.print("Temp_NTC: "); lcd.print(celsiusStr); lcd.print(" "); lcd.write(byte(223)); lcd.print("C");
break;
case 5:
lcd.clear();
break;
}
}
void sendToSerial(int mode, float t, float h, float lux, float celsius) {
switch (mode) {
case 0:
Serial.println("All sensors:");
Serial.print("Temp_DHT: "); Serial.print(round(t) ); Serial.println(" °C");
Serial.print("Humidity: "); Serial.print(round(h) ); Serial.println(" %");
Serial.print("LDR: "); Serial.print(round(lux) ); Serial.println(" lux");
Serial.print("Temp_NTC: "); Serial.print(round(celsius)); Serial.println(" °C");
break;
case 1:
Serial.print("Temp_DHT: "); Serial.print(t); Serial.println(" °C");
break;
case 2:
Serial.print("Humidity: "); Serial.print(h); Serial.println(" %");
break;
case 3:
Serial.print("LDR: "); Serial.print(lux); Serial.println(" lux");
break;
case 4:
Serial.print("Temp_NTC: "); Serial.print(celsius); Serial.println(" °C");
break;
case 5:
Serial.println("Empty screen");
break;
}
Serial.println();
}