【问题标题】:Make Servo motors move more smoothly using a joystick?使用操纵杆使伺服电机运动更顺畅?
【发布时间】:2019-02-25 20:45:35
【问题描述】:

所以我正在使用两个伺服电机制作一个“炮塔”类型的东西,由一个操纵杆控制。我正在运行的代码可以工作,但是它非常生涩并且移动得不是很好,尤其是在对角线上。我的代码如下:

#include <Servo.h>
#define LASER 11

int x = 0;

Servo servo_1;  // create servo object to control a servo
Servo servo_2;

// Arduino pin numbers
const int SW_pin = 2; // digital pin connected to switch output
const int X_pin = 0; // analog pin connected to X output
const int Y_pin = 1; // analog pin connected to Y output

int butt;
int joy_val;

void setup() {
  pinMode(SW_pin, INPUT);
  digitalWrite(SW_pin, HIGH);
  servo_1.attach(9);// attaches the servo on pin 9 to the servo object
  servo_2.attach(10);
  pinMode(LASER, OUTPUT);
  digitalWrite(LASER, HIGH);
  Serial.begin(9600);
}

void loop() {
  joy_val = analogRead(X_pin); // reads the value of joystick (between 0-1023)
  joy_val = map(joy_val, 0, 1023, 0, 180); // servo value between 0-180
  servo_1.write(joy_val); // sets the servo position according to the joystick value
  delay(150);

  joy_val = analogRead(Y_pin); // reads the value of joystick (between 0-1023)
  joy_val = map(joy_val, 0, 1023, 0, 180); // servo value between 0-180
  servo_2.write(joy_val); // sets the servo position according to the joystick 
value
  delay(150);
  delay(15);

  butt = digitalRead(SW_pin);

  if (butt == LOW){
    x = true;
  }

  if (x == true){
    digitalWrite(LASER, LOW);
    Serial.print(x);
  }
}

非常感谢任何建议或帮助,我对 arduino 还很陌生 :)

【问题讨论】:

  • 首先你有一些延迟。如果删除它们会怎样?
  • 您还应该解释一下 Jerky 的含义。我认为这意味着输入被延迟了,但阿德里安的回答是关于消除抖动的操纵杆值读数。

标签: arduino joystick servo


【解决方案1】:

伺服系统小而轻,并试图尽快移动到您告诉它们的位置。操纵杆也可以非常快速地更改值,并且它们也可能出现故障。因此,您的伺服系统会不断进行大量小而快的动作,这会使炮塔看起来很生涩。

我可以想到两个选项,您可能想同时做两个:

  1. 通过一些低通滤波来平滑操纵杆输入。这通常仅意味着使用当前值和先前值的加权平均值。这个想法是为了消除由于电位器中的脏触点而可能发生的一两个错误读数。

  2. 平滑运动。与其立即尝试将伺服系统直接移动到操纵杆的当前位置,不如将它们移向目标位置。在循环的每次迭代中,它们都会更接近目标位置,而不是试图几乎瞬间跳到那里。

对于#2,我喜欢使用几种方法。

一种是简单地使用舵机当前位置和目标位置的加权平均值。如果您将操纵杆移动一段距离,炮塔将快速旋转,但在接近目标位置时会减慢速度。

另一种是使用物理模型。想象一下,创建一个力矢量,该矢量从伺服器的当前位置指向操纵杆的目标位置,并且与它们之间的距离成正比。将该力应用于当前点。还要施加一个抵抗当前点速度的“摩擦”力。对循环中的速度和位置进行数值积分。如果您突然将操纵杆移动到一个新位置,那么炮塔将朝它加速,然后在接近它时减速。调整用于计算力的常数可以让您控制机制看起来有多“重”。

【讨论】:

    【解决方案2】:

    我设置了一个与伺服速度成正比的延迟。试试这个(取自我的教程:Arduino Servo Motor Basics and Control):

    #include <Servo.h>
    #include <math.h>
    
    Servo servo_1; // servo controller (multiple can exist)
    
    int servo_pin = 3; // PWM pin for servo control
    int joy_pin_x = A0; // pin for x-dir joystick
    int joy_pin_y = A1; // pin for y-dir joystick
    int offset_x = 0; // subtracting the initial joystick x-location
    int offset_y = 0; // subtracting the initial joystick y-location
    int pos = 90;    // servo starting position aligned with joystick
    int prev_deg = 0; // bound for reducing jitter
    int x_prev = 0; // bound for reducing jitter
    int y_prev = 0; // reducing jitter
    
    void setup() {
      servo_1.attach(servo_pin); // start servo control
      Serial.begin(9600);
      servo_1.write(pos); // move to center (joystick neutral)
      Serial.println("Positioned at 90 Degrees");  
      offset_x = analogRead(joy_pin_x); // initial joystick x-val
      offset_y = analogRead(joy_pin_y); // initial joystick y-val
    }
    
    void loop() {
      int x_val = analogRead(joy_pin_x)-offset_x; // relative joystick x
      int y_val = analogRead(joy_pin_y)-offset_y; // relative joystick y
      if (abs(x_prev-x_val)<10 and abs(y_prev-y_val)<10){
        // reduce jitter
      } else {
        x_prev = x_val;
        y_prev = y_val;
        float deg = 180-(int(atan2(x_val,y_val)*(180.0/PI))+90); // angle calc
        if (abs(deg-prev_deg)>2 and deg>0 and deg<180){
          servo_1.write(deg); // move servo to joystick location
          delay(abs(deg-prev_deg)*(10.0/6.0));
          prev_deg = deg;
          Serial.println(deg); // print out degree
        }
      }
    }
    

    注意延迟在功能上取决于它移动到的角度 - 这将“平滑”伺服并减少抖动(尽管不能完全消除它)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-03
      • 1970-01-01
      相关资源
      最近更新 更多