第一次提交

This commit is contained in:
2025-07-05 20:11:15 +08:00
commit 89b0708dfb
56 changed files with 10876 additions and 0 deletions

Binary file not shown.

224
app/app_brake.c Normal file
View File

@@ -0,0 +1,224 @@
#include "app_config.h"
#include "interface.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
#include "app_param_manage.h"
#include "app_power.h"
#include "app_brake.h"
#include "app_differential_drive.h"
// 使用内联函数
static inline uint8_t setBrakeOn(void) { return 1; }
static inline uint8_t setBrakeOff(void) { return 0; }
BrakeSystem brake_data;
// 判断是否需要刹车
static uint8_t shouldApplyBrake()
{
return (brake_data.emergency_stop_switch ||
brake_data.remote_emergency_stop ||
(brake_data.mode_signal == 0 && brake_data.remote_fault) ||
(brake_data.mode_signal == 1 && brake_data.can_bus_fault));//20241021 修改不计算以太网故障
// (brake_data.mode_signal == 1 && (brake_data.can_bus_fault || brake_data.ethernet_fault)));
}
// 判断是否需要释放刹车
static uint8_t shouldReleaseBrake()
{
return (!brake_data.emergency_stop_switch &&
!brake_data.remote_emergency_stop &&
((brake_data.mode_signal == 0 && !brake_data.remote_fault) ||
(brake_data.mode_signal == 1 && !brake_data.can_bus_fault)));//20241021 修改不计算以太网故障
// (brake_data.mode_signal == 1 && (!brake_data.can_bus_fault && !brake_data.ethernet_fault))));
}
// 输出处理函数
static void brakeOutput(void *signal_id)
{
(void)signal_id;
// 根据电机状态,填充发送数据结构,发送信号
switch (brake_data.brake_motor_state)
{
case 1: // 电机前进状态
un_h_bridge_output.bit_data.channel_01 = setBrakeOn();
un_h_bridge_output.bit_data.channel_04 = setBrakeOn();
un_h_bridge_output.bit_data.channel_02 = setBrakeOff();
un_h_bridge_output.bit_data.channel_03 = setBrakeOff();
un_h_bridge_output.bit_data.sleep_01 = setBrakeOn();
un_h_bridge_output.bit_data.sleep_02 = setBrakeOn(); // 正转
un_inf_can_kgf_output1.bit_data.KGF13 = setBrakeOff(); // 抱闸继电器
un_inf_can_kgf_output1.bit_data.KGF14 = setBrakeOff(); // 抱闸继电器
printf("Brake: Motor forward\n");
break;
case 2: // 电机后退状态
un_h_bridge_output.bit_data.channel_01 = setBrakeOff();
un_h_bridge_output.bit_data.channel_04 = setBrakeOff();
un_h_bridge_output.bit_data.channel_02 = setBrakeOn();
un_h_bridge_output.bit_data.channel_03 = setBrakeOn();
un_h_bridge_output.bit_data.sleep_01 = setBrakeOn();
un_h_bridge_output.bit_data.sleep_02 = setBrakeOn(); // 反转
un_inf_can_kgf_output1.bit_data.KGF13 = setBrakeOn(); // 抱闸继电器
un_inf_can_kgf_output1.bit_data.KGF14 = setBrakeOn(); // 抱闸继电器
printf("Brake: Motor reverse\n");
break;
default:
un_h_bridge_output.bit_data.channel_01 = setBrakeOff();
un_h_bridge_output.bit_data.channel_04 = setBrakeOff();
un_h_bridge_output.bit_data.channel_02 = setBrakeOff();
un_h_bridge_output.bit_data.channel_03 = setBrakeOff();
un_h_bridge_output.bit_data.sleep_01 = setBrakeOff();
un_h_bridge_output.bit_data.sleep_02 = setBrakeOff(); // 关闭
printf("Brake: Motor off\n");
break;
}
publishMessage(&un_h_bridge_output, 1);
publishMessage(&un_inf_can_kgf_output1, 1);
}
// 修改刹车定时器处理函数
static void brakeTimerProcess(void *signal_id)
{
(void)signal_id;
//#ifdef OIL_BRAKE
switch (brake_data.state)
{
case BRAKE_STATE_IDLE:
if (shouldApplyBrake())
{
brake_data.state = BRAKE_STATE_APPLYING_BRAKE;
brake_data.brake_motor_state = 1;
brakeOutput(NULL);
timerStart(&brake_data.brake_apply_timer, (uint32_t)(getParam("brk_on")), 0);
}
break;
case BRAKE_STATE_BRAKE_ON:
if (shouldReleaseBrake() && power_data.current_state == POWER_WORKING)
{
brake_data.state = BRAKE_STATE_RELEASING_BRAKE;
brake_data.brake_motor_state = 2;
brakeOutput(NULL);
timerStart(&brake_data.brake_release_timer, (uint32_t)(getParam("brk_off")), 0);
}
break;
case BRAKE_STATE_APPLYING_BRAKE:
if (!brake_data.brake_apply_timer.active)
{
brake_data.state = BRAKE_STATE_BRAKE_ON;
brake_data.brake_motor_state = 0;
brakeOutput(NULL);
brake_data.brake_position = 1; // 刹车位置1表示刹车
}
break;
case BRAKE_STATE_RELEASING_BRAKE:
if (!brake_data.brake_release_timer.active)
{
brake_data.state = BRAKE_STATE_IDLE;
brake_data.brake_motor_state = 0;
brakeOutput(NULL);
brake_data.brake_position = 0; // 刹车位置0表示未刹车
}
break;
default:
printf("ERROR: Unknown state\n");
brake_data.state = BRAKE_STATE_IDLE;
break;
}
// 如果刹车位置有变化存入EEPROM
if (brake_data.brake_position != brake_data.old_brake_position)
{
setParam("brk_pos", (float)brake_data.brake_position);
brake_data.old_brake_position = brake_data.brake_position;
printf("writeE2 brake_position = %d\n",brake_data.brake_position);
}
timerStart(&brake_data.brake_timer, 100, 1); // 周期调用
}
// 处理所有输入信号的函数
static void brakeInput(void *signal_id)
{
// BrakeSystem old_data = brake_data; // 定义并初始化old_data
// 填充数据
if (signal_id == &un_sw_sample)
{
brake_data.emergency_stop_switch = (uint8_t)un_sw_sample.bit_data.emergency_stop_switch;
}
else if ( (signal_id == &un_remote_control_input) && (1 == un_remote_control_input.bit_data.enable) )// 遥控器断线,不更新数据
{
brake_data.remote_emergency_stop = ((uint8_t)un_remote_control_input.bit_data.switch_b == 1) ? 0 : 1;
brake_data.mode_signal = ((uint8_t)un_remote_control_input.bit_data.switch_c == 1) ? 1 : 0;
}
else if (signal_id == &can_fault_info)
{
brake_data.remote_fault = !can_fault_info.bit_data.remote_state;
brake_data.can_bus_fault = !can_fault_info.bit_data.motor1_state || !can_fault_info.bit_data.motor2_state || !can_fault_info.bit_data.navigator_state;
}
else if (signal_id == &ethernet_fault_Info)
{
brake_data.ethernet_fault = !ethernet_fault_Info.bit_data.auto_state && !ethernet_fault_Info.bit_data.manual_state;
}
}
// 修改APP模块的初始化函数
void brakeAppInit(void)
{
// 初始化
memset(&brake_data, 0, sizeof(BrakeSystem));
brake_data.state = BRAKE_STATE_IDLE;
// 初始化时恢复刹车位置
brake_data.brake_position = (uint8_t)getParam("brk_pos");
brake_data.old_brake_position = brake_data.brake_position;
// 根据刹车位置恢复刹车状态
if (brake_data.brake_position == 1)
{
brake_data.state = BRAKE_STATE_BRAKE_ON;
}
else
{
brake_data.state = BRAKE_STATE_IDLE;
}
// 初始化定时器
timerInit(&brake_data.brake_timer);
timerInit(&brake_data.brake_apply_timer);
timerInit(&brake_data.brake_release_timer);
// 订阅输入信号,处理刹车逻辑
subscribe(&un_sw_sample, brakeInput);
subscribe(&un_remote_control_input, brakeInput);
subscribe(&can_fault_info, brakeInput);
subscribe(&ethernet_fault_Info, brakeInput);
// 订阅定时器信号,用于状态机的定时处理
subscribe(&brake_data.brake_timer, brakeTimerProcess);
subscribe(&brake_data.brake_apply_timer, brakeTimerProcess);
subscribe(&brake_data.brake_release_timer, brakeTimerProcess);
// 启动定时器,定期调用 brakeTimerProcess
timerStart(&brake_data.brake_timer, 500, 1);
printf("app_brake: initial OK \n");
}

58
app/app_brake.h Normal file
View File

@@ -0,0 +1,58 @@
#ifndef APP_BRAKE_H
#define APP_BRAKE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "app_config.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
#define OIL_BRAKE 0
#define ELECTROMAGNETIC_BRAKE 1
// 定义刹车状态机状态
typedef enum {
BRAKE_STATE_IDLE,
BRAKE_STATE_APPLYING_BRAKE,
BRAKE_STATE_RELEASING_BRAKE,
BRAKE_STATE_BRAKE_ON,
} BrakeState;
typedef struct BrakeSystem
{
uint32_t start_time;
Timer brake_timer; // 定时器结构体
uint8_t brake_command; // 刹车命令变量1表示刹车,2表示释放
uint8_t brake_motor_state; // 刹车电机状态变量0停止,1前进,2后退
uint8_t brake_command_in_progress; // 刹车命令执行状态0表示空闲,1表示正在执行
uint8_t emergency_stop_switch; // 急停开关
uint8_t remote_emergency_stop; // 遥控器急停开关
uint8_t remote_fault; // 遥控器故障
uint8_t can_bus_fault; // CAN总线故障
uint8_t ethernet_fault; // 以太网通信故障
uint8_t mode_signal; // 模式信号0表示手动模式,1表示自动模式
BrakeState state; // 刹车状态机
uint8_t brake_position; // 刹车位置0表示未刹车,1表示刹车
uint8_t old_brake_position; // 旧的刹车位置
Timer brake_apply_timer; // 刹车定时器
Timer brake_release_timer; // 释放刹车定时器
} BrakeSystem;
// 声明外部变量
extern BrakeSystem brake_data;
void brakeAppInit(void);
#ifdef __cplusplus
}
#endif
#endif // APP_BRAKE_H

39
app/app_config.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef APP_CONFIG_H
#define APP_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
// 标准库,每个模块中也会包含
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <float.h>
#include <math.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
//外部依赖放在这里,方便分层管理,实际代码中也有这个文件,但是没有依赖
//移植的时候,存放依赖的文件不用移植
#include "app_dependence.h"
// 接口,全局变量都放在这里
#include "interface.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
static inline uint8_t app_close(void) { return 1; }
static inline uint8_t app_open(void) { return 0; }
#ifdef __cplusplus
}
#endif
#endif // APP_CONFIG_H

90
app/app_dependence.h Normal file
View File

@@ -0,0 +1,90 @@
#ifndef TEST_H
#define TEST_H
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <float.h>
#include <math.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include "irq.h"
#include "udelay\udelay.h"
#define PERIOD_TICK 1000000.0f // 1000000us = 1s
#ifdef __cplusplus
extern "C" {
#endif
//unsigned int wrbyte_24c02(unsigned int addr, unsigned char data);
//unsigned char rdbyte_24c02(unsigned int addr);
//void feedWatchdog(void);
//uint32_t getCurrentTime(void);
//void udelay(uint32_t t );
//
//typedef unsigned int irq_state_t;
//static inline irq_state_t arch_irq_save(void)
//{
// unsigned int cpsr = 0;
// return cpsr;
//}
//
//static inline void arch_irq_restore(irq_state_t flags)
//{
// flags += 1;
//}
//// 故障信息
//typedef struct _StrCanFault
//{
// uint8_t navigator_count; // 导航仪计数器
// uint8_t motor1_count; // 左电机计数器
// uint8_t motor2_count; // 右电机计数器
// uint8_t bms_count; // bms计数器
// uint8_t temperature_count; // 温度计数器
// uint8_t remote_count; // 遥控计数器
//
// uint8_t navigator_state; // 导航仪故障状态
// uint8_t motor1_state; // 电机1故障状态
// uint8_t motor2_state; // 电机2故障状态
// uint8_t bms_state; // bms状态
// uint8_t temperature_state; // 温度计数器
// uint8_t remote_state; // 遥控状态
//} StrCanFault;
//typedef union _UnCanFault
//{
// StrCanFault bit_data; // 使用定义的结构体类型
// uint8_t arr[sizeof(StrCanFault)]; // 通过结构体确定数组大小
//} UnCanFault;
//extern UnCanFault can_fault_info;
//typedef struct _StrEthernetFault
//{
// uint8_t auto_count; // 自动数据计数器
// uint8_t manual_count; // 手动数据计数器
// uint8_t auto_state; // 自动状态 | 0正常 1故障
// uint8_t manual_state; // 手动状态 | 0正常 1故障
//} StrEthernetFault;
//
//typedef union _UnEthernetFault
//{
// StrEthernetFault bit_data; // 使用定义的结构体类型
// uint8_t arr[sizeof(StrEthernetFault)]; // 通过结构体大小确定数组大小
//} UnEthernetFault;
//extern UnEthernetFault ethernet_fault_Info;
#ifdef __cplusplus
}
#endif
#endif // TEST_H

View File

@@ -0,0 +1,932 @@
#include "app_config.h"
#include "interface.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
#include "app_param_manage.h"
#include "app_pid.h"
#include "app_differential_drive.h"
#include "app_brake.h"
#include "app_power.h"
Timer diff_app_timer;
// 定义全局变量
DiffData diff_data;
PID_t speed_pid;
PID_t yaw_rate_pid;
// 设置电机输出
void setMotorOutput(float *out_torq, float max_torque, uint16_t feed_power, uint16_t discharge_power)
{
float abs_left_front_speed = 0;
float abs_right_front_speed = 0;
float abs_left_rear_speed = 0;
float abs_right_rear_speed = 0;
// 档位
un_motor_output1.bit_data.gear = diff_data.state; // 1 表示前进2 表示后退0空挡
un_motor_output2.bit_data.gear = diff_data.state;
un_motor_output3.bit_data.gear = diff_data.state;
un_motor_output4.bit_data.gear = diff_data.state;
//增加系数以及偏移量
if(diff_data.state == STATE_FORWARD)//根据挡位来判断,扭矩的正负
{
abs_left_front_speed = (out_torq[0] + 300.0f) *100.0f;
abs_right_front_speed = (out_torq[1] + 300.0f) *100.0f;
abs_left_rear_speed = (out_torq[2] + 300.0f) *100.0f;
abs_right_rear_speed = (out_torq[3] + 300.0f) *100.0f;
}
else if(diff_data.state == STATE_BACKWARD)//倒挡直接修改为负扭矩发送出去
{
abs_left_front_speed = (-out_torq[0] + 300.0f) *100.0f;
abs_right_front_speed = (-out_torq[1] + 300.0f) *100.0f;
abs_left_rear_speed = (-out_torq[2] + 300.0f) *100.0f;
abs_right_rear_speed = (-out_torq[3] + 300.0f) *100.0f;
}
else//空挡直接发0
{
abs_left_front_speed = 0;
abs_right_front_speed = 0;
abs_left_rear_speed = 0;
abs_right_rear_speed = 0;
}
// 设置左右电机期望转速
// un_motor_output1.bit_data.set_rotation_speed = ((uint16_t)roundf(abs_left_speed) + 30000); // 20240921 增加偏移量 30000
// un_motor_output2.bit_data.set_rotation_speed = ((uint16_t)roundf(abs_right_speed) + 30000); // 20240921 增加偏移量 30000
// 设置模式为扭矩模式
un_motor_output1.bit_data.mode = MOTOR_MODE;
un_motor_output2.bit_data.mode = MOTOR_MODE;
un_motor_output3.bit_data.mode = MOTOR_MODE;
un_motor_output4.bit_data.mode = MOTOR_MODE;
// 设置最大扭矩
un_motor_output1.bit_data.set_torque = (uint16_t)( (int16_t)abs_left_front_speed );
un_motor_output2.bit_data.set_torque = (uint16_t)( (int16_t)abs_right_front_speed );
un_motor_output3.bit_data.set_torque = (uint16_t)( (int16_t)abs_left_rear_speed );
un_motor_output4.bit_data.set_torque = (uint16_t)( (int16_t)abs_right_rear_speed );
// 设置馈电功率
un_motor_output1.bit_data.feed_power = feed_power;
un_motor_output2.bit_data.feed_power = feed_power;
un_motor_output3.bit_data.feed_power = feed_power;
un_motor_output4.bit_data.feed_power = feed_power;
// 设置放电功率
un_motor_output1.bit_data.discharge_power = discharge_power;
un_motor_output2.bit_data.discharge_power = discharge_power;
un_motor_output3.bit_data.discharge_power = discharge_power;
un_motor_output4.bit_data.discharge_power = discharge_power;
}
// 限制值在最小值和最大值之间
float constrain(float value, float min_val, float max_val)
{
if (value < min_val)
{
return min_val;
}
else if (value > max_val)
{
return max_val;
}
else
{
return value;
}
}
// 计算当前速度、角速度
uint8_t calculateCurrentSpeedYawRate(void)
{
// 获取轮子周长
float wheel_circumference = (float)getParam("whl_dia") * M_PI;
// 获取减速比
float gear_ratio = (float)getParam("gRatio");
if (fabsf(gear_ratio) < EPSILON)
{
return 0; // 避免除以0的情况
}
// 将电机转速 (RPM) 转换为线速度 (m/s),考虑减速比
float left_speed_mps = (diff_data.left_motor_speed * wheel_circumference) / (60.0f * gear_ratio);
float right_speed_mps = (diff_data.right_motor_speed * wheel_circumference) / (60.0f * gear_ratio);
// float left_speed_mps = 0;
// float right_speed_mps = 0;
// float left_speed_mps = 0;
// float right_speed_mps = 0;
// 计算当前速度
diff_data.speed = (left_speed_mps + right_speed_mps) / 2.0f;
// 计算速度差
float speed_diff = left_speed_mps - right_speed_mps;
// 计算角速度
float wheel_base = (float)getParam("whl_bas");
if (fabsf(wheel_base) < EPSILON)
{
return 0; // 避免除以0的情况
}
diff_data.yaw_rate = speed_diff / wheel_base;
return 0;
}
// 计算加速度
float calculateAcceleration(float speed, float previous_speed, float dt)
{
if (fabs(dt) < EPSILON)
{
return 0; // 避免除以0的情况
}
float acceleration = (speed - previous_speed) / dt;
return acceleration;
}
// 计算减速度
float calculateDeceleration(float speed, float previous_speed, float dt)
{
if (fabs(dt) < EPSILON)
{
return 0; // 避免除以0的情况
}
float deceleration = calculateAcceleration(previous_speed, speed, dt); // 减速度就是负的加速度
return deceleration;
}
// 计算最大速度
float calculateMaxSpeed()
{
// 获取最大电机转速 (RPM)
float max_rpm = (float)getParam("max_rpm");
// 获取轮子周长
float wheel_circumference = (float)getParam("whl_dia") * M_PI;
// 获取减速比
float gear_ratio = (float)getParam("gRatio");
if (fabsf(gear_ratio) < EPSILON)
{
return 0; // 避免除以0的情况
}
// 将最大电机转速 (RPM) 转换为线速度 (m/s),考虑减速比
float max_speed = (max_rpm * wheel_circumference) / (60.0f * gear_ratio);
return max_speed;
}
// 计算最大加速度
float calculateMaxAcceleration(void)
{
// 获取车辆参数
float max_motor_torque = (float)getParam("maxTorq"); // 最大电机扭矩
float vehicle_mass = (float)getParam("VehMass"); // 车辆质量
float wheel_radius = (float)getParam("whl_dia") / 2.0f; // 轮子半径
float gear_ratio = (float)getParam("gRatio"); // 减速比
if (fabsf(wheel_radius) < EPSILON || fabsf(vehicle_mass) < EPSILON )
{
return 0; // 避免除以0的情况
}
// 减速比计算扭矩
float effective_torque = max_motor_torque * gear_ratio;
// 计算最大加速度
float max_acceleration = (effective_torque / wheel_radius) / vehicle_mass;
return max_acceleration;
}
// 计算当前状态,包括当前速度、角速度、加速度、减速度、最大速度
void calculateCurrentState(float dt)
{
static float previous_speed = 0.0f;
// 更新当前速度和当前角速度
calculateCurrentSpeedYawRate();
// 更新加速度、减速度等,根据需要计算
diff_data.acceleration = calculateAcceleration(diff_data.speed, previous_speed, dt);
diff_data.deceleration = calculateDeceleration(diff_data.speed, previous_speed, dt);
diff_data.max_speed = calculateMaxSpeed();
previous_speed = diff_data.speed;
}
/**
* @brief 基于转速反比的双电机扭矩分配函数
* @param rpm1 电机1当前转速单位rpm
* @param rpm2 电机2当前转速单位rpm
* @param total_torque 系统总需求扭矩单位Nm
* @param torque1 [out] 电机1分配到的扭矩单位Nm
* @param torque2 [out] 电机2分配到的扭矩单位Nm
* @note 分配原则:转速越高的电机分配扭矩越小,确保负载均衡
*/
void distributeTorque(float rpm1, float rpm2, float total_torque, float* torque1, float* torque2, float max_torque, float min_torque)
{
// 总扭矩为0时快速返回
if (fabs(total_torque) < 0.001f) {
*torque1 = 0.0f;
*torque2 = 0.0f;
return;
}
// // 保护条件:当两电机均静止时采用平均分配策略
// if (fabs(rpm1) < 0.001f && fabs(rpm2) < 0.001f) {
// *torque1 = total_torque / 2.0f;
// *torque2 = total_torque / 2.0f;
// return;
// }
// 计算权重因子(与转速成反比关系)
// 注添加0.001f防止零转速时除零错误fabs确保负转速正确处理
float weight1 = 1.0f / (fabs(rpm1) + 0.001f);
float weight2 = 1.0f / (fabs(rpm2) + 0.001f);
// 归一化计算分配比例
float total_weight = weight1 + weight2;
*torque1 = total_torque * (weight1 / total_weight);
*torque2 = total_torque * (weight2 / total_weight);
// 独立限制单侧扭矩(修改核心逻辑)
if (fabs(*torque1) > max_torque) {
*torque1 = copysignf(max_torque, *torque1);
}
if (fabs(*torque2) > max_torque) {
*torque2 = copysignf(max_torque, *torque2);
}
// 仅对非零扭矩应用下限限制
if (fabs(*torque1) < min_torque) {
*torque1 = copysignf(min_torque, *torque1);
}
if ( fabs(*torque2) < min_torque) {
*torque2 = copysignf(min_torque, *torque2);
}
}
/**
* @brief 根据轮速差动态调整电机扭矩(带非负限制)
* @param speed_left 左轮速度单位rpm或自定义
* @param speed_right 右轮速度单位rpm或自定义
* @param torque_left 左轮扭矩指针单位Nm或自定义
* @param torque_right 右轮扭矩指针单位Nm或自定义
* @param threshold 触发调整的速差阈值(单位同轮速)
* @param k 扭矩调整系数无量纲建议0<k<1
* @note 函数会直接修改传入的扭矩值并确保扭矩不小于0
*/
void adjust_torque_by_speed_diff(float speed_left, float speed_right,
float* torque_left, float* torque_right,
float threshold, float k) {
// 计算轮速差绝对值
float speed_diff = fabsf(speed_left - speed_right);
if (speed_diff > threshold) {
// 计算需要减少的扭矩量(速差超出阈值部分×系数)
float torque_reduction = (speed_diff - threshold) * k;
if (speed_left > speed_right) {
// 左轮过快时减少左扭矩并限制最小值为0
*torque_left = fmaxf(*torque_left - torque_reduction, 0.0f);
} else {
// 右轮过快时减少右扭矩并限制最小值为0
*torque_right = fmaxf(*torque_right - torque_reduction, 0.0f);
}
}
}
// 计算左右电机速度
void computeInverseKinematics(float linear_velocity_x, float yaw_rate, float max_speed, float *motor_speed)
{
// 防止速度过低导致不必要的计算
if (fabs(max_speed) < EPSILON)
{
motor_speed[0] = 0.0f;
motor_speed[1] = 0.0f;
motor_speed[2] = 0.0f;
motor_speed[3] = 0.0f;
return;
}
#if THROTTLE_PID_MODE
float max_torque = (float)getParam("maxTorq");
linear_velocity_x = constrain(linear_velocity_x, -max_torque, max_torque);
yaw_rate = constrain(yaw_rate, -2*max_torque, 2*max_torque);
float left_speed_mps = linear_velocity_x + yaw_rate;
float right_speed_mps = linear_velocity_x - yaw_rate;
//扭矩分配
if(max_torque < left_speed_mps)
{
right_speed_mps = right_speed_mps - (left_speed_mps - max_torque);//多减去超出限值得部分,保证转矩差
left_speed_mps = max_torque;
}
else if(-max_torque > left_speed_mps)
{
right_speed_mps = right_speed_mps - (left_speed_mps + max_torque);//多减去超出限值得部分,保证转矩差
left_speed_mps = -max_torque;
}
else if(max_torque < right_speed_mps)
{
left_speed_mps = left_speed_mps - (right_speed_mps - max_torque);//多减去超出限值得部分,保证转矩差
right_speed_mps = max_torque;
}
else if(-max_torque > right_speed_mps)
{
left_speed_mps = left_speed_mps - (right_speed_mps + max_torque);//多减去超出限值得部分,保证转矩差
right_speed_mps = -max_torque;
}
else{}
printf("input_torq: left=%.1f right=%.1f yaw_rate=%.1f\n", left_speed_mps, right_speed_mps, yaw_rate);
motor_speed[0] = left_speed_mps;
motor_speed[2] = left_speed_mps;
motor_speed[1] = right_speed_mps;
motor_speed[3] = right_speed_mps;
adjust_torque_by_speed_diff( diff_data.left_front_motor_speed,diff_data.left_rear_motor_speed, &motor_speed[0], &motor_speed[2],100, 5);
adjust_torque_by_speed_diff( diff_data.right_front_motor_speed,diff_data.right_rear_motor_speed, &motor_speed[1], &motor_speed[3],100, 5);
// printf("speed: FL=%.1f FR=%.1f RL=%.1f RR=%.1f\n", diff_data.left_front_motor_speed, diff_data.right_front_motor_speed, diff_data.left_rear_motor_speed, diff_data.right_rear_motor_speed);
// distributeTorque(diff_data.left_front_motor_speed,diff_data.left_rear_motor_speed,2*left_speed_mps,&motor_speed[0],&motor_speed[2],diff_data.max_Torq,diff_data.min_Torq);
// distributeTorque(diff_data.right_front_motor_speed,diff_data.right_rear_motor_speed,2*right_speed_mps,&motor_speed[1],&motor_speed[3],diff_data.max_Torq,diff_data.min_Torq);
// printf("torq: FL=%.1fNm FR=%.1fNm RL=%.1fNm RR=%.1fNm\n", motor_speed[0], motor_speed[1], motor_speed[2], motor_speed[3]);
// // 返回计算结果
// *left_motor_speed = left_speed_mps;
// *right_motor_speed = right_speed_mps;
#else
// 限制线速度和偏航率
linear_velocity_x = constrain(linear_velocity_x, -max_speed, max_speed);
float max_yaw_rate = max_speed / ((float)getParam("whl_bas") / 2.0f);
yaw_rate = constrain(yaw_rate, -max_yaw_rate, max_yaw_rate);
// 计算旋转速度
float rotational_velocity = ((float)getParam("whl_bas") / 2.0f) * yaw_rate;
// 计算车辆左右线速度 (m/s)
float left_speed_mps = linear_velocity_x - rotational_velocity; //20250316 为解决原地转向和直行转向相同,所以把左右输出的速度交换
float right_speed_mps = linear_velocity_x + rotational_velocity;
// 计算轮子周长
float wheel_circumference = (float)getParam("whl_dia") * M_PI;
// 将车辆左右线速度转换为轮子转速 (RPM)
float left_wheel_rpm = (left_speed_mps * 60.0f) / wheel_circumference;
float right_wheel_rpm = (right_speed_mps * 60.0f) / wheel_circumference;
// 获取减速比
float gear_ratio = (float)getParam("gRatio");
// 将轮子转速转换为电机转速,考虑减速比
float left_motor_rpm = left_wheel_rpm * gear_ratio;
float right_motor_rpm = right_wheel_rpm * gear_ratio;
// 限制电机的最大和最小转速
float max_motor_rpm = (float)getParam("max_rpm");
left_motor_rpm = constrain(left_motor_rpm, -max_motor_rpm, max_motor_rpm);
right_motor_rpm = constrain(right_motor_rpm, -max_motor_rpm, max_motor_rpm);
// 当电机转速小于50转时设置为0
if (fabsf(left_motor_rpm) < 50)//速度慢所以设置位10转
{
left_motor_rpm = 0;
}
if (fabsf(right_motor_rpm) < 50)//速度慢所以设置位10转
{
right_motor_rpm = 0;
}
// 左边电机方向反一下,因为电机安装反了,返回来的数据也要反一下
// left_motor_rpm = -left_motor_rpm;
// 返回计算结果
*left_motor_speed = left_motor_rpm;
*right_motor_speed = right_motor_rpm;
#endif
}
// 映射遥控器速度,分为死区、低速区和高速区。
float mapRemoteControlSpeed(
float input_speed,
float deadzone_limit,
float input_max,
float output_max,
float input_slow,
float output_slow
)
{
float output_speed = 0.0f;
// 获取输入速度的绝对值
float abs_input = fabsf(input_speed);
//diff_data.desired_speed, 0.1, 2, 10, 1, 5
// diff_data.desired_speed = mapRemoteControlSpeed(diff_data.desired_speed, 0.1, 20, 5, 5, 0.5);
if (abs_input < deadzone_limit + EPSILON)
{
output_speed = 0.0f;// 死区
}
else if (abs_input < input_slow + EPSILON)// 低速区
{
output_speed = (abs_input - deadzone_limit) * output_slow / (input_slow - deadzone_limit);//
}
else if (abs_input <= input_max + EPSILON)// 高速区
{
output_speed = output_slow + (abs_input - input_slow) * (output_max - output_slow) / (input_max - input_slow);// 0.2 + 3 - 0.5* 15-0.2 / 17 - 0.5
}
else // 超出范围
{
output_speed = output_max;
}
// 根据原始输入速度的符号恢复方向
if (input_speed < 0)
{
output_speed = -output_speed;
}
return output_speed;
}
/**
* @brief 状态机处理函数(修改后版本)
*/
void handleVehicleState(DiffData *ctx)
{
switch (ctx->state)
{
//-------------------------------------------
// 初始状态:根据期望速度方向跳转
//-------------------------------------------
case STATE_INIT:
{
if (ctx->desired_speed < 0.0f)
{
ctx->state = STATE_BACKWARD;
}
else
{
ctx->state = STATE_FORWARD;
}
break;
}
//-------------------------------------------
// 前进状态处理反向指令新增else分支
//-------------------------------------------
case STATE_FORWARD:
{
if ((ctx->desired_speed < 0.0f) && (ctx->speed == 0.0f))
{
ctx->state = STATE_BACKWARD; // 零速时允许切换方向
}
else if ((ctx->desired_speed < 0.0f) && (ctx->speed != 0.0f))
{
ctx->desired_speed = 0.0f; // 非零速时清空期望速度
ctx->state = STATE_FORWARD; // 显式保持当前状态
}
else
{
ctx->state = STATE_FORWARD; // 新增:其他情况保持前进状态
}
break;
}
//-------------------------------------------
// 倒车状态处理正向指令新增else分支
//-------------------------------------------
case STATE_BACKWARD:
{
if ((ctx->desired_speed > 0.0f) && (ctx->speed == 0.0f))
{
ctx->state = STATE_FORWARD; // 零速时允许切换方向
}
else if ((ctx->desired_speed > 0.0f) && (ctx->speed != 0.0f))
{
ctx->desired_speed = 0.0f; // 非零速时清空期望速度
ctx->state = STATE_BACKWARD; // 显式保持当前状态
}
else
{
ctx->state = STATE_BACKWARD; // 新增:其他情况保持倒车状态
}
break;
}
}
}
// 差速处理函数
static void diffProcess(void *signal_id)
{
(void)signal_id;
static float previous_time1 = 0.0f;
float time1 = (float)getCurrentTime();
float dt = (time1 - previous_time1) / PERIOD_TICK;
previous_time1 = time1;
// 计算当前状态,包括当前速度、角速度、加速度、减速度、最大速度
calculateCurrentState(dt);
// 当速度小于1时设定为原地转向 20250321 修改为考虑负号
if( (diff_data.desired_speed >= 0) && (diff_data.desired_speed <= 1.0f) )
{
diff_data.desired_yaw_rate = diff_data.desired_curvature * 1.0f;
}
else if( (diff_data.desired_speed < 0) && (diff_data.desired_speed >= -1.0f) )
{
diff_data.desired_yaw_rate = diff_data.desired_curvature * -1.0f;
}
else
{
diff_data.desired_yaw_rate = diff_data.desired_curvature * diff_data.desired_speed;
}
handleVehicleState(&diff_data); //20250704 换挡函数 速度为0才能换挡
// printf("desired_speed: %f, desired_yaw: %f\n", diff_data.desired_speed, diff_data.desired_yaw_rate);
// 使用 PID 控制器计算输出速度和曲率
float output_speed = calculatePidOutput(&speed_pid, diff_data.desired_speed, diff_data.speed, 0.0f, dt);
float output_yaw_rate = calculatePidOutput(&yaw_rate_pid, diff_data.desired_yaw_rate, diff_data.yaw_rate, 0.0f, dt);
// 计算最大加速度,用函数计算
float max_acceleration = calculateMaxAcceleration();
// 限制输出速度在当前速度和最大加速度计算出来的速度之间
// output_speed = constrain(output_speed, diff_data.speed - max_acceleration * dt, diff_data.speed + max_acceleration * dt);
if( (0 == diff_data.desired_yaw_rate) && (0 == diff_data.desired_speed) )//手柄回中速度小的时候清0
{
resetPidIntegral(&speed_pid);
resetPidIntegral(&yaw_rate_pid);
output_speed = 0;
output_yaw_rate = 0;
}
// printf("output_speed: %f, output_yaw: %f, integral: %f\n", output_speed, output_yaw_rate,speed_pid.integral);
// if(diff_data.desired_yaw_rate != 0)//有转向的情况下下
// {
// if( (output_yaw_rate > -500) && (output_yaw_rate < 500) )//如果是转向输出在-500~500之间那么开始原地转向扭矩太小所以设定最小扭矩。
// {
// output_yaw_rate = 500;
// }
// }
// 使用差速车辆动力学模型计算左右电机的期望速度
computeInverseKinematics(output_speed, output_yaw_rate, diff_data.max_speed, &diff_data.out_torq[0]);
// if( (left_speed < 200) && (left_speed > -200) )
// {
// left_speed = 0;
// }
//
// if( (right_speed < 200) && (right_speed > -200) )
// {
// right_speed = 0;
// }
// 设置电机输出
setMotorOutput(&diff_data.out_torq[0],
diff_data.max_Torq,//
(uint16_t)getParam("feedPwr"),
(uint16_t)getParam("dispPwr"));
// 发布左右电机期望转速,电源在工作状态才能发送
if (power_data.current_state == POWER_WORKING)
{
publishMessage(&un_motor_output1, 1);
publishMessage(&un_motor_output2, 1);
publishMessage(&un_motor_output3, 1);
publishMessage(&un_motor_output4, 1);
}
un_can_debug_output.bit_data.speed = (uint8_t)(int8_t)(diff_data.speed*10);
un_can_debug_output.bit_data.desired_speed = (uint8_t)(int8_t)(diff_data.desired_speed*10);
un_can_debug_output.bit_data.curvature = (uint8_t)(int8_t)(diff_data.yaw_rate*10);
un_can_debug_output.bit_data.desired_curvature = (uint8_t)(int8_t)(diff_data.desired_yaw_rate*10);
un_can_debug_output.bit_data.set_left_out = (uint16_t)(int16_t)(diff_data.left_motor_speed);
un_can_debug_output.bit_data.set_right_out = (uint16_t)(int16_t)(diff_data.right_motor_speed);
publishMessage(&diff_data, 1);
}
/******************************************************************************
Filter(); N个数中取两个
******************************************************************************/
int16_t Filter(int16_t *s,uint8_t Len)
{
uint8_t i,j;
int16_t temp;
//降序排序
for(i=0;i<Len-1;i++)
for(j=i+1;j<Len;j++)
{
if(*(s+i)>*(s+j))
{
*(s+i)=*(s+i)^*(s+j);
*(s+j)=*(s+j)^*(s+i);
*(s+i)=*(s+i)^*(s+j);
}
}
temp=(*(s+Len/2)+*(s+(Len/2-1)))/2;//20210225修改为除以2负数不能够右移
return(temp);
}
// 差速输入处理函数
static void diffInput(void *signal_id)
{
float motor_speed_temp = 0.0f;
if (signal_id == &un_sw_sample)
{
diff_data.emergency_stop_switch = (uint8_t)un_sw_sample.bit_data.emergency_stop_switch;
}
else if ( (signal_id == &un_remote_control_input) && (1 == un_remote_control_input.bit_data.enable) )// 遥控器断线,不更新数据
{
diff_data.remote_emergency_stop = !(uint8_t)un_remote_control_input.bit_data.switch_b;
diff_data.mode = un_remote_control_input.bit_data.switch_c == 1 ? MODE_AUTO : MODE_MANUAL;
if (diff_data.mode == MODE_MANUAL)
{
diff_data.desired_speed = (float)((int16_t)(un_remote_control_input.bit_data.speed));
diff_data.desired_curvature = (float)((int16_t)(un_remote_control_input.bit_data.curvature));
// 单位转换
diff_data.desired_speed = diff_data.desired_speed * 0.01f;
diff_data.desired_curvature = diff_data.desired_curvature * 0.0001f;
// 遥控器速度映射,参数含义为:输入速度,死区,最大输入,最大输出,低速输入,低速输出
diff_data.desired_speed = mapRemoteControlSpeed(diff_data.desired_speed, 0.1, 20, 5, 5, 0.5);
diff_data.desired_curvature = mapRemoteControlSpeed(diff_data.desired_curvature, 0.1, 2, 2, 1, 0.5);
if(diff_data.desired_speed >= 0)//20250320 增加根据速度大小来决定方向,解决后退时转弯反向的问题
{
diff_data.desired_curvature = diff_data.desired_curvature;
}
else
{
diff_data.desired_curvature = -diff_data.desired_curvature;
}
}
}
else if ( (signal_id == &un_manual_computer_input) && (diff_data.mode == MODE_AUTO) )
{
diff_data.desired_speed = (float)((int16_t)(un_manual_computer_input.bit_data.set_speed));
diff_data.desired_curvature = (float)((int16_t)(un_manual_computer_input.bit_data.set_curvature));
// 单位转换
diff_data.desired_speed = diff_data.desired_speed * 0.01f;
diff_data.desired_curvature = diff_data.desired_curvature * 0.0001f;
// 遥控器速度映射,参数含义为:输入速度,死区,最大输入,最大输出,低速输入,低速输出
diff_data.desired_speed = mapRemoteControlSpeed(diff_data.desired_speed, 0.2, 2, 10, 1, 5);//20250320 修改死区为0.2解决停不住的问题
diff_data.desired_curvature = mapRemoteControlSpeed(diff_data.desired_curvature, 0, 2, 2, 1, 1);
}
else if ( (signal_id == &un_auto_computer_input) && (diff_data.mode == MODE_AUTO) )
{
diff_data.desired_speed = (float)((int16_t)(un_auto_computer_input.bit_data.set_speed));
diff_data.desired_curvature = (float)((int16_t)(un_auto_computer_input.bit_data.set_curvature));
// 单位转换
diff_data.desired_speed = diff_data.desired_speed * 0.01f;
diff_data.desired_curvature = - diff_data.desired_curvature * 0.0001f;// 20241016 增加转弯反相
// 遥控器速度映射,参数含义为:输入速度,死区,最大输入,最大输出,低速输入,低速输出
diff_data.desired_speed = mapRemoteControlSpeed(diff_data.desired_speed, 0, 5, 10, 2.5, 5);
diff_data.desired_curvature = mapRemoteControlSpeed(diff_data.desired_curvature, 0, 2, 2, 1, 1);
}
else if ( (signal_id == &un_motor_input1) || (signal_id == &un_motor_input3) )// 处理第一个电机速度信号(左电机)
{
diff_data.left_front_motor_speed = (float)((int16_t)(un_motor_input1.bit_data.speed - 30000));//20240921 增加偏移量
diff_data.left_rear_motor_speed = (float)((int16_t)(un_motor_input3.bit_data.speed - 30000));//20240921 增加偏移量
if(fabs(diff_data.left_rear_motor_speed) > fabs(diff_data.left_front_motor_speed))//取速度较小的轮速
{
motor_speed_temp = diff_data.left_front_motor_speed;
}
else
{
motor_speed_temp = diff_data.left_rear_motor_speed;
}
diff_data.left_motor_speed = motor_speed_temp;
}
else if( (signal_id == &un_motor_input2) || (signal_id == &un_motor_input4) )// 处理第二个电机速度信号(右电机)
{
diff_data.right_front_motor_speed = (float)((int16_t)(un_motor_input2.bit_data.speed - 30000)); // 20250502 1号控制器增加反相
diff_data.right_rear_motor_speed = (float)((int16_t)(un_motor_input4.bit_data.speed - 30000));
if(fabs(diff_data.right_front_motor_speed) > fabs(diff_data.right_rear_motor_speed))//取速度较小的轮速
{
motor_speed_temp = diff_data.right_rear_motor_speed;
}
else
{
motor_speed_temp = diff_data.right_front_motor_speed;
}
diff_data.right_motor_speed = motor_speed_temp;
}
// 急停开关
diff_data.emergency_stop_state = (uint8_t)(diff_data.emergency_stop_switch == app_close() || diff_data.remote_emergency_stop == app_close());
// 如果急停被激活,强制设定速度为0,急停包括车上急停开关和遥控器急停开关
if (diff_data.emergency_stop_state == 1)
{
diff_data.desired_speed = 0.0;
diff_data.desired_curvature = 0.0;
}
// 遥控器断线而且是在手动模式期望值清0
if ( (diff_data.mode == MODE_MANUAL) && (0 == un_remote_control_input.bit_data.enable) )
{
diff_data.desired_speed = 0.0;
diff_data.desired_curvature = 0.0;
}
if (diff_data.emergency_stop_state == 1)//刹车 20241017 增加的扭矩限制
{
diff_data.max_Torq = 5;//20240403修改。刹车就是5N
}
else if ((0 == diff_data.desired_speed) && (0 == diff_data.desired_curvature) && (diff_data.left_motor_speed > -100) && (diff_data.left_motor_speed < 100)&& (((diff_data.right_motor_speed > -100) && (diff_data.right_motor_speed < 100))))//20240330只有当手柄回中然后当前已经停止的状态才设置为最小停车扭矩
{
diff_data.max_Torq = 5;//停车 就为0 20250425 修改为5解决手柄回中震荡问题
}
else
{
diff_data.max_Torq = (uint16_t)getParam("maxTorq");//参数读取设定最大扭矩
}
diffProcess(&diff_data);//计算左右电机期望转速
}
// 预充完成处理函数
void preChargeFinish(void *signal_id)
{
(void)signal_id;
float out_torq[4] = {0.0f,0.0f,0.0f,0.0f};
setMotorOutput(out_torq, (uint16_t)getParam("maxTorq"), (uint16_t)getParam("feedPwr"), (uint16_t)getParam("dispPwr"));
// 档位
// un_motor_output1.bit_data.gear = 0; // 0表示空挡
// un_motor_output2.bit_data.gear = 0;
publishMessage(&un_motor_output1, 1);
publishMessage(&un_motor_output2, 1);
}
void diffParametersInit(void *signal_id)
{
(void)signal_id; // 标记变量为已使用,避免编译器警告
if(diff_data.mode == MODE_AUTO)//20250504 自动模式PID
{
setPidParameters(&speed_pid,
getParam("Ospd_kp"),
getParam("Ospd_ki"),
getParam("Ospd_kd"),
getParam("Ospd_il"),
getParam("Ospd_ol")
);
setPidParameters(&yaw_rate_pid,
getParam("Ocrv_kp"),
getParam("Ocrv_ki"),
getParam("Ocrv_kd"),
getParam("Ocrv_il"),
getParam("Ocrv_ol")
);
}
else//手动模式
{
setPidParameters(&speed_pid,
getParam("spd_kp"),
getParam("spd_ki"),
getParam("spd_kd"),
getParam("spd_il"),
getParam("spd_ol")
);
setPidParameters(&yaw_rate_pid,
getParam("crv_kp"),
getParam("crv_ki"),
getParam("crv_kd"),
getParam("crv_il"),
getParam("crv_ol")
);
}
diff_data.min_Torq = (uint16_t)getParam("minTorq");//参数读取设定最大扭矩
printf("desired_speed: %f, desired_yaw_rate: %f\n", diff_data.desired_speed, diff_data.desired_yaw_rate);
printf("speed: %f, yaw_rate: %f\n", diff_data.speed, diff_data.yaw_rate);
// printf("speed: %f, yaw_rate: %f\n", diff_data.speed, diff_data.yaw_rate);
printf("left_motor_speed = %f\n",diff_data.left_motor_speed);
printf("right_motor_speed = %f\n",diff_data.right_motor_speed);
// printf("speed: FL=%.1f FR=%.1f RL=%.1f RR=%.1f\n", diff_data.left_front_motor_speed, diff_data.right_front_motor_speed, diff_data.left_rear_motor_speed, diff_data.right_rear_motor_speed);
// printf("torq: FL=%.1fNm FR=%.1fNm RL=%.1fNm RR=%.1fNm\n", diff_data.out_torq[0], diff_data.out_torq[1], diff_data.out_torq[2], diff_data.out_torq[3]);
float deffspeed = (float)((int16_t)(un_remote_control_input.bit_data.speed));
float deffcurvature = (float)((int16_t)(un_remote_control_input.bit_data.curvature));
// 单位转换
deffspeed = deffspeed * 0.01f;
deffcurvature = deffcurvature * 0.0001f;
printf("remote speed = %f, remote curvature = %f\n", deffspeed, deffcurvature);
timerStart(&diff_app_timer,1000,1);//1s调用一次
}
// 差速初始化函数
void diffAppInit(void)
{
// 初始化 diff_data
memset(&diff_data, 0, sizeof(DiffData));
// 订阅相关信号
subscribe(&un_sw_sample, diffInput); // 急停开关、高压开关
subscribe(&un_motor_input1, diffInput);
subscribe(&un_motor_input2, diffInput);
subscribe(&un_auto_computer_input, diffInput);
subscribe(&un_manual_computer_input, diffInput);
subscribe(&un_remote_control_input, diffInput);
subscribe(&power_data.pre_charge_finish, preChargeFinish);
// 初始化速度 PID 控制器
initializePid(&speed_pid, PID_MODE_DERIVATIVE_CALC, 0.0001f);
// 设置速度 PID 控制器的参数
setPidParameters(&speed_pid,
getParam("spd_kp"),
getParam("spd_ki"),
getParam("spd_kd"),
getParam("spd_il"),
getParam("spd_ol")
);
// 初始化曲率 PID 控制器
initializePid(&yaw_rate_pid, PID_MODE_DERIVATIVE_CALC, 0.0001f);
// 设置曲率 PID 控制器的参数
setPidParameters(&yaw_rate_pid,
getParam("crv_kp"),
getParam("crv_ki"),
getParam("crv_kd"),
getParam("crv_il"),
getParam("crv_ol")
);
subscribe(&diff_app_timer, diffParametersInit);
timerStart(&diff_app_timer,1000,1);//1s调用一次
printf("diffControl: diffAppInit OK \n");
}

View File

@@ -0,0 +1,84 @@
#ifndef APP_DIFFERENTIAL_DRIVE_H
#define APP_DIFFERENTIAL_DRIVE_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "app_config.h"
#define SPEED_FITER_NUM 6
#define SPEED_PID_MODE 0
#define THROTTLE_PID_MODE 1
#define SPEED_MODE 0x01
#define TORQUE_MODE 0x02
#define MOTOR_MODE TORQUE_MODE
#define ALPHA 0.1f // 滤波系数α∈[0.01,0.3]0.2对应截止频率约10Hz假设采样周期10ms
#define LOWPASS_FILTER(speed, prev) (ALPHA * (speed) + (1 - ALPHA) * (prev))
// 状态机内部状态
typedef enum
{
STATE_INIT, ///< 初始状态转速为0且等待扭矩方向判定
STATE_FORWARD, ///< 正向旋转状态(扭矩为正)
STATE_BACKWARD, ///< 反向旋转状态(扭矩为负)
} MotorState;
typedef enum
{
MODE_MANUAL, // 手动模式
MODE_AUTO // 自动模式
} ControlMode;
typedef struct DiffData
{
ControlMode mode ; // 控制模式
MotorState state; //当前状态机状态
float desired_speed; // 期望速度
float desired_curvature; // 期望曲率
float left_motor_speed; // 当前左电机速度
float right_motor_speed; // 当前右电机速度
float left_front_motor_speed; // 当前左前电机速度
float right_front_motor_speed; // 当前右前电机速度
float left_rear_motor_speed; // 当前左后电机速度
float right_rear_motor_speed; // 当前右后电机速度
float speed; // 当前车速
float curvature; // 当前曲率
float yaw_rate; // 当前角速度
float desired_yaw_rate; // 期望角速度
float acceleration; // 当前加速度
float deceleration; // 当前减速度
float max_speed; // 最大速度
float desired_acceleration; // 期望加速度
float desired_deceleration; // 期望减速度
uint8_t emergency_stop_switch; // 急停开关
uint8_t remote_emergency_stop; // 遥控器急停开关
uint8_t emergency_stop_state; // 急停状态
float out_left_motor_speed; // 输出左电机速度
float out_right_motor_speed; // 输出右电机速度
float out_torq[4]; //4个电机扭矩
float max_Torq; // 最大扭矩限制
float min_Torq; // 最小扭矩限制
} DiffData;
// 声明外部变量
extern DiffData diff_data;
void diffAppInit(void);
#ifdef __cplusplus
}
#endif
#endif // APP_DIFFERENTIAL_DRIVE_H

175
app/app_frm_monitor.c Normal file
View File

@@ -0,0 +1,175 @@
#include "app_config.h"
#include "interface.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
// 全局日志缓冲区实例
LogBuffer log_buffer;
// 打印当前信号队列状态
void printSignalQueueStatus(void)
{
for (uint32_t i = 0; i < PRIORITY_LEVELS; i++)
{
printf("Priority %u Signal Count: %d\n", i,
getSignalCount(i));
}
}
// 打印订阅者信息
void printSubscriberInfo(void)
{
printf("Total Subscribers: %u\n", getSubscriberCount());
}
// 打印定时器状态
void printTimerStatus(void)
{
printf("Current Timer Count: %u / %u\n",
getCurrentTimerCount(), MAX_TIMERS);
}
// 监控函数
void monitorSignalSystem(void)
{
static uint32_t last_print_time = 0;
uint32_t current_print_time = getCurrentTime();
uint32_t time_interval = current_print_time - last_print_time;
printf("---------------------------------------------------\n");
printf("Time since last print: %u us\n", time_interval);
printSignalQueueStatus();
printSubscriberInfo();
printTimerStatus();
printf("---------------------------------------------------\n");
last_print_time = current_print_time;
}
int logBufferWrite(LogBuffer *lb, const char *format, ...)
{
if (format == NULL || lb == NULL)
{
return -1;
}
char temp_buffer[256]; // 临时缓冲区假设单条日志不超过256字节
va_list args;
va_start(args, format);
int length = vsnprintf(temp_buffer, sizeof(temp_buffer), format, args);
va_end(args);
if (length <= 0)
{
return -1;
}
// 进入关键区,保护缓冲区的写操作
irq_state_t saved_state = enter_critical_section();
// 检查缓冲区是否有足够的空间
if (lb->count + length > LOG_BUFFER_SIZE)
{
// 缓冲区满,无法写入
exit_critical_section(saved_state);
return -1;
}
// 写入数据到缓冲区
for (int i = 0; i < length; i++)
{
lb->buffer[lb->tail] = temp_buffer[i];
lb->tail = (lb->tail + 1) % LOG_BUFFER_SIZE;
}
lb->count += length;
exit_critical_section(saved_state);
return 0;
}
int logBufferRead(LogBuffer *lb, char *data, uint32_t max_length)
{
if (max_length == 0 || data == NULL || lb == NULL)
{
return -1;
}
// 进入关键区,保护缓冲区的读操作
irq_state_t saved_state = enter_critical_section();
uint32_t length = lb->count < max_length ? lb->count : max_length;
// 从缓冲区读取数据
for (uint32_t i = 0; i < length; i++)
{
data[i] = lb->buffer[lb->head];
lb->head = (lb->head + 1) % LOG_BUFFER_SIZE;
}
lb->count -= length;
exit_critical_section(saved_state);
return length;
}
// 初始化日志缓冲区
void initLogBuffer(LogBuffer *lb)
{
lb->head = 0;
lb->tail = 0;
lb->count = 0;
memset(lb->buffer, 0, LOG_BUFFER_SIZE);
}
// 日志信号处理函数
void logSignalHandler(void *signal_id)
{
(void)signal_id;
char log_data[256]; // 假设单次读取不超过256字节
int read_length;
// 从缓冲区读取日志信息
read_length = logBufferRead(&log_buffer, log_data, sizeof(log_data) - 1);
if (read_length > 0)
{
log_data[read_length] = '\0'; // 确保字符串以NULL结尾
// 调用printf进行打印
printf("%s", log_data);
}
}
Timer log_timer;
void logTimerHandler(void *timer_id)
{
(void)timer_id;
// monitorSignalSystem();
timerStart(&log_timer, 1000, 1);
}
void appMonitorInit(void)
{
// 初始化日志缓冲区
initLogBuffer(&log_buffer);
// 订阅日志信号
subscribe(&log_buffer, logSignalHandler);
timerInit(&log_timer);
timerStart(&log_timer, 1000, 1);
subscribe(&log_timer, logTimerHandler);
}
// // 使用格式化字符串记录日志
// if (logBufferWrite(&log_buffer, "ISR triggered: IRQ %d\n", irq_number) == 0) {
// // 发送信号,通知主线程有新日志
// publishMessage(&log_buffer, LOG_SIGNAL_PRIORITY);
// }

41
app/app_frm_monitor.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef APP_FRM_MONITOR_H
#define APP_FRM_MONITOR_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#define LOG_BUFFER_SIZE 1024 // 日志缓冲区的大小
#define LOG_SIGNAL_PRIORITY 1 // 日志信号的优先级
typedef struct
{
char buffer[LOG_BUFFER_SIZE];
uint32_t head; // 读指针
uint32_t tail; // 写指针
uint32_t count; // 缓冲区中的数据量
} LogBuffer;
// 全局日志缓冲区实例
extern LogBuffer log_buffer;
// 函数声明
void printSignalQueueStatus(void);
void printSubscriberInfo(void);
void printTimerStatus(void);
void monitorSignalSystem(void);
// 新增函数接口
int32_t logBufferWrite(LogBuffer *lb, const char *format, ...);
int32_t logBufferRead(LogBuffer *lb, char *data, uint32_t max_length);
void initLogBuffer(LogBuffer *lb);
void logSignalHandler(void *signal_id);
void appMonitorInit(void);
#ifdef __cplusplus
}
#endif
#endif // APP_FRM_MONITOR_H

324
app/app_frm_signal.c Normal file
View File

@@ -0,0 +1,324 @@
#include "app_config.h"
#include "interface.h"
#include "app_frm_signal.h"
typedef struct
{
void *signals[MAX_SIGNALS];
uint32_t head;
uint32_t tail;
uint32_t count;
} SignalQueue;
typedef struct
{
void *signal_id;
CallbackFunc callbacks[MAX_CALLBACKS];
uint32_t callback_count;
} Subscriber;
// 优先级队列
static SignalQueue priority_queues[PRIORITY_LEVELS];
// 订阅者表
static Subscriber subscriber_table[MAX_SUBSCRIBERS] = {{NULL, {NULL}, 0}};
// 初始化队列
static void initQueue(SignalQueue *q)
{
q->head = 0;
q->tail = 0;
q->count = 0;
}
// 将信号请求添加到队列中(按优先级)
static int32_t enqueue(SignalQueue *q, void *signal_id)
{
if (q == NULL)
{
printf("Error: enqueue received NULL queue pointer\n");
return -1;
}
if (signal_id == NULL)
{
printf("Error: Cannot enqueue NULL signal_id\n");
return -1;
}
irq_state_t saved_state = enter_critical_section();
if (q->count >= MAX_SIGNALS)
{
// 队列已满,移除最前面的信号
q->signals[q->head] = NULL;
q->head = (q->head + 1) % MAX_SIGNALS;
q->count--;
printf("Error: Signal queue is full, remove the first signal\n");
}
// 添加新的信号到队列尾部
q->signals[q->tail] = signal_id;
q->tail = (q->tail + 1) % MAX_SIGNALS;
q->count++;
exit_critical_section(saved_state);
return 0;
}
// 从队列中取出信号请求(按优先级)
static int32_t dequeue(SignalQueue *q, void **signal_id)
{
if (q == NULL)
{
printf("Error: dequeue received NULL queue pointer\n");
return -1;
}
if (signal_id == NULL)
{
printf("Error: dequeue received NULL signal pointer\n");
return -1;
}
// 仅在修改共享资源时进入临界区
if (q->count > 0)
{
irq_state_t saved_state = enter_critical_section();
*signal_id = q->signals[q->head];
q->signals[q->head] = NULL; // 清除已取出的信号
q->head = (q->head + 1) % MAX_SIGNALS;
q->count--;
exit_critical_section(saved_state);
return 0;
}
// printf("Warning: dequeue attempted to remove signal from an empty queue\n");
return -1;
}
// 哈希函数
static uint32_t hash(void *ptr)
{
uintptr_t value = (uintptr_t)ptr;
uint32_t hash = 0;
while (value != 0)
{
hash += value & 0xFF;
hash += (hash << 10);
hash ^= (hash >> 6);
value >>= 8;
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
// 订阅信号, 给每个信号指定回调函数
int32_t subscribe(void *signal_id, CallbackFunc callback)
{
if (signal_id == NULL || callback == NULL)
{
printf("Error: Invalid signal_id or callback\n");
return -1;
}
irq_state_t saved_state = enter_critical_section();
uint32_t index = hash(signal_id) % MAX_SUBSCRIBERS;
uint32_t original_index = index;
do
{
if (subscriber_table[index].signal_id == NULL ||
subscriber_table[index].signal_id == signal_id)
{
if (subscriber_table[index].signal_id == NULL)
{
subscriber_table[index].signal_id = signal_id;
subscriber_table[index].callback_count = 0;
}
if (subscriber_table[index].callback_count < MAX_CALLBACKS)
{
subscriber_table[index].callbacks[subscriber_table[index].callback_count++] = callback;
exit_critical_section(saved_state);
return 0;
}
else
{
printf("Error: Maximum callbacks reached for this signal\n");
exit_critical_section(saved_state);
return -1;
}
}
index = (index + 1) % MAX_SUBSCRIBERS;
} while (index != original_index);
printf("Error: Subscriber table is full\n");
exit_critical_section(saved_state);
return -1;
}
// 检查信号是否有订阅者
static unsigned char hasSubscribers(void *signal_id)
{
irq_state_t saved_state = enter_critical_section();
uint32_t index = hash(signal_id) % MAX_SUBSCRIBERS;
uint32_t original_index = index;
do
{
if (subscriber_table[index].signal_id == signal_id)
{
unsigned char result = subscriber_table[index].callback_count > 0;
exit_critical_section(saved_state);
return result;
}
if (subscriber_table[index].signal_id == NULL)
{
exit_critical_section(saved_state);
return 0; // 没有订阅者
}
index = (index + 1) % MAX_SUBSCRIBERS;
} while (index != original_index);
exit_critical_section(saved_state);
return 0; // 没有订阅者
}
// 内部一致性检查
static void internalConsistencyCheck(void)
{
for (uint32_t i = 0; i < MAX_SUBSCRIBERS; i++)
{
assert(subscriber_table[i].callback_count <= MAX_CALLBACKS);
}
}
// 处理队列中的信号, 调用所有匹配的回调函数
static void processSignals(void)
{
void *signal_id;
for (uint32_t priority = 0; priority < PRIORITY_LEVELS; priority++)
{
SignalQueue *q = &priority_queues[priority];
while (dequeue(q, &signal_id) == 0)
{
// 进入临界区保护 subscriber_table 的读取
irq_state_t saved_state = enter_critical_section();
uint32_t index = hash(signal_id) % MAX_SUBSCRIBERS;
uint32_t original_index = index;
unsigned char found = 0;
do
{
if (subscriber_table[index].signal_id == signal_id)
{
CallbackFunc *callbacks = subscriber_table[index].callbacks;
uint32_t callback_count = subscriber_table[index].callback_count;
// 复制回调函数指针, 避免在临界区外访问共享数据
CallbackFunc local_callbacks[MAX_CALLBACKS];
memcpy(local_callbacks, callbacks, sizeof(CallbackFunc) * callback_count);
exit_critical_section(saved_state);
// 在临界区外调用回调函数
for (uint32_t i = 0; i < callback_count; i++)
{
local_callbacks[i](signal_id);
}
found = 1;
break;
}
if (subscriber_table[index].signal_id == NULL)
{
exit_critical_section(saved_state);
break; // 没有订阅者
}
index = (index + 1) % MAX_SUBSCRIBERS;
} while (index != original_index);
if (!found)
{
printf("Warning: No subscribers found for signal %p\n", signal_id);
}
}
}
internalConsistencyCheck(); // 处理完所有信号后进行一致性检查
}
// 初始化框架
void initFramework(void)
{
irq_state_t saved_state = enter_critical_section();
for (uint32_t i = 0; i < PRIORITY_LEVELS; i++)
{
initQueue(&priority_queues[i]);
}
memset(subscriber_table, 0, sizeof(subscriber_table));
exit_critical_section(saved_state);
}
// 将信号请求添加到指定优先级的队列中
int32_t publishMessage(void *signal_id, uint8_t priority)
{
if ((uint32_t)priority >= PRIORITY_LEVELS)
{
printf("Error: Invalid priority\n");
return -1;
}
if (hasSubscribers(signal_id))
{
return enqueue(&priority_queues[priority], signal_id);
}
else return 1;
}
// 处理所有优先级的信号
void processMessages(void)
{
processSignals();
}
// 获取当前队列中的信号数量
int32_t getSignalCount(uint32_t priority)
{
if (priority >= PRIORITY_LEVELS)
{
printf("Error: Invalid priority\n");
return -1;
}
return priority_queues[priority].count;
}
// 获取订阅者数量
uint32_t getSubscriberCount(void)
{
uint32_t count = 0;
irq_state_t saved_state = enter_critical_section();
for (uint32_t i = 0; i < MAX_SUBSCRIBERS; i++)
{
if (subscriber_table[i].signal_id != NULL)
{
count++;
}
}
exit_critical_section(saved_state);
return count;
}

47
app/app_frm_signal.h Normal file
View File

@@ -0,0 +1,47 @@
#ifndef APP_FRM_SIGNAL_H
#define APP_FRM_SIGNAL_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include "app_dependence.h"
#define MAX_SIGNALS 500u // 每个优先级的最大信号数量
#define MAX_SUBSCRIBERS 50u // 不同信号的订阅者数量
#define MAX_CALLBACKS 25u // 每个信号最多支持多少订阅者
#define PRIORITY_LEVELS 2u // 优先级层次
// 回调函数类型定义
typedef void (*CallbackFunc)(void *signal_id);
// 函数声明
void initFramework(void);
int32_t subscribe(void *signal_id, CallbackFunc callback);
int32_t publishMessage(void *signal_id, uint8_t priority);
void processMessages(void);
int32_t getSignalCount(uint32_t priority);
uint32_t getSubscriberCount(void);
// 进入临界区,禁用中断,并返回之前的中断状态
static inline irq_state_t enter_critical_section(void)
{
return arch_irq_save();
}
// 退出临界区,恢复之前的中断状态
static inline void exit_critical_section(irq_state_t saved_state)
{
arch_irq_restore(saved_state);
}
#ifdef __cplusplus
}
#endif
#endif // APP_FRM_SIGNAL_H

165
app/app_frm_timer.c Normal file
View File

@@ -0,0 +1,165 @@
#include "app_config.h"
#include "interface.h"
#include "app_frm_timer.h"
#include "app_frm_signal.h"
// 全局计时器列表头指针
static Timer *timer_list = NULL;
// 添加一个静态变量来跟踪当前定时器数量
static uint32_t current_timer_count = 0;
// 初始化定时器
void timerInit(Timer *timer)
{
if (timer == NULL)
{
return;
}
timer->target_time = 0;
timer->elapsed_time = 0;
timer->start_time = 0;
timer->active = 0;
timer->priority = 1; // 默认优先级为1
timer->next = NULL;
}
// 修改 timerStart 函数
void timerStart(Timer *timer, uint32_t target_time, unsigned char priority)
{
if (timer == NULL || target_time == 0)
{
printf("Error: Null timer pointer or invalid target time\n");
return;
}
// 检查定时器是否已经在列表中
Timer *current = timer_list;
while (current != NULL)
{
if (current == timer)
{
// 定时器已在列表中, 只需更新其参数
irq_state_t saved_state = enter_critical_section();
timer->target_time = target_time;
timer->start_time = getCurrentTime();
timer->elapsed_time = 0;
timer->active = 1;
timer->priority = priority;
exit_critical_section(saved_state);
return;
}
current = current->next;
}
// 检查是否达到最大定时器数量
if (current_timer_count >= MAX_TIMERS)
{
printf("Error: Maximum number of timers reached\n");
return;
}
// 初始化新定时器
irq_state_t saved_state = enter_critical_section();
timer->target_time = target_time;
timer->start_time = getCurrentTime();
timer->elapsed_time = 0;
timer->active = 1;
timer->priority = priority;
// 将定时器插入到定时器列表
timer->next = timer_list;
timer_list = timer;
current_timer_count++;
exit_critical_section(saved_state);
}
// 停止定时器
void timerStop(Timer *timer)
{
if (timer == NULL)
{
return;
}
irq_state_t saved_state = enter_critical_section();
Timer *current = timer_list;
Timer *prev = NULL;
while (current != NULL)
{
if (current == timer)
{
// 从链表中移除定时器
if (prev == NULL)
{
timer_list = current->next;
}
else
{
prev->next = current->next;
}
current_timer_count--;
timer->active = 0;
timer->next = NULL; // 断开链接
break;
}
prev = current;
current = current->next;
}
exit_critical_section(saved_state);
}
// 更新所有定时器, 在定时器中断中调用
void timerUpdateAll(void)
{
irq_state_t saved_state = enter_critical_section();
Timer *prev = NULL;
Timer *current = timer_list;
while (current != NULL)
{
if (current->active)
{
current->elapsed_time++;
if (current->elapsed_time >= current->target_time)
{
current->active = 0;
// 发送定时器过期消息
publishMessage((void *)(uintptr_t)current, current->priority);
// 从链表中移除已过期的定时器
if (prev == NULL)
{
timer_list = current->next;
}
else
{
prev->next = current->next;
}
current_timer_count--;
Timer *expired_timer = current;
current = current->next;
expired_timer->next = NULL; // 断开链接
continue; // 跳过前进 prev 指针
}
}
prev = current;
current = current->next;
}
exit_critical_section(saved_state);
}
// 获取当前定时器数量
uint32_t getCurrentTimerCount(void)
{
return current_timer_count;
}

35
app/app_frm_timer.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef APP_FRM_TIMER_H
#define APP_FRM_TIMER_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_TIMERS 100 // 定义最大定时器数量
// 定时器结构体定义
typedef struct Timer {
uint32_t target_time;
uint32_t elapsed_time;
uint32_t start_time;
unsigned char active;
unsigned char priority;
struct Timer *next;
} Timer;
// 函数声明
void timerInit(Timer *timer);
void timerStart(Timer *timer, uint32_t target_time, unsigned char priority);
void timerStop(Timer *timer);
void timerUpdateAll(void);
uint32_t getCurrentTimerCount(void);
#ifdef __cplusplus
}
#endif
#endif // APP_FRM_TIMER_H

240
app/app_light.c Normal file
View File

@@ -0,0 +1,240 @@
#include "app_config.h"
#include "interface.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
#include "app_param_manage.h"
#include "app_light.h"
#include "app_power.h"
// 声明 light_data 变量
LightSystem light_data;
// ... existing code ...
// 定义灯光按钮状态枚举
typedef enum {
BUTTON_STATE_INITIAL,
BUTTON_STATE_SHORT_PRESS,
BUTTON_STATE_DOUBLE_PRESS_DETECTED,
BUTTON_STATE_SECOND_PRESS_DETECTED
} LightButtonState;
// 定义灯光按钮结构体
typedef struct {
LightButtonState state;
uint32_t press_start_time;
uint32_t release_start_time;
uint8_t is_light_on;
Timer timer;
} LightButton;
// 全局变量
static LightButton light_button = {BUTTON_STATE_INITIAL, 0, 0, 0, {0}};
static uint8_t power_state = 0;
// 灯光按钮处理函数
static void handleLightButton(void)
{
switch (light_button.state)
{
case BUTTON_STATE_INITIAL:
if (light_data.light_switch == app_close())
{
light_button.state = BUTTON_STATE_SHORT_PRESS;
timerStart(&light_button.timer, 300, 0); // 启动短按定时器300ms
}
break;
case BUTTON_STATE_SHORT_PRESS:
if (light_data.light_switch == app_open())
{
if (light_button.timer.active) // 定时器未到期,短按完成,等待双击
{
light_button.state = BUTTON_STATE_DOUBLE_PRESS_DETECTED;
timerStart(&light_button.timer, 300, 0); // 启动双击等待定时器300ms
}
}
else if (!light_button.timer.active) // 短按定时器到期,重置为初始状态
{
light_button.state = BUTTON_STATE_INITIAL;
}
break;
case BUTTON_STATE_DOUBLE_PRESS_DETECTED:
if (light_data.light_switch == app_close())
{
light_button.state = BUTTON_STATE_SECOND_PRESS_DETECTED;
timerStart(&light_button.timer, 300, 0); // 启动第二次按下定时器300ms
}
else if (!light_button.timer.active) // 双击等待定时器到期,重置为初始状态
{
light_button.state = BUTTON_STATE_INITIAL;
}
break;
case BUTTON_STATE_SECOND_PRESS_DETECTED:
if (light_data.light_switch == app_open())
{
if (!light_button.timer.active) // 第二次按下完成,切换灯光状态
{
light_button.is_light_on = !light_button.is_light_on;
printf("LightButton: is_light_on = %d\n", light_button.is_light_on);
light_button.state = BUTTON_STATE_INITIAL;
}
}
else if (!light_button.timer.active) // 第二次按下定时器到期,重置为初始状态
{
light_button.state = BUTTON_STATE_INITIAL;
}
break;
default:
light_button.state = BUTTON_STATE_INITIAL;
break;
}
}
// 灯光输出处理函数
static void lightOutput(void *signal_id)
{
(void)signal_id;
// 根据当前状态,控制各个灯光
for (int32_t i = 0; i < LIGHT_COUNT; i++)
{
uint8_t state_value = (light_data.states[i] == LIGHT_ON) ? setLightOn() : setLightOff();
// 先判断灯光类型并设置状态
switch (i)
{//正常所有灯光熄灭
case LIGHT_HEAD://头灯前面4个灯
un_inf_can_kgf_output1.bit_data.KGF05 = state_value;
un_inf_can_kgf_output1.bit_data.KGF06 = state_value;
un_inf_can_kgf_output1.bit_data.KGF10 = state_value;
un_inf_can_kgf_output1.bit_data.KGF11 = state_value;
break;
case LIGHT_TAIL://尾灯后面4个灯
un_inf_can_kgf_output2.bit_data.KGF12 = state_value;
un_inf_can_kgf_output2.bit_data.KGF13 = state_value;
un_inf_can_kgf_output2.bit_data.KGF14 = state_value;
un_inf_can_kgf_output2.bit_data.KGF15 = state_value;
break;
case LIGHT_LEFT_TURN://左转向左边4个灯
un_inf_can_kgf_output1.bit_data.KGF06 = state_value;
un_inf_can_kgf_output1.bit_data.KGF11 = state_value;
un_inf_can_kgf_output2.bit_data.KGF12 = state_value;
un_inf_can_kgf_output2.bit_data.KGF13 = state_value;
break;
case LIGHT_RIGHT_TURN://右转向灯右边4个灯
un_inf_can_kgf_output1.bit_data.KGF05 = state_value;
un_inf_can_kgf_output1.bit_data.KGF10 = state_value;
un_inf_can_kgf_output2.bit_data.KGF14 = state_value;
un_inf_can_kgf_output2.bit_data.KGF15 = state_value;
break;
case LIGHT_BRAKE://刹车灯,四个黄灯
un_inf_can_kgf_output1.bit_data.KGF10 = state_value;
un_inf_can_kgf_output1.bit_data.KGF11 = state_value;
un_inf_can_kgf_output2.bit_data.KGF13 = state_value;
un_inf_can_kgf_output2.bit_data.KGF15 = state_value;
break;
case LIGHT_ALARM://报警灯,四个红灯
un_inf_can_kgf_output1.bit_data.KGF05 = state_value;
un_inf_can_kgf_output1.bit_data.KGF06 = state_value;
un_inf_can_kgf_output2.bit_data.KGF12 = state_value;
un_inf_can_kgf_output2.bit_data.KGF14 = state_value;
break;
}
}
// 灯的状态有变化就存入参数一个灯对应一位共6位
for (int32_t i = 0; i < LIGHT_COUNT; i++)
{
light_data.light_state |= (light_data.states[i] << i);
}
if (light_data.light_state != light_data.old_light_state)
{
setParam("lightSt", (float)light_data.light_state);
light_data.old_light_state = light_data.light_state;
}
publishMessage(&un_inf_can_kgf_output1, 1);
}
// 灯光状态处理函数
static void lightProcess(void *signal_id)
{
(void)signal_id;
if(0 != power_state)//处于非掉电模式才能打开
{
// 调用按钮处理函数
handleLightButton();
}
else
{
light_button.state = BUTTON_STATE_INITIAL;//一直保持初始化模式
light_button.is_light_on = LIGHT_OFF;//一直关闭
}
// 根据双击标志控制灯光输出,相当于灯光总开关
for (int32_t i = 0; i < LIGHT_COUNT; i++)
{
light_data.states[i] = (LightState)(light_button.is_light_on);
}
lightOutput(NULL);
timerStart(&light_data.timer_function, 100, 1);
}
// 处理输入信号的函数
static void lightInput(void *signal_id)
{
// LightSystem old_data = light_data;
// 填充数据
if ( (signal_id == &un_remote_control_input) && (1 == un_remote_control_input.bit_data.enable) )// 遥控器断线,不更新数据
{
// 保存遥控器输入开关状态
light_data.light_switch = un_remote_control_input.bit_data.switch_d ? LIGHT_ON : LIGHT_OFF;
}
else if(signal_id == &power_data)
{
power_state = power_data.current_state;
}
}
// APP模块的初始化
void lightAppInit(void)
{
// 初始化时恢复灯光状态
light_data.light_state = (uint8_t)getParam("lightSt");
light_data.old_light_state = light_data.light_state;
// 根据灯光状态恢复灯光
for (int32_t i = 0; i < LIGHT_COUNT; i++)
{
light_data.states[i] = (LightState)( (light_data.light_state >> i) & 1 );
}
// 初始化
memset(&light_data, 0, sizeof(LightSystem));
for (int32_t i = 0; i < LIGHT_COUNT; i++)
{
light_data.states[i] = LIGHT_OFF;
light_data.brightness[i] = 255; // 默认最大亮度
light_data.blink_state[i] = 0; // 初始化闪烁状态
light_data.blink_interval[i] = 500; // 默认闪烁间隔500ms
}
// 订阅输入信号,处理灯光逻辑
subscribe(&un_remote_control_input, lightInput);
subscribe(&power_data, lightInput);
// 订阅定时器
subscribe(&light_data.timer_function, lightProcess);
timerStart(&light_data.timer_function, 500, 1);
printf("app_light: initial OK \n");
}

62
app/app_light.h Normal file
View File

@@ -0,0 +1,62 @@
#ifndef APP_LIGHT_H
#define APP_LIGHT_H
#ifdef __cplusplus
extern "C"
{
#endif
// 定义灯光状态枚举
typedef enum
{
LIGHT_OFF,
LIGHT_ON,
LIGHT_BLINK
} LightState;
// 定义灯光类型枚举
typedef enum
{
LIGHT_HEAD,
LIGHT_TAIL,
LIGHT_LEFT_TURN,
LIGHT_RIGHT_TURN,
LIGHT_BRAKE,
LIGHT_ALARM,
LIGHT_COUNT
} LightType;
typedef struct
{
LightState states[LIGHT_COUNT];
uint8_t brightness[LIGHT_COUNT];
uint16_t blink_interval[LIGHT_COUNT]; // 闪烁间隔(毫秒)
uint8_t blink_state[LIGHT_COUNT]; // 闪烁状态
Timer timer;// 设置定时器,定时调用灯光处理函数
uint8_t old_light_state; // 旧的灯光状态
uint8_t light_state; // 当前的灯光状态
Timer timer_function; // 函数定时器
uint8_t light_switch; // 当前的灯光开关状态
uint8_t double_click_flag;//双击标志
} LightSystem;
// 在头文件中声明外部变量
extern LightSystem light_data;
// 使用内联函数
static inline uint8_t setLightOn(void) { return 1; }
static inline uint8_t setLightOff(void) { return 0; }
void lightAppInit(void);
void setLightState(LightType light, LightState state);
void setLightBrightness(LightType light, uint8_t brightness);
void setBlinkInterval(uint16_t interval);
#ifdef __cplusplus
}
#endif
#endif // APP_LIGHT_H

464
app/app_param_manage.c Normal file
View File

@@ -0,0 +1,464 @@
#include "app_config.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
#include "app_param_manage.h"
#define E2_RESERVE_COUNT 0x20 //增加IP地址 修改为0x20 20250110
// 待发送的参数请求信号
UnParamRequest un_param_request1 ;
UnParamRequest un_param_request2;
RequestContext request_send ;
RequestContext request_context ;
uint8_t read_write_e2_finished = 0;
// 定义全局信号实例,读写信号现在包括 offset 和 size
ParamSignal param_signal = {
.param_ptr = NULL, // 参数指针初始化为 NULL
.type = READ_OPERATION, // 操作类型设置为读操作
.offset = 0, // 整个数据块的偏移
.size = sizeof(param_manager.arr) // 整个数据块的大小
};
// 全局变量:初始化参数名称结构体
ParamNames param_names = {
#define X(name) .name = #name,
PARAM_LIST
#undef X
};
UnParamManager param_manager ;
static uint8_t is_param_initialized = 0;
// 打印所有参数的名称和值, 每行 4 个参数
void printParams()
{
unsigned int param_count = 0;
#define X(name) \
printf("%-8s: %-8.2f", param_names.name, param_manager.bit_data.name); \
param_count++; \
if (param_count % 4 == 0) { \
printf("\n"); \
} else { \
printf(" "); \
}
PARAM_LIST
#undef X
// 如果最后一行不足 4 个参数, 打印换行
if (param_count % 4 != 0)
{
printf("\n");
}
}
void writeByte24c02(uint16_t addr, uint8_t data)
{
if(0 != wrbyte_24c02(addr,data))
{
printf("E2PROM write error!\n");
}
}
uint8_t readByte24c02(uint16_t addr)
{
return rdbyte_24c02(addr);
}
// 定义一个通用的 EEPROM 访问函数
uint8_t accessEeprom(size_t offset, void *data, size_t size, OperationType type)
{
if (data == NULL || size == 0)
{
return 1; // 返回错误状态,表示无效的参数
}
uint8_t *byte_data = (uint8_t *)data; // 将 void* 转换为 uint8_t*,方便逐字节操作
size_t index;
if (type == WRITE_OPERATION)
{
// 写入操作
for (index = 0; index < size; index++)
{
writeByte24c02((uint16_t)(offset + index + E2_RESERVE_COUNT), byte_data[index]);
udelay(4000);//写入一个字节延时4ms
}
// 校验
for (index = 0; index < size; index++)
{
if (readByte24c02((uint16_t)(offset + index + E2_RESERVE_COUNT)) != byte_data[index])
{
return 2; // 返回错误状态,表示写入验证失败
}
}
}
else
{
// 读取操作
for (index = 0; index < size; index++)
{
byte_data[index] = readByte24c02((uint16_t)(offset + index + E2_RESERVE_COUNT));
}
}
return 0; // 返回状态,表示成功
}
void handleParamOp(void *data)
{
ParamSignal *signal = (ParamSignal *)data;
if (signal->param_ptr == NULL)
{
// 操作整个参数管理器
if (accessEeprom(0, param_manager.arr, sizeof(param_manager.arr), signal->type) == 0)
{
read_write_e2_finished = 1;
publishMessage(&read_write_e2_finished, 1); // 读写成功
}
else
{
read_write_e2_finished = 2;
publishMessage(&read_write_e2_finished, 1); // 读写失败
}
}
else
{
// 根据信号中的偏移和大小操作单个参数
if (accessEeprom(signal->offset, signal->param_ptr, signal->size, signal->type) == 0)
{
read_write_e2_finished = 1;
publishMessage(&read_write_e2_finished, 1); // 读写成功
}
else
{
read_write_e2_finished = 2;
publishMessage(&read_write_e2_finished, 1); // 读写失败
}
}
}
uint8_t calculateCRC(const uint8_t* data, uint32_t length) {
uint8_t crc = 0;
for (uint32_t i = 0; i < length; ++i) {
crc += data[i]; // 简单的校验和,按字节累加
}
return crc;
}
float readParameter(const char *param_name) {
float float_value = 0;
unsigned int offset = 0;
#define X(name) \
if (strcmp(param_name, param_names.name) == 0) { \
accessEeprom(offset, &param_manager.bit_data.name,sizeof(param_manager.bit_data.name), READ_OPERATION);\
memcpy(&float_value, &param_manager.bit_data.name, sizeof(param_manager.bit_data.name)); \
return float_value; \
} \
offset += 4;
PARAM_LIST
#undef X
printf("Parameter not found: %s\n", param_name);
return 0;
}
void writeParameter(const char *param_name, const uint8_t *data) {
unsigned int offset = 0;
#define X(name) \
if (strcmp(param_name, param_names.name) == 0) { \
memcpy(&param_manager.bit_data.name, data, sizeof(param_manager.bit_data.name)); \
accessEeprom(offset, &param_manager.bit_data.name,sizeof(param_manager.bit_data.name), WRITE_OPERATION);\
return; \
} \
offset += 4;
PARAM_LIST
#undef X
printf("Parameter not found: %s\n", param_name);
}
void sendParamRequestResponse(UnParamRequest *paramRequest, uint32_t sender_ip, uint16_t sender_port, uint8_t isWriteOperation) {
// 准备响应帧
paramRequest->bit_data.frame_header = 0xFF80;
paramRequest->bit_data.frame_type = 0x002B;
paramRequest->bit_data.frame_length = sizeof(StrParamRequest);
paramRequest->bit_data.accumulated = 0;
paramRequest->bit_data.request_id = isWriteOperation ? 98 : 99;
paramRequest->bit_data.crc = calculateCRC(paramRequest->arr, sizeof(paramRequest->arr) - 1);
request_send.param_request = paramRequest;
request_send.sender_ip = sender_ip;
request_send.sender_port = sender_port;
// 发送信号从UDP发送
publishMessage(&request_send, 1);
}
void processReadAllParams(UnParamRequest *paramRequest, uint32_t sender_ip, uint16_t sender_port) {
uint8_t allParams[256][4]; // Size based on E2 size
unsigned int i = 0;
float param_value;
uint8_t exceeded_max = 0; // 新增标志变量
// 清零 paramRequest
memset(paramRequest, 0, sizeof(UnParamRequest));
accessEeprom(0, param_manager.arr, sizeof(param_manager.arr), READ_OPERATION);
printf("Sending parameter data:\n");
#define X(name) \
if (!exceeded_max) { \
if (i < 256) { \
strncpy((char *)paramRequest->bit_data.param_name[i], #name, sizeof(paramRequest->bit_data.param_name[i]) - 1); \
paramRequest->bit_data.param_name[i][sizeof(paramRequest->bit_data.param_name[i]) - 1] = '\0'; \
memcpy(allParams[i], &param_manager.bit_data.name, sizeof(param_manager.bit_data.name)); \
memcpy(&param_value, allParams[i], sizeof(float)); \
printf("Parameter name: %-20s Value: %f\n", #name, param_value); \
i++; \
} else { \
printf("Warning: Exceeded maximum number of parameters\n"); \
exceeded_max = 1; \
} \
}
PARAM_LIST
#undef X
// Pack all parameter data into paramRequest
memcpy(paramRequest->bit_data.data, allParams, sizeof(allParams));
printf("Total parameters sent: %d\n", i);
// Send response
sendParamRequestResponse(paramRequest, sender_ip, sender_port, 0);
}
void processWriteRequestFrame(UnParamRequest *paramRequest, uint32_t sender_ip, uint16_t sender_port) {
float value;
printf("Processing write request.\n");
// 先发送信号,然后从结构体读数
for (int i = 0; i < 256; ++i) {
if (strlen((char *)paramRequest->bit_data.param_name[i]) > 0) {
writeParameter(paramRequest->bit_data.param_name[i], paramRequest->bit_data.data[i]);
printf("paramRequest->bit_data.param_name[i]:%s \n",paramRequest->bit_data.param_name[i]);
memcpy(&value, paramRequest->bit_data.data[i], sizeof(float));
printf("paramRequest->bit_data.data[i]:%f \n", value);
}
}
// 发送响应,发送所有参数
processReadAllParams(paramRequest, sender_ip, sender_port);
}
void processReadRequestFrame(UnParamRequest *paramRequest, uint32_t sender_ip, uint16_t sender_port) {
// 处理读请求的逻辑
printf("Processing read request.\n");
// 清零 paramRequest
memset(paramRequest, 0, sizeof(UnParamRequest));
// 先发送信号,然后从结构体读数
for (int i = 0; i < 256; ++i) {
if (strlen((char *)paramRequest->bit_data.param_name[i]) > 0) {
float readData = readParameter(paramRequest->bit_data.param_name[i]);
memcpy(paramRequest->bit_data.data[i], &readData, sizeof(paramRequest->bit_data.data[i]));
}
}
// 发送响应
sendParamRequestResponse(paramRequest, sender_ip, sender_port, 0);
}
void OnParamSignal(void *data)
{
RequestContext *signal = (RequestContext *)data;
uint8_t *datagram = (uint8_t *)signal->param_request->arr;
uint16_t request_id = ((uint16_t)datagram[7] << 8) | (uint16_t)datagram[8];// 大端模式
// 调试输出
printf("Received request ID: 0x%04X\n", request_id);
// 计算CRC
uint8_t calculatedCrc = calculateCRC(datagram, sizeof(UnParamRequest) - 1);
uint8_t receivedCrc = datagram[sizeof(UnParamRequest) - 1];
// 比较CRC
if (calculatedCrc != receivedCrc)
{
printf("CRC check failed, discarding data\n");
printf("Calculated CRC: 0x%02X, Received CRC: 0x%02X\n", calculatedCrc, receivedCrc);
return;
}
printf("CRC check passed\n");
if (request_id == 100)
{ // 读请求
processReadRequestFrame(signal->param_request, signal->sender_ip, signal->sender_port);
}
else if (request_id == 101)
{ // 写请求
processWriteRequestFrame(signal->param_request, signal->sender_ip, signal->sender_port);
}
else if (request_id == 102)
{ // 读取所有参数
processReadAllParams(signal->param_request, signal->sender_ip, signal->sender_port);
}
else
{
printf("Unknown request ID.\n");
return;
}
}
float getParam(const char *param_name)
{
// 检查是否已初始化
if (!is_param_initialized)
{
printf("Parameters not initialized, reinitializing\n");
accessEeprom(0, param_manager.arr, sizeof(param_manager.arr), READ_OPERATION);//Read all parameters from E2
is_param_initialized = 1; // Mark as initialized
printParams();
return 0.0f;
}
// 检查参数名是否为空
if (param_name == NULL)
{
printf("Error: Parameter name is empty\n");
return 0.0f;
}
// 遍历所有参数
#define X(name) \
if (strcmp(param_name, #name) == 0) \
{ \
return param_manager.bit_data.name; \
}
PARAM_LIST
#undef X
// 如果没有找到匹配的参数名
printf("Error: Parameter %s not found\n", param_name);
return 0.0f;
}
// setParam 函数
uint8_t setParam(const char *param_name, float value)
{
// 检查参数名是否为空
if (param_name == NULL)
{
printf("Error: Parameter name is empty\n");
return 2; // 返回错误码
}
// 参数名和值写入EEPROM先转成字节数组
uint8_t data[sizeof(float)];
memcpy(data, &value, sizeof(float));
writeParameter(param_name, data);
// 更新参数
#define X(name) \
if (strcmp(param_name, #name) == 0) \
{ \
memcpy(&param_manager.bit_data.name, data, sizeof(param_manager.bit_data.name)); \
}
PARAM_LIST
#undef X
return 0;
}
void paramAppInit(void)
{
// 初始化全局变量
memset(&un_param_request1, 0, sizeof(UnParamRequest));
memset(&un_param_request2, 0, sizeof(UnParamRequest));
// 正确初始化 RequestContext 结构体
request_send.param_request = &un_param_request1;
request_send.sender_ip = 0;
request_send.sender_port = 0;
request_context.param_request = &un_param_request2;
request_context.sender_ip = 0;
request_context.sender_port = 0;
// 上电读取所有参数
memset(param_manager.arr, 0, sizeof(param_manager.arr));
accessEeprom(0, param_manager.arr, sizeof(param_manager.arr), READ_OPERATION);
// 初始化每个参数
// param_manager.bit_data.whl_bas = 1.5f; // 初始化轮距
// param_manager.bit_data.max_rpm = 5500.0f; // 初始化最大转速
// param_manager.bit_data.whl_dia = 0.6f; // 初始化轮直径
// param_manager.bit_data.max_acc = 1.0f; // 初始化最大加速度
// param_manager.bit_data.spd_kp = 5.0f; // 初始化速度控制 KP
// param_manager.bit_data.spd_ki = 1.0f; // 初始化速度控制 KI
// param_manager.bit_data.spd_kd = 0.0f; // 初始化速度控制 KD
// param_manager.bit_data.spd_il = 5.0f; // 初始化速度控制 IL
// param_manager.bit_data.spd_ol = 5.0f; // 初始化速度控制 OL
// param_manager.bit_data.crv_kp = 1.0f; // 初始化曲线控制 KP
// param_manager.bit_data.crv_ki = 0.0f; // 初始化曲线控制 KI
// param_manager.bit_data.crv_kd = 0.0f; // 初始化曲线控制 KD
// param_manager.bit_data.crv_il = 2.0f; // 初始化曲线控制 IL
// param_manager.bit_data.crv_ol = 2.0f; // 初始化曲线控制 OL
// param_manager.bit_data.brk_on = 1500.0f; // 初始化制动开启参数
// param_manager.bit_data.brk_off = 800.0f; // 初始化制动关闭参数
// param_manager.bit_data.maxTorq = 60.0f; // 初始化最大扭矩
// param_manager.bit_data.feedPwr = 10000.0f; // 初始化馈电功率
// param_manager.bit_data.dispPwr = 10000.0f; // 初始化显示功率
// param_manager.bit_data.VehMass = 700.0f; // 初始化车辆质量
// param_manager.bit_data.gRatio = 28.0f; // 初始化减速比
// param_manager.bit_data.prCTime = 5.0f; // 初始化预充时间
// param_manager.bit_data.brk_pos = 0.0f; // 初始化刹车位置, 0表示未刹车
// param_manager.bit_data.pwr_sta = 0.0f; // 初始化电源状态
// param_manager.bit_data.lightSt = 0.0f; // 初始化灯光状态
// param_manager.bit_data.pwr_btn = 0.0f; // 初始化电源按钮状态
// param_manager.bit_data.test = 0.0f; // 初始化测试参数
// 订阅信号
subscribe(&param_signal, handleParamOp);
subscribe(&request_context, OnParamSignal);// 接收到上位机读写参数信号
printParams();//打印所有参数
is_param_initialized = 1; // 标记初始化完成
printf("paramAPP init OK! %d\n",getCurrentTime());
}

145
app/app_param_manage.h Normal file
View File

@@ -0,0 +1,145 @@
#ifndef APP_PARAM_MANAGE_H
#define APP_PARAM_MANAGE_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "app_config.h"
// 定义参数列表宏
#define PARAM_LIST \
X(whl_bas) \
X(max_rpm) \
X(whl_dia) \
X(max_acc) \
X(spd_kp) \
X(spd_ki) \
X(spd_kd) \
X(spd_il) \
X(spd_ol) \
X(crv_kp) \
X(crv_ki) \
X(crv_kd) \
X(crv_il) \
X(crv_ol) \
X(brk_on) \
X(brk_off) \
X(maxTorq) \
X(feedPwr) \
X(dispPwr) \
X(VehMass) \
X(gRatio) \
X(prCTime) \
X(brk_pos) \
X(pwr_sta) \
X(high_sw) \
X(stop_sw) \
X(lightSt) \
X(pwr_btn) \
X(sleepTm) \
X(wakeTm) \
X(Ospd_kp) \
X(Ospd_ki) \
X(Ospd_kd) \
X(Ospd_il) \
X(Ospd_ol) \
X(Ocrv_kp) \
X(Ocrv_ki) \
X(Ocrv_kd) \
X(Ocrv_il) \
X(Ocrv_ol) \
X(minTorq) \
X(test)
// 定义一个包含所有参数名称的结构体
typedef struct {
#define X(name) const char* name;
PARAM_LIST
#undef X
} ParamNames;
// 参数结构体不能使用位域不要超过E2的大小, 1K byte
typedef struct
{
#define X(name) float name;
PARAM_LIST
#undef X
} ParamData;
typedef union
{
ParamData bit_data; // 使用定义的结构体变量名
uint8_t arr[sizeof(ParamData)]; // 通过结构体类型确定大小
} UnParamManager;
// 定义信号操作类型
typedef enum
{
READ_OPERATION,
WRITE_OPERATION
} OperationType;
// 定义信号数据结构
typedef struct
{
void *param_ptr; // 参数数据的指针
OperationType type; // 操作类型
size_t offset; // 参数在结构体中的偏移
size_t size; // 参数大小
} ParamSignal;
#pragma pack(push, 1)
typedef struct _StrParamRequest {
//--------------------------------------------------
uint16_t frame_header; // 帧头 固定值0xFF80 (16位)
uint16_t frame_type; // 帧类型 固定值0x002A (16位)
uint16_t frame_length; // 帧长 根据参数数据的长度动态设置 (16位)
uint8_t accumulated; // 累加值 按帧累加 (8位)
uint16_t request_id; // 请求帧ID 请求ID 100表示读101 表示写参数 (16位)
char param_name[256][8]; // 参数名称 标识要写入或读出的参数
uint8_t data[256][4]; // 数据 用于写入或读出的参数值一个参数最大4字节 (8位*4)
uint8_t crc; // CRC 按字节累加之和 取低8位 (8位)
} StrParamRequest;
typedef union _UnParamRequest {
StrParamRequest bit_data; // 使用定义的结构体变量名
unsigned char arr[sizeof(StrParamRequest)]; // 通过结构体类型确定大小
} UnParamRequest;
typedef struct {
UnParamRequest *param_request; // 指向 UnParamRequest 的指针
uint32_t sender_ip; // 发送方的 IP 地址使用标准的32位整数表示
uint16_t sender_port; // 发送方的端口号使用标准的16位整数表示
} RequestContext;
#pragma pack(pop)
extern UnParamRequest un_param_request;// 声明用于参数响应的帧实例
extern RequestContext request_context;
// 声明全局信号实例
extern ParamNames param_names;
extern UnParamManager param_manager; // 全局参数管理实例
extern ParamSignal param_signal;
extern uint8_t read_write_e2_finished;
extern RequestContext request_send;// 待发送的参数请求信号
uint8_t access_eeprom(size_t offset, void *data, size_t size, OperationType type);
void paramAppInit(void);
// 在适当的位置添加以下函数声明
float getParam(const char *param_name);
uint8_t setParam(const char *param_name, float value);
void printParams(void);
void handleParamOp(void *data);
void OnParamSignal(void *data);
#ifdef __cplusplus
}
#endif
#endif // APP_PARAM_MANAGE_H

130
app/app_pid.c Normal file
View File

@@ -0,0 +1,130 @@
#include "app_config.h"
#include "app_pid.h"
// PID控制器初始化
void initializePid(PID_t *pid, pid_mode_t mode, float dtMin)
{
pid->mode = mode;
pid->dt_min = dtMin > SIGMA ? dtMin : SIGMA;
pid->kp = 0.0f;
pid->ki = 0.0f;
pid->kd = 0.0f;
pid->integral = 0.0f;
pid->integral_limit = 0.0f;
pid->output_limit = 0.0f;
pid->error_previous = 0.0f;
pid->last_output = 0.0f;
}
// 设置PID参数
int32_t setPidParameters(PID_t *pid, float kp, float ki, float kd, float integralLimit, float outputLimit)
{
int32_t ret = 0;
if (isfinite(kp)) {
pid->kp = kp;
} else {
ret = -1;
}
if (isfinite(ki)) {
pid->ki = ki;
} else {
ret = -2;
}
if (isfinite(kd)) {
pid->kd = kd;
} else {
ret = -3;
}
if (isfinite(integralLimit)) {
pid->integral_limit = integralLimit;
} else {
ret = -4;
}
if (isfinite(outputLimit)) {
pid->output_limit = outputLimit;
} else {
ret = -5;
}
return ret;
}
/**
* @brief 计算PID控制器的输出
*
* @param pid 指向PID_t结构体的指针包含PID控制器的状态和参数
* @param sp 设定值(Setpoint),期望系统达到的目标值
* @param val 当前值(Current Value),系统的实际测量值
* @param val_dot 当前值的导数(Derivative of Current Value),即测量值的变化率(用于微分项计算)
* @param dt 时间增量(Time Increment),两次调用之间的时间间隔,用于计算积分和微分
*
* @return float 返回PID控制器计算出的输出值
*/
float calculatePidOutput(PID_t *pid, float sp, float val, float val_dot, float dt)
{
// 检查输入参数的有效性
if (!isfinite(sp) || !isfinite(val) || !isfinite(val_dot) || !isfinite(dt) || dt < pid->dt_min) {
return pid->last_output;
}
// 计算误差
float error = sp - val;
// 根据模式计算微分项
float derivative = 0.0f;
switch (pid->mode) {
case PID_MODE_DERIVATIVE_CALC:
derivative = (error - pid->error_previous) / dt;
pid->error_previous = error;
break;
case PID_MODE_DERIVATIVE_CALC_NO_SP:
derivative = (-val - pid->error_previous) / dt;
pid->error_previous = -val;
break;
case PID_MODE_DERIVATIVE_SET:
derivative = -val_dot;
break;
default:
derivative = 0.0f;
break;
}
// 计算比例和微分项的输出
float output = (pid->kp * error) + (pid->kd * derivative);
// 计算积分项,并检查积分饱和
if (pid->ki > SIGMA) {
pid->integral += error * dt;
if (pid->integral > pid->integral_limit) {
pid->integral = pid->integral_limit;
} else if (pid->integral < -pid->integral_limit) {
pid->integral = -pid->integral_limit;
}
output += pid->ki * pid->integral;
}
// 限制输出范围
if (output > pid->output_limit) {
output = pid->output_limit;
} else if (output < -pid->output_limit) {
output = -pid->output_limit;
}
pid->last_output = output;
return output;
}
// 重置积分器
void resetPidIntegral(PID_t *pid)
{
pid->integral = 0.0f;
}

46
app/app_pid.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef PID_H
#define PID_H
#ifdef __cplusplus
extern "C" {
#endif
// 防止除零和其他误差的极小值
#define EPSILON 1e-5f
#define SIGMA EPSILON
#include "app_config.h"
// PID 控制模式
typedef enum {
PID_MODE_DERIVATIVE_NONE = 0, // PI 控制器模式,无微分项
PID_MODE_DERIVATIVE_CALC, // 根据当前误差计算微分项
PID_MODE_DERIVATIVE_CALC_NO_SP, // 根据当前值计算微分项,忽略设定值
PID_MODE_DERIVATIVE_SET // 使用外部提供的微分项值
} pid_mode_t;
// PID 控制器结构体
typedef struct {
pid_mode_t mode; // 控制模式
float dt_min; // 最小时间间隔
float kp; // 比例系数
float ki; // 积分系数
float kd; // 微分系数
float integral; // 积分累积值
float integral_limit; // 积分限幅
float output_limit; // 输出限幅
float error_previous; // 上一次的误差值
float last_output; // 上一次的输出值
} PID_t;
// 函数声明
void initializePid(PID_t *pid, pid_mode_t mode, float dtMin);
int32_t setPidParameters(PID_t *pid, float kp, float ki, float kd, float integralLimit, float outputLimit);
float calculatePidOutput(PID_t *pid, float sp, float val, float val_dot, float dt);
void resetPidIntegral(PID_t *pid);
#ifdef __cplusplus
}
#endif
#endif // PID_H

429
app/app_power.c Normal file
View File

@@ -0,0 +1,429 @@
#include "app_config.h"
#include "interface.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
#include "app_param_manage.h"
#include "app_power.h"
// 定义按钮状态枚举
typedef enum {
BUTTON_STATE_INITIAL,
BUTTON_STATE_SHORT_PRESS,
BUTTON_STATE_SHORT_PRESS_DETECTED,
BUTTON_STATE_WAIT_FOR_LONG_PRESS,
BUTTON_STATE_LONG_PRESS,
BUTTON_STATE_LONG_PRESS_WAIT
} ButtonState;
// 定义按钮结构体
typedef struct {
ButtonState state;
uint32_t press_start_time;
uint32_t release_start_time;
uint8_t is_power_on;
Timer timer;
uint8_t old_is_power_on;
Timer timer1;
} PowerButton;
// 全局变量
PowerSystem power_data;
static PowerButton power_button = {BUTTON_STATE_INITIAL, 0, 0, 0, {0},0};
// 电源按钮处理函数
static void handlePowerButton(void)
{
switch (power_button.state)
{
case BUTTON_STATE_INITIAL:
if (power_data.remote_power_switch == app_close())
{
power_button.state = BUTTON_STATE_SHORT_PRESS_DETECTED;
timerStart(&power_button.timer, 500, 0); // 启动短按定时器500ms
}
break;
case BUTTON_STATE_SHORT_PRESS_DETECTED:
if (power_data.remote_power_switch == app_open())
{
if (power_button.timer.active) // 定时器未到期,短按完成,启动等待长按定时器
{
power_button.state = BUTTON_STATE_WAIT_FOR_LONG_PRESS;
timerStart(&power_button.timer, 500, 0); // 启动等待长按定时器500ms
}
}
else if (!power_button.timer.active)// 短按定时器到期,按键仍被按下,视为无效,重置为初始状态
{
power_button.state = BUTTON_STATE_INITIAL;
}
break;
case BUTTON_STATE_WAIT_FOR_LONG_PRESS:
if (power_data.remote_power_switch == app_close())// 检测是否在等待时间内进行长按
{
power_button.state = BUTTON_STATE_LONG_PRESS;
timerStart(&power_button.timer, 1000, 0); // 启动长按定时器1000ms
}
else if (!power_button.timer.active) // 等待长按超时,重置为初始状态
{
power_button.state = BUTTON_STATE_INITIAL;
}
break;
case BUTTON_STATE_LONG_PRESS:
if (!power_button.timer.active)// 长按完成,切换电源状态 20250423 修改不需要判断松开按键就打开控制器
{
power_button.is_power_on = !power_button.is_power_on;
printf("PowerButton: is_power_on = %d\n", power_button.is_power_on);
power_button.state = BUTTON_STATE_LONG_PRESS_WAIT;
}
else if(power_data.remote_power_switch == app_open())
{
power_button.state = BUTTON_STATE_INITIAL;
printf("Long press for short duration");
}
else
break;
case BUTTON_STATE_LONG_PRESS_WAIT:
if (power_data.remote_power_switch == app_open())// 检测按键释放
{
power_button.state = BUTTON_STATE_INITIAL;
printf("Release the button");
}
default:
power_button.state = BUTTON_STATE_INITIAL;
break;
}
}
// 输出处理函数
static void powerOutput(void *signal_id)
{
(void)signal_id;
// 根据当前状态,控制各个设备的电源
switch (power_data.current_state)
{
case POWER_PRE_CHARGE:
publishMessage(&power_data.pre_charge_finish, 1);//发布预充完成信号100ms发送一次直到预充完成
un_inf_can_kgf_output1.bit_data.KGF04 = setPowerOn(); // 预充继电器
un_inf_can_kgf_output1.bit_data.KGF07 = setPowerOff(); // 高压继电器
un_inf_can_kgf_output1.bit_data.KGF08 = setPowerOff(); // 高压继电器
un_inf_can_kgf_output2.bit_data.KGF10 = setPowerOn(); // 低压继电器
un_inf_can_kgf_output2.bit_data.KGF11 = setPowerOn(); // 低压继电器
un_inf_can_kgf_output2.bit_data.KGF01 = setPowerOn(); // 计算机
un_inf_can_kgf_output2.bit_data.KGF02 = setPowerOn(); // 计算机
un_inf_can_kgf_output2.bit_data.KGF03 = setPowerOn(); // 遥控器
un_inf_can_kgf_output2.bit_data.KGF05 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output2.bit_data.KGF06 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output1.bit_data.KGF09 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output2.bit_data.KGF04 = setPowerOn(); // E3
break;
case POWER_NEUTRAL:
publishMessage(&power_data.pre_charge_finish, 1);//20250316增加发送空挡信号保证电机控制器高压上电后发送空挡信号
un_inf_can_kgf_output1.bit_data.KGF04 = setPowerOff(); // 预充继电器
un_inf_can_kgf_output1.bit_data.KGF07 = setPowerOn(); // 高压继电器
un_inf_can_kgf_output1.bit_data.KGF08 = setPowerOn(); // 高压继电器
un_inf_can_kgf_output2.bit_data.KGF10 = setPowerOn(); // 低压继电器
un_inf_can_kgf_output2.bit_data.KGF11 = setPowerOn(); // 低压继电器
un_inf_can_kgf_output2.bit_data.KGF01 = setPowerOn(); // 计算机
un_inf_can_kgf_output2.bit_data.KGF02 = setPowerOn(); // 计算机
un_inf_can_kgf_output2.bit_data.KGF03 = setPowerOn(); // 遥控器
un_inf_can_kgf_output2.bit_data.KGF05 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output2.bit_data.KGF06 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output1.bit_data.KGF09 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output2.bit_data.KGF04 = setPowerOn(); // E3
break;
case POWER_STANDBY:
// 初始状态,只开启基本设备
un_inf_can_kgf_output1.bit_data.KGF04 = setPowerOff(); // 预充继电器
un_inf_can_kgf_output1.bit_data.KGF07 = setPowerOff(); // 高压继电器
un_inf_can_kgf_output1.bit_data.KGF08 = setPowerOff(); // 高压继电器
un_inf_can_kgf_output2.bit_data.KGF10 = setPowerOff(); // 低压继电器
un_inf_can_kgf_output2.bit_data.KGF11 = setPowerOff(); // 低压继电器
un_inf_can_kgf_output2.bit_data.KGF01 = setPowerOn(); // 计算机
un_inf_can_kgf_output2.bit_data.KGF02 = setPowerOn(); // 计算机
un_inf_can_kgf_output2.bit_data.KGF03 = setPowerOn(); // 遥控器
un_inf_can_kgf_output2.bit_data.KGF05 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output2.bit_data.KGF06 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output1.bit_data.KGF09 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output2.bit_data.KGF04 = setPowerOn(); // E3
break;
case POWER_WORKING:
// 工作状态,除预充继电器外所有设备开启
un_inf_can_kgf_output1.bit_data.KGF04 = setPowerOff(); // 预充继电器
un_inf_can_kgf_output1.bit_data.KGF07 = setPowerOn(); // 高压继电器
un_inf_can_kgf_output1.bit_data.KGF08 = setPowerOn(); // 高压继电器
un_inf_can_kgf_output2.bit_data.KGF10 = setPowerOn(); // 低压继电器
un_inf_can_kgf_output2.bit_data.KGF11 = setPowerOn(); // 低压继电器
un_inf_can_kgf_output2.bit_data.KGF01 = setPowerOn(); // 计算机
un_inf_can_kgf_output2.bit_data.KGF02 = setPowerOn(); // 计算机
un_inf_can_kgf_output2.bit_data.KGF03 = setPowerOn(); // 遥控器
un_inf_can_kgf_output2.bit_data.KGF05 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output2.bit_data.KGF06 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output1.bit_data.KGF09 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output2.bit_data.KGF04 = setPowerOn(); // E3
break;
case POWER_EMERGENCY:
// 急停状态,断开高压
un_inf_can_kgf_output1.bit_data.KGF04 = setPowerOff(); // 预充继电器
un_inf_can_kgf_output1.bit_data.KGF07 = setPowerOff(); // 高压继电器
un_inf_can_kgf_output1.bit_data.KGF08 = setPowerOff(); // 高压继电器
un_inf_can_kgf_output2.bit_data.KGF10 = setPowerOn(); // 低压继电器
un_inf_can_kgf_output2.bit_data.KGF11 = setPowerOn(); // 低压继电器
un_inf_can_kgf_output2.bit_data.KGF01 = setPowerOn(); // 计算机
un_inf_can_kgf_output2.bit_data.KGF02 = setPowerOn(); // 计算机
un_inf_can_kgf_output2.bit_data.KGF03 = setPowerOn(); // 遥控器
un_inf_can_kgf_output2.bit_data.KGF05 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output2.bit_data.KGF06 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output1.bit_data.KGF09 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output2.bit_data.KGF04 = setPowerOn(); // E3
break;
case POWER_SLEEP:
// 休眠状态,关闭所有设备
un_inf_can_kgf_output1.bit_data.KGF04 = setPowerOff(); // 预充继电器
un_inf_can_kgf_output1.bit_data.KGF07 = setPowerOff(); // 高压继电器
un_inf_can_kgf_output1.bit_data.KGF08 = setPowerOff(); // 高压继电器
un_inf_can_kgf_output2.bit_data.KGF10 = setPowerOff(); // 低压继电器
un_inf_can_kgf_output2.bit_data.KGF11 = setPowerOff(); // 低压继电器
un_inf_can_kgf_output2.bit_data.KGF01 = setPowerOn(); // 计算机
un_inf_can_kgf_output2.bit_data.KGF02 = setPowerOn(); // 计算机
un_inf_can_kgf_output2.bit_data.KGF03 = setPowerOn(); // 遥控器
un_inf_can_kgf_output2.bit_data.KGF05 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output2.bit_data.KGF06 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output1.bit_data.KGF09 = setPowerOn(); // 网络交换机
un_inf_can_kgf_output2.bit_data.KGF04 = setPowerOn(); // E3
break;
default:
break;
}
publishMessage(&power_data, 1);
publishMessage(&un_inf_can_kgf_output1, 1);
publishMessage(&un_inf_can_kgf_output2, 1);
}
static void wakeupProcess(void *signal_id)
{
(void)signal_id;
un_gather_output.bit_data.sleep_duration = (uint16_t)getParam("sleepTm");
un_gather_output.bit_data.wakeup_interval = (uint16_t)getParam("wakeTm");
if(un_gather_output.bit_data.sleep_duration < 5)//最小值限定
{
un_gather_output.bit_data.sleep_duration = 5;
}
if(un_gather_output.bit_data.wakeup_interval < 5)//最小值限定
{
un_gather_output.bit_data.wakeup_interval = 5;
}
un_gather_output.bit_data.vehicle_mode = power_data.current_state;
publishMessage(&un_gather_output, 1);
timerStart(&power_data.timer1, 500, 1); //周期调用
}
// 定时器处理函数
static void powerTimerProcess(void *signal_id)
{
(void)signal_id;
// 调用电源按钮处理函数
handlePowerButton();
// 电源按钮状态有变化,保存到参数
if (power_button.is_power_on != power_button.old_is_power_on)
{
setParam("pwr_btn", (float)power_button.is_power_on);
power_button.old_is_power_on = power_button.is_power_on;
}
// 状态转换逻辑
switch (power_data.current_state)
{
case POWER_PRE_CHARGE:
if (!power_data.timer_pre_charge.active) // 预充时间到
{
power_data.current_state = POWER_NEUTRAL; // 工作
power_data.pre_charge_finish = 1; // 预充完成
printf("Power: Transitioning from PRE_CHARGE to POWER_NEUTRAL state\n");
}
break;
case POWER_NEUTRAL://20250316增加发送空挡信号
if (power_data.neutral_cnt >= 5) // 运行5次
{
power_data.neutral_cnt = 0;
power_data.current_state = POWER_WORKING; // 工作
power_data.pre_charge_finish = 1; // 预充完成
printf("Power: Transitioning from POWER_NEUTRAL to WORKING state\n");
}
else
{
power_data.neutral_cnt ++;
power_data.current_state = POWER_NEUTRAL; // 空挡
power_data.pre_charge_finish = 1; // 预充完成
}
break;
case POWER_STANDBY:
if (power_data.high_voltage_switch == app_open()) // 高压开关断开
{
power_data.current_state = POWER_SLEEP; // 休眠
printf("Power: Transitioning from STANDBY to SLEEP state\n");
}
else if (power_button.is_power_on == app_close() && power_data.emergency_stop == app_close()) // 遥控器电源开关闭合且急停开关闭合
{
power_data.current_state = POWER_EMERGENCY; // 急停
printf("Power: Transitioning from STANDBY to EMERGENCY state\n");
}
break;
case POWER_WORKING:
if (power_data.high_voltage_switch == app_open()) // 高压开关断开
{
power_data.current_state = POWER_SLEEP; // 休眠
printf("Power: Transitioning from STANDBY to SLEEP state\n");
}
else if (power_data.emergency_stop == app_close()) // 急停开关闭合
{
power_data.current_state = POWER_EMERGENCY; // 急停
printf("Power: Transitioning from WORKING to EMERGENCY state\n");
printf("emergency_stop_switch: %d, remote_emergency_stop: %d\n", power_data.emergency_stop_switch, power_data.remote_emergency_stop); //打印状态
printf("remote_stop: %d\n", un_remote_control_input.bit_data.switch_b);
}
break;
case POWER_EMERGENCY:
if (power_data.high_voltage_switch == app_open()) // 高压开关断开
{
power_data.current_state = POWER_SLEEP; // 休眠
printf("Power: Transitioning from EMERGENCY to SLEEP state\n");
}
else if (power_button.is_power_on == app_open()) // 遥控器电源开关断开
{
power_data.current_state = POWER_STANDBY; // 待机
printf("Power: Transitioning from EMERGENCY to STANDBY state\n");
}
else if (power_data.emergency_stop == app_open()) // 急停断开
{
power_data.current_state = POWER_PRE_CHARGE; // 预充
timerStart(&power_data.timer_pre_charge, (uint32_t)(getParam("prCTime") * 1000), 1); // 启动预充定时器
printf("Power: Transitioning from EMERGENCY to PRE_CHARGE state\n");
}
break;
case POWER_SLEEP:
if (power_data.high_voltage_switch == app_close()) // 高压开关闭合
{
power_data.current_state = POWER_STANDBY; // 待机
printf("Power: Transitioning from SLEEP to STANDBY state\n");
}
break;
default:
power_data.current_state = POWER_STANDBY; // 待机
break;
}
powerOutput(NULL); // 输出
// 电源状态有变化,记录到参数
if (power_data.old_state != power_data.current_state)
{
power_data.old_state = power_data.current_state;
setParam("pwr_sta", (float)power_data.current_state);
}
timerStart(&power_data.timer, 100, 1); //周期调用
}
// 处理所有输入信号的函数
static void powerInput(void *signal_id)
{
//不能直接赋值用memcpy
PowerSystem old_data;
memcpy(&old_data, &power_data, sizeof(PowerSystem));
// 填充数据
if (signal_id == &un_sw_sample)
{
power_data.emergency_stop_switch = (uint8_t)un_sw_sample.bit_data.emergency_stop_switch;//急停开关
power_data.high_voltage_switch = (uint8_t)un_sw_sample.bit_data.High_voltage_switch;//高压开关
}
else if ( (signal_id == &un_remote_control_input) && (1 == un_remote_control_input.bit_data.enable) )// 遥控器断线,不更新数据
{
power_data.remote_power_switch = (uint8_t)un_remote_control_input.bit_data.switch_d; // 遥控器电源开关
power_data.remote_emergency_stop = ((uint8_t)un_remote_control_input.bit_data.switch_b == 1) ? 0 : 1;// 遥控器急停开关
}
// 急停开关
power_data.emergency_stop = (uint8_t)( (power_data.emergency_stop_switch == app_close()) || (power_data.remote_emergency_stop == app_close()) );
// 急停开关有变化,记录到参数
if (power_data.old_emergency_stop != power_data.emergency_stop)
{
power_data.old_emergency_stop = power_data.emergency_stop;
setParam("stop_sw", (float)power_data.emergency_stop);
}
// 高压开关状态有变化,记录到参数
if (power_data.old_high_voltage_switch != power_data.high_voltage_switch)
{
power_data.old_high_voltage_switch = power_data.high_voltage_switch;
setParam("high_sw", (float)power_data.high_voltage_switch);
}
}
// APP模块的初始化
void powerAppInit(void)
{
// 初始化变量
memset(&power_data, 0, sizeof(PowerSystem));
power_data.current_state = POWER_STANDBY;
// 初始化时恢复电源状态
power_data.current_state = (PowerState)getParam("pwr_sta");
power_data.old_state = power_data.current_state;
// 恢复电源按钮状态
power_button.is_power_on = (uint8_t)getParam("pwr_btn");
power_button.old_is_power_on = power_button.is_power_on;
//恢复高压开关状态
power_data.high_voltage_switch = (uint8_t)getParam("high_sw");
power_data.old_high_voltage_switch = power_data.high_voltage_switch;
//恢复急停开关状态
power_data.emergency_stop = (uint8_t)getParam("stop_sw");
power_data.old_emergency_stop = power_data.emergency_stop;
// 订阅输入信号
subscribe(&un_sw_sample, powerInput); // 急停开关、高压开关
subscribe(&un_remote_control_input, powerInput); // 遥控器电源开关
// 定时器
timerInit(&power_data.timer);
subscribe(&power_data.timer, powerTimerProcess);
timerStart(&power_data.timer, 500, 1); // 周期调用
//定时器唤醒
timerInit(&power_data.timer1);
subscribe(&power_data.timer1, wakeupProcess);
timerStart(&power_data.timer1, 500, 1); // 周期调用
//预充定时器
timerInit(&power_data.timer_pre_charge);
subscribe(&power_data.timer_pre_charge, powerTimerProcess);
printf("app_power: initial OK\n");
}

57
app/app_power.h Normal file
View File

@@ -0,0 +1,57 @@
#ifndef APP_POWER_H
#define APP_POWER_H
#ifdef __cplusplus
extern "C" {
#endif
#include "app_config.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
// 定义电源状态枚举
typedef enum {
POWER_STANDBY,
POWER_WORKING,
POWER_EMERGENCY,
POWER_PRE_CHARGE,
POWER_NEUTRAL,
POWER_SLEEP
} PowerState;
// 使用内联函数
static inline uint8_t setPowerOn(void) { return 1; }
static inline uint8_t setPowerOff(void) { return 0; }
// 声明 power_data 变量结构体
typedef struct {
PowerState current_state; // 当前电源状态
uint32_t start_time; // 定时器起始时间
Timer timer; // 定时器
Timer timer1;
Timer timer_pre_charge; // 预充定时器
PowerState last_state; // 上一次状态
uint8_t emergency_stop_switch; // 急停开关
uint8_t high_voltage_switch; // 高压开关
uint8_t old_high_voltage_switch; // 上一次高压开关
uint8_t remote_power_switch; // 遥控器电源开关
uint8_t remote_emergency_stop; // 遥控器急停开关
uint8_t emergency_stop; // 急停状态
uint8_t old_emergency_stop; // 上一次急停开关
uint8_t pre_charge_finish; // 预充完成标志位
uint8_t old_state; // 上一次状态
uint8_t neutral_cnt;
} PowerSystem;
// 声明外部变量
extern PowerSystem power_data;
void powerAppInit(void);
#ifdef __cplusplus
}
#endif
#endif // APP_POWER_H

396
app/app_request.c Normal file
View File

@@ -0,0 +1,396 @@
#include "app_config.h"
#include "interface.h"
#include "app_request.h"
#include "app_param_manage.h"
uint16_t request_id = 0;
static void processRequestframe(uint16_t id)
{
uint32_t TempAcc = 0;
uint8_t i = 0;
static uint8_t VehicleStaACC0 = 0;
static uint8_t VehicleStaACC1 = 0;
static uint8_t VehicleStaACC2 = 0;
static uint8_t VehicleStaACC3 = 0;
uint16_t RgExchangeTemp = 0;
uint32_t Rg32ExchangeTemp = 0;
//-----------------------------------------------------------
// printf("request_read_id:%d\n",id);
switch (id)//注意是高位在前,低位在后
{
case 0x2000://状态帧
un_vehicle_Info_output.bit_data.frame_header = 0xCCAA;//帧头
un_vehicle_Info_output.bit_data.frame_type = 0x2000;//帧类型
un_vehicle_Info_output.bit_data.frame_length = 0x2900;//帧长
un_vehicle_Info_output.bit_data.accumulated = VehicleStaACC0++;//累加值
TempAcc = 0;
for (i = 0; i < 40; i++)//累加前40个字节
{
TempAcc = TempAcc + (uint32_t)(un_vehicle_Info_output.arr[i]);
}
un_vehicle_Info_output.bit_data.crc = (uint8_t)TempAcc;//累加值
publishMessage(&un_vehicle_Info_output, 1);
break;
case 0x2100://电机帧
un_motor_status_output.bit_data.frame_header = 0xCCAA;//帧头
un_motor_status_output.bit_data.frame_type = 0x2100;//帧类型
un_motor_status_output.bit_data.frame_length = 0x1E00;//帧长
un_motor_status_output.bit_data.accumulated = VehicleStaACC1++;//累加值
RgExchangeTemp = ( (uint16_t)getParam("maxTorq") + 300 ) *100 ;
un_motor_status_output.bit_data.left_torque_limit = ((RgExchangeTemp << 8) | (RgExchangeTemp >> 8));//左侧扭矩限制
un_motor_status_output.bit_data.right_torque_limit = ((RgExchangeTemp << 8) | (RgExchangeTemp >> 8));//右侧扭矩限制
un_motor_status_output.bit_data.left_power_in = (((uint16_t)getParam("feedPwr") << 8) | ((uint16_t)getParam("feedPwr") >> 8));//左侧馈电功率
un_motor_status_output.bit_data.right_power_in = (((uint16_t)getParam("feedPwr") << 8) | ((uint16_t)getParam("feedPwr") >> 8));//右侧馈电功率
un_motor_status_output.bit_data.left_power_out = (((uint16_t)getParam("dispPwr") << 8) | ((uint16_t)getParam("dispPwr") >> 8));//左侧放电功率
un_motor_status_output.bit_data.right_power_out = (((uint16_t)getParam("dispPwr") << 8) | ((uint16_t)getParam("dispPwr") >> 8));//右侧放电功率
TempAcc = 0;
for (i = 0; i < 31; i++)//累加前31个字节
{
TempAcc = TempAcc + (uint32_t)(un_motor_status_output.arr[i]);
un_motor_status_output.bit_data.checksum = (uint8_t)TempAcc;//累加值
}
publishMessage(&un_motor_status_output, 1);
break;
case 0x2200:
un_pid_output.bit_data.frame_header = 0xCCAA;//帧头
un_pid_output.bit_data.frame_type = 0x2200;//帧类型
un_pid_output.bit_data.frame_length = 0x3800;//帧长
un_pid_output.bit_data.accumulated = VehicleStaACC2++;//累加值
Rg32ExchangeTemp = (uint32_t)(int32_t)(getParam("spd_kp")*1000);
Rg32ExchangeTemp = ( ((Rg32ExchangeTemp >> 24) &0xff ) | ((Rg32ExchangeTemp >> 8) & 0xFF00) | ((Rg32ExchangeTemp << 8) & 0xFF0000) | ((Rg32ExchangeTemp << 24)) );
un_pid_output.bit_data.rc_straight_p = Rg32ExchangeTemp;//遥控直行P参数
Rg32ExchangeTemp = (uint32_t)(int32_t)(getParam("spd_ki")*1000);
Rg32ExchangeTemp = ( ((Rg32ExchangeTemp >> 24) &0xff ) | ((Rg32ExchangeTemp >> 8) & 0xFF00) | ((Rg32ExchangeTemp << 8) & 0xFF0000) | ((Rg32ExchangeTemp << 24)) );
un_pid_output.bit_data.rc_straight_i = Rg32ExchangeTemp;//遥控直行I参数
Rg32ExchangeTemp = (uint32_t)(int32_t)(getParam("spd_kd")*1000);
Rg32ExchangeTemp = ( ((Rg32ExchangeTemp >> 24) &0xff ) | ((Rg32ExchangeTemp >> 8) & 0xFF00) | ((Rg32ExchangeTemp << 8) & 0xFF0000) | ((Rg32ExchangeTemp << 24)) );
un_pid_output.bit_data.rc_straight_d = Rg32ExchangeTemp;//遥控直行D参数
Rg32ExchangeTemp = (uint32_t)(int32_t)(getParam("spd_il")*1000);
Rg32ExchangeTemp = ( ((Rg32ExchangeTemp >> 24) &0xff ) | ((Rg32ExchangeTemp >> 8) & 0xFF00) | ((Rg32ExchangeTemp << 8) & 0xFF0000) | ((Rg32ExchangeTemp << 24)) );
un_pid_output.bit_data.auto_straight_p = Rg32ExchangeTemp;//自主直行P参数
Rg32ExchangeTemp = (uint32_t)(int32_t)(getParam("spd_ol")*1000);
Rg32ExchangeTemp = ( ((Rg32ExchangeTemp >> 24) &0xff ) | ((Rg32ExchangeTemp >> 8) & 0xFF00) | ((Rg32ExchangeTemp << 8) & 0xFF0000) | ((Rg32ExchangeTemp << 24)) );
un_pid_output.bit_data.auto_straight_i = Rg32ExchangeTemp;//自主直行I参数
Rg32ExchangeTemp = (uint32_t)(int32_t)(getParam("spd_kd")*1000);
Rg32ExchangeTemp = ( ((Rg32ExchangeTemp >> 24) &0xff ) | ((Rg32ExchangeTemp >> 8) & 0xFF00) | ((Rg32ExchangeTemp << 8) & 0xFF0000) | ((Rg32ExchangeTemp << 24)) );
un_pid_output.bit_data.auto_straight_d = Rg32ExchangeTemp;//自主直行D参数
Rg32ExchangeTemp = (uint32_t)(int32_t)(getParam("crv_kp")*1000);
Rg32ExchangeTemp = ( ((Rg32ExchangeTemp >> 24) &0xff ) | ((Rg32ExchangeTemp >> 8) & 0xFF00) | ((Rg32ExchangeTemp << 8) & 0xFF0000) | ((Rg32ExchangeTemp << 24)) );
un_pid_output.bit_data.rc_turn_p = Rg32ExchangeTemp;//遥控转弯P参数
Rg32ExchangeTemp = (uint32_t)(int32_t)(getParam("crv_ki")*1000);
Rg32ExchangeTemp = ( ((Rg32ExchangeTemp >> 24) &0xff ) | ((Rg32ExchangeTemp >> 8) & 0xFF00) | ((Rg32ExchangeTemp << 8) & 0xFF0000) | ((Rg32ExchangeTemp << 24)) );
un_pid_output.bit_data.rc_turn_i = Rg32ExchangeTemp;//遥控转弯I参数
Rg32ExchangeTemp = (uint32_t)(int32_t)(getParam("crv_kd")*1000);
Rg32ExchangeTemp = ( ((Rg32ExchangeTemp >> 24) &0xff ) | ((Rg32ExchangeTemp >> 8) & 0xFF00) | ((Rg32ExchangeTemp << 8) & 0xFF0000) | ((Rg32ExchangeTemp << 24)) );
un_pid_output.bit_data.rc_turn_d = Rg32ExchangeTemp;//遥控转弯D参数
Rg32ExchangeTemp = (uint32_t)(int32_t)(getParam("crv_il")*1000);
Rg32ExchangeTemp = ( ((Rg32ExchangeTemp >> 24) &0xff ) | ((Rg32ExchangeTemp >> 8) & 0xFF00) | ((Rg32ExchangeTemp << 8) & 0xFF0000) | ((Rg32ExchangeTemp << 24)) );
un_pid_output.bit_data.auto_turn_p = Rg32ExchangeTemp;//自主转弯P参数
Rg32ExchangeTemp = (uint32_t)(int32_t)(getParam("crv_ol")*1000);
Rg32ExchangeTemp = ( ((Rg32ExchangeTemp >> 24) &0xff ) | ((Rg32ExchangeTemp >> 8) & 0xFF00) | ((Rg32ExchangeTemp << 8) & 0xFF0000) | ((Rg32ExchangeTemp << 24)) );
un_pid_output.bit_data.auto_turn_i = Rg32ExchangeTemp;//自主转弯I参数
Rg32ExchangeTemp = (uint32_t)(int32_t)(getParam("spd_kd")*1000);
Rg32ExchangeTemp = ( ((Rg32ExchangeTemp >> 24) &0xff ) | ((Rg32ExchangeTemp >> 8) & 0xFF00) | ((Rg32ExchangeTemp << 8) & 0xFF0000) | ((Rg32ExchangeTemp << 24)) );
un_pid_output.bit_data.auto_turn_d = Rg32ExchangeTemp;//自主转弯I参数
TempAcc = 0;
for (i = 0; i < 55; i++)//累加前40个字节
{
TempAcc = TempAcc + (uint32_t)(un_pid_output.arr[i]);
}
un_pid_output.bit_data.checksum = (uint8_t)TempAcc;//累加值
publishMessage(&un_pid_output, 1);
break;
case 0x2300:
// ETHTxtempArr[0] = 0xAA;
// ETHTxtempArr[1] = 0xCC;
// ETHTxtempArr[2] = 0x00;
// ETHTxtempArr[3] = 0x23;
// ETHTxtempArr[4] = 0;
// ETHTxtempArr[5] = 27;
// ETHTxtempArr[6] = VehicleStaACC3++;
// //AIAO
// memcpy(&ETHTxtempArr[7],(uint8_t *)&(UnAIAOSignal_1.ArrData.ArrRx[0]),17);//电池数据拷贝
// ETHTxtempArr[24] = (u8)(RgCanToAiAOCnt>>8);
// ETHTxtempArr[25] = (u8)RgCanToAiAOCnt;//累加值
//
// TempAcc = 0;
// for (i = 0; i < 26; i++)//累加前40个字节
// {
// TempAcc = TempAcc + (u32)(ETHTxtempArr[i]);
// }
// ETHTxtempArr[26] = (uint8_t)TempAcc;//累加值
//
// TxLen = 27;
// UdpSendToData(UDPCB_2,(uint8_t *)(&un_analog_signal_output), 27, (uint8_t *)&ethernet_parameter.upper_ip[0], ethernet_parameter.target_upper_port);
break;
case 0x2400:
un_remote_control_output.bit_data.frame_header = 0xCCAA;//帧头
un_remote_control_output.bit_data.frame_type = 0x2400;//帧类型
un_remote_control_output.bit_data.frame_length = 0x1400;//帧长
un_remote_control_output.bit_data.accumulated = VehicleStaACC3++;//累加值
//RCH_3
TempAcc = 0;
for (i = 0; i < 17; i++)//累加前40个字节
{
TempAcc = TempAcc + (uint32_t)(un_remote_control_output.arr[i]);
}
un_remote_control_output.bit_data.crc = (uint8_t)TempAcc;//累加值
publishMessage(&un_remote_control_output, 1);
break;
case 0x2500:
un_manual_control_output.bit_data.frame_type = 0x2500;
TempAcc = 0;
for (i = 0; i < 14; i++)//累加前40个字节
{
TempAcc = TempAcc + (uint32_t)(un_manual_control_output.arr[i]);
}
un_manual_control_output.bit_data.crc_2 = (uint8_t)TempAcc;//累加值
publishMessage(&un_manual_control_output, 1);
break;
case 0x2600:
un_auto_control_output.bit_data.frame_type = 0x2600;
TempAcc = 0;
for (i = 0; i < 27; i++)//累加前40个字节
{
TempAcc = TempAcc + (uint32_t)(un_auto_control_output.arr[i]);
}
un_auto_control_output.bit_data.crc = (uint8_t)TempAcc;//累加值
publishMessage(&un_auto_control_output, 1);
break;
// case 0x2700:
// memcpy(&ETHTxtempArr[0],(uint8_t *)&RemoteControlRoomToVcuBuf,11);//手柄拷贝
// ETHTxtempArr[2] = 0;//修改帧类型为0x0025
// ETHTxtempArr[3] = 0x27;
// ETHTxtempArr[11] = (u8)(RgETHToRemoteControlCnt>>8);
// ETHTxtempArr[12] = (u8)RgETHToRemoteControlCnt;//累加值
// TempAcc = 0;
// for (i = 0; i < 13; i++)//累加前40个字节
// {
// TempAcc = TempAcc + (u32)(ETHTxtempArr[i]);
// }
// ETHTxtempArr[13] = (uint8_t)TempAcc;//累加值
//
// TxLen = 14;
// UdpSendToData(SocketId2,ETHTxtempArr,&TxLen,ip_addr,port);//测试
// break;
// case 0xFFFF:
// memcpy(&ETHTxtempArr[0],(uint8_t *)&RemoteControlRoomToVcuBuf,11);//手柄拷贝
// ETHTxtempArr[2] = 0x27;//修改帧类型为0x0025
// ETHTxtempArr[3] = 0;
// ETHTxtempArr[11] = (u8)RgETHToRemoteControlCnt;
// ETHTxtempArr[12] = (u8)(RgETHToRemoteControlCnt>>8);//累加值
// TempAcc = 0;
// for (i = 0; i < 13; i++)//累加前40个字节
// {
// TempAcc = TempAcc + (u32)(ETHTxtempArr[i]);
// }
// ETHTxtempArr[13] = (uint8_t)TempAcc;//累加值
//
// TxLen = 14;
// UdpSendToData(SocketId2,ETHTxtempArr,&TxLen,ip_addr,port);//测试
// break;
default: break;
}
}
// 处理所有输入信号的函数
static void requestInput(void *signal_id)
{
uint16_t request16_temp = 0;
//--------------------------------------------------------
if (signal_id == &diff_data)
{
request16_temp = (uint16_t)(int16_t)(diff_data.desired_speed * 100.0);
un_vehicle_Info_output.bit_data.desired_speed = ((request16_temp << 8) | (request16_temp >> 8));//当前速度
request16_temp = (uint16_t)(int16_t)(diff_data.desired_curvature * 10000.0);
un_vehicle_Info_output.bit_data.desired_curvature = ((request16_temp << 8) | (request16_temp >> 8));//当前曲率
request16_temp = (uint16_t)(int16_t)(diff_data.speed * 100.0);
un_vehicle_Info_output.bit_data.speed = ((request16_temp << 8) | (request16_temp >> 8));//当前速度
request16_temp = (uint16_t)(int16_t)(diff_data.curvature * 10000.0);
un_vehicle_Info_output.bit_data.curvature = ((request16_temp << 8) | (request16_temp >> 8));//当前曲率
request16_temp = (uint16_t)(int16_t)(diff_data.left_motor_speed *6);
un_vehicle_Info_output.bit_data.set_left_speed = ((request16_temp << 8) | (request16_temp >> 8));//当前速度
request16_temp = (uint16_t)(int16_t)(diff_data.right_motor_speed *6);
un_vehicle_Info_output.bit_data.set_right_speed = ((request16_temp << 8) | (request16_temp >> 8));//当前曲率
}
else if(signal_id == &un_auto_computer_input)
{
un_vehicle_Info_output.bit_data.longitude = un_auto_computer_input.bit_data.longitude;//经度
un_vehicle_Info_output.bit_data.latitude = un_auto_computer_input.bit_data.latitude;
un_vehicle_Info_output.bit_data.altitude = un_auto_computer_input.bit_data.altitude;
un_vehicle_Info_output.bit_data.heading_angle = un_auto_computer_input.bit_data.heading;//航向
memcpy(&un_auto_control_output.arr[0],&(un_auto_computer_input.arr[0]),25);//手柄拷贝
}
else if(signal_id == &un_bms_input)
{
un_vehicle_Info_output.bit_data.battery_voltage = un_bms_input.bit_data.bus_voltage/10;//电池电压读取得的10mV所以输出的是100mV单位所以缩小10倍
un_vehicle_Info_output.bit_data.battery_soc = un_bms_input.bit_data.soc;//SOC
un_vehicle_Info_output.bit_data.battery_current = un_bms_input.bit_data.bus_current;//电池电流
}
else if(signal_id == &un_motor_input1)
{
// un_motor_status_output.bit_data.left_wheel_speed = SWAP_ENDIAN_16( (uint16_t)((int16_t)(un_motor_input1.bit_data.MotCon_1Signal4) + 30000) );
// un_motor_status_output.bit_data.left_torque = ((un_motor_input1.bit_data.torque << 8) | (un_motor_input1.bit_data.torque >> 8));//左侧扭矩
// un_motor_status_output.bit_data.left_voltage = ((un_motor_input1.bit_data.bus_voltage << 8) | (un_motor_input1.bit_data.bus_voltage >> 8));//左侧电压
// un_motor_status_output.bit_data.left_fault_code = un_motor_input1.bit_data.fault_code;//左侧故障码
}
else if(signal_id == &un_motor_input2)
{
// un_motor_status_output.bit_data.right_wheel_speed = SWAP_ENDIAN_16 ( (uint16_t)((int16_t)(un_motor_input1.bit_data.MotCon_1Signal3) + 30000) );//左侧轮速
// un_motor_status_output.bit_data.right_torque = ((un_motor_input2.bit_data.torque << 8) | (un_motor_input2.bit_data.torque >> 8));//右侧扭矩
// un_motor_status_output.bit_data.right_fault_code = un_motor_input2.bit_data.fault_code;//右侧故障码
// un_motor_status_output.bit_data.right_voltage = ((un_motor_input2.bit_data.bus_voltage << 8) | (un_motor_input2.bit_data.bus_voltage >> 8));//右侧电压
}
else if(signal_id == &un_remote_control_input)
{
//RCH_3
un_remote_control_output.bit_data.speed = ((un_remote_control_input.bit_data.speed << 8) | (un_remote_control_input.bit_data.speed >> 8));//遥控器期望速度
un_remote_control_output.bit_data.curvature = ((un_remote_control_input.bit_data.curvature << 8) | (un_remote_control_input.bit_data.curvature >> 8));//遥控器期望曲率
memcpy(&un_remote_control_output.arr[11],&un_remote_control_input.arr[4],4);//遥控数据拷贝
}
else if(signal_id == &un_manual_computer_input)
{
memcpy(&un_manual_control_output.arr[0],&(un_manual_computer_input.arr[0]),12);//手柄拷贝
}
else if(signal_id == &ethernet_fault_Info)
{
un_auto_control_output.arr[25] = (uint8_t)(ethernet_fault_Info.bit_data.auto_count>>8);
un_auto_control_output.arr[26] = (uint8_t)(ethernet_fault_Info.bit_data.auto_count);//累加值
un_manual_control_output.arr[12] = (uint8_t)(ethernet_fault_Info.bit_data.manual_count>>8);
un_manual_control_output.arr[13] = (uint8_t)(ethernet_fault_Info.bit_data.manual_count);//累加值
}
else if(signal_id == &can_fault_info)
{
un_remote_control_output.arr[15] = (uint8_t)(can_fault_info.bit_data.remote_count>>8);
un_remote_control_output.arr[16] = (uint8_t)(can_fault_info.bit_data.remote_count);//累加值
}
else if(signal_id == &un_request_frame)
{
request_id = REQUEST_READ_ID;
processRequestframe(request_id);
}
else{}
}
// 修改APP模块的初始化函数
void requestAppInit(void)
{
// 订阅消息,使用静态成员函数作为回调 参数回馈
subscribe(&diff_data, requestInput);
subscribe(&un_auto_computer_input, requestInput);
subscribe(&un_bms_input, requestInput);
subscribe(&un_motor_input1, requestInput);
subscribe(&un_motor_input2, requestInput);
subscribe(&un_remote_control_input, requestInput);
subscribe(&can_fault_info, requestInput);
subscribe(&ethernet_fault_Info, requestInput);
// // 订阅消息,使用静态成员函数作为回调 参数回馈
subscribe(&un_request_frame, requestInput);
printf("app_request: initial OK \n");
}

89
app/app_request.h Normal file
View File

@@ -0,0 +1,89 @@
#ifndef APP_REQUEST_H
#define APP_REQUEST_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "app_config.h"
#include "app_differential_drive.h"
#define SWAP_ENDIAN_16(x) ((((x) & 0xFF) << 8) | (((x) >> 8) & 0xFF))
#define SWAP_ENDIAN_32(x) (((x) << 24) | (((x) & 0xFF00) << 8) | (((x) >> 8) & 0xFF00) | ((x) >> 24))
//typedef enum
//{
// MODE_MANUAL, // 手动模式
// MODE_AUTO // 自动模式
//} ControlMode;
//
typedef struct RequestData
{
float desired_speed; // 期望速度
float desired_curvature; // 期望曲率
float left_motor_speed; // 当前左电机速度
float right_motor_speed; // 当前右电机速度
float speed; // 当前车速
float curvature; // 当前曲率
float yaw_rate; // 当前角速度
float desired_yaw_rate; // 期望角速度
float acceleration; // 当前加速度
float deceleration; // 当前减速度
float max_speed; // 最大速度
float desired_acceleration; // 期望加速度
float desired_deceleration; // 期望减速度
float out_left_motor_speed; // 输出左电机速度
float out_right_motor_speed; // 输出右电机速度
} RequestData;
// 声明外部变量
extern DiffData diff_data;
void requestAppInit(void);
#ifdef __cplusplus
}
#endif
#endif // APP_DIFFERENTIAL_DRIVE_H

285
app/app_temp.c Normal file
View File

@@ -0,0 +1,285 @@
#include "app_config.h"
#include "interface.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
#include "app_param_manage.h"
#include "app_temp.h"
// 声明 temp_data 变量
TempSystem temp_data;
static void handleTemperatureAlarm(int16_t current_temp, float alarm_temp,
float critical_temp, float threshold_temp,
TempState *state)
{
switch (*state)
{
case TEMP_NORMAL:
// 从正常状态进入警告状态的条件
if (current_temp > (alarm_temp + threshold_temp))
{
*state = TEMP_WARNING;
printf("Temperature Warning: Activated! Current temp: %d°C\n", current_temp);
}
// 从正常状态直接进入严重状态的条件
else if (current_temp > (critical_temp + threshold_temp))
{
*state = TEMP_CRITICAL;
printf("Temperature Critical: Activated! Current temp: %d°C\n", current_temp);
}
else
{
*state = TEMP_NORMAL;
}
break;
case TEMP_WARNING:
// 从警告状态返回正常状态的条件
if (current_temp < (alarm_temp - threshold_temp))
{
*state = TEMP_NORMAL;
printf("Temperature Warning: Deactivated! Current temp: %d°C\n", current_temp);
}
// 从警告状态进入严重状态的条件
else if (current_temp > (critical_temp + threshold_temp))
{
*state = TEMP_CRITICAL;
printf("Temperature Critical: Activated! Current temp: %d°C\n", current_temp);
}
else
{
*state = TEMP_WARNING;
}
break;
case TEMP_CRITICAL:
// 从严重状态返回警告状态的条件
if (current_temp < (critical_temp - threshold_temp))
{
*state = TEMP_WARNING;
printf("Temperature Critical: Deactivated! Current temp: %d°C\n", current_temp);
}
// 从严重状态直接返回正常状态的条件
else if (current_temp < (alarm_temp - threshold_temp))
{
*state = TEMP_NORMAL;
printf("Temperature Warning: Deactivated! Current temp: %d°C\n", current_temp);
}
else
{
*state = TEMP_CRITICAL;
}
break;
default:
*state = TEMP_NORMAL;
break;
}
}
// 温度输出处理函数
static void tempOutput(void *signal_id)
{
(void)signal_id;
// 电机1风扇 左前
switch (temp_data.state[0])
{
case TEMP_NORMAL:
un_inf_can_kgf_output1.bit_data.KGF01 = setFanOff();//电机控制器风扇
un_inf_can_kgf_output1.bit_data.pwm_01 = 0;
break;
case TEMP_WARNING:
un_inf_can_kgf_output1.bit_data.KGF01 = setFanOn();//电机控制器风扇
un_inf_can_kgf_output1.bit_data.pwm_01 = 5;
break;
case TEMP_CRITICAL:
un_inf_can_kgf_output1.bit_data.KGF01 = setFanOn();//电机控制器风扇
un_inf_can_kgf_output1.bit_data.pwm_01 = 0;
break;
}
// 电机2风扇 右前
switch (temp_data.state[1])
{
case TEMP_NORMAL:
un_inf_can_kgf_output1.bit_data.KGF02 = setFanOff();//电机控制器风扇
un_inf_can_kgf_output1.bit_data.pwm_02 = 0;
break;
case TEMP_WARNING:
un_inf_can_kgf_output1.bit_data.KGF02 = setFanOn();//电机控制器风扇
un_inf_can_kgf_output1.bit_data.pwm_02 = 5;
break;
case TEMP_CRITICAL:
un_inf_can_kgf_output1.bit_data.KGF02 = setFanOn();//电机控制器风扇
un_inf_can_kgf_output1.bit_data.pwm_02 = 0;
break;
}
// 电机3风扇 左后
switch (temp_data.state[2])
{
case TEMP_NORMAL:
un_inf_can_kgf_output1.bit_data.KGF07 = setFanOff();//电机控制器风扇
un_inf_can_kgf_output1.bit_data.pwm_07 = 0;
break;
case TEMP_WARNING:
un_inf_can_kgf_output1.bit_data.KGF07 = setFanOn();//电机控制器风扇
un_inf_can_kgf_output1.bit_data.pwm_07 = 5;
break;
case TEMP_CRITICAL:
un_inf_can_kgf_output1.bit_data.KGF07 = setFanOn();//电机控制器风扇
un_inf_can_kgf_output1.bit_data.pwm_07 = 0;
break;
}
// 电机4风扇 右后
switch (temp_data.state[3])
{
case TEMP_NORMAL:
un_inf_can_kgf_output1.bit_data.KGF08 = setFanOff();//电机控制器风扇
un_inf_can_kgf_output1.bit_data.pwm_08 = 0;
break;
case TEMP_WARNING:
un_inf_can_kgf_output1.bit_data.KGF08 = setFanOn();//电机控制器风扇
un_inf_can_kgf_output1.bit_data.pwm_08 = 5;
break;
case TEMP_CRITICAL:
un_inf_can_kgf_output1.bit_data.KGF08 = setFanOn();//电机控制器风扇
un_inf_can_kgf_output1.bit_data.pwm_08 = 0;
break;
}
// // 电机3风扇
// switch (temp_data.state[2])
// {
// case TEMP_NORMAL:
// un_inf_can_kgf_output1.bit_data.KGF01 = setFanOff();//电机控制器风扇
// un_inf_can_kgf_output1.bit_data.pwm_01 = 0;
// break;
// case TEMP_WARNING:
// un_inf_can_kgf_output1.bit_data.KGF01 = setFanOn();//电机控制器风扇
// un_inf_can_kgf_output1.bit_data.pwm_01 = 5;
// break;
// case TEMP_CRITICAL:
// un_inf_can_kgf_output1.bit_data.KGF01 = setFanOn();//电机控制器风扇
// un_inf_can_kgf_output1.bit_data.pwm_01 = 0;
// break;
// }
publishMessage(&un_inf_can_kgf_output1, 1);
}
// 温度状态处理函数
static void tempProcess(void *signal_id)
{
(void)signal_id;
int16_t max_temp[4] = {0,0};
max_temp[0] = temp_data.current_temp[0];
max_temp[1] = temp_data.current_temp[1];
// printf("motor1 temp: %d, motor2 temp: %d\n", max_temp[0], max_temp[1]);
handleTemperatureAlarm(max_temp[0], MOTOR_WARNING_TEMP, MOTOR_CRITICAL_TEMP, MOTOR_THRESHOLD_TEMP, &temp_data.state[0]);
handleTemperatureAlarm(max_temp[1], MOTOR_WARNING_TEMP, MOTOR_CRITICAL_TEMP, MOTOR_THRESHOLD_TEMP, &temp_data.state[1]);
handleTemperatureAlarm(max_temp[2], MOTOR_WARNING_TEMP, MOTOR_CRITICAL_TEMP, MOTOR_THRESHOLD_TEMP, &temp_data.state[2]);
handleTemperatureAlarm(max_temp[3], MOTOR_WARNING_TEMP, MOTOR_CRITICAL_TEMP, MOTOR_THRESHOLD_TEMP, &temp_data.state[3]);
// if (max_temp[0] >= 60) // 假设60度为危险温度
// {
// temp_data.state[0] = TEMP_CRITICAL;
// }
// else if (max_temp[0] >= 40) // 假设40度为警告温度
// {
// temp_data.state[0] = TEMP_WARNING;
// }
// else
// {
// temp_data.state[0] = TEMP_NORMAL;
// }
//
//
// max_temp[1] = temp_data.current_temp[1];
// if (max_temp[1] >= 60) // 假设60度为危险温度
// {
// temp_data.state[1] = TEMP_CRITICAL;
// }
// else if (max_temp[1] >= 40) // 假设40度为警告温度
// {
// temp_data.state[1] = TEMP_WARNING;
// }
// else
// {
// temp_data.state[1] = TEMP_NORMAL;
// }
//
//// printf("motor1 temp: %d, motor2 temp: %d\n", max_temp[0], max_temp[1]);
//// printf("motor1 state: %d, motor2 state: %d\n", temp_data.state[0], temp_data.state[1]);
tempOutput(NULL);
timerStart(&temp_data.timer, 1000, 1); //1s
}
// 处理输入信号的函数
static void tempInput(void *signal_id)
{
(void)signal_id;
// 填充数据
if (signal_id == &un_motor_temp1)
{
temp_data.current_temp[0] = ( (int16_t)(un_motor_temp1.bit_data.controller_temp) - 40);//40偏移量
}
else if(signal_id == &un_motor_temp2)
{
temp_data.current_temp[1] = ( (int16_t)(un_motor_temp2.bit_data.controller_temp) - 40);
}
else if(signal_id == &un_motor_temp3)
{
temp_data.current_temp[2] = ( (int16_t)(un_motor_temp3.bit_data.controller_temp) - 40);
}
else if(signal_id == &un_motor_temp4)
{
temp_data.current_temp[3] = ( (int16_t)(un_motor_temp4.bit_data.controller_temp) - 40);
}
else{}
}
// APP模块的初始化
void tempAppInit(void)
{
// 初始化
timerInit(&temp_data.timer);
memset(&temp_data, 0, sizeof(TempSystem));
temp_data.state[0] = TEMP_NORMAL;
temp_data.state[1] = TEMP_NORMAL;
temp_data.mode = TEMP_MODE_AUTO;
temp_data.target_temp = 25; // 默认目标温度25度
// 订阅输入信号,处理温度逻辑
subscribe(&un_motor_temp1, tempInput);
subscribe(&un_motor_temp2, tempInput);
subscribe(&un_motor_temp3, tempInput);
subscribe(&un_motor_temp4, tempInput);
// 启动定时器,每秒检查一次温度
subscribe(&temp_data.timer, tempProcess);
timerStart(&temp_data.timer, 1000, 1); //1s
printf("app_temp: initial OK \n");
}

58
app/app_temp.h Normal file
View File

@@ -0,0 +1,58 @@
#ifndef APP_TEMP_H
#define APP_TEMP_H
#ifdef __cplusplus
extern "C"
{
#endif
#define MOTOR_WARNING_TEMP 40
#define MOTOR_CRITICAL_TEMP 60
#define MOTOR_THRESHOLD_TEMP 5//回滞值
// 定义温度状态枚举
typedef enum
{
TEMP_NORMAL,
TEMP_WARNING,
TEMP_CRITICAL
} TempState;
// 定义温度控制模式枚举
typedef enum
{
TEMP_MODE_AUTO,
TEMP_MODE_MANUAL
} TempMode;
typedef struct
{
TempState state[8];
TempMode mode;
int16_t current_temp[8]; // 当前温度,8个不同的温度
int16_t target_temp; // 目标温度
uint8_t fan_speed[8]; // 风扇速度 8个通道
Timer timer; // 定时器
} TempSystem;
// 在头文件中声明外部变量
extern TempSystem temp_data;
// 使用内联函数
static inline uint8_t setFanOn(void) { return 1; }
static inline uint8_t setFanOff(void) { return 0; }
void tempAppInit(void);
void setTempMode(TempMode mode);
void setTargetTemp(int16_t temp);
void setFanSpeed(uint8_t speed);
#ifdef __cplusplus
}
#endif
#endif // APP_TEMP_H

62
app/app_test.c Normal file
View File

@@ -0,0 +1,62 @@
#include "app_config.h"
#include "app_dependence.h"
#include "interface.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
#include "sdrv_vic.h"
#include "app_test.h"
#include "app_differential_drive.h"
// 定时器结构体
Timer test_timer;
// 定时器信号处理函数
void testTimerProcess(void *signal_id)
{
(void)signal_id; // 标记变量为已使用,避免编译器警告
// static uint32_t start_time = 0;
// uint32_t test_irq[6] = {0};
// 再次启动定时器,实现周期定时
timerStart(&test_timer, 5000,1);
// printf("speed = %f ",diff_data.desired_speed);
// printf("curvature = %f ",diff_data.desired_curvature);
// printf("mode = %d\n",diff_data.mode);
//
// sdrv_vic_lld_read_all(test_irq);//打印所有中断使能位
// printf("irq state = %#X ",test_irq[0]);
// printf("irq state = %#X ",test_irq[1]);
// printf("irq state = %#X ",test_irq[2]);
// printf("irq state = %#X ",test_irq[3]);
// printf("irq state = %#X ",test_irq[4]);
// printf("irq state = %#X\n",test_irq[5]);
// printf("testAPP: %d us \n",getCurrentTime() - start_time);
// start_time = getCurrentTime();
}
// APP模块的初始化
void testAppInit(void)
{
// 初始化定时器
timerInit(&test_timer);
// 订阅定时器信号,用于停止电机
subscribe(&test_timer, testTimerProcess);
printf("testAPP: initial OK %d\n",getCurrentTime());
timerStart(&test_timer, 5000,1);
}

18
app/app_test.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef TEST_H
#define TEST_H
#ifdef __cplusplus
extern "C" {
#endif
extern void testAppInit(void);
#ifdef __cplusplus
}
#endif
#endif // TEST_H

83
app/app_ultrasonic.c Normal file
View File

@@ -0,0 +1,83 @@
#include "app_config.h"
#include "app_dependence.h"
#include "interface.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
#include "sdrv_vic.h"
#include "app_ultrasonic.h"
// 定时器结构体
Timer ultrasonic_timer;
Timer ultrasonic_timer1;
uint16_t fornt_distance = 0;//mm
// 定时器信号处理函数
void ultrasonicTimer1Process(void *signal_id)
{
(void)signal_id; // 标记变量为已使用,避免编译器警告
printf("fornt distance = %d\n",fornt_distance);
timerStart(&ultrasonic_timer1, 1000,1);
}
// 定时器信号处理函数
void ultrasonicTimerProcess(void *signal_id)
{
(void)signal_id; // 标记变量为已使用,避免编译器警告
un_ultrasonic_output1.bit_data.node = ULTRASONIC_FRONT_NODE;
un_ultrasonic_output1.bit_data.function_code = ULTRASONIC_READ;
un_ultrasonic_output1.bit_data.register_address = REALTIME_DISTANCE_REG;
un_ultrasonic_output1.bit_data.data = 0x100;
publishMessage(&un_ultrasonic_output1, 1);
timerStart(&ultrasonic_timer, 200,1);
}
void ultrasonicInput(void *signal_id)
{
if(signal_id == &un_ultrasonic_input1)
{
fornt_distance = SWAP_ENDIAN_16(un_ultrasonic_input1.bit_data.data);//高低字节交换
}
}
// APP模块的初始化
void ultrasonicAppInit(void)
{
// 初始化定时器
timerInit(&ultrasonic_timer);
timerInit(&ultrasonic_timer1);
// 订阅定时器信号
subscribe(&ultrasonic_timer, ultrasonicTimerProcess);
subscribe(&ultrasonic_timer1, ultrasonicTimer1Process);
subscribe(&un_ultrasonic_input1, ultrasonicInput);
printf("ultrasonicAPP: initial OK %d\n",getCurrentTime());
timerStart(&ultrasonic_timer, 200,1);
timerStart(&ultrasonic_timer1, 1000,1);
}

75
app/app_ultrasonic.h Normal file
View File

@@ -0,0 +1,75 @@
#ifndef ULTRASONIC_H
#define ULTRASONIC_H
#ifdef __cplusplus
extern "C" {
#endif
#define ULTRASONIC_FRONT_NODE 0x1
#define ULTRASONIC_BACK_NODE 0x2
#define ULTRASONIC_ID_1 0x520 + ULTRASONIC_FRONT_NODE
#define ULTRASONIC_ID_2 0x520 + ULTRASONIC_BACK_NODE
#define ULTRASONIC_READ 0x03
#define ULTRASONIC_WRITE 0x06
#define SOFTWARE_VERSION_REG 0x0000 // ģ<><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B1BE><><CAAE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ), <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: uint16_t
#define PROCESSED_DISTANCE_REG 0x0100 /*
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD><C4BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ(mm), <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: uint16_t
* <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3B7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <20><>Ӧʱ<D3A6>䣺190-750ms(<28><><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD><CCB6><EFBFBD>)
*/
#define REALTIME_DISTANCE_REG 0x0101 /*
* ʵʱ<CAB5><CAB1><EFBFBD>β<EFBFBD><CEB2><EFBFBD>ֵ(mm), <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: uint16_t
* <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD>󴥷<EFBFBD><F3B4A5B7><EFBFBD><EFBFBD>β<EFBFBD><CEB2><EFBFBD>
* <20><>Ӧʱ<D3A6>䣺15-140ms(<28><><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD><CCB6><EFBFBD>)
*/
#define TEMPERATURE_REG 0x0102 /*
* <20>¶ȴ<C2B6><C8B4><EFBFBD><EFBFBD><EFBFBD>ֵ, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: int16_t
* <20><>λ<EFBFBD><CEBB>0.1<EFBFBD><EFBFBD>ʼֵ<CABC><D6B5>/10), <20>ֱ<EFBFBD><D6B1>ʣ<EFBFBD>0.5<EFBFBD><EFBFBD>
* <20><>Ӧʱ<D3A6>䣺15-140ms(<28><><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD><CCB6><EFBFBD>)
*/
#define ECHO_TIME_REG 0x010A /*
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD>ʱ<EFBFBD><CAB1>ԭʼֵ(<28><>s), <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: uint16_t
* <20><><EFBFBD><EFBFBD>㣺ֵ/5.75 = <20><><EFBFBD>׾<EFBFBD><D7BE><EFBFBD>
* <20><>Ӧʱ<D3A6>䣺15-140ms(<28><><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD><CCB6><EFBFBD>)
*/
#define SWAP_ENDIAN_16(x) ((((x) & 0xFF) << 8) | (((x) >> 8) & 0xFF))
#define SWAP_ENDIAN_32(x) (((x) << 24) | (((x) & 0xFF00) << 8) | (((x) >> 8) & 0xFF00) | ((x) >> 24))
void ultrasonicAppInit(void);
#ifdef __cplusplus
}
#endif
#endif // ULTRASONIC_H