(noob) 2 сервопривода для одновременного перемещения робота (голова и грудь) с разной скоростью

У меня есть Arduino Uno и два цифровых сервопривода Hi-tec HS-40 и 5055, которые я использую для базовой сборки робота. Я пытаюсь заставить 1 сервопривод(HS-40) поворачивать голову вперед и назад (слева направо) немного быстрее, чем другой сервопривод (HS-5055), управляющий верхней частью туловища. Я хотел бы, чтобы каждый сервопривод работал в одно и то же время, но не с одинаковой скоростью, не дожидаясь, пока 1 сервопривод завершит свое движение. Я попробовал скетч с задержкой 45-50, который, кажется, отлично подходит для скорости движения, а 0-75 градусов идеально подходят для перемещения головы и 0-65 градусов для перемещения туловища. Я хотел бы, чтобы это движение повторялось непрерывно, чтобы робот имитировал, как он естественно смотрит из стороны в сторону или слева направо. Пожалуйста, помогите, так как я перепробовал много скетчей, но не могу найти ни одного, который работал бы так. Я пробовал модифицировать другие коды, но не могу заставить их работать. Любая помощь будет очень признательна.

Как изменить этот код так, чтобы только второй сервопривод работал на 40 оборотах, что замедлит работу как раз достаточно? Кроме того, это не мой код, но он, кажется, близок к тому, что я пытаюсь сделать.

#include <Servo.h>

Servo servo1; 
Servo servo2;

int i = 0;

void setup() {
  servo1.attach(8);
  servo2.attach(9); 
   
}

void loop() {
  for (i = 0; i < 70; i++) { 
    servo1.write(i);              
    servo2.write(i);     
    delay(50);                      
  }
  for (i = 70; i > 0; i--) { 
    servo1.write(i);                
    servo2.write(i);     
    delay(50);                      
  }

}

, 👍1

Обсуждение

Пожалуйста, опубликуйте какой-нибудь код, который вы используете. Без отправной точки трудно предложить какую-либо помощь. Но найдите в Google "мигать без промедления", чтобы найти подход, который может сработать., @tavis

Вот код. Можно ли добавить команду "Задержка" ко второму сервоприводу, чтобы замедлить его до 40? #включить<Servo.h> Сервопривод серво1; Сервопривод servo2; int i = 0; недействительная настройка() { servo1.attach(8); servo2.прикрепить(9); } void loop() { для (i = 0; i < 70; i++) { servo1.запись(i); servo2.запись(i); задержка(50); } для (i = 70; i > 0; i--) { servo1.запись(i); servo2.запись(i); задержка(50); } }, @John Conner

измените строку на " servo1.напишите(2*i);`, @jsotola


2 ответа


1

Вот небольшой скетч, который вы можете попробовать. Он использует время для достижения различных скоростей сервопривода. Это не даст вам точное следящее перемещение каждого цикла, но похоже, что вы не возражаете, если он случайно выключен на несколько градусов каждый цикл.

#include <Servo.h>
Servo servo1;
Servo servo2;
int i = 0;
void setup() {
  Serial.begin(9600);
  servo1.attach(8); 
  servo2.attach(9); 
} 

int sweep_time = 3500; // 70 * 50ms = 3500

int head_degrees = 75; // sweep degrees for the head to move
int body_degrees = 65; // sweep degrees for the body to move

int millis_per_head_move = sweep_time / head_degrees;
int millis_per_body_move = sweep_time / body_degrees;

void loop() {
  int i = 0; int j = 0;
  unsigned long now_millis = 0;
  unsigned long start_sweep = millis(); // mark the time when we start the first sweep
  
  while ( millis() - start_sweep < sweep_time ) {  // keep moving first sweep until sweep time has elapsed
    now_millis = millis() - start_sweep;
    if (now_millis % millis_per_head_move == 0 ) servo1.write(i++);
    if (now_millis % millis_per_body_move == 0 ) servo2.write(j++);
    delay(1);
  }
  Serial.print(i); Serial.print(" "); Serial.println(j);
  
  start_sweep = millis();  // mark the time when we start the second/back sweep
  while ( millis() - start_sweep < sweep_time ) {  // keep moving second sweep until sweep time has elapsed
    now_millis = millis() - start_sweep;
    if (now_millis % millis_per_head_move == 0) servo1.write(i--);
    if (now_millis % millis_per_body_move == 0) servo2.write(j--);
    delay(1);
  }
  Serial.print(i); Serial.print(" "); Serial.println(j);
}
,

Большое вам за это спасибо. Я немного нервничал с предыдущим кодом, когда голова откинулась назад, но я думаю, что мне нужно добавить немного веса для балласта в голову и туловище, чтобы помочь стабилизировать их. Этот код, по-видимому, сводит к минимуму некоторые колебания. Я проверил его с некоторым добавленным весом, и теперь, похоже, он стал лучше. Надеюсь, как только я закончу этот проект, я опубликую ссылку, по которой вы сможете увидеть его в действии. Еще раз спасибо за всю помощь! Очень признателен., @John Conner

Рад, что это работает! Если мой ответ решил проблему, пожалуйста, отметьте его как принятый ответ., @tavis

Вы делаете это, щелкнув галочку рядом с чьим-то ответом., @Austin


0

Спасибо за ответ от @tavis

Вот симуляция их кода, и он точно отвечает на ваши вопросы.

Код (такой же, как и выше, за исключением изменения времени развертки)

#include <Servo.h>
Servo servo1;
Servo servo2;
int i = 0;
void setup() {
  Serial.begin(9600);
  servo1.attach(8); 
  servo2.attach(9); 
} 

int sweep_time = 1000; // 70 * 50ms = 3500

int head_degrees = 75; // градусы развертки для перемещения головы
int body_degrees = 65; // градусы развертки для перемещения тела

int millis_per_head_move = sweep_time / head_degrees;
int millis_per_body_move = sweep_time / body_degrees;

void loop() {
  int i = 0; int j = 0;
  unsigned long now_millis = 0;
  unsigned long start_sweep = millis(); // отметьте время, когда мы начинаем первую развертку
  
  while ( millis() - start_sweep < sweep_time ) {  // keep moving first sweep until sweep time has elapsed
    now_millis = millis() - start_sweep;
    if (now_millis % millis_per_head_move == 0 ) servo1.write(i++);
    if (now_millis % millis_per_body_move == 0 ) servo2.write(j++);
    delay(1);
  }
  Serial.print(i); Serial.print(" "); Serial.println(j);
  
  start_sweep = millis();  // отметьте время, когда мы начинаем вторую/обратную развертку
  while ( millis() - start_sweep < sweep_time ) {  // keep moving second sweep until sweep time has elapsed
    now_millis = millis() - start_sweep;
    if (now_millis % millis_per_head_move == 0) servo1.write(i--);
    if (now_millis % millis_per_body_move == 0) servo2.write(j--);
    delay(1);
  }
  Serial.print(i); Serial.print(" "); Serial.println(j);
}

Ссылка на симуляцию:
https://wokwi.com/arduino/projects/303847722463527490

Вот еще один пример с тремя сервомоторами, работающими в три разных времени развертки:
https://wokwi.com/arduino/projects/299552195816194570

,