sercom based channel mid calibrations

git-svn-id: https://arducopter.googlecode.com/svn/trunk@224 f9c3cf11-9bcb-44bc-f272-b75c42450872
This commit is contained in:
jphelirc 2010-08-18 01:27:35 +00:00
parent 5e976861e8
commit f0776a962d
5 changed files with 197 additions and 16 deletions

View File

@ -19,6 +19,7 @@
*/ */
#include "WProgram.h" #include "WProgram.h"
#include "UserConfig.h"
/*******************************************************************/ /*******************************************************************/
// ArduPilot Mega specific hardware and software settings // ArduPilot Mega specific hardware and software settings
@ -214,6 +215,10 @@ int num_iter;
float aux_debug; float aux_debug;
// Radio definitions // Radio definitions
int roll_mid;
int pitch_mid;
int yaw_mid;
int Neutro_yaw; int Neutro_yaw;
int ch_roll; int ch_roll;
int ch_pitch; int ch_pitch;
@ -329,6 +334,9 @@ float xmitFactor;
#define KP_RATEYAW_ADR 156 #define KP_RATEYAW_ADR 156
#define KI_RATEYAW_ADR 160 #define KI_RATEYAW_ADR 160
#define KD_RATEYAW_ADR 164 #define KD_RATEYAW_ADR 164
#define CHROLL_MID 168
#define CHPITCH_MID 172
#define CHYAW_MID 176
// Utilities for writing and reading from the EEPROM // Utilities for writing and reading from the EEPROM
float readEEPROM(int address) { float readEEPROM(int address) {
@ -396,4 +404,8 @@ void readUserConfig() {
Ki_RateYaw = readEEPROM(KI_RATEYAW_ADR); Ki_RateYaw = readEEPROM(KI_RATEYAW_ADR);
Kd_RateYaw = readEEPROM(KD_RATEYAW_ADR); Kd_RateYaw = readEEPROM(KD_RATEYAW_ADR);
xmitFactor = readEEPROM(XMITFACTOR_ADR); xmitFactor = readEEPROM(XMITFACTOR_ADR);
roll_mid = readEEPROM(CHROLL_MID);
pitch_mid = readEEPROM(CHPITCH_MID);
yaw_mid = readEEPROM(CHYAW_MID);
} }

View File

@ -161,7 +161,7 @@ void Attitude_control_v2()
// New control term... // New control term...
roll_rate = ToDeg(Omega[0]); // Omega[] is the raw gyro reading plus Omega_I, so it´s bias corrected roll_rate = ToDeg(Omega[0]); // Omega[] is the raw gyro reading plus Omega_I, so it´s bias corrected
err_roll_rate = ((ch_roll - ROLL_MID) >> 1) - roll_rate; err_roll_rate = ((ch_roll - roll_mid) >> 1) - roll_rate;
roll_I += err_roll * G_Dt; roll_I += err_roll * G_Dt;
roll_I = constrain(roll_I, -20, 20); roll_I = constrain(roll_I, -20, 20);
@ -184,7 +184,7 @@ void Attitude_control_v2()
// New control term... // New control term...
pitch_rate = ToDeg(Omega[1]); pitch_rate = ToDeg(Omega[1]);
err_pitch_rate = ((ch_pitch - PITCH_MID) >> 1) - pitch_rate; err_pitch_rate = ((ch_pitch - pitch_mid) >> 1) - pitch_rate;
pitch_I += err_pitch*G_Dt; pitch_I += err_pitch*G_Dt;
pitch_I = constrain(pitch_I,-20,20); pitch_I = constrain(pitch_I,-20,20);
@ -221,7 +221,7 @@ void Rate_control()
// ROLL CONTROL // ROLL CONTROL
currentRollRate = read_adc(0); // I need a positive sign here currentRollRate = read_adc(0); // I need a positive sign here
err_roll = ((ch_roll - ROLL_MID) * xmitFactor) - currentRollRate; err_roll = ((ch_roll - roll_mid) * xmitFactor) - currentRollRate;
roll_I += err_roll * G_Dt; roll_I += err_roll * G_Dt;
roll_I = constrain(roll_I, -20, 20); roll_I = constrain(roll_I, -20, 20);
@ -234,7 +234,7 @@ void Rate_control()
// PITCH CONTROL // PITCH CONTROL
currentPitchRate = read_adc(1); currentPitchRate = read_adc(1);
err_pitch = ((ch_pitch - PITCH_MID) * xmitFactor) - currentPitchRate; err_pitch = ((ch_pitch - pitch_mid) * xmitFactor) - currentPitchRate;
pitch_I += err_pitch*G_Dt; pitch_I += err_pitch*G_Dt;
pitch_I = constrain(pitch_I,-20,20); pitch_I = constrain(pitch_I,-20,20);
@ -247,7 +247,7 @@ void Rate_control()
// YAW CONTROL // YAW CONTROL
currentYawRate = read_adc(2); currentYawRate = read_adc(2);
err_yaw = ((ch_yaw - YAW_MID) * xmitFactor) - currentYawRate; err_yaw = ((ch_yaw - yaw_mid) * xmitFactor) - currentYawRate;
yaw_I += err_yaw*G_Dt; yaw_I += err_yaw*G_Dt;
yaw_I = constrain(yaw_I,-20,20); yaw_I = constrain(yaw_I,-20,20);
@ -316,6 +316,12 @@ void setup()
#endif #endif
readUserConfig(); // Load user configurable items from EEPROM readUserConfig(); // Load user configurable items from EEPROM
// Safety measure for Channel mids
if(roll_mid < 1400 || roll_mid > 1600) roll_mid = 1500;
if(pitch_mid < 1400 || pitch_mid > 1600) pitch_mid = 1500;
if(yaw_mid < 1400 || yaw_mid > 1600) yaw_mid = 1500;
// RC channels Initialization (Quad motors) // RC channels Initialization (Quad motors)
APM_RC.OutputCh(0,MIN_THROTTLE); // Motors stoped APM_RC.OutputCh(0,MIN_THROTTLE); // Motors stoped
@ -342,7 +348,6 @@ void setup()
delay(30000); delay(30000);
} }
Read_adc_raw(); Read_adc_raw();
delay(20); delay(20);
@ -371,7 +376,7 @@ void setup()
for(int y=0; y<=2; y++) for(int y=0; y<=2; y++)
AN_OFFSET[y]=aux_float[y]; AN_OFFSET[y]=aux_float[y];
Neutro_yaw = APM_RC.InputCh(3); // Take yaw neutral radio value // Neutro_yaw = APM_RC.InputCh(3); // Take yaw neutral radio value
#ifndef CONFIGURATOR #ifndef CONFIGURATOR
for(i=0;i<6;i++) for(i=0;i<6;i++)
{ {
@ -380,10 +385,11 @@ void setup()
} }
Serial.print("Yaw neutral value:"); Serial.print("Yaw neutral value:");
Serial.println(Neutro_yaw); // Serial.println(Neutro_yaw);
Serial.print(yaw_mid);
#endif #endif
#if (RADIO_TEST_MODE) // RADIO TEST MODE TO TEST RADIO CHANNELS #ifdef RADIO_TEST_MODE // RADIO TEST MODE TO TEST RADIO CHANNELS
while(1) while(1)
{ {
if (APM_RC.GetState()==1) if (APM_RC.GetState()==1)
@ -502,7 +508,8 @@ void loop(){
command_rx_pitch_old = command_rx_pitch; command_rx_pitch_old = command_rx_pitch;
command_rx_pitch = (ch_pitch-CHANN_CENTER) / 12.0; command_rx_pitch = (ch_pitch-CHANN_CENTER) / 12.0;
command_rx_pitch_diff = command_rx_pitch - command_rx_pitch_old; command_rx_pitch_diff = command_rx_pitch - command_rx_pitch_old;
aux_float = (ch_yaw-Neutro_yaw) / 180.0; // aux_float = (ch_yaw-Neutro_yaw) / 180.0;
aux_float = (ch_yaw-yaw_mid) / 180.0;
command_rx_yaw += aux_float; command_rx_yaw += aux_float;
command_rx_yaw_diff = aux_float; command_rx_yaw_diff = aux_float;
if (command_rx_yaw > 180) // Normalize yaw to -180,180 degrees if (command_rx_yaw > 180) // Normalize yaw to -180,180 degrees

146
Arducopter/Functions.pde Normal file
View File

@ -0,0 +1,146 @@
/*
ArduCopter 1.3 - Aug 2010
www.ArduCopter.com
Copyright (c) 2010. All rights reserved.
An Open Source Arduino based multicopter.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
void RadioCalibration() {
long command_timer;
int command;
int counter = 5;
boolean Cmd_ok;
long roll_new = 0;
long pitch_new = 0;
long yaw_new = 0;
Serial.flush();
Serial.println("Entering Radio Calibration mode");
Serial.println("Current channel MID values are:");
Serial.print("ROLL: ");
Serial.print(roll_mid);
Serial.print(" PITCH: ");
Serial.print(pitch_mid);
Serial.print(" YAW: ");
Serial.print(yaw_mid);
Serial.println();
Serial.println("Recalibrate Channel MID's [Y/N]?: ");
command_timer = millis();
// Start counter loop and wait serial input. If not input for 5 seconds, return to normal mode
while(millis() - command_timer < 5000) {
if (Serial.available()) {
queryType = Serial.read();
if(queryType == 'y' || queryType == 'Y') {
Cmd_ok = TRUE;
break;
}
else {
Cmd_ok = FALSE;
break;
}
}
}
if(Cmd_ok) {
// We have a go. Let's do new calibration
Serial.println("Starting calibration run in 5 seconds. Place all sticks to their middle including trims");
for(counter = 5; counter >= 0; counter --) {
command_timer = millis();
while(millis() - command_timer < 1000) {
}
Serial.println(counter);
}
// Do actual calibration now
Serial.println("Measuring average channel values");
Serial.println("ROLL, PITCH, YAW");
counter = 0; // Reset counter for just in case.
command_timer = millis();
while(millis() - command_timer < 1000) {
if (APM_RC.GetState()==1) { // New radio frame?
// Commands from radio Rx...
ch_roll = channel_filter(APM_RC.InputCh(0), ch_roll);
ch_pitch = channel_filter(APM_RC.InputCh(1), ch_pitch);
ch_throttle = channel_filter(APM_RC.InputCh(2), ch_throttle);
ch_yaw = channel_filter(APM_RC.InputCh(3), ch_yaw);
ch_aux = APM_RC.InputCh(4);
ch_aux2 = APM_RC.InputCh(5);
Serial.print(ch_roll);
comma();
Serial.print(ch_pitch);
comma();
Serial.print(ch_yaw);
Serial.println();
roll_new += ch_roll;
pitch_new += ch_pitch;
yaw_new += ch_yaw;
counter++;
}
}
Serial.print("New samples received: ");
Serial.println(counter);
roll_new = roll_new / counter;
pitch_new = pitch_new / counter;
yaw_new = yaw_new / counter;
Serial.print("New values as: ");
Serial.print("ROLL: ");
Serial.print(roll_new);
Serial.print(" PITCH: ");
Serial.print(pitch_new);
Serial.print(" YAW: ");
Serial.print(yaw_new);
Serial.println();
Serial.println("Accept & Save values [Y/N]?: ");
Cmd_ok = FALSE;
while(millis() - command_timer < 5000) {
if (Serial.available()) {
queryType = Serial.read();
if(queryType == 'y' || queryType == 'Y') {
Cmd_ok = TRUE;
roll_mid = roll_new;
pitch_mid = pitch_new;
yaw_mid = yaw_new;
Serial.println("Values accepted, remember to save them to EEPROM with 'W' command");
break;
}
else {
Cmd_ok = TRUE;
break;
}
}
}
}
if(queryType == 'n' || queryType == 'N') Cmd_ok = TRUE;
if(Cmd_ok)
Serial.println("Returning normal mode...");
else Serial.println("Command timeout, returning normal mode....");
}
void comma() {
Serial.print(',');
}

View File

@ -129,6 +129,9 @@ void readSerialCommand() {
writeEEPROM(Ki_RateYaw, KI_RATEYAW_ADR); writeEEPROM(Ki_RateYaw, KI_RATEYAW_ADR);
writeEEPROM(Kd_RateYaw, KD_RATEYAW_ADR); writeEEPROM(Kd_RateYaw, KD_RATEYAW_ADR);
writeEEPROM(xmitFactor, XMITFACTOR_ADR); writeEEPROM(xmitFactor, XMITFACTOR_ADR);
writeEEPROM(roll_mid, CHROLL_MID);
writeEEPROM(pitch_mid, CHPITCH_MID);
writeEEPROM(yaw_mid, CHYAW_MID);
break; break;
case 'Y': // Initialize EEPROM with default values case 'Y': // Initialize EEPROM with default values
KP_QUAD_ROLL = 1.8; KP_QUAD_ROLL = 1.8;
@ -173,6 +176,9 @@ void readSerialCommand() {
Ki_RateYaw = 0.3; Ki_RateYaw = 0.3;
Kd_RateYaw = 0; Kd_RateYaw = 0;
xmitFactor = 0.8; xmitFactor = 0.8;
roll_mid = 1500;
pitch_mid = 1500;
yaw_mid = 1500;
break; break;
} }
} }
@ -289,6 +295,7 @@ void sendSerialTelemetry() {
queryType = 'X'; queryType = 'X';
break; break;
case 'L': // Spare case 'L': // Spare
RadioCalibration();
queryType = 'X'; queryType = 'X';
break; break;
case 'N': // Send magnetometer config case 'N': // Send magnetometer config
@ -385,7 +392,14 @@ void sendSerialTelemetry() {
comma(); comma();
Serial.print(ch_aux); // AUX1 (Mode) Serial.print(ch_aux); // AUX1 (Mode)
comma(); comma();
Serial.println(ch_aux2); // AUX2 Serial.print(ch_aux2); // AUX2
comma();
Serial.print(roll_mid); // Roll MID value
comma();
Serial.print(pitch_mid); // Pitch MID value
comma();
Serial.println(yaw_mid); // Yaw MID Value
break; break;
case 'V': // Spare case 'V': // Spare
break; break;
@ -422,7 +436,9 @@ float readFloatSerial() {
return atof(data); return atof(data);
} }
/*
void comma() { void comma() {
Serial.print(','); Serial.print(',');
} }
*/

View File

@ -59,10 +59,10 @@ TODO:
//#define RADIO_TEST_MODE //#define RADIO_TEST_MODE
#define ROLL_MID 1500 // Radio Roll channel mid value #define ROLL_MID 1478 // Radio Roll channel mid value
#define PITCH_MID 1500 // Radio Pitch channel mid value #define PITCH_MID 1483 // Radio Pitch channel mid value
#define YAW_MID 1500 // Radio Yaw channel mid value #define YAW_MID 1500 // Radio Yaw channel mid value
#define THROTTLE_MID 1500 // Radio Throttle channel mid value #define THROTTLE_MID 1502 // Radio Throttle channel mid value
#define AUX_MID 1500 #define AUX_MID 1500
#define CHANN_CENTER 1500 // Channel center, legacy #define CHANN_CENTER 1500 // Channel center, legacy