Управление сервоприводом DS04-NFC

Всех приветствую!

Помогите пожалуйста разобраться с проблеммой:

Сервопривод при написании myServo.detach(); перестаёт вообще работать и выполнять команды

А если не писать myServo.detach(); , то он начинает медленно крутиться и не останавливается

Также у меня не выполняется if: он прерывается или пропускает какие то шаги:

if (temperatureC < 25.0) {  // Температура ниже 25.0 °C
      myServo.attach(9);           // Подключить сигнал
      myServo.write(80);          // Повернуть на 80°
      myServo.detach();           // Отключить сигнал
      digitalWrite(relayPin1, HIGH); // Выключить вентилятор
}

Сервопривод DS04-NFC

Вот полный код:

#include <Wire.h>
#include <U8g2lib.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Servo.h>

// Пин для DS18B20
#define ONE_WIRE_BUS 2

Servo myServo;
const int relayPin1 = 22;  // Реле для вентилятора
const int relayPin2 = 23;  // Реле для питания сервопривода
const int relayPin3 = 24;
const int relayPin4 = 25;
const int relayPin5 = 26;

// Пины для остальных датчиков
const int soilMoisturePin = A0;  // Влажность почвы
const int photoPin = A1;         // Освещенность
const int trigPin = 12;          // Триггер ультразвука
const int echoPin = 11;          // Эхо ультразвука

// Объявление для DS18B20
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Объявление для дисплея
U8G2_SH1107_128X128_F_HW_I2C display(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

// Время (имитация)
int hours = 13;
int minutes = 28;
int seconds = 0;
unsigned long lastTimeUpdate = 0;

// Таймеры для разных обновлений
unsigned long lastTempUpdate = 0;
unsigned long lastSoilUpdate = 0;
unsigned long lastLightUpdate = 0;
unsigned long lastDistUpdate = 0;
unsigned long lastDisplayUpdate = 0;

// Переменные для хранения данных
float temperatureC = 0.0;
int soilPercent = 0;
int brightness = 0;
int distance_mm = -1;

void setup() {
  Serial.begin(9600);
  sensors.begin();

  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  
  display.begin();
  display.clearBuffer();
  display.setContrast(128);

  pinMode(relayPin1, OUTPUT);         
  pinMode(relayPin2, OUTPUT);         
  pinMode(relayPin3, OUTPUT);
  pinMode(relayPin4, OUTPUT); 
  pinMode(relayPin5, OUTPUT);         
  digitalWrite(relayPin1, HIGH);       
  digitalWrite(relayPin2, HIGH);       
  digitalWrite(relayPin3, HIGH);
  digitalWrite(relayPin4, HIGH);
  digitalWrite(relayPin5, HIGH);
  myServo.attach(9);  // Подключить сигнал перед командой
}

void loop() {
  unsigned long currentMillis = millis();

  // Обновление времени каждую секунду
  if (currentMillis - lastTimeUpdate >= 1000) {
    lastTimeUpdate = currentMillis;
    seconds++;
    if (seconds >= 60) {
      seconds = 0;
      minutes++;
      if (minutes >= 60) {
        minutes = 0;
        hours++;
        if (hours >= 24) hours = 0;
      }
    }
  }

  // Обновление температуры каждую 1 секунду
  if (currentMillis - lastTempUpdate >= 1000) {
    lastTempUpdate = currentMillis;
    sensors.requestTemperatures();
    temperatureC = sensors.getTempCByIndex(0);
    
    // Логика для температуры
    if (temperatureC < 25.0) {  // Температура ниже 25.0 °C
      myServo.attach(9);           // Подключить сигнал
      myServo.write(80);          // Повернуть на 80°
      myServo.detach();           // Отключить сигнал
      digitalWrite(relayPin1, HIGH); // Выключить вентилятор
}

    if (temperatureC > 25.0) {  //меньше
        digitalWrite(relayPin1, LOW);
        myServo.attach(9);  // Подключить сигнал перед командой
        myServo.write(0);  // Повернуть сервопривод на 0 градусов
        myServo.detach();  // Отключаем сигнал для экономии энергии
    }
  }
  // Остальные обновления (влажность, освещенность, расстояние, дисплей)
  if (currentMillis - lastSoilUpdate >= 100) {
    lastSoilUpdate = currentMillis;
    int soilVal = analogRead(soilMoisturePin);
    soilPercent = map(soilVal, 1023, 0, 0, 100);
    if (soilPercent < 0) soilPercent = 0;
    if (soilPercent > 100) soilPercent = 100;
  }

  if (currentMillis - lastLightUpdate >= 100) {
    lastLightUpdate = currentMillis;
    brightness = analogRead(photoPin);
  }

  if (currentMillis - lastDistUpdate >= 100) {
    lastDistUpdate = currentMillis;
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    unsigned long duration = pulseIn(echoPin, HIGH, 30000);
    distance_mm = (duration == 0) ? -1 : (int)((duration * 0.343) / 2);
  }

  if (currentMillis - lastDisplayUpdate >= 400) {
    lastDisplayUpdate = currentMillis;
    display.clearBuffer();
    display.setFont(u8g2_font_ncenB08_tr);

    char timeStr[50];
    snprintf(timeStr, sizeof(timeStr), "           Time: %02d:%02d:%02d", hours, minutes, seconds);
    display.drawStr(0, 10, timeStr);

    char tempStr[50];
    dtostrf(temperatureC, 4, 1, tempStr);
    display.drawStr(0, 20, "           Temp: ");
    display.drawStr(70, 20, tempStr);
    display.drawStr(90, 20, " C");

    char soilStr[50];
    snprintf(soilStr, sizeof(soilStr), "           Soil: %d%%", soilPercent);
    display.drawStr(0, 30, soilStr);
    if (distance_mm >= 0) {
      char distStr[50];
      snprintf(distStr, sizeof(distStr), "           Dist: %d mm", distance_mm);
      display.drawStr(0, 40, distStr);
    } else {
      display.drawStr(0, 40, "           Dist: no signal");
    }
    char lightStr[50];
    snprintf(lightStr, sizeof(lightStr), "           Lux: %d", brightness);
    display.drawStr(0, 50, lightStr);
    display.sendBuffer();
  }
}

Он жеж постоянного вращения! Какой нафиг // Повернуть на 80°? У них же вроде скорость устанавливается, а потом, соответственно, скорость в ноль надоть. Наверное :roll_eyes:

Он у меня поворачивается на 80°, но потом если не прописать myServo.detach();, он начинает медленно вращаться

А если прописать myServo.detach(); то он вообще не реагирует на команды

Ну может и не стоит так делать? Что мешает написать

У него по умолчанию скорость на 0.

Речь о том, что бы прекратить насиловать серву и не использовать myServo.attach(9); при каждом обращении, достаточно один раз в сетапе.

Если я делаю myServo.attach(9); , то логично нужно myServo.detach();

Но myServo.detach(); вообще выключает пин для серво и он перестаёт реагировать на команды, а включение пина myServo.attach(9); не помогает

Ёжики и кактусы?

Без myServo.detach(); он будет бесконечно крутить серво

И даже при myServo.write(0); ?

Да, он просто берёт питание с пина

Меняйте серву!

А в чём проблема то?

Вот и узнаете: либо бракованная серва либо конфликт библиотек! А для начала проверьте только серву примитивным скетчем на запуск и остановку.

в том что серва умеет только крутить, она не умеет перемещать на определённый угол

Севопривод вообще не работает

Вот код:

#include <Servo.h>

Servo motor;

void setup() {
  motor.attach(9);       // Подключение сервопривода к пину 9
}

void loop() {
  motor.attach(9);       // Подключение сервопривода к пину 9
  motor.write(80);          // Повернуть на 80 градусов
  motor.detach();       // Подключение сервопривода к пину 9
  delay(1000);
  motor.attach(9);       // Подключение сервопривода к пину 9
  motor.write(-80);
  motor.detach();       // Подключение сервопривода к пину 9   
}

Или вы поговорить пришли?

Вот так работает, но мне нужно без delay()

#include <Servo.h>

Servo motor;

void setup() {
  motor.attach(9);       // Подключение сервопривода к пину 9
}

void loop() {
  motor.attach(9);       // Подключение сервопривода к пину 9
  motor.write(-80);          // Повернуть на 80 градусов
  delay(1000);
  motor.write(80);
  motor.detach();       // Подключение сервопривода к пину 9
  delay(1000);
}

А это как так? :roll_eyes:

У вас точно этот привод?

Вот: