23 changed files with 926 additions and 838 deletions
-
5.vscode/settings.json
-
248app/MDK-ARM/app.uvguix.h_zha
-
72app/MDK-ARM/app.uvoptx
-
25app/MDK-ARM/app.uvprojx
-
2dep/libiflytop_micro
-
1src/board/device_io_service.cpp
-
3src/board/device_io_service.hpp
-
0src/board/fan_state_monitor.cpp
-
0src/board/fan_state_monitor.hpp
-
148src/board/hardware.cpp
-
36src/board/hardware.hpp
-
35src/board/libtmcimpl.cpp
-
11src/board/libtmcimpl.hpp
-
28src/libtmcimpl.cpp
-
129src/lncubator_temperature_control_service.cpp
-
55src/lncubator_temperature_control_service.hpp
-
2src/project_board.hpp
-
182src/umain.cpp
248
app/MDK-ARM/app.uvguix.h_zha
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1 +1 @@ |
|||
Subproject commit 1be6e0ea5a7193a1eac2460413476302bd9c8dea |
|||
Subproject commit 645e10e79f235ef9a05d3026091d692b18f6b5f8 |
@ -0,0 +1,148 @@ |
|||
#include "hardware.hpp"
|
|||
|
|||
#include "i2c.h"
|
|||
using namespace iflytop; |
|||
#define TAG "hardware"
|
|||
void Hardware::hardwareinit() { |
|||
m_os = &m_deviceIoService; |
|||
/*******************************************************************************
|
|||
* CANSLAVEService初始化 * |
|||
*******************************************************************************/ |
|||
IflytopCanSlave::iflytop_can_slave_config_t *config = canSlaveService.createDefaultConfig(DEVICE_ID); |
|||
canSlaveService.initialize(m_os, config); |
|||
/*******************************************************************************
|
|||
* 帕尔贴初始化 * |
|||
*******************************************************************************/ |
|||
m_deviceIoService.peltier_init(); |
|||
/*******************************************************************************
|
|||
* 温度传感器初始化 * |
|||
*******************************************************************************/ |
|||
tmp117[0].initializate(&hi2c1, TMP117::ID0); |
|||
tmp117[1].initializate(&hi2c1, TMP117::ID1); |
|||
tmp117[2].initializate(&hi2c1, TMP117::ID2); |
|||
tmp117[3].initializate(&hi2c1, TMP117::ID3); |
|||
|
|||
/*******************************************************************************
|
|||
* 电机初始化 * |
|||
*******************************************************************************/ |
|||
m_deviceIoService.tmc_init(); |
|||
m_deviceIoService.tmc_extern_clk_enable(); |
|||
// 4361初始化
|
|||
TMC4361AImpl::TMC4361AConfig_t *tmc4361aconfig = TMC4361AImpl::createDeafultTMC4361AConfig(); |
|||
tmc4361aconfig->base_config.fs_per_rev = 200; |
|||
tmc4361aconfig->encoder_config.diff_enc_in_disable = false; |
|||
tmc4361aconfig->encoder_config.enc_in_res = 4000; |
|||
tmc4361aconfig->close_loop_config.enable_closed_loop = true; |
|||
|
|||
tmc4361motor1.initialize(&m_deviceIoService, MOTOR_1_TMC4361A_CHANNEL, TMC4361A::IC_TMC2160, tmc4361aconfig); |
|||
tmc4361motor1.setMaximumAcceleration(300000); |
|||
tmc4361motor1.setMaximumDeceleration(300000); |
|||
|
|||
// 2160初始化
|
|||
tmc2160motor1.setMaximumCurrent(3); |
|||
tmc2160motor1.initialize(&m_deviceIoService, &tmc4361motor1, MOTOR_1_TMC2160_CHANNEL); |
|||
|
|||
HAL_Delay(100); |
|||
// 使能电机
|
|||
tmc4361motor1.enableIC(true); |
|||
tmc2160motor1.enableIC(true); |
|||
/**
|
|||
* @brief 通过读取Version寄存器来判断芯片是否正常 |
|||
*/ |
|||
int32_t ic4361Version = tmc4361motor1.readICVersion(); |
|||
int32_t ic2160Version = tmc2160motor1.readICVersion(); |
|||
// 期望 4361Version:2 ic2160Version:30
|
|||
ZLOGI(TAG, "TMC4361Version:%x TMC2160VERSION:%x", ic4361Version, ic2160Version); |
|||
if (ic4361Version != 2 || ic2160Version != 30) { |
|||
ZLOGE(TAG, "TMC4361 or TMC2160 is not normal"); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* 风扇初始化 * |
|||
*******************************************************************************/ |
|||
m_deviceIoService.fanInit(1000); |
|||
/**
|
|||
* @brief 风扇反馈初始化 |
|||
* |
|||
* FAN0_FB_INT PC1 |
|||
* FAN1_FB_INT PC4 |
|||
* FAN2_FB_INT PC5 |
|||
* FAN3_FB_INT PC6 |
|||
* FAN4_FB_INT PC7 |
|||
* FAN5_FB_INT PC10 |
|||
*/ |
|||
|
|||
m_fanStateMonitor[0].initialize(m_os, GPIOC, GPIO_PIN_1, m_deviceIoService.fanGetPowerState(0)); |
|||
m_fanStateMonitor[1].initialize(m_os, GPIOC, GPIO_PIN_4, m_deviceIoService.fanGetPowerState(1)); |
|||
m_fanStateMonitor[2].initialize(m_os, GPIOC, GPIO_PIN_5, m_deviceIoService.fanGetPowerState(2)); |
|||
m_fanStateMonitor[3].initialize(m_os, GPIOC, GPIO_PIN_6, m_deviceIoService.fanGetPowerState(3)); |
|||
m_fanStateMonitor[4].initialize(m_os, GPIOC, GPIO_PIN_7, m_deviceIoService.fanGetPowerState(4)); |
|||
m_fanStateMonitor[5].initialize(m_os, GPIOC, GPIO_PIN_10, m_deviceIoService.fanGetPowerState(5)); |
|||
} |
|||
void Hardware::periodicJob() { |
|||
/**
|
|||
* @brief 风扇状态监控服务周期调度 |
|||
*/ |
|||
for (size_t i = 0; i < ZARRAY_SIZE(m_fanStateMonitor); i++) { |
|||
m_fanStateMonitor[i].periodicJob(); |
|||
} |
|||
do_debug_light_state(); |
|||
} |
|||
void Hardware::do_debug_light_state() { |
|||
static uint32_t lastprocess = 0; |
|||
if (sys_haspassedms(lastprocess) > 300) { |
|||
lastprocess = HAL_GetTick(); |
|||
HAL_GPIO_TogglePin(DEBUG_LIGHT_PORT, DEBUG_LIGHT_PIN); |
|||
} |
|||
} |
|||
/*******************************************************************************
|
|||
* 硬件测试 * |
|||
*******************************************************************************/ |
|||
void Hardware::testTmp117() { |
|||
static uint32_t lastcall; |
|||
if (m_os->hasPassedMS(lastcall) > 1000) { |
|||
lastcall = m_os->getTicket(); |
|||
for (size_t i = 0; i < 4; i++) { |
|||
float temp = tmp117[i].getTemperature(); |
|||
if (tmp117[i].getLastCallStatus() == HAL_OK) { |
|||
ZLOGI(TAG, "tmp117_%d:%f", i, temp); |
|||
} else { |
|||
ZLOGI(TAG, "tmp117_%d:read fail", i); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/**
|
|||
* @brief 测试CAN的发送和接收 |
|||
*/ |
|||
void Hardware::testCanSlaveTxAndRx(bool canOnRxDataFlag) { |
|||
{ |
|||
static uint32_t lastcall; |
|||
static uint8_t tx[8] = {1, 2, 3, 4, 5, 6, 7, 8}; |
|||
if (m_os->hasPassedMS(lastcall) > 1000) { |
|||
lastcall = m_os->getTicket(); |
|||
canSlaveService.translate(0x01, tx, 8, 2); |
|||
if (canSlaveService.getLastTransmitStatus() == HAL_OK) { |
|||
ZLOGI(TAG, "send ok"); |
|||
} else { |
|||
ZLOGI(TAG, "send fail"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/**
|
|||
* @brief 接收CAN消息 |
|||
*/ |
|||
if (canOnRxDataFlag) { |
|||
canOnRxDataFlag = false; |
|||
static CAN_RxHeaderTypeDef packetHeader; |
|||
static uint8_t packetData[8]; |
|||
while (canSlaveService.getRxMessage(&packetHeader, packetData)) { |
|||
ZLOGI(TAG, "rx packet:"); |
|||
ZLOGI(TAG, "\tid:%x len:%d", packetHeader.StdId, packetHeader.DLC); |
|||
ZLOGI_HEX(TAG, packetData, packetHeader.DLC); |
|||
} |
|||
canSlaveService.activateRxIT(); |
|||
} |
|||
} |
@ -0,0 +1,36 @@ |
|||
|
|||
#pragma once
|
|||
#include "board/device_io_service.hpp"
|
|||
#include "board/fan_state_monitor.hpp"
|
|||
#include "board/libtmcimpl.hpp"
|
|||
#include "libiflytop_micro\stm32\component\iflytop_can_slave_v1\iflytop_can_slave.hpp"
|
|||
#include "libiflytop_micro\stm32\component\tmp117\tmp117.hpp"
|
|||
|
|||
namespace iflytop { |
|||
class Hardware { |
|||
private: |
|||
/* data */ |
|||
public: |
|||
TMC4361AImpl tmc4361motor1; |
|||
TMC2160Impl tmc2160motor1; |
|||
TMP117 tmp117[4]; |
|||
FanStateMonitor m_fanStateMonitor[6]; |
|||
IflytopCanSlave canSlaveService; |
|||
IflytopMicroOS* m_os; |
|||
DeviceIoService m_deviceIoService; |
|||
|
|||
Hardware(/* args */){}; |
|||
~Hardware(){}; |
|||
|
|||
void hardwareinit(); |
|||
void periodicJob(); |
|||
|
|||
/*******************************************************************************
|
|||
* 测试 * |
|||
*******************************************************************************/ |
|||
void testTmp117(); |
|||
void testCanSlaveTxAndRx(bool canOnRxDataFlag); |
|||
void do_debug_light_state(); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
@ -0,0 +1,35 @@ |
|||
#pragma once
|
|||
#include "libtmcimpl.hpp"
|
|||
|
|||
#include "device_io_service.hpp"
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
/*******************************************************************************
|
|||
* TMC4361AImpl * |
|||
*******************************************************************************/ |
|||
void TMC4361AImpl::setResetPinState(bool state) { m_deviceIoService->tmc_nRESET_pin_set_state(m_channel, state); }; |
|||
void TMC4361AImpl::setFREEZEPinState(bool state) { m_deviceIoService->tmc_nFREEZE_pin_set_state(m_channel, state); }; |
|||
void TMC4361AImpl::setENNPinState(bool state) { m_deviceIoService->tmc_ENN_pin_set_state(m_channel, state); }; |
|||
bool TMC4361AImpl::getTargetReachedPinState() { return false; }; |
|||
void TMC4361AImpl::sleepus(int32_t us) { m_deviceIoService->sleepus(us); }; |
|||
void TMC4361AImpl::readWriteArray(uint8_t *data, size_t length) { //
|
|||
m_deviceIoService->tmc_motor_spi_write_and_read(m_channel, data, length); |
|||
}; |
|||
|
|||
void TMC4361AImpl::initialize(DeviceIoService *deviceIoService, uint8_t channel, driver_ic_type_t driver_ic_type, TMC4361AConfig_t *config) { |
|||
m_deviceIoService = deviceIoService; |
|||
TMC4361A::initialize(channel, driver_ic_type, config); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* TMC2160Impl * |
|||
*******************************************************************************/ |
|||
void TMC2160Impl::initialize(DeviceIoService *deviceIoService, TMC4361A *tmc4361, uint8_t channelId) { |
|||
m_tmc4361 = tmc4361; |
|||
m_deviceIoService = deviceIoService; |
|||
TMC2160::initialize(channelId); |
|||
} |
|||
void TMC2160Impl::setENNPinState(bool state) { m_deviceIoService->tmc_ENN_pin_set_state(m_channel, state); }; |
|||
void TMC2160Impl::sleepus(int32_t us) { m_deviceIoService->sleepus(us); }; |
|||
void TMC2160Impl::readWriteArray(uint8_t *data, size_t length) { m_tmc4361->readWriteCover(data, length); }; |
|||
} // namespace iflytop
|
@ -1,28 +0,0 @@ |
|||
#pragma once
|
|||
#include "libtmcimpl.hpp"
|
|||
|
|||
#include "device_io_service.hpp"
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
/*******************************************************************************
|
|||
* TMC4361AImpl * |
|||
*******************************************************************************/ |
|||
void TMC4361AImpl::setResetPinState(bool state) { deviceIoService.tmc_nRESET_pin_set_state(m_channel, state); }; |
|||
void TMC4361AImpl::setFREEZEPinState(bool state) { deviceIoService.tmc_nFREEZE_pin_set_state(m_channel, state); }; |
|||
void TMC4361AImpl::setENNPinState(bool state) { deviceIoService.tmc_ENN_pin_set_state(m_channel, state); }; |
|||
bool TMC4361AImpl::getTargetReachedPinState() { return false; }; |
|||
void TMC4361AImpl::sleepus(int32_t us) { deviceIoService.sleepus(us); }; |
|||
void TMC4361AImpl::readWriteArray(uint8_t *data, size_t length) { //
|
|||
deviceIoService.tmc_motor_spi_write_and_read(m_channel, data, length); |
|||
}; |
|||
/*******************************************************************************
|
|||
* TMC2160Impl * |
|||
*******************************************************************************/ |
|||
void TMC2160Impl::initialize(uint8_t channel, TMC4361A *tmc4361) { |
|||
m_tmc4361 = tmc4361; |
|||
TMC2160::initialize(channel); |
|||
} |
|||
void TMC2160Impl::setENNPinState(bool state) { deviceIoService.tmc_ENN_pin_set_state(m_channel, state); }; |
|||
void TMC2160Impl::sleepus(int32_t us) { deviceIoService.sleepus(us); }; |
|||
void TMC2160Impl::readWriteArray(uint8_t *data, size_t length) { m_tmc4361->readWriteCover(data, length); }; |
|||
} // namespace iflytop
|
@ -0,0 +1,129 @@ |
|||
#include "lncubator_temperature_control_service.hpp"
|
|||
using namespace iflytop; |
|||
#define TAG "LTCS"
|
|||
|
|||
const int LncubatorTemperatureControlService::m_compute_periodms = 1000; |
|||
const float LncubatorTemperatureControlService::m_error_limit = 50; |
|||
const float LncubatorTemperatureControlService::m_kp = 30; |
|||
const float LncubatorTemperatureControlService::m_ki = 1; |
|||
const float LncubatorTemperatureControlService::m_kd = 0; |
|||
const float LncubatorTemperatureControlService::m_max_output = 100; |
|||
const float LncubatorTemperatureControlService::m_min_output = -100; |
|||
const bool LncubatorTemperatureControlService::m_dumpvalue = false; |
|||
|
|||
void LncubatorTemperatureControlService::initialize(Hardware* hardware) { |
|||
#if 0
|
|||
pid_ctrl_config_t m_init_config; |
|||
pid_ctrl_block_handle_t m_pidblock; |
|||
IflytopMicroOS* m_os; |
|||
float m_nowoutput = 0; |
|||
bool m_workingState; |
|||
#endif
|
|||
|
|||
m_init_config.init_param.kp = 30; |
|||
m_init_config.init_param.ki = 1; |
|||
m_init_config.init_param.kd = 0; |
|||
m_init_config.init_param.cal_type = PID_CAL_TYPE_POSITIONAL; |
|||
m_init_config.init_param.max_output = m_max_output; |
|||
m_init_config.init_param.min_output = m_min_output; |
|||
m_init_config.init_param.max_integral = m_error_limit; |
|||
m_init_config.init_param.min_integral = -m_error_limit; |
|||
|
|||
pid_new_control_block(&m_init_config, &m_pidblock); |
|||
ZASSERT(m_pidblock != NULL); |
|||
m_hardware = hardware; |
|||
m_nowoutput = 0; |
|||
|
|||
m_target_temperature = 25; |
|||
|
|||
m_periodicJobLastExecuteTicket = 0; |
|||
} |
|||
|
|||
void LncubatorTemperatureControlService::setTargetTemperature(int targetTemperature) { //
|
|||
m_target_temperature = targetTemperature; |
|||
} |
|||
void LncubatorTemperatureControlService::setPidKp(float value) { |
|||
m_init_config.init_param.kp = value; |
|||
pid_update_parameters(m_pidblock, &m_init_config.init_param); |
|||
} |
|||
void LncubatorTemperatureControlService::setPidKi(float value) { |
|||
m_init_config.init_param.ki = value; |
|||
pid_update_parameters(m_pidblock, &m_init_config.init_param); |
|||
} |
|||
void LncubatorTemperatureControlService::setPidKd(float value) { |
|||
m_init_config.init_param.kd = value; |
|||
pid_update_parameters(m_pidblock, &m_init_config.init_param); |
|||
} |
|||
|
|||
void LncubatorTemperatureControlService::setPidParameters(float kp, float ki, float kd) { |
|||
m_init_config.init_param.kp = kp; |
|||
m_init_config.init_param.ki = ki; |
|||
m_init_config.init_param.kd = kd; |
|||
pid_update_parameters(m_pidblock, &m_init_config.init_param); |
|||
} |
|||
float LncubatorTemperatureControlService::getTemperature() { |
|||
float temperature[4]; |
|||
temperature[0] = m_hardware->tmp117[0].getTemperature(); |
|||
temperature[1] = m_hardware->tmp117[1].getTemperature(); |
|||
temperature[2] = m_hardware->tmp117[2].getTemperature(); |
|||
temperature[3] = m_hardware->tmp117[3].getTemperature(); |
|||
|
|||
float temperature_median = 0; |
|||
// 取温度的中位数
|
|||
for (int i = 0; i < 4; i++) { |
|||
for (int j = i + 1; j < 4; j++) { |
|||
if (temperature[i] > temperature[j]) { |
|||
float temp = temperature[i]; |
|||
temperature[i] = temperature[j]; |
|||
temperature[j] = temp; |
|||
} |
|||
} |
|||
} |
|||
temperature_median = (temperature[1] + temperature[2]) / 2; |
|||
return temperature_median; |
|||
} |
|||
void LncubatorTemperatureControlService::setPwmOutput(float output) { m_hardware->m_deviceIoService.peltier_set_pwm(output); } |
|||
|
|||
void LncubatorTemperatureControlService::start() { |
|||
pid_reset(m_pidblock); |
|||
/**
|
|||
* @brief |
|||
* 启动时,之所以将积分极限积分,主要是因为正常使用时,温度基本上是从20度开始,加热过程中积分通常会累计到极限值, |
|||
* 同时为了方便确定当前PID参数是否正确,需要多次测试到达目标温度后,曲线是否稳定,但每次测试降低温度温度到室温 |
|||
* 很耽误时间,所以这里直接将积分拉满,这样就不需要降低温度就能测试PID参数了。 |
|||
*/ |
|||
pid_set_integral_err(m_pidblock, m_error_limit); |
|||
m_workingState = true; |
|||
} |
|||
void LncubatorTemperatureControlService::stop() {} |
|||
|
|||
void LncubatorTemperatureControlService::periodicJob() { |
|||
if (!m_workingState) return; |
|||
if (m_hardware->m_os->hasPassedMS(m_periodicJobLastExecuteTicket) < m_compute_periodms) { |
|||
return; |
|||
} |
|||
m_periodicJobLastExecuteTicket = m_os->getTicket(); |
|||
|
|||
float current_temperature = getTemperature(); |
|||
float output = 0; |
|||
pid_compute(m_pidblock, m_target_temperature - current_temperature, &output); |
|||
pwmOutputFilter(output, &m_nowoutput); |
|||
if (m_dumpvalue) { |
|||
ZLOGI(TAG, "%.2f,%.2f,%.2f,%.2f", m_target_temperature, current_temperature, pid_get_integral_err(m_pidblock), m_nowoutput); |
|||
} |
|||
setPwmOutput(m_nowoutput); |
|||
} |
|||
|
|||
void LncubatorTemperatureControlService::pwmOutputFilter(float now, float* output) { |
|||
/**
|
|||
* @brief 控制PWM输出最多以每次10的步进进行变化 |
|||
*/ |
|||
if (now > *output) { |
|||
*output += 10; |
|||
if (*output > now) { |
|||
*output = now; |
|||
} |
|||
} else if (now < *output) { |
|||
*output = now; |
|||
} |
|||
} |
@ -0,0 +1,55 @@ |
|||
#pragma once
|
|||
#include "board/device_io_service.hpp"
|
|||
#include "board\hardware.hpp"
|
|||
#include "libiflytop_micro\stm32\basic\iflytop_micro_os.hpp"
|
|||
#include "libiflytop_micro\stm32\component\pid\pid_ctrl.h"
|
|||
#include "libiflytop_micro\stm32\component\tmp117\tmp117.hpp"
|
|||
namespace iflytop { |
|||
|
|||
class LncubatorTemperatureControlService { |
|||
/*******************************************************************************
|
|||
* Config * |
|||
*******************************************************************************/ |
|||
static const int m_compute_periodms; |
|||
static const float m_error_limit; |
|||
static const float m_kp; |
|||
static const float m_ki; |
|||
static const float m_kd; |
|||
static const float m_max_output; |
|||
static const float m_min_output; |
|||
static const bool m_dumpvalue; |
|||
|
|||
pid_ctrl_config_t m_init_config; |
|||
pid_ctrl_block_handle_t m_pidblock; |
|||
Hardware* m_hardware; |
|||
IflytopMicroOS* m_os; |
|||
float m_nowoutput; |
|||
bool m_workingState; |
|||
float m_target_temperature; |
|||
|
|||
uint32_t m_periodicJobLastExecuteTicket; |
|||
|
|||
public: |
|||
void initialize(Hardware* hardware); |
|||
|
|||
void setPidParameters(float kp, float ki, float kd); |
|||
void setPidKp(float value); |
|||
void setPidKi(float value); |
|||
void setPidKd(float value); |
|||
void setTargetTemperature(int targetTemperature); |
|||
|
|||
void start(); |
|||
void stop(); |
|||
|
|||
/**
|
|||
* @brief 主循环中尽可能多的机会调用该方法 |
|||
*/ |
|||
void periodicJob(); |
|||
|
|||
private: |
|||
void pwmOutputFilter(float now, float* output); |
|||
float getTemperature(); |
|||
void setPwmOutput(float output); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue