I'm using the MPU6050 to detect the pitching angle of an experimental aircraft, depending of the angle, the elevator moves up or down. This is possible using a servo of 180 degrees but I'm unable to understand why it only moves about 90 degrees.
this is the code
/*==================================
FUENTE EXTERNA 6.4 V
//==================================
====================================
SERVO
====================================
SNG-----PIN 8
GND-----PROTO GND-----BOARD GND
VCC-----VCC PROTO
====================================
IMU
====================================
GND-----GND
VCC-----VCC
SDA-----Pin A4
SCL-----Pin A5
ADO-----GND
*/
// Librerias I2C para controlar el mpu6050
// la libreria MPU6050.h necesita I2Cdev.h, I2Cdev.h necesita Wire.h
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"
#include "Servo.h"
// La dirección del MPU6050 puede ser 0x68 o 0x69, dependiendo
// del estado de AD0. Si no se especifica, 0x68 estará implicito
/// Definir los pines de entrada y salida
const int servoPin = 8; // Pin de salida del servomotor
// La dirección del MPU6050 puede ser 0x68 o 0x69, dependiendo
// del estado de AD0. Si no se especifica, 0x68 estará implicito
const int mpuAddress = 0x68; // Puede ser 0x68 o 0x69
MPU6050 mpu(mpuAddress);
// Definir las constantes del PID
const double Kp = 0.5;
const double Ki = 0.2;
const double Kd = 0.1;
// Datos de la IMU
int16_t ax, ay, az; //aceleraciones
int16_t gx, gy, gz; //rotaciones
//Cnsideraciones para obtenerl los valores de la IMU
long tiempo_prev;
float dt;
float ang_x, ang_y;
float ang_x_prev, ang_y_prev;
// Definir variables para el PID
double setpoint = 0;
double PWM;
double input, output;
double error, lastError = 0;
double integral = 0, derivative;
// Definir el objeto Servo
Servo myservo;
float aero;
double tp =1500; //posicion deseada del timon (el servo trabaja con 1500 en 0 grados, 2000 en 90 grados y 1000 en -90 grados)
void setup()
{
Serial.begin(9600);
Wire.begin();
mpu.initialize();
myservo.attach(servoPin);
myservo.write(0); //posicion inicial del servo en el centro
if(mpu.testConnection()){
Serial.println("IMU iniciado correctamente");
}
else{
Serial.println("ERROR");
}
}
void loop()
{
// Leer las aceleraciones y velocidades angulares
mpu.getAcceleration(&ax, &ay, &az);
mpu.getRotation(&gx, &gy, &gz);
dt = (millis() - tiempo_prev) / 1000.0;
tiempo_prev = millis();
//Calcular los ángulos con acelerometro
float accel_ang_x = atan(ay / sqrt(pow(ax, 2) + pow(az, 2)))*(180.0 / 3.14);
float accel_ang_y = atan(-ax / sqrt(pow(ay, 2) + pow(az, 2)))*(180.0 / 3.14);
//Calcular angulo de rotación con giroscopio y filtro complementario
ang_x = 0.98*(ang_x_prev + (gx / 131)*dt) + 0.02*accel_ang_x;
ang_y = 0.98*(ang_y_prev + (gy / 131)*dt) + 0.02*accel_ang_y;
ang_x_prev = ang_x;
ang_y_prev = ang_y;
//Imprimir los valores del angulo de rotacion en x
Serial.print(F("Rotacion en X: "));
Serial.print(ang_x);
Serial.print("\n");
//Calcular el error
input = ang_x;
error = setpoint - input;
if(setpoint > error)
{
// Calcular la integral y derivada del error
integral += error;
derivative = error - lastError;
// Calcular la salida PWM utilizando PID
PWM = Kp * error + Ki * integral + Kd * derivative;
output = tp+PWM;
}
if (setpoint < error)
{
// Calcular la integral y derivada del error
integral += error;
derivative = error - lastError;
// Calcular la salida PWM utilizando PID
PWM = Kp * error + Ki * integral + Kd * derivative;
output = tp-PWM;
}
// Limitar la salida entre -90 y 90 grados
if(output < 1000) {
output = 1000;
} else if(output > 2000) {
output = 2000;
}
//Mandar al servo la deflexion correspondiente
myservo.write(output);
lastError = error;
//Retraso minimo capaz de ser usado = 20 ms
delay(20);
}