Ciao ragazzi ho un problema con il mio quadricottero............. Oscilla e si ribalta paurosamente:
Vi dico cosa ho fatto..... i codici qui di seguito sono per determinare il PID di pitch e roll:
double Compute_Pitch()
{
Pitch_Roll (); // Ottengo Pitch e Roll
unsigned long now = millis(); // comincia a contare
double timeChange = (double)(now - lastTime); // Delta t calcolato
double error_Pitch = SETPOINT - pitch; // Calcolo l'errore: Vorrei rimanere a 0.00°
if (abs(error_Pitch) < threshold){ // windup control
errSum += (error_Pitch * timeChange);} // Sommo l'errore attuale con i precedenti : sistema integrale
else {
errSum = 0;
}
double dErr = (error_Pitch - lastErr)/timeChange; // Rapporto incrementale del sistema derivativo
Output_Pitch = kpPitch * error_Pitch + kiPitch * errSum + kdPitch * dErr; // Calcolo il PID, dovrà essere in ingresso ai motori
if (Output_Pitch > VAL_MAX) Output_Pitch = VAL_MAX;
if (Output_Pitch < VAL_MIN) Output_Pitch= VAL_MIN;
lastErr = error_Pitch; // registro l'errore
lastTime = now; // registro il tempo
return Output_Pitch;
}
double Compute_Roll()
{
Pitch_Roll ();
unsigned long now = millis(); // comincia a contare
double timeChange = (double)(now - lastTime); // Delta t calcolato
double error_Roll = SETPOINT - roll; // Calcolo l'errore: Vorrei rimanere a 0.00°
if (abs(error_Roll) < threshold){ // windup control
errSum += (error_Roll * timeChange);} // Sommo l'errore attuale con i precedenti : sistema integrale
else {
errSum = 0;
}
double dErr = (error_Roll - lastErr)/timeChange; // Rapporto incrementale del sistema derivativo
Output_Roll = kp * error_Roll + ki *errSum + kd * dErr; // Calcolo il PID, dovrà essere in ingresso ai motori
if (Output_Roll > VAL_MAX) Output_Roll = VAL_MAX;
if (Output_Roll < VAL_MIN) Output_Roll = VAL_MIN;
lastErr = error_Roll; // registro l'errore
lastTime = now; // registro il tempo
return Output_Roll;
}
Poi lasciando stare i codici delle virate...... ho provveduto a sommare i valori di PID_roll e PID_Pitch ai PWM dei motori
Vi assicuro che tutti e tre i parametri Accx,Accy,Accz vanno a 0 se non eseguo nessuna virata, quindi il problema è sui PID....quello che succede è che appena aumento di poco il Throttle, il quadricottero vibra pesantemente e quasi tutte le volte mi si è ribaltato... I range dei motori è di 90 - 120, mentre il limite di PID lo ho impostato tra i 10 e -10.... ho provato cambiando molti valori dei coefficenti del PID, ma nisba... continua a ribaltarsi.
Nessuno mi può aiutare?
Di solito quando si ribalta e perché i motori sono invertiti, e anche da controllare che i motori girano nel senso giusto
dovresti dire che configurazione stai utilizzando a X o a + come si chiama il programma che utilizzi non lo mai visto.
Quando dico che i motori sono invertiti significa che per esempio ai messo il motore 2 dove ci andava
il motore 3 e dunque si ribalta.
Guarda ho rivisto i collegamenti ..... ho riguardata i sensi dei motori ed è tutto apposto.
Il programma lo ho scritto io, perché volevo capire bene come funzionava il tutto. Il drone è un quadricottero ad X. Ho notato una cosa però, che potrebbe essere il nodo Gordiano. Dal seriale faccio uscire i segnali del PID(sia di pitch che di roll) e ho visto che se utilizzo dei coefficenti di PID un pò elevati (ma è necessario se voglio che la risposta del Sistema sia veloce), vanno ad influire su tutti e due i PID. Mi spiego meglio:
ho creato due programmi per calcolare i PID, non avendo fatto una libreria.... come ho postato al'inizio.....infatti per un quadricottero servono 2 PID, per il pitch e per il roll. Solo che se faccio delle prove e magari agisco solo sul pitch(inclino il quadricottero) , e metto dei coefficenti Ki, Kp , Kd più alti dell'unità, vanno ad influire anche sul PID di roll, che dovrebbe rimanere inalterato..... forse è per questo che mi si ribalta , dando dei valori bassi i due PID non interferiscono, ma il quadricottero ci mette un'eternità a rispondere ai cambiamenti di angolo. Qui di seguito vi posto come li ho calcolati...
void SetTunings(double Kp, double Ki, double Kd)
{
kp = Kp;
ki = Ki;
kd = Kd;
}
double Compute_Pitch()
{
Pitch_Roll (); // Ottengo Pitch e Roll
unsigned long now = millis(); // comincia a contare
double timeChange = (double)(now - lastTime); // Delta t calcolato
double error_Pitch = SETPOINT - pitch; // Calcolo l'errore: Vorrei rimanere a 0.00°
if (abs(error_Pitch) < threshold){ // windup control
errSum += (error_Pitch * timeChange);} // Sommo l'errore attuale con i precedenti : sistema integrale
else {
errSum = 0;
}
double dErr = (error_Pitch - lastErr)/timeChange; // Rapporto incrementale del sistema derivativo
Output_Pitch = kp * error_Pitch + ki * errSum + kd * dErr; // Calcolo il PID, dovrà essere in ingresso ai motori
if (Output_Pitch > VAL_MAX) Output_Pitch = VAL_MAX;
if (Output_Pitch < VAL_MIN) Output_Pitch= VAL_MIN;
lastErr = error_Pitch; // registro l'errore
lastTime = now; // registro il tempo
return Output_Pitch;
}
double Compute_Roll()
{
Pitch_Roll ();
unsigned long now = millis(); // comincia a contare
double timeChange = (double)(now - lastTime); // Delta t calcolato
double error_Roll = SETPOINT - roll; // Calcolo l'errore: Vorrei rimanere a 0.00°
if (abs(error_Roll) < threshold){ // windup control
errSum += (error_Roll * timeChange);} // Sommo l'errore attuale con i precedenti : sistema integrale
else {
errSum = 0;
}
double dErr = (error_Roll - lastErr)/timeChange; // Rapporto incrementale del sistema derivativo
Output_Roll = kp * error_Roll + ki *errSum + kd * dErr; // Calcolo il PID, dovrà essere in ingresso ai motori
if (Output_Roll > VAL_MAX) Output_Roll = VAL_MAX;
if (Output_Roll < VAL_MIN) Output_Roll = VAL_MIN;
lastErr = error_Roll; // registro l'errore
lastTime = now; // registro il tempo
return Output_Roll;
}
.non capisco perché si danno fastidio, eppure tranne che per il tempo non ho variabili condivise
Ciao, Nazukao
Caspita se lo scrivi tu e veramente una bella impresa premetto che io non ne so nulla di programmazione
ma forse sarebbe interessante per te vedere dei programmi già funzionati come multiwii.
Per il tuo problema ci sarebbe da vedere che sensori utilizzi e come sono orinatati anche quello fa ribaltare e vibrare
il tu quadro.
A parere mio già con un programma funzionate come multiwii ci sono all'inizio sempre dei problemi figurati
con un programma scritto di sana pianta comunque tanto di cappello se riesci ad ottenere dei buoni risultati
io da qui non posso aiutarti.
void Xwing()
{
int PID_Roll = Compute_Roll();
int PID_Pitch = Compute_Pitch();
if (value[1] < THROTTLE_RMIN){
AccX =0;
AccY =0;
AccZ =0;
}else {
/***************************************************************************************************/
/* // controllo volo // */
/***************************************************************************************************/
if (value[4] > 1200){ // 4th canale che serve per l'accensione e lo spegnimento 1000 = spento 2000 = acceso //
throttle=map(value[1],THROTTLE_RMIN,THROTTLE_RMAX,MIN_LVL_MOTORI,THROTTLE_WMAX); // mappo il canale di Throttle 1100-1400 //
// Situazione di Roll Comandata //
if (value[3] < 1490){
AccX = map(value[3], VELO_RMIN, 1500, ACC_MIN, 0);
}
else{
AccX = map(value[3], 1500, VELO_RMAX, 0, ACC_MAX);
}
// Situazione di Pitch //
if (value[2] < 1510 ){
AccY = map(value[2], VELO_RMIN, 1528, ACC_MIN, 0);
}
else{
AccY = map(value[2], 1530, VELO_RMAX, 0, ACC_MAX);
}
// Situazione di Yaw //
if (value[0] < 1490 ){
AccZ = map(value[0], 1200, 1500, ACC_MIN, 0);
}
else{
AccZ = map(value[0], 1500, 1850, 0, ACC_MAX);
}
}// end if //
else throttle = MIN_SPEGNIMENTO; } // se il 4th canale va a 1000 spenge il Drone //
// Trigger del PID //
// in condizione di riposo tutti i canali inviano 1500 come segnale quindi AccX AccY AccZ = 0 //
int v0 =throttle - PID_Pitch - AccX + AccY - AccZ;
int v1 =throttle - AccX - AccY + AccZ - PID_Roll;
int v2 =throttle + PID_Pitch + AccX - AccY - AccZ;
int v3 =throttle + AccX + AccY + AccZ + PID_Roll;
motore0.writeMicroseconds(v0);
motore1.writeMicroseconds(v1);
motore2.writeMicroseconds(v2);
motore3.writeMicroseconds(v3);
}
Facendo dei banchi di prova ho notato che praticamente il PID non viene letto dai motori mentre se V0,V1,V2,V3 li vado a leggere sul Seriale sono corretti, è come se i servo leggessero solo i valori dai canali del Telecomando e se ne infischiano delle operazioni di PID.
Ciao a tutti!
Ho provato anche a far uscire il segnale di PID ogni 20 ms (50 Hz)..... Pensavo infatti che doveva avere la stessa frequenza del segnale PWM che arrivava dai canali della ricevente... ma niente....i motori accelerano e decelerano come se vedessero sempre un errore d' angolo, questo succede anche quando è in posizione orizzontale. LA cosa strana è che sul Monitor Seriale mi da i valori esatti di accelerazione e di decelerazione....Ufff.......Sono bloccato da 2 giorni ormai......I