231 lines
6.7 KiB
C
231 lines
6.7 KiB
C
/**
|
|
* @file magnetometer_direction.h
|
|
* @author Woon Jun Wei
|
|
* @brief This file contains the functions to calculate the direction of
|
|
* the car using the accelerometer and magnetometer data
|
|
*
|
|
* @details The direction of the car is calculated using the roll, pitch and yaw
|
|
* The roll and pitch are calculated using the accelerometer data
|
|
* The yaw is calculated using the magnetometer data
|
|
* The roll, pitch and yaw are combined to calculate the direction
|
|
* of the car
|
|
*
|
|
* The direction of the car is calculated using the complementary
|
|
* filter
|
|
*
|
|
* The complementary filter is used to combine the accelerometer
|
|
* and magnetometer data to calculate the direction of the car
|
|
*
|
|
*/
|
|
|
|
#ifndef MAGNETOMETER_DIRECTION_H
|
|
#define MAGNETOMETER_DIRECTION_H
|
|
|
|
#include "magnetometer_init.h"
|
|
|
|
/**
|
|
* @brief Roll Calculation with Accelerometer Data
|
|
* @param acceleration Accelerometer Data
|
|
* @return
|
|
*/
|
|
static inline float
|
|
calculate_roll(int16_t acceleration[3]) {
|
|
return atan2(acceleration[1], acceleration[2]) * (180.0 / M_PI);
|
|
}
|
|
|
|
/**
|
|
* @brief Pitch Calculation with Accelerometer Data
|
|
* @param acceleration Accelerometer Data
|
|
* @return
|
|
*/
|
|
static inline float
|
|
calculate_pitch(int16_t acceleration[3]) {
|
|
return atan2(- acceleration[0], sqrt(acceleration[1] * acceleration[1] +
|
|
acceleration[2] * acceleration[2])) *
|
|
(180.0 / M_PI);
|
|
}
|
|
|
|
/**
|
|
* @brief Yaw Calculation with Magnetometer Data
|
|
* @param magnetometer Magnetometer Data
|
|
* @return
|
|
*/
|
|
static inline float
|
|
calculate_yaw_magnetometer(int16_t magnetometer[3]) {
|
|
return atan2(magnetometer[1], magnetometer[0]) * (180.0 / M_PI);
|
|
}
|
|
|
|
/**
|
|
* @brief Complementary Filter for Yaw
|
|
* @param yaw_acc Yaw calculated from Accelerometer Data
|
|
* @param yaw_mag Yaw calculated from Magnetometer Data
|
|
* @return yaw Yaw calculated from Complementary Filter
|
|
*/
|
|
static inline float
|
|
calculate_yaw_complementary(float yaw_acc, float yaw_mag) {
|
|
return ALPHA * yaw_acc + (1 - ALPHA) * yaw_mag;
|
|
}
|
|
|
|
/**
|
|
* @brief Adjust Yaw to be between 0 and 360 degrees
|
|
* @param yaw Yaw calculated from Complementary Filter
|
|
* @return yaw Yaw adjusted to be between 0 and 360 degrees
|
|
*/
|
|
static inline float
|
|
adjust_yaw(float yaw) {
|
|
return (yaw < 0) ? yaw + 360.0f : yaw;
|
|
}
|
|
|
|
/**
|
|
* @brief Calculate the Compass Direction (N, NE, E, SE, S, SW, W, NW)
|
|
* 22.5 = 360 / 16, used to calculate the compass direction from
|
|
* the compass direction enum
|
|
* @param yaw Yaw calculated from Complementary Filter
|
|
* @return Compass Direction
|
|
*/
|
|
static inline compass_direction_t
|
|
calculate_compass_direction(float yaw) {
|
|
int orientation = (int) ((yaw + 22.5) / 45.0) % 8; // 8 compass directions
|
|
switch (orientation)
|
|
{
|
|
case 0:
|
|
return NORTH;
|
|
case 1:
|
|
return NORTH_EAST;
|
|
case 2:
|
|
return EAST;
|
|
case 3:
|
|
return SOUTH_EAST;
|
|
case 4:
|
|
return SOUTH;
|
|
case 5:
|
|
return SOUTH_WEST;
|
|
case 6:
|
|
return WEST;
|
|
case 7:
|
|
return NORTH_WEST;
|
|
default:
|
|
return NORTH;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Update the Orientation Data
|
|
* @param roll Roll calculated from Accelerometer Data
|
|
* @param pitch Pitch calculated from Accelerometer Data
|
|
* @param yaw Yaw calculated from Complementary Filter
|
|
* @param compass_direction Compass Direction
|
|
*/
|
|
static inline void
|
|
update_orientation_data(float roll, float pitch, float yaw,
|
|
compass_direction_t compass_direction) {
|
|
g_direction.roll = roll;
|
|
g_direction.pitch = pitch;
|
|
g_direction.yaw = yaw;
|
|
g_direction.orientation = compass_direction;
|
|
}
|
|
|
|
/**
|
|
* @brief Read the Accelerometer and Magnetometer Data and
|
|
* Calculate the Direction of the Car
|
|
* @details Alpha is set to 0.98 to give more weight to the accelerometer data
|
|
* @param acceleration Accelerometer Data
|
|
* @param magnetometer Magnetometer Data
|
|
*/
|
|
static void
|
|
read_direction(int16_t acceleration[3], int16_t magnetometer[3]) {
|
|
float roll = calculate_roll(acceleration);
|
|
float pitch = calculate_pitch(acceleration);
|
|
float yaw_mag = calculate_yaw_magnetometer(magnetometer);
|
|
|
|
float yaw_acc = atan2(acceleration[1], acceleration[0]) * (180.0 / M_PI);
|
|
float yaw = calculate_yaw_complementary(yaw_acc, yaw_mag);
|
|
|
|
yaw = adjust_yaw(yaw);
|
|
|
|
compass_direction_t compass_direction = calculate_compass_direction(yaw);
|
|
|
|
update_orientation_data(roll, pitch, yaw, compass_direction);
|
|
}
|
|
|
|
/**
|
|
* FreeRTOS Tasks
|
|
*/
|
|
|
|
/**
|
|
* @brief Task to Monitor the Direction of the Car
|
|
* @param params
|
|
*/
|
|
void
|
|
monitor_direction_task(__unused void *params) {
|
|
for (;;)
|
|
{
|
|
if (xSemaphoreTake(g_direction_sem, portMAX_DELAY) == pdTRUE)
|
|
{
|
|
// Read from message buffer
|
|
int16_t magnetometer[3];
|
|
int16_t accelerometer[3];
|
|
|
|
read_magnetometer(magnetometer);
|
|
read_accelerometer(accelerometer);
|
|
|
|
read_direction(accelerometer, magnetometer);
|
|
|
|
printf("Roll: %f, Pitch: %f, Yaw: %f\n",
|
|
g_direction.roll, g_direction.pitch, g_direction.yaw);
|
|
|
|
printf("Direction:");
|
|
|
|
switch (g_direction.orientation)
|
|
{
|
|
case NORTH:
|
|
printf("North\n");
|
|
break;
|
|
case NORTH_EAST:
|
|
printf("North East\n");
|
|
break;
|
|
case EAST:
|
|
printf("East\n");
|
|
break;
|
|
case SOUTH_EAST:
|
|
printf("South East\n");
|
|
break;
|
|
case SOUTH:
|
|
printf("South\n");
|
|
break;
|
|
case SOUTH_WEST:
|
|
printf("South West\n");
|
|
break;
|
|
case WEST:
|
|
printf("West\n");
|
|
break;
|
|
case NORTH_WEST:
|
|
printf("North West\n");
|
|
break;
|
|
}
|
|
|
|
switch (g_direction.roll_angle)
|
|
{
|
|
case LEFT:
|
|
printf("You're Flying!\n");
|
|
break;
|
|
case RIGHT:
|
|
printf("You're Plunging!\n");
|
|
break;
|
|
}
|
|
|
|
switch (g_direction.pitch_angle)
|
|
{
|
|
case UP:
|
|
printf("Your left wheel is in the air!\n");
|
|
break;
|
|
case DOWN:
|
|
printf("Your right wheel is in the air!\n");
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif |