因此,我正在使用两个由操纵杆控制的伺服电机来制造“炮塔”型的东西。我正在运行的代码可以正常工作,但是它非常生涩,并且运行得不好,尤其是在对角线上。我的代码如下:
#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还是很陌生:)
答案 0 :(得分: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
}
}
}
请注意,延迟在功能上取决于其移动的角度-这将“平滑”伺服并减少抖动(尽管不能完全消除)。