BaseFlight Sensor - FabLabSeoul/WingProject GitHub Wiki

์ด ๊ธ€์€ ์˜คํ”ˆ์†Œ์Šค Multiwii Baseflight ๋ฅผ ๋ถ„์„ํ•œ ๊ธ€์ด๋‹ค.

Baseflight๋Š” ๊ฐ€์†์„ผ์„œ, ์ž์ด๋กœ์Šค์ฝ”ํ”„, ์ง€์ž๊ธฐ์„ผ์„œ๋ฅผ Sensor๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค. ์ด 9 DOF๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‹ค.

์˜ˆ์ œ ์†Œ์Šค๋Š” STM32\stm32vldiscovery_package\Project\Examples\Sensor_Baseflight ๊ฒฝ๋กœ์— ์žˆ๋‹ค. Baseflight Sensor๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•ด MPU-6050๊ณผ HMC5883L ์„ผ์„œ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ์˜ˆ์ œ๋‹ค.

Sensor๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ Baseflight์˜ ๊ธฐ๋ณธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๊ธฐ๋ณธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • drv_system
  • drv_gpio
  • drv_usart
  • drv_serial
  • serial
  • drv_hmc5883l
  • drv_mpu5060
  • drv_i2c
  • printf

Sensor๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์œ„์— ์—ด๊ฑฐํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ชจ๋‘ ์“ฐ๊ณ  ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ถ”๊ฐ€๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • imu
  • util
  • sensor

์ด ๊ธ€์—์„œ๋Š” ์ฃผ๋กœ util, imu, sensor ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค๋ช…ํ•˜๊ณ , ์ „์ฒด ํ๋ฆ„์„ ์„ค๋ช…ํ•˜๋Š”๋ฐ ์ค‘์ ์„ ๋‘๊ฒ ๋‹ค.

์ดˆ๊ธฐํ™”

Sensor ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ์œ„ํ•ด ์ดˆ๊ธฐํ™” ํ•˜๋Š” ๊ณผ์ •์„ ๋ณด์—ฌ์ค€๋‹ค.


void setup()
{
	gpio_config_t gpio;
	bool sensorsOK = false;

	mcfg.emf_avoidance = 0;
	mcfg.gyro_cmpf_factor = 600;    // default MWC	
	mcfg.gyro_cmpfm_factor = 250;   // default MWC
	mcfg.gyro_lpf = 42;             // supported by all gyro drivers now. In case of ST gyro, will default to 32Hz instead
	mcfg.gyro_align = ALIGN_DEFAULT;
	mcfg.acc_align = ALIGN_DEFAULT;
	mcfg.mag_align = ALIGN_DEFAULT;
	mcfg.vbatscale = 110;
	mcfg.currentscale = 400; // for Allegro ACS758LCB-100U (40mV/A)
	mcfg.moron_threshold = 32;

	cfg.mag_declination = 0;    // For example, -6deg 37min, = -637 Japan, format is [sign]dddmm (degreesminutes) default is zero.
	cfg.small_angle = 25;
	cfg.throttle_correction_value = 0;      // could 10 with althold or 40 for fpv
	cfg.throttle_correction_angle = 800;    // could be 80.0 deg with atlhold or 45.0 for fpv
	cfg.accz_lpf_cutoff = 5.0f;
	cfg.acc_lpf_factor = 4;
	cfg.accz_deadband = 40;
	cfg.accxy_deadband = 40;
	
    // RCC ์ดˆ๊ธฐํ™”.
    SystemInit();

	// ํด๋Ÿญ, ํƒ€์ด๋จธ ์ดˆ๊ธฐํ™”
	systemInit();

	// sleep for 100ms
	delay(100);

	// Stm32 ๋ณด๋“œ์— ์žˆ๋Š” LED3,4๋ฅผ ํ™œ์„ฑํ™” ํ•œ๋‹ค.
	gpio.pin = Pin_All;
	gpio.speed = Speed_2MHz;
	gpio.mode = Mode_Out_PP;
	gpioInit(GPIOC, &gpio);

	// MPU-6050, HMC5883L๊ณผ ํ†ต์‹ ํ•  i2c๋ฅผ ์ดˆ๊ธฐํ™” ํ•œ๋‹ค.
	i2cInit(I2CDEV_1, 0x00); // Init Master i2c 

    // MPU-6050, HMC6553L ์„ผ์„œ ์ฒดํฌ
    // ์„ผ์„œ ์ดˆ๊ธฐํ™”.
	sensorsOK = sensorsAutodetect();
	
	// if gyro was not detected due to whatever reason, we give up now.
	if (!sensorsOK)
			failureMode(3);

	// IMU ์ดˆ๊ธฐํ™”
    // ์ง€์ž๊ธฐ ์„ผ์„œ HMC6553L ์ดˆ๊ธฐํ™”
	imuInit();

	// ์‹œ๋ฆฌ์–ผ ํ†ต์‹  ์ดˆ๊ธฐํ™”.
    // PA10,9 (Rx,Tx)
	serialInit(115200);
}

๋จผ์ € ์ „์—ญ์ ์œผ๋กœ ํ•„์š”ํ•œ ์ •๋ณด๋“ค์„ master_t๊ตฌ์กฐ์ฒด์™€ config_t๊ตฌ์กฐ์ฒด์˜ ๊ฐ๊ฐ ์ „์—ญ๋ณ€์ˆ˜ mcfg, cfg ๋ฅผ ์ดˆ๊ธฐํ™” ํ•œ๋‹ค. ํ˜„์žฌ Sensor ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ํ•„์š”ํ•œ ๊ฐ’๋“ค๋งŒ ์ดˆ๊ธฐํ™” ํ–ˆ๋‹ค.

delay() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ์œ„ํ•ด Baseflightํ•จ์ˆ˜ systeminit() ๋ฅผ ๋จผ์ € ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Stm32 value line discovery ๋ณด๋“œ์˜ LED3,4 ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ์œ„ํ•ด GPIOC๋ฅผ ํ™œ์„ฑํ™” ํ•œ๋‹ค.

์„ผ์„œ์™€ ํ†ต์‹ ์„ ์œ„ํ•ด I2C๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ i2cInit(I2CDEV_1, 0x00); ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์ดˆ๊ธฐํ™” ํ•œ๋‹ค. ์ฒซ ๋ฒˆ์งธ I2C ์žฅ์น˜๋ฅผ ์ด์šฉํ•˜๊ณ , ๋งˆ์Šคํ„ฐ๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ฃผ์†Œ๊ฐ’์€ ํ•„์š”์—†์œผ๋ฏ€๋กœ 0x00์œผ๋กœ ์„ค์ •ํ•œ๋‹ค.

์—ฌ๊ธฐ๊นŒ์ง€ ์ง„ํ–‰๋˜์—ˆ๋‹ค๋ฉด, ๋ณธ๊ฒฉ์ ์œผ๋กœ ์„ผ์„œ์™€ ํ†ต์‹ ์„ ์‹œ์ž‘ํ•œ๋‹ค. sensorsAutodetect() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด MPU-6050, HMC6553L๊ณผ ํ†ต์‹ ์„ ์‹œ๋„ํ•ด ์—ฐ๊ฒฐ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ณ , ๊ธฐ๋ณธ ์„ค์ •๊ฐ’์œผ๋กœ ์„ผ์„œ๋ฅผ ์ดˆ๊ธฐํ™” ํ•œ๋‹ค.

imuInit() ํ•จ์ˆ˜์—์„œ ์ง€์ž๊ธฐ์„ผ์„œ์— ํ•„์š”ํ•œ ๋ณ€์ˆ˜๋“ค์„ ์ดˆ๊ธฐํ™” ํ•œ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ ๋””๋ฒ„๊น…์„ ์œ„ํ•ด serialInit(115200) ํ•จ์ˆ˜๋กœ PA10,9(Rx,Tx) ํฌํŠธ๋กœ ์‹œ๋ฆฌ์–ผํ†ต์‹ ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ, ํฌํŠธ๋ฅผ ์—ฐ๋‹ค.

Sensor ๊ตฌ์กฐ์ฒด

๊ฐ€์†๋„ ์„ผ์„œ, ์ž์ด๋กœ์Šค์ฝ”ํ”„, ์ง€์ž๊ธฐ ์„ผ์„œ๋Š” sensor_t ๊ตฌ์กฐ์ฒด๋กœ ํ‘œํ˜„๋œ๋‹ค. ๋ฉค๋ฒ„ํ•จ์ˆ˜ํฌ์ธํ„ฐ init, read๋ฅผ ํ†ตํ•ด ์„ผ์„œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ , ์ •๋ณด๋ฅผ ์ฝ์–ด์˜จ๋‹ค. ๋‹ค์–‘ํ•œ ์„ผ์„œ์— ๋งž์ถฐ ํ™•์žฅ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋„๋ก ๋””์ž์ธ ๋˜์—ˆ๋‹ค. C++์˜ ์ถ”์ƒ ํด๋ž˜์Šค์™€ ๋‹ฎ์•˜๋‹ค.

typedef struct sensor_t {
    sensorInitFuncPtr init;               // initialize function
    sensorReadFuncPtr read;               // read 3 axis data function
    sensorReadFuncPtr temperature;        // read temperature if available
    float scale;           // scalefactor (currently used for gyro only, todo for accel)
} sensor_t;

typedef void (*sensorInitFuncPtr)(sensor_align_e align);   // sensor init prototype
typedef void (*sensorReadFuncPtr)(int16_t *data);          // sensor read and align prototype

typedef enum {
    ALIGN_DEFAULT = 0,                                      // driver-provided alignment
    CW0_DEG = 1,
    CW90_DEG = 2,
    CW180_DEG = 3,
    CW270_DEG = 4,
    CW0_DEG_FLIP = 5,
    CW90_DEG_FLIP = 6,
    CW180_DEG_FLIP = 7,
    CW270_DEG_FLIP = 8
} sensor_align_e;

sensorsAutodetect() ํ•จ์ˆ˜

MPU-6050 ๊ณผ HMC5883L ์„ผ์„œ๊ฐ€ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ์ง€ ๊ฒ€์‚ฌํ•œ๋‹ค.

mpu6050Detect() ํ•จ์ˆ˜์— ๊ด€ํ•ด์„œ๋Š” Baseflight MPU-6050๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์ž.

hmc5883lDetect() ํ•จ์ˆ˜์— ๊ด€ํ•ด์„œ๋Š” Baseflight HMC5883L๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์ž.

sensor_t acc;                       // acc access functions
sensor_t gyro;                      // gyro access functions
sensor_t mag;                       // mag access functions
uint8_t accHardware = ACC_DEFAULT;  // which accel chip is used/detected
uint8_t magHardware = MAG_DEFAULT;

bool sensorsAutodetect(void)
{
    int16_t deg, min;

	// Autodetect gyro hardware. We have MPU3050 or MPU6050 or MPU6500 on SPI
    if (mpu6050Detect(&acc, &gyro, mcfg.gyro_lpf, &core.mpu6050_scale)) 
    {
    } 
	else
    {
            // if this fails, we get a beep + blink pattern. we're doomed, no gyro or i2c error.
           return false;
    }

	mpu6050Detect(&acc, &gyro, mcfg.gyro_lpf, &core.mpu6050_scale); // yes, i'm rerunning it again.  re-fill acc struct
	accHardware = ACC_MPU6050;

		
    // Now time to init things, acc first
    acc.init(mcfg.acc_align);
    // this is safe because either mpu6050 or mpu3050 or lg3d20 sets it, and in case of fail, we never get here.
    gyro.init(mcfg.gyro_align);

		
	if (hmc5883lDetect(&mag)) 
	{
			magHardware = MAG_HMC5883L;
	}

	// calculate magnetic declination
    deg = cfg.mag_declination / 100;
    min = cfg.mag_declination % 100;
    magneticDeclination = (deg + ((float)min * (1.0f / 60.0f))) * 10; // heading is in 0.1deg units

    return true;
}

์„ผ์„œ ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ

  • BaseFlight Sensor2 ๋ฌธ์„œ์— ์„ค๋ช…๋˜์–ด ์žˆ๋‹ค.

IMU ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•œ ์„ผ์„œ ๊ฐ’ ๊ณ„์‚ฐ

  • Baseflight IMU ๋ฌธ์„œ์— ์„ค๋ช…๋˜์–ด์žˆ๋‹ค.