我有一个 Arduino 项目,其中我使用操纵杆模块移动 2 个伺服系统。效果不错,但动作一点也不流畅。我观看了许多有关插值的视频,但不知道如何在现有代码中实现它。你能帮我吗?
这是我使用的代码:
#include <Servo.h>
#define SERVO_PIN 9
#define GROUND_JOY_PIN A3 //joystick ground pin will connect to Arduino analog pin A3
#define VOUT_JOY_PIN A2 //joystick +5 V pin will connect to Arduino analog pin A2
#define XJOY_PIN A1 //X axis reading from joystick will go into analog pin A1
#define YJOY_PIN A0
Servo myservoX;
Servo myservoY;
void setup()
{
Serial.begin(9600);
pinMode(VOUT_JOY_PIN, OUTPUT) ; //pin A3 shall be used as output
pinMode(GROUND_JOY_PIN, OUTPUT) ; //pin A2 shall be used as output
digitalWrite(VOUT_JOY_PIN, HIGH) ; //set pin A3 to high (+5V)
digitalWrite(GROUND_JOY_PIN,LOW) ; //set pin A3 to low (ground)
myservoX.attach(9);
myservoY.attach(6);
}
void loop()
{
int joystickXVal = analogRead(XJOY_PIN) ; //read joystick input on pin A1
Serial.print(joystickXVal); //print the value from A1
Serial.println(" = input from joystick"); //print "=input from joystick" next to the value
Serial.print((joystickXVal+520)/5); //print a from A1 calculated, scaled value
Serial.println(" = output to servo"); //print "=output to servo" next to the value
Serial.println() ;
myservoX.write((joystickXVal+520)/10); //write the calculated value to the servo
int joystickYVal = analogRead(YJOY_PIN) ; //read joystick input on pin A1
Serial.print(joystickYVal); //print the value from A1
Serial.println(" = input from joystick"); //print "=input from joystick" next to the value
Serial.print((joystickYVal+520)/5); //print a from A1 calculated, scaled value
Serial.println(" = output to servo"); //print "=output to servo" next to the value
Serial.println() ;
myservoY.write((joystickYVal+520)/10); //write the calculated value to the servo
}
我尝试使用延迟,但没有成功
将模拟输入可靠地转换为伺服输出的一种简单方法是 Arduino 功能:
int joystickXVal = analogRead(XJOY_PIN);
int servoX = map(joystickXVal, 0, 1023, 0, 180);
myservoX.write(servoX);
低通滤波由于控制电路和伺服机构的物理原理,输出侧已经有一些滤波,所以我通常从平滑输入开始。
一个简单有效的方法是使用
指数平滑。
// We use a static (or global) variable to persist the filtered
// position of the joystick.
static int xVal = 512;
// Update the filtered position by doing a weighted average
// with the "instantaneous" reading.
int joystickXVal = analogRead(XJOY_PIN);
xVal = (7*xVal + joystickXVal) / 8;
// Note that we now use xVal, the filtered position, when
// figuring out where we want the servo.
int servoX = map(xVal, 0, 1023, 0, 180);
myservoX.write(servoX);
如果您大约定期更新位置,则此方法效果很好。与分配给瞬时读数的权重相比,您对现有位置的权重越大,变化就越平滑。不过,如果朝这个方向走得太远,您会发现舵机明显滞后于操纵杆。
请注意,由于我们使用 int 值,因此我们必须警惕平均整数的陷阱和可能的溢出。这就是为什么我设置表达式最后进行除法,以及为什么我选择系数以确保中间结果不会超过 2^15。