#include <DHT.h>
#include <Adafruit_Sensor.h>
#include <Servo.h>
#include <SoftwareSerial.h>
SoftwareSerial bluetooth(10, 11); // создание переменных для блютуз
Servo servo1;
DHT dht(2, DHT11); // причисление датчику пина
int currentAngle = 90; // текущее положение стрелки в градусах
String input = ""; // буфер для входящих команд по Bluetooth
// создание переменных для лимита температуры
float minTemp = 0.0; // при 0°C -> 0°
float maxTemp = 40.0; // при 40°C -> 180°
// корректное линейное преобразование для float значений
float mapFloat(float x, float in_min, float in_max, float out_min, float out_max) {
if (in_max == in_min) return out_min; // защита от деления на ноль
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
void setup() {
dht.begin(); // запуск DHT
Serial.begin(9600); // для отладки через компьютер
bluetooth.begin(9600); // скорость Bluetooth-модуля
servo1.attach(9); // подключение серво к пину 9
servo1.write(90); // начальное положение (середина)
delay(1000);
bluetooth.println("Термометр готов"); // сообщение при старте
}
void loop() {
// Чтение температуры
float t = dht.readTemperature();
// Если чтение успешно, пересчитываем угол и двигаем серво
if (!isnan(t)) {
// mapFloat возвращает float, округляем и приводим к int
int angle = (int)round(mapFloat(t, minTemp, maxTemp, 0.0, 180.0));
angle = constrain(angle, 0, 180); // защита от выхода за пределы
currentAngle = angle;
servo1.write(currentAngle); // поворот сервопривода
}
else {
// При ошибке чтения оставляем предыдущий угол.
}
// Обработка входящих данных по Bluetooth
// Учёт разных окончаний строк: '\n' и '\r'
while (bluetooth.available()) {
char c = bluetooth.read();
if (c == '\n' || c == '\r') {
if (input.length() > 0) {
input.trim(); // убираем пробелы по краям
// Команда "temp" — отправляем текущую с 1 знак после запятой
if (input.equalsIgnoreCase("temp")) {
if (!isnan(t)) {
bluetooth.print("Температура: ");
bluetooth.print(t, 1); // формат с 1 десятичным знаком
bluetooth.println("°C");
} else {
bluetooth.println("ERR_READ"); // ошибка чтения датчика
}
// Команда "angle" — возвращаем текущий угол
} else if (input.equalsIgnoreCase("angle")) {
bluetooth.println(currentAngle);
// Команда "SET:<число>" — ручная установка угла
} else if (input.startsWith("SET:")) {
int manualAngle = input.substring(4).toInt();
if (manualAngle >= 0 && manualAngle <= 180) {
currentAngle = manualAngle;
servo1.write(currentAngle);
bluetooth.println("OK");
} else {
bluetooth.println("ERR"); // неверный диапазон
}
} else {
bluetooth.println("UNKNOWN"); // неизвестная команда
}
}
input = ""; // очищаем буфер после обработки
} else {
input += c; // накапливаем символы команды
}
}
delay(100); // небольшая пауза перед следующим циклом
}