#include <Stepper.h>
#include <math.h>
// --- Настройки шагового двигателя ---
const int stepsPerRev = 580;
// Инициализация библиотеки (Пины: 8, 9, 10, 11)
Stepper stepper(stepsPerRev, 11,10,9,8);
// --- Настройки пинов фоторезисторов ---
const int pinNorth = A5; // Север
const int pinWest = A4; // Запад
const int pinEast = A3; // Восток
const int pinSouth = A2; // Юг
// --- Переменные состояния ---
int currentStep = 0; // Текущее положение стрелки (от 0 до 519)
// При включении считаем, что стрелка смотрит на Восток (0 градусов)
void setup() {
Serial.begin(9600);
// Устанавливаем скорость вращения (об/мин).
// Подберите значение, подходящее для вашего мотора.
stepper.setSpeed(100);
}
void loop() {
// 1. Считываем значения освещенности (от 0 до 1023)
int valNorth = analogRead(pinNorth);
int valWest = analogRead(pinWest);
int valEast = analogRead(pinEast);
int valSouth = analogRead(pinSouth);
// 2. Вычисляем вектор направления света
// Если Восток = 500, а Запад = 0, то x = 500 (тянет на Восток)
float x = valEast - valWest;
// Если Север = 1000, а Юг = 0, то y = 1000 (сильно тянет на Север)
float y = valNorth - valSouth;
// Мертвая зона (шумоподавление): если разница слишком мала,
// значит освещение равномерное или его нет. Мотор не дергается.
if (abs(x) < 30 && abs(y) < 30) {
delay(100);
return;
}
// 3. Вычисляем целевой угол в радианах (от -PI до PI)
float angle = atan2(y, x);
// Приводим угол к круговому диапазону от 0 до 2*PI
if (angle < 0) {
angle += 2 * PI;
}
// 4. Переводим радианы в шаги мотора (от 0 до 519)
// angle / (2 * PI) — это доля от полного круга
int targetStep = round((angle / (2 * PI)) * stepsPerRev);
if (targetStep >= stepsPerRev) targetStep = 0;
// 5. Находим кратчайший путь вращения
int diff = targetStep - currentStep;
// Если разница больше половины круга, выгоднее покрутить в обратную сторону
if (diff > stepsPerRev / 2) {
diff -= stepsPerRev;
} else if (diff < -stepsPerRev / 2) {
diff += stepsPerRev;
}
// 6. Двигаем мотор, если цель изменилась
if (diff != 0) {
stepper.step(-diff);
// Запоминаем новую позицию
currentStep = targetStep;
// Отладочный вывод в монитор порта
Serial.print("Degree: ");
Serial.print(angle * 180.0 / PI);
Serial.print("\tShag: ");
Serial.print(targetStep);
Serial.print("\tSdvig: ");
Serial.println(diff);
}
// Небольшая пауза для стабильности системы
delay(150);
}