问题描述
我有一个arduino程序,当它处于奇数角时运行伺服,但是五秒钟后(如果仍以该奇数角)将其设置为新中心。问题是由于某种原因,当我将当前旋转角度设置为新的中心时,这些值会混合在一起。此外,中心值似乎在五秒钟之前就已更新。我认为这与编译器有关。我的代码在这里:
copy
/*
Arduino and mpu6050 Accelerometer and gyroscope Sensor Tutorial
by Dejan,https://howtomechatronics.com
*/
#include <Wire.h>
#include <Servo.h>
#define SERVO_PIN 9 //PWM pin that is connected to the servo
Servo demoServo; //create a servo object
int servoAngle = 0; //servo angle which can vary from 0 - 180
const int mpu = 0x68; // mpu6050 I2C address
float AccX,AccY,AccZ;
float GyroX,GyroY,GyroZ;
float accAngleX,accAngleY,gyroAngleX,gyroAngleY,gyroAngleZ;
float roll,pitch,yaw;
float rot[1];
float AccErrorX,AccErrorY,GyroErrorX,GyroErrorY,GyroErrorZ;
float elapsedtime,currentTime,prevIoUsTime;
int c = 0;
bool shake;
int shakeTime = 0;
float stablePos[1];
void setup() {
Serial.begin(19200);
Wire.begin(); // Initialize comunication
Wire.beginTransmission(mpu); // Start communication with mpu6050 // mpu=0x68
Wire.write(0x6B); // Talk to the register 6B
Wire.write(0x00); // Make reset - place a 0 into the 6B register
Wire.endTransmission(true); //end the transmission
demoServo.attach(SERVO_PIN);
delay(20);
stablePos[0] = 0;
stablePos[1] = 0;
rot[0] = 0;
rot[1] = 1;
}
void setIMU(float rot[])
{
// === Read acceleromter data === //
Wire.beginTransmission(mpu);
Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(mpu,6,true); // Read 6 registers total,each axis value is stored in 2 registers
//For a range of +-2g,we need to divide the raw values by 16384,according to the datasheet
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis value
// Calculating Roll and Pitch from the accelerometer data
accAngleX = (atan(AccY / sqrt(pow(AccX,2) + pow(AccZ,2))) * 180 / PI) - 0.93; // AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details
accAngleY = (atan(-1 * AccX / sqrt(pow(AccY,2))) * 180 / PI) - 4.23; // AccErrorY ~(-1.58)
// === Read gyroscope data === //
prevIoUsTime = currentTime; // PrevIoUs time is stored before the actual time read
currentTime = millis(); // Current time actual time read
elapsedtime = (currentTime - prevIoUsTime) / 1000; // Divide by 1000 to get seconds
Wire.beginTransmission(mpu);
Wire.write(0x43); // Gyro data first register address 0x43
Wire.endTransmission(false);
Wire.requestFrom(mpu,true); // Read 4 registers total,each axis value is stored in 2 registers
GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // For a 250deg/s range we have to divide first the raw value by 131.0,according to the datasheet
GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
// Correct the outputs with the calculated error values
GyroX = GyroX + 0.43; // GyroErrorX ~(-0.56)
GyroY = GyroY + 0.63; // GyroErrorY ~(2)
GyroZ = GyroZ + 1.67; // GyroErrorZ ~ (-0.8)
// Currently the raw values are in degrees per seconds,deg/s,so we need to multiply by sendonds (s) to get the angle in degrees
gyroAngleX = gyroAngleX + GyroX * elapsedtime; // deg/s * s = deg
gyroAngleY = gyroAngleY + GyroY * elapsedtime;
yaw = yaw + GyroZ * elapsedtime;
// Complementary filter - combine acceleromter and gyro angle values
roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;
rot[0] = pitch-10 > rot[0] || pitch+10 < rot[0] ? pitch : rot[0];
rot[1] = roll-10 > rot[1] || roll+10 < rot[1] ? roll : rot[1];
}
void loop() {
setIMU(rot);
Serial.print("STABLE AT:");
Serial.print(stablePos[0]);
Serial.print("/");
Serial.print(stablePos[1]);
Serial.print("\t CURRENTLY AT:");
Serial.print(rot[0]);
Serial.print("/");
Serial.println(rot[1]);
shake = (rot[0]>stablePos[0]+20 || rot[0]<stablePos[0]-20) ? true : (rot[1]>stablePos[1]+20 || rot[1]<stablePos[1]-20);
shakeTime = shake && shakeTime == 0 ? millis() + 5000 : shakeTime;
if (shakeTime < millis() && shakeTime != 0){
shakeTime = 0;
shake = false;
stablePos[0] = rot[0];
stablePos[1] = rot[1];
}
Serial.println(shake);
//Serial.println(shakeTime/1000);
demoServo.write(shake ? 180 : 0);
}
如您所见,不仅在STABLE AT:0.00/0.00 CURRENTLY AT:0.00/0.00
0
STABLE AT:0.00/0.00 CURRENTLY AT:0.00/0.00
0
STABLE AT:0.00/0.00 CURRENTLY AT:0.00/-0.00
0
STABLE AT:0.00/0.00 CURRENTLY AT:0.00/-0.14
0
STABLE AT:0.00/0.00 CURRENTLY AT:0.00/-0.26
0
STABLE AT:0.00/0.00 CURRENTLY AT:0.00/0.05
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/0.41
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/-0.00
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/0.16
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/0.00
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/1.49
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/1.86
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/0.00
0
STABLE AT:0.00/21.30 CURRENTLY AT:21.30/0.63
1
STABLE AT:0.00/21.30 CURRENTLY AT:21.30/2.57
1
STABLE AT:0.00/21.30 CURRENTLY AT:21.30/2.70
1
STABLE AT:0.00/21.30 CURRENTLY AT:21.30/2.69
1
STABLE AT:0.00/31.95 CURRENTLY AT:31.95/2.56
1
STABLE AT:0.00/31.95 CURRENTLY AT:31.95/-0.00
1
STABLE AT:0.00/31.95 CURRENTLY AT:31.95/-0.00
1
布尔值设置为2之前,稳定位置会更新为10.98
,而且位置也会相反。
解决方法
float stablePos[1];
是一个元素的数组;唯一有效的索引是stablePos[0]
。通过访问stablePos[1]
,您的程序表现出未定义的行为。与rot
相同。