使用操纵杆使伺服电机运动更平稳吗?

时间:2019-02-25 20:45:36

标签: arduino joystick servo

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

#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还是很陌生:)

2 个答案:

答案 0 :(得分:2)

伺服小巧轻便,并试图尽快移至您告诉他们的位置。游戏杆还可以非常快速地更改值,并且它们也可能出现故障。结果,您的伺服器会不断地进行许多小而快速的运动,这会使转塔显得生涩。

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

  1. 通过一些低通滤波来平滑操纵杆输入。这通常仅意味着使用当前值和先前值的加权平均值。这样做的目的是消除由于电位计接触不良而导致的一两个不良读数。

  2. 使动作平滑。与其立即尝试将舵机直接移至操纵杆的当前位置,不如将其移向目标位置。在循环的每次迭代中,它们都会靠近目标位置,而不是试图立即跳到那里。

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

一种方法是简单地使用伺服器当前位置和目标位置的加权平均值。如果将操纵杆移动一定距离,则转塔将快速旋转,但随着其接近目标位置而变慢。

另一种是使用物理模型。想象一下创建一个力矢量,该矢量从伺服器的当前位置指向操纵杆的目标位置,并与它们之间的距离成比例。向当前点施加该力。还要施加抵抗当前点速度的“摩擦”力。对速度和回路中的位置进行数值积分。如果将操纵杆突然移动到新位置,那么转塔将向其加速,然后随着其接近而减速。调整用于计算力的常数将使您可以控制该机制的“沉重”程度。

答案 1 :(得分:0)

我设置了与伺服速度成比例的延迟。试试看(摘自我的教程: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
    }
  }
}

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