1、增加电压电流温度检测代码。

This commit is contained in:
cui635
2025-10-16 15:32:55 +08:00
parent b2c97d6a78
commit 3ccc65158c
6 changed files with 327 additions and 39 deletions
+6 -34
View File
@@ -153,40 +153,7 @@
<Name></Name> <Name></Name>
</SetRegEntry> </SetRegEntry>
</TargetDriverDllRegistry> </TargetDriverDllRegistry>
<Breakpoint> <Breakpoint/>
<Bp>
<Number>0</Number>
<Type>0</Type>
<LineNumber>71</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>17972</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>..\source\Module\dc_motor\dc_motor.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\BombSensor\../source/Module/dc_motor/dc_motor.c\71</Expression>
</Bp>
<Bp>
<Number>1</Number>
<Type>0</Type>
<LineNumber>747</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>6022</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>..\source\Module\dc_motor\dc_motor.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\BombSensor\../source/Module/dc_motor/dc_motor.c\747</Expression>
</Bp>
</Breakpoint>
<WatchWindow1> <WatchWindow1>
<Ww> <Ww>
<count>0</count> <count>0</count>
@@ -288,6 +255,11 @@
<WinNumber>1</WinNumber> <WinNumber>1</WinNumber>
<ItemText>g_motorSpeed,0x0A</ItemText> <ItemText>g_motorSpeed,0x0A</ItemText>
</Ww> </Ww>
<Ww>
<count>20</count>
<WinNumber>1</WinNumber>
<ItemText>g_adc_val,0x0A</ItemText>
</Ww>
</WatchWindow1> </WatchWindow1>
<Tracepoint> <Tracepoint>
<THDelay>0</THDelay> <THDelay>0</THDelay>
@@ -1,7 +1,11 @@
#include "dc_motor.h" #include "dc_motor.h"
#include "hc32_ddl.h" #include "hc32_ddl.h"
#include "Debug.h" #include "Debug.h"
#include "math.h"
#define ADC_CH_NUM 3 /* 需要转换的通道数目 */
#define ADC_COLL 100 /* 单采集次数 */
#define ADC_SUM ADC_CH_NUM * ADC_COLL /* 总采集次数 */
// 全局变量 // 全局变量
@@ -67,6 +71,252 @@ void DCMOTORDBGOnOff(uint8_t OnOff)
#endif #endif
extern uint16_t m_au16Adc1SaValue[ADC_CH_NUM * ADC_COLL];
uint16_t init_adc_val;
uint16_t AdcInitCnt = 0;
#define Adc 0.80566 //3.3/4096=0.00080566 //ADC分辨率
#define ADC_CH_NUM 3
uint16_t g_adc_val[ADC_CH_NUM];
/************************************* 第二部分 电压电流温度采集 **********************************************/
/*
Rt = Rp *exp(B*(1/T1-1/T2))
Rt 是热敏电阻在T1温度下的阻值;
Rp是热敏电阻在T2常温下的标称阻值;
exp是e的n次方,e是自然常数,就是自然对数的底数,近似等于 2.7182818;
B值是热敏电阻的重要参数,教程中用到的热敏电阻B值为3380;
这里T1和T2指的是开尔文温度,T2是常温25℃,即(273.15+25)K
T1就是所求的温度
*/
const float Rp = 10000.0f; /* 10K */
const float T2 = (273.15f + 25.0f); /* T2 */
const float Bx = 3380.0f; /* B */
const float Ka = 273.15f;
/**
* @brief 计算温度值
* @param para: 温度采集对应ADC通道的值(已滤波)
* @note 计算温度分为两步:
1.根据ADC采集到的值计算当前对应的Rt
2.根据Rt计算对应的温度值
* @retval 温度值
*/
float get_temp(uint16_t para)
{
float Rt;
float temp;
/*
第一步:
Rt = 3.3 * 4700 / VTEMP - 4700 ,其中VTEMP就是温度检测通道采集回来的电压值,VTEMP = ADC值* 3.3/4096
由此我们可以计算出当前Rt的值:Rt = 3.3f * 4700.0f / (para * 3.3f / 4096.0f ) - 4700.0f;
*/
Rt = 3.3f * 4700.0f / (para * 3.3f / 4096.0f ) - 4700.0f; /* 根据当前ADC值计算出Rt的值 */
/*
第二步:
根据当前Rt的值来计算对应温度值:Rt = Rp *exp(B*(1/T1-1/T2))
*/
temp = Rt / Rp; /* 解出exp(B*(1/T1-1/T2)) ,即temp = exp(B*(1/T1-1/T2)) */
temp = log(temp); /* 解出B*(1/T1-1/T2) ,即temp = B*(1/T1-1/T2) */
temp /= Bx; /* 解出1/T1-1/T2 ,即temp = 1/T1-1/T2 */
temp += (1.0f / T2); /* 解出1/T1 ,即temp = 1/T1 */
temp = 1.0f / (temp); /* 解出T1 ,即temp = T1 */
temp -= Ka; /* 计算T1对应的摄氏度 */
return temp; /* 返回温度值 */
}
/**
* @brief 计算ADC的平均值(滤波)
* @param * p :存放ADC值的指针地址
* @note 此函数对电压、温度、电流对应的ADC值进行滤波,
* p[0]-p[2]对应的分别是电压、温度和电流
* @retval 无
*/
void calc_adc_val(uint16_t * p)
{
uint32_t temp[3] = {0,0,0};
int i;
for(i=0;i<ADC_COLL;i++) /* 循环ADC_COLL次取值,累加 */
{
temp[0] += m_au16Adc1SaValue[0+i*ADC_CH_NUM];
temp[1] += m_au16Adc1SaValue[1+i*ADC_CH_NUM];
temp[2] += m_au16Adc1SaValue[2+i*ADC_CH_NUM];
}
temp[0] /= ADC_COLL; /* 取平均值 */
temp[1] /= ADC_COLL;
temp[2] /= ADC_COLL;
p[0] = temp[0]; /* 存入电压ADC通道平均值 */
p[1] = temp[1]; /* 存入温度ADC通道平均值 */
p[2] = temp[2]; /* 存入电流ADC通道平均值 */
}
/************************************* 第三部分 编码器测速 ****************************************************/
Motor_TypeDef g_motor_data; /*电机参数变量*/
ENCODE_TypeDef g_encode; /*编码器参数变量*/
/**
* @brief 电机速度计算
* @param encode_now:当前编码器总的计数值
* ms:计算速度的间隔,中断1ms进入一次,例如ms = 5即5ms计算一次速度
* @retval 无
*/
void speed_computer(int32_t encode_now, uint8_t ms)
{
uint8_t i = 0, j = 0;
float temp = 0.0;
static uint8_t sp_count = 0, k = 0;
static float speed_arr[10] = {0.0}; /* 存储速度进行滤波运算 */
if (sp_count == ms) /* 计算一次速度 */
{
/* 计算电机转速
第一步 :计算ms毫秒内计数变化量
第二步 ;计算1min内计数变化量:g_encode.speed * ((1000 / ms) * 60
第三步 :除以编码器旋转一圈的计数次数(倍频倍数 * 编码器分辨率)
第四步 :除以减速比即可得出电机转速
*/
g_encode.encode_now = encode_now; /* 取出编码器当前计数值 */
g_encode.speed = (g_encode.encode_now - g_encode.encode_old); /* 计算编码器计数值的变化量 */
speed_arr[k++] = (float)(g_encode.speed * ((1000 / ms) * 60.0) / REDUCTION_RATIO / ROTO_RATIO ); /* 保存电机转速 */
g_encode.encode_old = g_encode.encode_now; /* 保存当前编码器的值 */
/* 累计10次速度值,后续进行滤波*/
if (k == 10)
{
for (i = 10; i >= 1; i--) /* 冒泡排序*/
{
for (j = 0; j < (i - 1); j++)
{
if (speed_arr[j] > speed_arr[j + 1]) /* 数值比较 */
{
temp = speed_arr[j]; /* 数值换位 */
speed_arr[j] = speed_arr[j + 1];
speed_arr[j + 1] = temp;
}
}
}
temp = 0.0;
for (i = 2; i < 8; i++) /* 去除两边高低数据 */
{
temp += speed_arr[i]; /* 将中间数值累加 */
}
temp = (float)(temp / 6); /*求速度平均值*/
/* 一阶低通滤波
* 公式为:Y(n)= qX(n) + (1-q)Y(n-1)
* 其中X(n)为本次采样值;Y(n-1)为上次滤波输出值;Y(n)为本次滤波输出值,q为滤波系数
* q值越小则上一次输出对本次输出影响越大,整体曲线越平稳,但是对于速度变化的响应也会越慢
*/
g_motor_data.speed = (float)( ((float)0.48 * temp) + (g_motor_data.speed * (float)0.52) );
k = 0;
}
sp_count = 0;
}
sp_count ++;
}
/*****************************************************************************************
* 函数名称: Adc1mSRoutine
* 功能描述: Adc 1毫秒服务函数
* 参 数: 无
* 返 回 值: 无
*****************************************************************************************/
bool AdcInitStatus = false; //ADC初始化状态标志位
bool AdcInitSta = false; //ADC电流电压采集初始化标志位
uint16_t AdcDly = 0; //ADC采样定时计数
void Adc1mSRoutine(void)
{
if(AdcInitStatus == false)
AdcInitStatus = true;
if(AdcInitSta == true)
{
ADC_Start();
}
if(AdcDly > 0)
AdcDly--;
}
/*****************************************************************************************
* 函数名称: AdcLoopHander
* 功能描述: Adc主循环函数
* 参 数: 无
* 返 回 值: 无
*****************************************************************************************/
void AdcLoopHander(void)
{
float temp_c = 0.0;
//开机等待电流数据稳定,采集稳定电流值为初始值
if((AdcInitStatus == true) && (AdcInitSta == false))
{
AdcInitCnt++;
ADC_Start();
while(DMA_GetChFlag(M4_DMA1, DmaCh0Sta) != DmaTransferComplete);
init_adc_val += m_au16Adc1SaValue[2u]; /* 现在的值和上一次存储的值相加 */
init_adc_val /= 2; /* 取平均值 */
if(AdcInitCnt < 1000)
{
AdcInitStatus = false;
return;
}
else
{
DCMOTOR_DBG_LOG("init_adc_val %d.\n", init_adc_val);
AdcInitSta = true;
}
}
//计算ADC采样值并滤波
if(AdcDly == 0)
{
float BatVoltage = 0;
AdcDly = 1000;
if(AdcInitSta == true)
{
while(DMA_GetChFlag(M4_DMA1, DmaCh0Sta) != DmaTransferComplete);
DMA_Cmd(M4_DMA1, Disable);
calc_adc_val(g_adc_val); /* 计算ADC的平均值 */
DCMOTOR_DBG_LOG("ADC1_IN1 value %d.\t Temp:%.1fC \r\n", g_adc_val[0u], get_temp((float)g_adc_val[0]*Adc));
DCMOTOR_DBG_LOG("ADC2_IN2 value %d.\t Valtage:%.1fV \r\n", g_adc_val[1u], (float)g_adc_val[1]*ADC2VBUS);
temp_c = (g_adc_val[2]-init_adc_val)*ADC2CURT;
DCMOTOR_DBG_LOG("ADC3_IN3 value %d.\t Current:%.1fmA \r\n", g_adc_val[2u], temp_c);
g_motor_data.current = (float)((g_motor_data.current * (float)0.60) + ((float)0.40 * temp_c)); /* 一阶低通滤波 */
if (g_motor_data.current <= 20) /* 过滤掉微弱浮动电流 */
{
g_motor_data.current = 0.0;
}
DCMOTOR_DBG_LOG("\t\t\t g_motor_data.current:%.1fmA \r\n", g_adc_val[2u], g_motor_data.current);
DMA_Cmd(M4_DMA1, Enable);
}
}
}
void Timer41_Init(uint8_t dir) void Timer41_Init(uint8_t dir)
{ {
uint8_t E_OC_Port = 0; uint8_t E_OC_Port = 0;
@@ -373,7 +623,7 @@ void dcmotor_init(void)
stcPortInit.enPinMode = Pin_Mode_Out; stcPortInit.enPinMode = Pin_Mode_Out;
stcPortInit.enPinOType = Pin_OType_Cmos; stcPortInit.enPinOType = Pin_OType_Cmos;
stcPortInit.enPinDrv = Pin_Drv_H; stcPortInit.enPinDrv = Pin_Drv_H;
stcPortInit.enPullUp = Disable; stcPortInit.enPullUp = Enable;
PORT_Init(SHUTDOWN1_GPIO_Port, SHUTDOWN1_Pin, &stcPortInit); PORT_Init(SHUTDOWN1_GPIO_Port, SHUTDOWN1_Pin, &stcPortInit);
PORT_SetBits(SHUTDOWN1_GPIO_Port, SHUTDOWN1_Pin); PORT_SetBits(SHUTDOWN1_GPIO_Port, SHUTDOWN1_Pin);
@@ -53,6 +53,29 @@ typedef enum {
/************************************* 第一部分 电压电流温度采集 ******************************/
/* 电流计算公式:
* I=(最终输出电压-初始参考电压)/(6*0.02)A
* ADC值转换为电压值:电压=ADC值*3.3/4096,这里电压单位为V,我们换算成mV,4096/1000=4.096,后面就直接算出为mA
* 整合公式可以得出电流 I= (当前ADC值-初始参考ADC值)* 3.3 / 4.096 / 0.12
*/
#define ADC2CURT (float)(3.3f / 4.096f / 0.12f)
/* 电压计算公式:
* V_POWER = V_BUS * 25
* ADC值转换为电压值:电压=ADC值*3.3/4096
* 整合公式可以得出电压V_POWER= ADC值 *3.3f * 25 / 4096
*/
#define ADC2VBUS (float)(3.3f * 25 / 4096)
/*****************************************************************************************************/
/* 停止引脚操作宏定义 /* 停止引脚操作宏定义
* 此引脚控制H桥是否生效以达到开启和关闭电机的效果 * 此引脚控制H桥是否生效以达到开启和关闭电机的效果
*/ */
@@ -70,6 +93,40 @@ typedef enum {
#endif #endif
/******************************************************************************************/ /******************************************************************************************/
/* 编码器参数结构体 */
typedef struct
{
int encode_old; /* 上一次计数值 */
int encode_now; /* 当前计数值 */
float speed; /* 编码器速度 */
} ENCODE_TypeDef;
extern ENCODE_TypeDef g_encode; /* 编码器参数变量 */
/************************************* 第三部分 编码器测速 ****************************************************/
#define ROTO_RATIO 44 /* 线数*倍频系数,即11*4=44 */
#define REDUCTION_RATIO 30 /* 减速比30:1 */
/* 电机参数结构体 */
typedef struct
{
uint8_t state; /*电机状态*/
float current; /*电机电流*/
float volatage; /*电机电压*/
float power; /*电机功率*/
float speed; /*电机实际速度*/
float location; /*电机位置*/
int32_t motor_pwm; /*设置比较值大小 */
} Motor_TypeDef;
extern Motor_TypeDef g_motor_data; /*电机参数变量*/
/*********************************************************************************************************************/
void dcmotor_init(void); /* 直流有刷电机初始化 */ void dcmotor_init(void); /* 直流有刷电机初始化 */
void dcmotor_start(void); /* 开启电机 */ void dcmotor_start(void); /* 开启电机 */
void dcmotor_stop(void); /* 关闭电机 */ void dcmotor_stop(void); /* 关闭电机 */
@@ -78,6 +135,13 @@ void dcmotor_speed(uint16_t para); /*
void motor_pwm_set(float para); /* 电机控制 */ void motor_pwm_set(float para); /* 电机控制 */
float get_temp(uint16_t para);
void AdcLoopHander(void);
void Adc1mSRoutine(void);
void Adc_Init(void);
void calc_adc_val(uint16_t * p);
void Encoder (void);
MotorDirection Motor_GetDirection(void);/* 获取电机转动方向 */ MotorDirection Motor_GetDirection(void);/* 获取电机转动方向 */
+2 -2
View File
@@ -11,12 +11,12 @@
/*模块启用与关闭*/ /*模块启用与关闭*/
#define USE_DEBUG 1 //DEBUG开关,0、关闭,1、启用 #define USE_DEBUG 1 //DEBUG开关,0、关闭,1、启用
#define USE_AD 0 //AD获取选择,0、关闭,1、启用 #define USE_AD 1 //AD获取选择,0、关闭,1、启用
#define USE_WDT 0 //看门狗选择,0、关闭,1启用 #define USE_WDT 0 //看门狗选择,0、关闭,1启用
#define USE_EXFALSE 0 //外部FALSE存储选择,0、关闭,1、启用 #define USE_EXFALSE 0 //外部FALSE存储选择,0、关闭,1、启用
#define USE_RTC 0 //RTC时钟开关,0、关闭,1、开启 #define USE_RTC 0 //RTC时钟开关,0、关闭,1、开启
#define USE_LPTIM0 0 //LPTIM0开关,0、关闭,1、开启 #define USE_LPTIM0 0 //LPTIM0开关,0、关闭,1、开启
#define USE_DMA 0 //DMA开关,0、关闭,1、开启 #define USE_DMA 1 //DMA开关,0、关闭,1、开启
#define USE_RS485 0 //RS485开关,0、关闭,1、启用 #define USE_RS485 0 //RS485开关,0、关闭,1、启用
#define USE_I2C1 0 //I2C1开关,0、关闭,1、启用 #define USE_I2C1 0 //I2C1开关,0、关闭,1、启用
#define USE_SPI1 0 //SPI1开关,0、关闭,1、启用 #define USE_SPI1 0 //SPI1开关,0、关闭,1、启用
+2 -2
View File
@@ -1359,8 +1359,8 @@ void BSP_Init(void)
//Spi_Config(); //Spi_Config();
// Spi3_Config(); // Spi3_Config();
dcmotor_init(); dcmotor_init();
//Adc1_Config(); Adc1_Config();
//Dma_Config(); Dma_Config();
//FeedDog(); //FeedDog();
SysTick_Init(1000u); SysTick_Init(1000u);
SysTick_Delay(1000); SysTick_Delay(1000);
+2
View File
@@ -596,6 +596,7 @@ int main(void)
RIGHTLOW_CS1237DataLoopCollect(); RIGHTLOW_CS1237DataLoopCollect();
ReadLoopHandler(); ReadLoopHandler();
DcmotorLoopHandler(); DcmotorLoopHandler();
AdcLoopHander();
AppLoopHandler(); AppLoopHandler();
} }
} }
@@ -616,6 +617,7 @@ void SysTick_IrqHandler(void)
RIGHTUP_CS12371mSRoutine(); RIGHTUP_CS12371mSRoutine();
RIGHTLOW_CS12371mSRoutine(); RIGHTLOW_CS12371mSRoutine();
Dcmotor1msRoutine(); Dcmotor1msRoutine();
Adc1mSRoutine();
} }
/***************************************************************************************** /*****************************************************************************************