#include <Servo.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <GyverSettings.h>
// Настройки WiFi
const char* ssid = "MausModern";
const char* password = "modern2025";
// Создаем объекты сервоприводов
Servo servoX; // Сервопривод по оси X
Servo servoY; // Сервопривод по оси Y
Servo servoZ; // Сервопривод по оси Z
// Пины подключения сервоприводов
const int servoXPin = 9; // Пин для сервопривода X
const int servoYPin = 10; // Пин для сервопривода Y
const int servoZPin = 11; // Пин для сервопривода Z
const int pirPin = 2; // Пин для PIR датчика
const int switchPin = 3; // Пин для движкового переключателя
const int joystickX = A0; // Пин для оси X джойстика
const int joystickY = A1; // Пин для оси Y джойстика
const int potPin = A2; // Пин для потенциометра оси Z
// Параметры для сохранения в EEPROM
Settings settings;
int minPosX = 0;
int maxPosX = 180;
int minPosY = 60;
int maxPosY = 150;
int minPosZ = 150;
int maxPosZ = 180;
int midPos = 90;
int step = 1;
// Текущие и целевые положения
int currentX = midPos;
int targetX = midPos;
int currentY = midPos;
int targetY = midPos;
int currentZ = midPos;
int targetZ = midPos;
// Таймеры для движения
unsigned long moveTimerX = 0;
unsigned long moveTimerY = 0;
unsigned long moveTimerZ = 0;
unsigned long changeTimerX = 0;
unsigned long changeTimerY = 0;
unsigned long changeTimerZ = 0;
unsigned long pauseTimerX = 0;
unsigned long pauseTimerY = 0;
unsigned long pauseTimerZ = 0;
unsigned long emergencyTimer = 0;
// Интервалы времени
unsigned long moveInterval = 50;
const unsigned long changeInterval = 50;
unsigned long pauseInterval = 0;
bool emergencyMode = false;
bool manualMode = false;
// Веб-сервер
ESP8266WebServer server(80);
void setup() {
// Инициализация EEPROM
EEPROM.begin(512);
settings.begin(EEPROM, 0);
settings.load();
// Инициализация сервоприводов
servoX.attach(servoXPin);
servoY.attach(servoYPin);
servoZ.attach(servoZPin);
// Настройка пинов
pinMode(pirPin, INPUT);
pinMode(switchPin, INPUT_PULLUP);
// Устанавливаем начальное положение
servoX.write(midPos);
servoY.write(midPos);
servoZ.write(midPos);
// Задаем начальные таймеры
moveTimerX = millis();
moveTimerY = millis();
moveTimerZ = millis();
changeTimerX = millis();
changeTimerY = millis();
changeTimerZ = millis();
// Инициализация WiFi
WiFi.mode(WIFI_AP);
WiFi.softAP(ssid, password);
// Настройка веб-сервера
server.on("/", handleRoot);
server.on("/manual", handleManual);
server.on("/settings", handleSettings);
server.begin();
Serial.begin(115200);
Serial.println("Maus");
}
void loop() {
server.handleClient();
// Проверка состояния переключателя
manualMode = digitalRead(switchPin) == LOW;
if (manualMode) {
// Ручной режим управления через веб-интерфейс
moveServo(currentX, targetX, targetX, 1, servoX);
moveServo(currentY, targetY, 1, servoY);
moveServo(currentZ, targetZ, 1, servoZ);
} else {
// Автоматический режим
step = random(1, 5);
moveInterval = random(random(1, 50), random(50, 500));
pauseInterval = random(1, random(1, mint));
// Проверка состояния PIR датчика
if (digitalRead(pirPin) == HIGH) {
if (!emergencyMode) {
servoX.write(midPos);
servoY.write(midPos);
servoZ.write(0);
currentX = midPos;
currentY = midPos;
currentZ = 0;
emergencyMode = true;
emergencyTimer = millis();
}
} else {
if (emergencyMode) {
if (millis() - emergencyTimer >= 15000) {
emergencyMode = false;
}
}
}
if (emergencyMode) {
return;
}
// Движение по осям
if (millis() - moveTimerX >= moveInterval) {
if (millis() - pauseTimerX >= pauseInterval) {
moveServo(currentX, targetX, step, servoX);
moveTimerX = millis();
pauseTimerX = millis();
if (millis() - changeTimerX >= random(1000, 360000)) {
targetX = random(minPosX, maxPosX + 1);
changeTimerX = millis();
}
}
}
if (millis() - moveTimerY >= moveInterval) {
if (millis() - pauseTimerY >= pauseInterval) {
moveServo(currentY, targetY, step, servoY);
moveTimerY = millis();
pauseTimerY = millis();
if (millis() - changeTimerY >= random(100, 360000)) {
targetY = random(minPosY, maxPosY + 1);
changeTimerY = millis();
}
}
}
if (millis() - moveTimerZ >= moveInterval) {
if (millis() - pauseTimerZ >= pauseInterval) {
moveServo(currentZ, targetZ, step, servoZ);
moveTimerZ = millis();
pauseTimerZ = millis();
if (millis() - changeTimerZ >= random(100, 360000)) {
targetZ = random(minPosZ, maxPosZ + 1);
changeTimerZ = millis();
}
}
}
}
}
// Функция плавного перемещения сервопривода
void moveServo(int ¤t, int target, int step, Servo servo) {
if (current < target) {
current = min(current + step, target);
} else if (current > target) {
current = max(current - step, target);
}
servo.write(current);
}
// Обработчик корневого URL
void handleRoot() {
String html = "<html><head><title>MausModern</title></head><body>";
html += "<h1>Управление MausModern</h1>";
html += "<p>Режим: ";
html += (manualMode ? "Ручной" : "Автоматический");
html += "</p>";
html += "<a href='/manual'>Перейти в ручное управление</a><br>";
html += "<a href='/settings'>Настройки</a>";
html += "</body></html>";
server.send(200, "text/html", html);
}
// Обработчик ручного управления
void handleManual() {
String html = "<html><head><title>Ручное управление</title></head><body>";
html += "<h1>Ручное управление</h1>";
html += "<form action='/manual' method='post'>";
html += "X: <input type='range' name='x' min='0' max='180' value='" + String(currentX) + "'><br>";
html += "Y: <input type='range' name='y' min='0' max='180' value='" + String(currentY) + "'><br>";
html += "Z: <input type='range' name='z' min='0' max='180' value='" + String(currentZ) + "'><br>";
html += "<input type='submit' value='Установить'>";
html += "</form>";
html += "<a href='/'>Назад</a>";
server.send(200, "text/html", html);
if (server.hasArg("x")) {
targetX = server.arg("x").toInt();
}
if (server.hasArg("y")) {
targetY = server.arg("y").toInt();
}
if (server.hasArg("z")) {
targetZ = server.arg("z").toInt();
}
}
// Обработчик настроек
void handleSettings() {
String html = "<html><head><title>Настройки</title></head><body>";
html += "<h1>Настройки параметров движения</h1>";
html += "<form action='/settings' method='post'>";
html += "Min X: <input type='number' name='minX' value='" + String(minPosX) + "'><br>";
html += "Max X: <input type='number' name='maxX' value='" + String(maxPosX) + "'><br>";
html += "Min Y: <input type='number' name='minY' value='" + String(minPosY) + "'><br>";
html += "Max Y: <input type='number' name='maxY' value='" + String(maxPosY) + "'><br>";
html += "Min Z: <input type='number' name='minZ' value='" + String(minPosZ) + "'><br>";
html += "Max Z: <input type='number' name='maxZ' value='" + String(maxPosZ) + "'><br>";
html += "Шаг движения: <input type='number' name='step' value='" + String(step) + "'><br>";
html += "<input type='submit' value='Сохранить'>";
html += "</form>";
html += "<a href='/'>Назад</a>";
server.send(200, "text/html", html);
if (server.hasArg("minX")) {
minPosX = server.arg("minX").toInt();
settings.write("minPosX", minPosX);
}
if (server.hasArg("maxX")) {
maxPosX = server.arg("maxX").toInt();
settings.write("maxPosX", maxPosX);
}
if (server.hasArg("minY")) {
minPosY = server.arg("minY").toInt();
settings.write("minPosY", minPosY);
}
if (server.hasArg("maxY")) {
maxPosY = server.arg("maxY").toInt();
settings.write("maxPosY", maxPosY);
}
if (server.hasArg("minZ")) {
minPosZ = server.arg("minZ").toInt();
settings.write("minPosZ", minPosZ);
}
if (server.hasArg("maxZ")) {
maxPosZ = server.arg("maxZ").toInt();
settings.write("maxPosZ", maxPosZ);
}
if (server.hasArg("step")) {
step = server.arg("step").toInt();
settings.write("step", step);
}
settings.save();
}
// Загрузка настроек из EEPROM при старте
void loadSettings() {
minPosX = settings.read("minPosX", 0);
maxPosX = settings.read("maxPosX", 180);
minPosY = settings.read("minPosY", 60);
maxPosY = settings.read("maxPosY", 150);
minPosZ = settings.read("minPosZ", 150);
maxPosZ = settings.read("maxPosZ", 180);
step = settings.read("step", 1);
}