Серва при включении скетча устанавливается в какое-то среднее положение

Здравствуйте!
Серва при включении скетча устанавливается в какое-то среднее положение. Причем это не края и не середина, а как-то около.
Потом работает нормально. Всё из скетча лишнее убрал, от классов отказался. (

#include <Servo.h>
#include <IRremote.h>
#include <EEPROM.h>

#define KEY_2 0xB946FF00   // открыть
#define KEY_3 0xB847FF00   // закрыть

int IR = 11;     // IR приёмник
int trigPin = 9; // дальномер зеленый
int echoPin = 8; // дальномер синий
int servoPin1 = 7; // под сервопривод 1

Servo servo;
void move(int corner) {
  int angle;
  int delta = 5;  // дополнительная задержка в конце
  int latency = 20; // основная задержка в конце
  int b_corner = servo.read();

  if (b_corner < corner) {
    // Цикл для поворота от 0 до 90°:  
    for (angle = b_corner; angle <= corner; angle++) {  
        servo.write(angle);
        delay(latency);  
    }  
  }
  if (b_corner > corner) {
    for (angle = b_corner; angle >= corner; angle--) {  
        servo.write(angle);
        delay(latency);  
    }
  }
}

///////////////////////////////////////////////////////
void setup() {
  IrReceiver.begin(IR, DISABLE_LED_FEEDBACK); // вход IR приёмника

  servo.attach(servoPin1);
}


///////////////////////////////////////////////////////
void loop() { 

  if (IrReceiver.decode()) {

    // штатное управление
    switch (IrReceiver.decodedIRData.decodedRawData) {
    case KEY_2:
      move(EEPROM.read(0)); // открыть
      break;
    case KEY_3:
      move(EEPROM.read(1)); // закрыть
      break;
    }

    IrReceiver.resume();             
  }

  delay (100);                 
}

Может серва запомнить что-то или где я туплю?

Спасибо за помощь!

Александр

А де подключение библиотеки для серво?
И код отформатируйте!

Молодцом!

Серва может быть тупо бракованной! Она у вас одна?
Как вариант: обе библиотеки вроде используют прерывание - оттуда и глюки.

@ajkpro А где вы записываете положение сервы в EEPROM?

EEPROM уже ни причем. Я взял примеры из библиотеки. Knob сбрасывает серву в такое же “среднее” положение, а со Sweep серва дает другое начальное положение. Кажется, это положение серва принимает по команде attach.
При чём делает это рывком. А мне медведя крутить.
Ну, так же не должно быть.

Мкей!

“Компьютер не обманешь!”(с) Sweep даёт гарантированный ноль, а Knob как повезёт.
Подключите серву только к питанию и посмотрите на поведение.

Вот, видео запуска.
Изначально некое крайнее положение. Гружу скетч (можно просто включить или перезагрузить) и внимание: рычаг по команде attach вылетает в некое “запомненное” положение, а потом уже ползет в нулевое положение.

Вот, такая фигня.

Дубль два!

И где скетч, если уж

Уберите все из loop, какая реакция?
И что за серва?

ну так добавьте при включении установку угла в определенный угол, это делается в void setup() { в чем проблема то ?)))
при первой прошивки или перепрошивки может работать не пойми как… но это уже другая история)))

Вот, реальный

void setup() {
  Serial.begin(9600);
  Serial.println("========================");

  IrReceiver.begin(IR, DISABLE_LED_FEEDBACK); // вход IR приёмника

  //pinMode(servoPin1, INPUT); // Настраиваем пин как выход
  myServo1.attach(servoPin1); // Подключаем сервопривод к пину
  myServo1.move(EEPROM.read(1)); // поворот мотора в нуль
  //delay(500);

  //pinMode(audioPin, INPUT);  // Устанавливаем пин в высокоимпедансное состояние
  pinMode(audioPin1, OUTPUT); // Настраиваем пин как выход, включатель звука
  digitalWrite(audioPin1, HIGH); // Устанавливаем в 1
  pinMode(audioPin2, OUTPUT); // Настраиваем пин как выход, включатель звука
  digitalWrite(audioPin2, HIGH); // Устанавливаем в 1

в том видео на attach серва дергается, а потом на move плавно ползет.

:grinning_face:

И огрызок скетча - молодцом(с)

Полный скетч был выше.
Но можно повторить

#include <Servo.h>
#include <IRremote.h>
#include <EEPROM.h>

#define KEY_2 0xB946FF00   // открыть
#define KEY_3 0xB847FF00   // закрыть

int IR = 11;     // IR приёмник
int trigPin = 9; // дальномер зеленый
int echoPin = 8; // дальномер синий
int servoPin1 = 7; // под сервопривод 1

Servo servo;
void move(int corner) {
  int angle;
  int delta = 5;  // дополнительная задержка в конце
  int latency = 20; // основная задержка в конце
  int b_corner = servo.read();

  if (b_corner < corner) {
    // Цикл для поворота от 0 до 90°:  
    for (angle = b_corner; angle <= corner; angle++) {  
        servo.write(angle);
        delay(latency);  
    }  
  }
  if (b_corner > corner) {
    for (angle = b_corner; angle >= corner; angle--) {  
        servo.write(angle);
        delay(latency);  
    }
  }
}

///////////////////////////////////////////////////////
void setup() {
  IrReceiver.begin(IR, DISABLE_LED_FEEDBACK); // вход IR приёмника
  servo.attach(servoPin1);
  move(EEPROM.read(1)); // в нуль
}


///////////////////////////////////////////////////////
void loop() { 

  if (IrReceiver.decode()) {

    // штатное управление
    switch (IrReceiver.decodedIRData.decodedRawData) {
    case KEY_2:
      move(EEPROM.read(0)); // открыть
      break;
    case KEY_3:
      move(EEPROM.read(1)); // закрыть
      break;
    }

    IrReceiver.resume();             
  }

  delay (100);                 
}

Из доков

attach() Прикрепите переменную Servo к контакту. Обратите внимание, что в Arduino IDE 0016 и более ранних версиях библиотека Servo поддерживает сервоприводы только на двух контактах: 9 и 10.
Синтаксис
servo.attach(вывод) servo.attach(вывод, минимальный, максимальный)
Параметры сервопривода: переменная типа Servo
pin: номер контакта, к которому подключен сервопривод
min (опционально): длительность импульса в микросекундах, соответствующая минимальному углу (0 градусов) на сервоприводе (по умолчанию 544)
max. (опционально): длительность импульса в микросекундах, соответствующая максимальному углу (180 градусов) на сервоприводе (по умолчанию 2400).

Перепаял на 9 пин - не помогло

Ну и я могу повторить!

А какое вам надо?

И выше уже спрашивали, как ведет себя серва без ардуино при подаче питания и нуле на сигнальном пине. Если дергается, то это дерганьн скорее всего не устранить.

Если не дергается, и вы знаете положение сервы при включении, то передайте ей это значение перед attach

servo.write(angle);
servo.attach(servoPin1);

#include <Servo.h>
#include <IRremote.h>
#include <EEPROM.h>

#define KEY_2 0xB946FF00   // открыть
#define KEY_3 0xB847FF00   // закрыть

int IR = 11;     // IR приёмник
int trigPin = 9; // дальномер зеленый
int echoPin = 8; // дальномер синий
int servoPin1 = 7; // под сервопривод 1

// Адреса EEPROM
#define EEPROM_OPEN 0
#define EEPROM_CLOSE 1
#define EEPROM_INIT 2  // флаг инициализации

Servo servo;

// Плавное перемещение сервы с защитой
void move(int corner) {
  // ЗАЩИТА: ограничиваем угол 0-180°
  corner = constrain(corner, 0, 180);
  
  int angle;
  int latency = 20; // скорость перемещения
  int currentAngle = servo.read(); // текущее положение

  Serial.print("Перемещение с ");
  Serial.print(currentAngle);
  Serial.print(" на ");
  Serial.println(corner);

  if (currentAngle < corner) {
    for (angle = currentAngle; angle <= corner; angle++) {  
        servo.write(angle);
        delay(latency);  
    }  
  }
  else if (currentAngle > corner) {
    for (angle = currentAngle; angle >= corner; angle--) {  
        servo.write(angle);
        delay(latency);  
    }
  }
}

// Безопасное чтение из EEPROM
int safeEEPROMRead(int addr, int defaultValue) {
  int value = EEPROM.read(addr);
  // Проверяем, что значение в допустимом диапазоне
  if (value < 0 || value > 180) {
    Serial.print("Ошибка EEPROM адрес ");
    Serial.print(addr);
    Serial.print(": значение ");
    Serial.print(value);
    Serial.print(", используем по умолчанию: ");
    Serial.println(defaultValue);
    return defaultValue;
  }
  return value;
}

// Инициализация EEPROM при первом запуске
void initEEPROM() {
  Serial.println("Проверка инициализации EEPROM...");
  
  // Проверяем флаг инициализации и корректность данных
  if (EEPROM.read(EEPROM_INIT) != 123 || 
      EEPROM.read(EEPROM_OPEN) > 180 || 
      EEPROM.read(EEPROM_CLOSE) > 180) {
    
    Serial.println("Первая инициализация EEPROM...");
    
    EEPROM.write(EEPROM_OPEN, 0);    // положение "открыто" = 0°
    EEPROM.write(EEPROM_CLOSE, 180); // положение "закрыто" = 180°
    EEPROM.write(EEPROM_INIT, 123);  // устанавливаем флаг инициализации
    
    Serial.println("EEPROM инициализирована значениями: OPEN=0, CLOSE=180");
  } else {
    Serial.println("EEPROM уже инициализирована");
  }
}

// Функция для отладки - печать состояния EEPROM
void printEEPROMState() {
  Serial.println("=== Состояние EEPROM ===");
  Serial.print("OPEN: "); Serial.println(EEPROM.read(EEPROM_OPEN));
  Serial.print("CLOSE: "); Serial.println(EEPROM.read(EEPROM_CLOSE));
  Serial.print("INIT: "); Serial.println(EEPROM.read(EEPROM_INIT));
  Serial.println("========================");
}

///////////////////////////////////////////////////////
void setup() {
  // Инициализация Serial для отладки
  Serial.begin(9600);
  Serial.println("Запуск системы...");
  
  // Инициализация IR приемника
  IrReceiver.begin(IR, DISABLE_LED_FEEDBACK);
  Serial.println("IR приемник инициализирован");
  
  // Инициализация EEPROM ПЕРВЫМ ДЕЛОМ!
  initEEPROM();
  printEEPROMState();
  
  // Инициализация сервопривода
  servo.attach(servoPin1);
  Serial.println("Сервопривод инициализирован");
  
  // Даем серве время на инициализацию
  delay(200);
  
  // БЕЗОПАСНОЕ начальное положение - закрытое
  int safeClosePosition = safeEEPROMRead(EEPROM_CLOSE, 90);
  Serial.print("Установка в начальное положение: ");
  Serial.println(safeClosePosition);
  
  move(safeClosePosition);
  
  Serial.println("Система готова к работе");
  Serial.println("Команды: KEY_2 - открыть, KEY_3 - закрыть");
}

///////////////////////////////////////////////////////
void loop() { 
  if (IrReceiver.decode()) {
    Serial.print("Получена IR команда: ");
    Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);
    
    // Штатное управление
    switch (IrReceiver.decodedIRData.decodedRawData) {
      case KEY_2:
        Serial.println("Команда: ОТКРЫТЬ");
        move(safeEEPROMRead(EEPROM_OPEN, 0));
        break;
      case KEY_3:
        Serial.println("Команда: ЗАКРЫТЬ");
        move(safeEEPROMRead(EEPROM_CLOSE, 180));
        break;
      default:
        Serial.println("Неизвестная команда");
        break;
    }
    
    IrReceiver.resume();             
  }
  
  delay(100);                 
}

// может пригодится

EEPROM тут ни при чём. Я его устанавливал в полной версии программы. И вообще удалял и ставил просто углы.

Помогла строчка установки в 0 перед attach. Тогда он начинает с этого места и соответстветственно перед включением устройство должно быть в нуле.

  // Инициализация сервопривода
  servo.write(180); // помогла строчка установки в 0
  servo.attach(servoPin1);
  Serial.println("Сервопривод инициализирован");

Видимо библиотека постоянно шлет некий импульс. В данном случае 180. А если не задать, то какой-то…

Если я сейчас выдерну разъем сервы, повинуну её и потом включу, то он резко встанет в последнее заданное положение.
Т.е. это библиотека постоянно шлет некий импульс соответсвующий заданному градусу.

Конечно лучше было бы, что бы туда никто ничего не слал до первой команды на движение.

Такая фигня.

Спасибо!

When you attach() a servo it will automatically move to its default angle, which is 90 degrees. If you need it to move to another angle when attached then you need to write() that angle to the servo before using attach()

If you want the servo to not move when attached then you must write() the required angle to it before attaching it which means that you must have saved it and read the angle back in some way, perhaps using EEPRM or an SD card

The servo has no memory so read() returns the last angle that the sketch wrote to the servo. It does not read from the servo

Такой ответ на arduino.cc
У сервопривода нет памяти, поэтому функция read() возвращает последний угол, который sketch записал в сервопривод. Она не считывается с сервопривода

а спросите там, это помогло бы ?))) как раз сетуп можно выполнить серво врайт)))

Помню попадались бракованные сг90, при подаче питания поворачивались на градусов десять по часовой.