FlySky FS i6X enhanced firmware - iNavFlight/inav GitHub Wiki
/* USER CODE BEGIN Header / /*
- @file : main.c
- @brief : Main program body
- @attention
- Copyright (c) 2025 STMicroelectronics.
- All rights reserved.
- This software is licensed under terms that can be found in the LICENSE file
- in the root directory of this software component.
- If no LICENSE file comes with this software, it is provided AS-IS.
/ / USER CODE END Header / / Includes ------------------------------------------------------------------*/ #include "main.h" #include "usart.h" #include "tim.h" #include "gpio.h" #include <string.h> #include <math.h>
/* Private includes ----------------------------------------------------------/ / USER CODE BEGIN Includes */
#include "main.h" #include "usart.h" #include "tim.h" #include "gpio.h" #include <string.h> #include <math.h> #include <stdlib.h>
#define SERVO_MIN 1000 #define SERVO_MAX 2000 #define MOTOR_MIN 1000 #define MOTOR_MAX 2000 #define PI 3.14159265
// GPS б��е� uint8_t gpsBuffer[100]; uint8_t gpsDataReady = 0;
// GPS коо�дина�и float currentLat = 0.0f, currentLon = 0.0f; float targetLat = 50.4501f, targetLon = 30.5234f; // �и�в дл� п�иклад�
// PPM зм�нн� volatile uint16_t ppm_channels[8]; volatile uint8_t ppm_index = 0;
// --- �б�обка �айме�а PPM --- void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { static uint32_t last_time = 0; if (htim->Instance == TIM2) { uint32_t now = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); uint32_t diff = (now >= last_time) ? (now - last_time) : (0xFFFF - last_time + now); last_time = now;
if (diff > 3000) {
ppm_index = 0; // sync
} else if (ppm_index < 8) {
ppm_channels[ppm_index++] = diff;
}
}
}
// --- �б�обка UART GPS --- void HAL_UART_RxCpltCallback(UART_HandleTypeDef huart) { if (huart->Instance == USART1) { if (strstr((char)gpsBuffer, "$GNGGA") != NULL || strstr((char*)gpsBuffer, "$GPGGA") != NULL) { // �а��инг GGA (п�о��ий) char* token = strtok((char*)gpsBuffer, ","); int field = 0; while (token != NULL) { if (field == 2) currentLat = atof(token) / 100.0f; if (field == 4) currentLon = atof(token) / 100.0f; token = strtok(NULL, ","); field++; } } gpsDataReady = 1; HAL_UART_Receive_IT(&huart1, gpsBuffer, sizeof(gpsBuffer)); } }
// --- Ф�нк��� дл� к���� �а в�д��ан� --- float calculateDistance(float lat1, float lon1, float lat2, float lon2) { float dLat = (lat2 - lat1) * PI / 180.0f; float dLon = (lon2 - lon1) * PI / 180.0f; float a = sin(dLat / 2) * sin(dLat / 2) + cos(lat1 * PI / 180.0f) * cos(lat2 * PI / 180.0f) * sin(dLon / 2) * sin(dLon / 2); float c = 2 * atan2(sqrt(a), sqrt(1 - a)); float R = 6371000.0f; return R * c; }
float calculateBearing(float lat1, float lon1, float lat2, float lon2) { float dLon = (lon2 - lon1) * PI / 180.0f; lat1 = lat1 * PI / 180.0f; lat2 = lat2 * PI / 180.0f;
float y = sin(dLon) * cos(lat2);
float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
float bearing = atan2(y, x) * 180.0f / PI;
return fmod((bearing + 360.0f), 360.0f);
}
// --- �е��ванн� --- void set_servo_angle(uint16_t pwm_us) { if (pwm_us < SERVO_MIN) pwm_us = SERVO_MIN; if (pwm_us > SERVO_MAX) pwm_us = SERVO_MAX; __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwm_us); }
void set_motor_throttle(uint16_t pwm_us) { if (pwm_us < MOTOR_MIN) pwm_us = MOTOR_MIN; if (pwm_us > MOTOR_MAX) pwm_us = MOTOR_MAX; __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, pwm_us); }
int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); MX_TIM2_Init(); MX_TIM3_Init();
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
HAL_UART_Receive_IT(&huart1, gpsBuffer, sizeof(gpsBuffer));
while (1) {
float distance = calculateDistance(currentLat, currentLon, targetLat, targetLon);
float bearing = calculateBearing(currentLat, currentLon, targetLat, targetLon);
if (ppm_channels[4] > 1500) { // ав�оп�ло� �в�мкнений
float current_heading = 0.0f; // GPS-к���� нема � о��ни�и зм�но� коо�дина� (можна дода�и)
float error = bearing - current_heading;
if (error > 180) error -= 360;
if (error < -180) error += 360;
uint16_t servo_pwm = 1500 + (int)(error * 3.0f);
set_servo_angle(servo_pwm);
if (distance > 5) {
set_motor_throttle(1600); // ��� впе�ед
} else {
set_motor_throttle(1000); // ��оп
}
} else {
// Р��не ке��ванн�
set_servo_angle(ppm_channels[0]);
set_motor_throttle(ppm_channels[1]);
}
HAL_Delay(20);
}
}
// --- Си��емна ��нк��� �ак��ванн� --- void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
Error_Handler();
}
}
void Error_Handler(void) { __disable_irq(); while (1) { // �б�обка помилки } }
#ifdef USE_FULL_ASSERT /**
- @brief Reports the name of the source file and the source line number
-
where the assert_param error has occurred.
- @param file: pointer to the source file name
- @param line: assert_param error line source number
- @retval None */ void assert_failed(uint8_t file, uint32_t line) { / USER CODE BEGIN 6 / / User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) / / USER CODE END 6 / } #endif / USE_FULL_ASSERT */