Ed ecco il risultato finale:
purtroppo non è ancora provato sul campo, infatti anche il valori in pasto al PID sono sicuramente errati
#include <Wire.h>
#include "NunchukFarlocco.h"
#include "IMU.h"
#include "Motore.h"
#include "Giroscopio.h"
#include "InputPin.h"
#include "PID.h"
#define ledPin 13
#define gyroXpin 1
#define gyroYpin 2
#define gyroZpin 3
#define motore1PWMPin 3
#define motore2PWMPin 9
#define motore3PWMPin 10
#define motore4PWMPin 11
//If max PWM value is 255, and the max input of PID is -PI<input<PI then -100<P<100 because PI*100=314 that is bigger than 255
#define PofPID 1
#define MIN_RADIO_VALUE 900
#define MAX_RADIO_VALUE 1900
#define maxReceiverAngle 0.2
//maxReceiverAngle is in radiant
#define PITCH_STABLE_ANGLE 0
#define ROLL_STABLE_ANGLE 1.55
#define YAW_STABLE_ANGLE 0
Giroscopio gyro[3];
NunchukFarlocco nun;
IMU orizzonte;
PID pid[4]={PID(PofPID), PID(PofPID), PID(PofPID), PID(PofPID)};
Motore motori[] = { Motore(motore1PWMPin), Motore(motore2PWMPin), Motore(motore3PWMPin), Motore(motore4PWMPin) };
//channel 0=power, 1=pitch, 2=roll, 3=yaw from 900 to 1900
InputPin inputs;
unsigned long time;
boolean statoLedPin=false;
void setup(){
time = micros();
Serial.begin(19200);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
//setting gyro pin, automagigally they calibration
gyro[0].setPin(gyroXpin);
gyro[1].setPin(gyroXpin);
gyro[2].setPin(gyroXpin);
digitalWrite(ledPin, LOW);
Serial.println("begin nunchuck");
nun.nunchuck_init();
Serial.println("end nunchuck");
}
int loopCount=0;
unsigned long timeMid=0;
unsigned long time2;
float lastYaw=0;
void loop(){
//Serial.print("loop");
loopCount++;
time2=micros();
if (timeMid==0){
timeMid=time2-time;
}else{
timeMid= (timeMid+(time2-time) )/2;
}
time=time2;
if ( nun.nunchuck_get_data() ){
orizzonte.IMUupdate(gyro[0].leggi(), gyro[1].leggi(), gyro[2].leggi(), nun.x, nun.y, nun.z);
//orizzonte.IMUupdate(0, 0, 0, nun.x, nun.y, nun.z); //FOR DEBUG
}else{
Serial.println("Nunckuck non pronto!!");
}
float roll=atan2(2*(orizzonte.q0*orizzonte.q1+orizzonte.q2*orizzonte.q3), 1-2*(orizzonte.q1*orizzonte.q1+orizzonte.q2*orizzonte.q2));
float pitch=asin( 2*(orizzonte.q0*orizzonte.q2-orizzonte.q1*orizzonte.q3) );
float yaw=atan2(2*(orizzonte.q0*orizzonte.q3+orizzonte.q1*orizzonte.q2), 1-2*(orizzonte.q2*orizzonte.q2+orizzonte.q3*orizzonte.q3));
if (loopCount>200){
Serial.print("Actual angle:");
Serial.print(roll);
Serial.print(" ");
Serial.print(pitch);
Serial.print(" ");
Serial.print(yaw);
Serial.println();
}
//find out actual estimated yaw angular rotation. We can also use directly gyro value with a proportion :-D
yaw-=lastYaw;
lastYaw=yaw;
/* because a quadricopter, engine setup:
0
2 3
1
*/
float engineAngle[4];
engineAngle[0]=roll+yaw;
engineAngle[1]=-roll+yaw;
engineAngle[2]=-pitch-yaw;
engineAngle[3]=pitch-yaw;
int i;
/*
//USER INPUT
*/
// FAKE INPUT, FOR DEBUG PURPOISE
//
long enginesPower=0;
float desiredAngle[4];
for (i=0; i < 4; i++){
desiredAngle[0]= ROLL_STABLE_ANGLE+YAW_STABLE_ANGLE;
desiredAngle[1]= -ROLL_STABLE_ANGLE+YAW_STABLE_ANGLE;
desiredAngle[2]= -PITCH_STABLE_ANGLE-YAW_STABLE_ANGLE;
desiredAngle[3]= PITCH_STABLE_ANGLE-YAW_STABLE_ANGLE;
}
//
// END FAKE INPUT
//
/*
//
// REAL INPUT
//
enginesPower=map( inputs.getDuration(0), MIN_RADIO_VALUE, MAX_RADIO_VALUE, 0, 200 );
//angle in radiant!!
pitch = map( inputs.getDuration(1), MIN_RADIO_VALUE, MAX_RADIO_VALUE, -maxReceiverAngle, maxReceiverAngle )+PITCH_STABLE_ANGLE;
roll = map( inputs.getDuration(2), MIN_RADIO_VALUE, MAX_RADIO_VALUE, -maxReceiverAngle, maxReceiverAngle )+ROLL_STABLE_ANGLE;
yaw = map( inputs.getDuration(3), MIN_RADIO_VALUE, MAX_RADIO_VALUE, -maxReceiverAngle, maxReceiverAngle )+YAW_STABLE_ANGLE;
desiredAngle[0]=roll+yaw;
desiredAngle[1]=-roll+yaw;
desiredAngle[2]=-pitch-yaw;
desiredAngle[3]=pitch-yaw;
//
// END REAL INPUT
//
*/
/*
//END USER INPUT
*/
float enginePower[4];
int maxP=0;
for (i=0; i < 4; i++){
enginePower[i]=pid[i].update(engineAngle[i], desiredAngle[i])+enginesPower;
if (enginePower[i]>maxP)
maxP=enginePower[i];
}
if (maxP>255){//if motor power requested is bigger than maximus (255 for PWM)
for (i=0; i < 4; i++){
enginePower[i]=map(enginePower[i], 0, maxP, 0, 255);//scale engine power
}
}
for (i=0; i < 4; i++){
motori[i].update( enginePower[i] );
}
if (loopCount>200){
/*
Serial.print(gyroX);
Serial.print(" ");
Serial.print(gyroY);
Serial.print(" ");
Serial.print(gyroZ);
Serial.println();
Serial.print(nun.x);
Serial.print(" ");
Serial.print(nun.y);
Serial.print(" ");
Serial.print(nun.z);
Serial.println();
Serial.print(gyroMid[0]);
Serial.print(" ");
Serial.print(gyroMid[1]);
Serial.print(" ");
Serial.print(gyroMid[2]);
Serial.println(" ");
*/
statoLedPin=!statoLedPin;
if (statoLedPin)
digitalWrite(ledPin, HIGH);
else
digitalWrite(ledPin, LOW);
Serial.print("TIME:");
Serial.println(timeMid);
Serial.print(orizzonte.q0);
Serial.print(" ");
Serial.print(orizzonte.q1);
Serial.print(" ");
Serial.print(orizzonte.q2);
Serial.print(" ");
Serial.print(orizzonte.q3);
Serial.println();
//recalculate absolute yaw, because was angular yaw rotation
//yaw=atan2(2*(orizzonte.q0*orizzonte.q3+orizzonte.q1*orizzonte.q2), 1-2*(orizzonte.q2*orizzonte.q2+orizzonte.q3*orizzonte.q3));
Serial.print(roll);
Serial.print(" ");
Serial.print(pitch);
Serial.print(" ");
Serial.print(yaw);
Serial.println();
Serial.print("Motori:");
Serial.print(enginePower[0]);
Serial.print(" ");
Serial.print(enginePower[1]);
Serial.print(" ");
Serial.print(enginePower[2]);
Serial.print(" ");
Serial.println(enginePower[3]);
loopCount=0;
}
}