BaseFlight Sensor2 - FabLabSeoul/WingProject GitHub Wiki
μ΄ κΈμ Multiwii Baseflight μ€νμμ€λ₯Ό λΆμν κΈμ΄λ€.
Stm32 value line discovery 보λμ λ§κ² μ½λλ₯Ό μ¬μμ± νλ€.
μ΄ κΈμ Baseflightμ Sensor λΌμ΄λΈλ¬λ¦¬λ₯Ό λΆμν κΈμ΄λ€. Sensor μ΄κΈ°νμ κ΄λ ¨λ κΈμ Sensor 첫 λ²μ§Έ λ¬Έμ BaseFlight Sensor λ¬Έμλ₯Ό μ°Έμ‘°νμ.
Sensorμ κ΄ν κΈμ΄ κΈΈμ΄μ Έ λ λ¬Έμλ‘ λλμλ€. μ¬κΈ°μλ μΌμ κ°μ μ½μ΄μ€λ μ½λλ₯Ό μ£Όλ‘ λΆμνλ€.
Sensor λΌμ΄λΈλ¬λ¦¬(sensors.c) μμ μΌμ κ°μ κ°μ Έμ€λ ν¨μλ λ€μκ³Ό κ°λ€.
- ACC_getADC()
- κ°μλ μΌμλ‘λΆν° κ°μ μ½μ΄μ¨ ν,
ACC_Common()
ν¨μλ₯Ό νΈμΆνλ€.
- κ°μλ μΌμλ‘λΆν° κ°μ μ½μ΄μ¨ ν,
- ACC_Common()
- κ°μλ μΌμ κ°μ νν°λ§ν΄ x,y,zμΆ κ°μλ(g) μ΅μ’
κ°μ
accADC[]
μ μ μ₯νλ€.
- κ°μλ μΌμ κ°μ νν°λ§ν΄ x,y,zμΆ κ°μλ(g) μ΅μ’
κ°μ
- Gyro_getADC()
- μμ΄λ‘μ€μ½ν κ°μ μ½μ΄μ¨ ν,
GYRO_Common()
ν¨μλ₯Ό νΈμΆνλ€.
- μμ΄λ‘μ€μ½ν κ°μ μ½μ΄μ¨ ν,
- GYRO_Common()
- μμ΄λ‘μ€μ½ν κ°μ νν°λ§ν΄ x,y,zμΆ κ°μλ(degree/seconds) μ΅μ’
κ°μ
gyroADC[]
μ μ μ₯νλ€.
- μμ΄λ‘μ€μ½ν κ°μ νν°λ§ν΄ x,y,zμΆ κ°μλ(degree/seconds) μ΅μ’
κ°μ
- Mag_getADC()
- μ§μκΈ° μΌμ κ°μ νν°λ§ν΄ x,y,zμΆ μκΈ°μ₯(gauss) μ΅μ’
κ°μ
magADC[]
μ μ μ₯νλ€.
- μ§μκΈ° μΌμ κ°μ νν°λ§ν΄ x,y,zμΆ μκΈ°μ₯(gauss) μ΅μ’
κ°μ
ACC_Common() ν¨μ
Baseflight Sensor::ACC_Common()
ν¨μλ λ€μκ³Ό κ°λ€.
#define CALIBRATING_ACC_CYCLES 400
int16_t accADC[3];
uint16_t calibratingA = CALIBRATING_ACC_CYCLES; // the calibration is done is the main loop. Calibrating decreases at each cycle down to 0, then we enter in a normal mode.
uint16_t acc_1G = 256; // this is the 1G measured acceleration.
static void ACC_Common(void)
{
static int32_t a[3];
int axis;
if (calibratingA > 0) {
for (axis = 0; axis < 3; axis++) {
// Reset a[axis] at start of calibration
if (calibratingA == CALIBRATING_ACC_CYCLES)
a[axis] = 0;
// Sum up CALIBRATING_ACC_CYCLES readings
a[axis] += accADC[axis];
// Clear global variables for next reading
accADC[axis] = 0;
mcfg.accZero[axis] = 0;
}
// Calculate average, shift Z down by acc_1G and store values in EEPROM at end of calibration
if (calibratingA == 1) {
mcfg.accZero[ROLL] = (a[ROLL] + (CALIBRATING_ACC_CYCLES / 2)) / CALIBRATING_ACC_CYCLES;
mcfg.accZero[PITCH] = (a[PITCH] + (CALIBRATING_ACC_CYCLES / 2)) / CALIBRATING_ACC_CYCLES;
mcfg.accZero[YAW] = (a[YAW] + (CALIBRATING_ACC_CYCLES / 2)) / CALIBRATING_ACC_CYCLES - acc_1G;
cfg.angleTrim[ROLL] = 0;
cfg.angleTrim[PITCH] = 0;
}
calibratingA--;
}
accADC[ROLL] -= mcfg.accZero[ROLL];
accADC[PITCH] -= mcfg.accZero[PITCH];
accADC[YAW] -= mcfg.accZero[YAW];
}
νλ‘κ·Έλ¨μ΄ μμλλ©΄, 400 μ¬μ΄ν΄λμ κ°μλ κ°μ μΈ‘μ ν΄ νκ· μ λ΄μ΄ mcfg.accZero[]
μ μ μ₯νλ€. κ·Έλ¦¬κ³ νκ· κ°μ λ°μ¬λ¦ΌνκΈ° μν΄μ νκ· κ°μ 1/2λ₯Ό λν κ°μ μ μ₯νλ€. ZμΆμ - acc_1G
λ₯Ό νλ μ΄μ λ κΈ°λ³Έ μ€λ ₯ κ°μλκ° μ΄λ―Έ λ°μλ μνμ΄λ―λ‘ κ·Έ κ°μ μ κ±°νκΈ° μν κ³μ°μ΄λ€.
Calibration, μ¦ κ΅μ λ¨κ³κ° λλλ©΄, 본격μ μΌλ‘ κ°μλ μΌμ κ°μ μ½μ΄ μ¨λ€. μ΅μ’
κ°μ accADC[]
μ μ λ³μμ μ μ₯λλ€.
accADC[ROLL] -= mcfg.accZero[ROLL];
accADC[PITCH] -= mcfg.accZero[PITCH];
accADC[YAW] -= mcfg.accZero[YAW];
μ²μ κ°μλ μΌμ κ΅μ μ μΈ‘μ λμλ κ°μ΄ mcfg.accZero[]
μ μ μ₯λμ΄ μκΈ° λλ¬Έμ, μ΄ κ°μ μ€μ μΌμκ°μμ λΉΌμ μ μ₯νλ€. μ΄λ κ² νλ μ΄μ λ, μ΄κΈ° μΌμμ μμΈλ₯Ό μμ μΌλ‘, μ΄κΈ° μμΈμμ λ³νλ κ°μλ κ°μ μ»κΈ° μν΄μλ€. νλ‘κ·Έλ¨μ΄ μμλ λ, μΌμκ° κΈ°μΈμ΄μ Έ μλ κ²½μ°κ° μκ³ , μ²μλΆν° κΈ°μΈμ΄μ§ μνλ‘ μ€κ³λμλλΌλ, μμ μμ λ³νλ κ°λ§ μ½μ΄μ€κΈ° λλ¬Έμ, λ¬Έμ μμ΄ κ°μλ κ°μ μ»μ΄μ¬ μ μκ² λλ€.
GYRO_Common() ν¨μ
Baseflight Sensor::GYRO_Common()
ν¨μλ λ€μκ³Ό κ°λ€.
#define CALIBRATING_GYRO_CYCLES 1000
uint16_t calibratingG = CALIBRATING_GYRO_CYCLES;
int16_t gyroADC[3], accADC[3], accSmooth[3];
int16_t gyroZero[3] = { 0, 0, 0 };
mcfg.moron_threshold = 32;
static void GYRO_Common(void)
{
int axis;
static int32_t g[3];
static stdev_t var[3];
if (calibratingG > 0) {
for (axis = 0; axis < 3; axis++) {
// Reset g[axis] at start of calibration
if (calibratingG == CALIBRATING_GYRO_CYCLES) {
g[axis] = 0;
devClear(&var[axis]);
}
// Sum up 1000 readings
g[axis] += gyroADC[axis];
devPush(&var[axis], gyroADC[axis]);
// Clear global variables for next reading
gyroADC[axis] = 0;
gyroZero[axis] = 0;
if (calibratingG == 1) {
float dev = devStandardDeviation(&var[axis]);
// check deviation and startover if idiot was moving the model
if (mcfg.moron_threshold && dev > mcfg.moron_threshold) {
calibratingG = CALIBRATING_GYRO_CYCLES;
devClear(&var[0]);
devClear(&var[1]);
devClear(&var[2]);
g[0] = g[1] = g[2] = 0;
continue;
}
gyroZero[axis] = (g[axis] + (CALIBRATING_GYRO_CYCLES / 2)) / CALIBRATING_GYRO_CYCLES;
blinkLED(10, 15, 1);
}
}
calibratingG--;
}
for (axis = 0; axis < 3; axis++)
gyroADC[axis] -= gyroZero[axis];
}
μμ΄λ‘μ€μ½ν κ°μ νμ€ νΈμ°¨λ₯Ό ꡬνκΈ° μν ν¨μλ€
- stdev_t
- νμ€ νΈμ°¨λ₯Ό ꡬνκΈ°μν λ³μλ€ μ μ₯
- devClear()
- devPush()
- νκ· , νΈμ°¨ μ μ₯
- devVariance()
- λΆμ° κ³μ°
- devStandardDeviation()
- νμ€ νΈμ°¨ κ³μ°
νλ‘κ·Έλ¨μ΄ μμλλ©΄ 1000 μ¬μ΄ν΄ λμ μμ΄λ‘μ€μ½ν κ΅μ (Calibration)λ¨κ³λ₯Ό μ§ννλ€. 1000 μ¬μ΄ν΄λμ μΌμμ νμ€νΈμ°¨κ° mcfg.moron_threshold
λ³΄λ€ ν¬λ€λ©΄, κ΅μ λ¨κ³λ₯Ό λ€μ κ±°μΉλ€. mcfg.moron_threshold
κ°μ 32
λ‘ μ€μ λμ΄ μλ€. μ΄ μλ―Έλ, μ΄κΈ° μΌμ μμΈκ° μμ§μ΄μ§μκ³ , κ³ μ λμ΄ μμ΄μΌ νλ€λ λ»μ΄λ€. κ΅μ λ¨κ³κ° λ¬Έμ μμ΄ λλ¬λ€λ©΄, 1000 μ¬μ΄ν΄ λμμ μμ΄λ‘μΌμ κ°μ νκ· μ gyroZero[]
λ³μμ μ μ₯νλ€. gyroZero[]
λ μμ΄λ‘μ€μ½νμ μμ μ΄ λλ€.
for (axis = 0; axis < 3; axis++)
gyroADC[axis] -= gyroZero[axis];
μμ΄λ‘μ€μ½ν Calibrationκ³Όμ μ΄ λͺ¨λ λλ¬λ€λ©΄, μ½μ΄μ¨ μμ΄λ‘ μΌμ κ°μ gyroZero[]
κ°μ λΉΌμ μ΅μ’
κ°μ gyroADC[]
μ μ μ₯νλ€. μ΄ μλ―Έλ νλ‘κ·Έλ¨μ΄ μμλ λ, μΌμμ μμΈλ₯Ό κΈ°λ³Έ μμΈλ‘ν΄μ κ·Έ λ³ν κ°μ μ΅μ’
κ°λλ‘ κ²°μ νκ² λ€λ λ»μ΄λ€.
Mag_getADC() ν¨μ
Baseflight Sensor::Mag_getADC()
ν¨μλ λ€μκ³Ό κ°λ€.
int16_t magADC[3];
int Mag_getADC(void)
{
static uint32_t t, tCal = 0;
static int16_t magZeroTempMin[3];
static int16_t magZeroTempMax[3];
uint32_t axis;
if ((int32_t)(currentTime - t) < 0)
return 0; //each read is spaced by 100ms
t = currentTime + 100000;
// Read mag sensor
mag.read(magADC);
if (f.CALIBRATE_MAG) {
tCal = t;
for (axis = 0; axis < 3; axis++) {
mcfg.magZero[axis] = 0;
magZeroTempMin[axis] = magADC[axis];
magZeroTempMax[axis] = magADC[axis];
}
f.CALIBRATE_MAG = 0;
}
if (magInit) { // we apply offset only once mag calibration is done
magADC[X] -= mcfg.magZero[X];
magADC[Y] -= mcfg.magZero[Y];
magADC[Z] -= mcfg.magZero[Z];
}
if (tCal != 0) {
if ((t - tCal) < 30000000) { // 30s: you have 30s to turn the multi in all directions
LED0_TOGGLE;
for (axis = 0; axis < 3; axis++) {
if (magADC[axis] < magZeroTempMin[axis])
magZeroTempMin[axis] = magADC[axis];
if (magADC[axis] > magZeroTempMax[axis])
magZeroTempMax[axis] = magADC[axis];
}
} else {
tCal = 0;
for (axis = 0; axis < 3; axis++)
mcfg.magZero[axis] = (magZeroTempMin[axis] + magZeroTempMax[axis]) / 2; // Calculate offsets
//writeEEPROM(1, true);
}
}
return 1;
}
Mag_getADC()
ν¨μλ 1μ΄μ 10λ²λ§ κ³μ°νκ² λμ΄ μλ€. μ§μκΈ° μΌμκ° μ ννμ§ μκΈ° λλ¬Έμ κ·Έλ°κ² μλκ° μκ°νλ€. μ§μκΈ° μΌμ κ°μ ν¬κ² κ°κ³΅νμ§ μκ³ κ·Έλλ‘ μ΅μ’
κ°μ΄ λλ€.
μ§μκΈ° μΌμμ κ΅μ (calibration)λ¨κ³λ κΈ°λ³Έμ μΌλ‘ κ±°μΉμ§ μλλ€. κ΅μ μμ
μ f.CALIBRATE_MAG
μ΄ νμ±ν λμμ λ λΆν° μμνκ³ , κ΅μ μ΄ λλ ν, μ΅μ’
μμ μ (tCal != 0) && ((t - tCal) > 30000000)
μ‘°κ±΄μ΄ μ±λ¦½νμ λ, κ³μ°λλ€.
νμ¬ μ½λμμ tCal
μ΄ μ
λ°μ΄νΈ λλ κ²½μ°λ f.CALIBRATE_MAG
μ΄ 1μ΄μμΌ λ, μ€μ λλ€. μ΄ νλκ·Έλ μΈλΆ μ
λ ₯μΌλ‘ νμ±ν λλ€. μ§μκΈ° μΌμκ° Calibrationμ μμνκ² λλ©΄, 30μ΄ λμ 3μΆμ μΌμ κ°μ μ΅λ, μ΅μκ°μ ꡬν ν, μ€κ° κ°μ μμ κ°μΌλ‘ κ²°μ μ§λλ€. μ§μκΈ° μΌμ μμ κ°μ mcfg.magZero[]
μ μ μ₯λλ€. κ΅μ κ³Όμ μ κ±°μΉμ§ μμΌλ©΄, μΌμμ νμ¬ μμΈκ° κΈ°λ³Έ κ°μ΄ λλ€. μ΄ μλ―Έλ, μ§μκΈ° μΌμμ N λ°©ν₯μ΄ μμ λνλ΄λ―λ‘, μΏΌλμ½₯ν°μ μ λ©΄μ΄ λΆμͺ½μ ν₯ν΄μλ€κ³ κ°μ νλ€λ λ»μ΄λ€.
μ§μκΈ° μΌμμ μ΅μ’
νν°λ§ λ κ°μ magADC[]
μ μ μ₯λλ€.