919 lines
28 KiB
C
919 lines
28 KiB
C
/*
|
||
* @Author: shenghao.xu
|
||
* @Date: 2023-04-04 08:17:16
|
||
* @LastEditors: shenghao.xu
|
||
* @LastEditTime: 2023-07-04 13:15:43
|
||
* @Description:
|
||
* email:545403892@qq.com
|
||
* Copyright (c) 2023 by shenghao.xu, All Rights Reserved.
|
||
*/
|
||
#include "app.h"
|
||
|
||
#ifdef STM32
|
||
#include "sys.h"
|
||
#include "uart.h"
|
||
#include "flash.h"
|
||
#include "board.h"
|
||
#include "easyflash.h"
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#endif
|
||
|
||
static bool reset_flag = false; // 设备复位软标记
|
||
uint16_t ip_dac_value = 0; // IP转换器电流值uA
|
||
float32 ip_pwm_duty = 0; // IP转换器PWM值
|
||
uint16_t proportional_valve_dac_value = 0; // 比例阀压力值
|
||
bool pid_pressure_flag = false; // 压力传感器PID标记,当该标志位true时需要根据压力传感器的值进行PID控制
|
||
sensor_bits_e pid_pressure_no; // PID压力传感器设备编号
|
||
|
||
static data_interupt_cb_t uart_data_analysis_cb = NULL; // 数据解析回调
|
||
|
||
volatile app_t app; // APP全局变量
|
||
|
||
agreement_req_cb_t agreement_req_cb;
|
||
|
||
static void get_sensor_pressure_data(const sensor_bits_e sensor_bits, float32_t *ptr);
|
||
// 初始化传感器
|
||
static void sensor_init(void)
|
||
{
|
||
ip_dac_value = 0;
|
||
proportional_valve_dac_value = 0;
|
||
app.adc.ip_in6.is_open = true;
|
||
app.adc.proportional_valve_in1.is_open = true;
|
||
app.relay.data = 0;
|
||
app.process_state.process_index = 0;
|
||
app.process_state.plan_index = 0;
|
||
app.process_state.action_index = 0;
|
||
pid_pressure_no.data = 0;
|
||
}
|
||
|
||
static void flash_write_address(void)
|
||
{
|
||
#ifdef STM32
|
||
hal_int_state_t s;
|
||
HAL_ENTER_CRITICAL(s);
|
||
flash_write_no_buffer(FLASH_DEVICE_ADDRESS, (uint32_t *)&app.device_address, sizeof(app.device_address));
|
||
HAL_EXIT_CRITICAL(s);
|
||
#endif
|
||
}
|
||
|
||
static void flash_write_ip_mode(void)
|
||
{
|
||
#ifdef STM32
|
||
hal_int_state_t s;
|
||
HAL_ENTER_CRITICAL(s);
|
||
flash_write_no_buffer(FLASH_IP_OUT_MODE_ADDRESS, (uint32_t *)&app.ip_out_mode, sizeof(app.ip_out_mode));
|
||
HAL_EXIT_CRITICAL(s);
|
||
#endif
|
||
}
|
||
|
||
static void flash_write_ip_pwm_frequency(void)
|
||
{
|
||
#ifdef STM32
|
||
hal_int_state_t s;
|
||
HAL_ENTER_CRITICAL(s);
|
||
flash_write_no_buffer(FLASH_IP_OUT_PWM_FREQUENCY_ADDRESS, (uint32_t *)&app.ip_out_pwm_frequency, sizeof(app.ip_out_pwm_frequency));
|
||
HAL_EXIT_CRITICAL(s);
|
||
#endif
|
||
}
|
||
|
||
static void flash_write_process_config(config_t config)
|
||
{
|
||
#ifdef STM32
|
||
pbuf_t *pbuf = pbuf_allocz(LARGE_PBUF_BUFFER_SIZE __PLINE1);
|
||
DBG_ASSERT(pbuf != NULL __DBG_LINE);
|
||
pbuf->data_len += 2; // 偏移2个字节用来在flash中存储长度
|
||
config_convert_pbuf(config, &pbuf);
|
||
if (pbuf->data_len > 0)
|
||
{
|
||
osel_memcpy(&pbuf->data_p[0], (uint8_t *)&pbuf->data_len, 2);
|
||
hal_int_state_t s;
|
||
HAL_ENTER_CRITICAL(s);
|
||
flash_write_no_buffer(FLASH_PROCESS_CONFIG, (uint32_t *)&pbuf->data_p[0], pbuf->data_len);
|
||
HAL_EXIT_CRITICAL(s);
|
||
}
|
||
|
||
pbuf_freez(&pbuf __PLINE2);
|
||
#endif
|
||
}
|
||
|
||
void flash_load(void)
|
||
{
|
||
#ifdef STM32
|
||
flash_read_byte(FLASH_IP_OUT_MODE_ADDRESS, (uint8_t *)&app.ip_out_mode, sizeof(uint8_t));
|
||
if (app.ip_out_mode != IP_OUT_PWM && app.ip_out_mode != IP_OUT_DAC)
|
||
{
|
||
app.ip_out_mode = IP_OUT_DAC;
|
||
}
|
||
|
||
flash_read_byte(FLASH_IP_OUT_PWM_FREQUENCY_ADDRESS, (uint8_t *)&app.ip_out_pwm_frequency, sizeof(uint8_t));
|
||
if (app.ip_out_pwm_frequency == 0)
|
||
{
|
||
app.ip_out_pwm_frequency = 20;
|
||
}
|
||
|
||
flash_read_byte(FLASH_DEVICE_ADDRESS, (uint8_t *)&app.device_address, sizeof(app.device_address));
|
||
if (app.device_address == 0)
|
||
{
|
||
app.device_address = 1;
|
||
}
|
||
|
||
pbuf_t *pbuf = pbuf_allocz(LARGE_PBUF_BUFFER_SIZE __PLINE1);
|
||
DBG_ASSERT(pbuf != NULL __DBG_LINE);
|
||
uint16_t size = 0, offset = 2;
|
||
if (flash_read_byte(FLASH_PROCESS_CONFIG, (uint8_t *)&size, offset))
|
||
{
|
||
if (size > 0 && size < LARGE_PBUF_BUFFER_SIZE)
|
||
{
|
||
if (flash_read_byte(FLASH_PROCESS_CONFIG + offset, pbuf->data_p, size))
|
||
{
|
||
pbuf->data_len = size;
|
||
data_convert_config(pbuf->data_p, size);
|
||
}
|
||
}
|
||
}
|
||
pbuf_freez(&pbuf __PLINE2);
|
||
#endif
|
||
}
|
||
|
||
// 需要复位
|
||
bool need_reset(void)
|
||
{
|
||
return reset_flag;
|
||
}
|
||
|
||
// 获取IP转换器需要设置的电流值
|
||
uint32_t get_ip_dac_out(void)
|
||
{
|
||
// DAC = val / 1000*37*20.3/1000/3*4096 Imax=4.00mA
|
||
// DAC = (val *37*20.3*4096)/3000000
|
||
float64 ip_tmp = 0;
|
||
#if PID_IP == 0
|
||
ip_tmp = ip_dac_value; // μA
|
||
#else
|
||
#ifdef STM32
|
||
ip_tmp = pid_position_control(XDAC_CHANNEL_2, ip_dac_value, get_ip_adc_in(app.adc.ip_in6.original_value).f);
|
||
#endif
|
||
#endif
|
||
|
||
if (ip_tmp > (4000))
|
||
{
|
||
ip_tmp = 4000;
|
||
}
|
||
else if (ip_tmp < 0)
|
||
{
|
||
ip_tmp = 0;
|
||
}
|
||
|
||
ip_tmp = (ip_tmp * 3076505.6) / 3000000;
|
||
return ip_tmp;
|
||
}
|
||
|
||
float32_t get_ip_adc_in(uint32_t adc_val)
|
||
{
|
||
// current =(adc/4096)*300/48
|
||
float32_t f;
|
||
if (adc_val == 0)
|
||
{
|
||
f.f = 0;
|
||
}
|
||
else
|
||
{
|
||
float64 tmp = adc_val;
|
||
tmp = (tmp * 300000) / 196608;
|
||
f.f = (int32_t)tmp;
|
||
}
|
||
return f;
|
||
}
|
||
|
||
uint32_t get_proportional_valve_dac_out(void)
|
||
{
|
||
/**
|
||
* 电流 0-20mA,电阻15k,最大电压3V
|
||
* 压力和电流关系 电流值 = (压力值 - 最小压力值) * (最大电流值 - 最小电流值) / (最大压力值 - 最小压力值) + 最小电流值 => mA = (p - 0) * (20 - 4) / (900 - 0) + 4
|
||
* mA和DAC关系 mA = (DAC/4096)*3*1000*10/1500
|
||
* 推导关系转化 (p - PROPORTIONAL_VALVE_MIN) * (20 - 4) / (PROPORTIONAL_VALVE_MAX -PROPORTIONAL_VALVE_MIN) + 4 = (DAC/4096)*3*1000*10/1500
|
||
* DAC = (((p - PROPORTIONAL_VALVE_MIN) * (20 - 4) / (PROPORTIONAL_VALVE_MAX -PROPORTIONAL_VALVE_MIN) + 4)*1500)*4096/(3*1000*10)
|
||
* 简化后的关系 DAC = ((p - PROPORTIONAL_VALVE_MIN) / (PROPORTIONAL_VALVE_MAX - PROPORTIONAL_VALVE_MIN) * 16 + 4) * 204.8
|
||
*/
|
||
if (proportional_valve_dac_value == 0)
|
||
{
|
||
return 0;
|
||
}
|
||
float32 tmp;
|
||
|
||
// float32 tmp = proportional_valve_dac_value;
|
||
#ifdef STM32
|
||
if (pid_pressure_flag)
|
||
{
|
||
float32_t f;
|
||
get_sensor_pressure_data(pid_pressure_no, &f);
|
||
tmp = pid_position_control(XDAC_CHANNEL_1, proportional_valve_dac_value, f.f);
|
||
}
|
||
else
|
||
{
|
||
tmp = pid_position_control(XDAC_CHANNEL_1, proportional_valve_dac_value, get_proportional_valve_adc_in(app.adc.proportional_valve_in1.original_value).f);
|
||
}
|
||
|
||
#endif
|
||
|
||
if (tmp > PROPORTIONAL_VALVE_MAX)
|
||
{
|
||
tmp = PROPORTIONAL_VALVE_MAX;
|
||
}
|
||
else if (tmp < PROPORTIONAL_VALVE_MIN)
|
||
{
|
||
tmp = PROPORTIONAL_VALVE_MIN;
|
||
}
|
||
|
||
return ((tmp - PROPORTIONAL_VALVE_MIN) / (PROPORTIONAL_VALVE_MAX - PROPORTIONAL_VALVE_MIN) * 16 + 4) * 204.8;
|
||
}
|
||
|
||
// 获取比例阀压力值
|
||
float32_t get_proportional_valve_adc_in(uint32_t adc_val)
|
||
{
|
||
/**
|
||
* ITV-2050-012N 模拟输出电压1-5V,单片机分压后到ADC的电压1-2.5V
|
||
* 压力和电压关系 v = (p - PROPORTIONAL_VALVE_MIN) * (5 - 1) / (PROPORTIONAL_VALVE_MAX - PROPORTIONAL_VALVE_MIN) + 1
|
||
* 电压和ADC关系 v = ADC*3*2/4096
|
||
* 推导关系转化 (p - PROPORTIONAL_VALVE_MIN) * 4 / (PROPORTIONAL_VALVE_MAX - PROPORTIONAL_VALVE_MIN) + 1 = ADC*3*2/4096
|
||
* 简化后的关系 p = (ADC*6/4096 -1)* (PROPORTIONAL_VALVE_MAX - PROPORTIONAL_VALVE_MIN)/4 + PROPORTIONAL_VALVE_MIN
|
||
*/
|
||
float32_t f;
|
||
float32 tmp = adc_val;
|
||
if ((tmp * 6 / 4096) < 0.9)
|
||
{
|
||
f.f = 0;
|
||
}
|
||
else
|
||
{
|
||
f.f = (int32_t)((tmp * 6 / 4096 - 1) * (PROPORTIONAL_VALVE_MAX - PROPORTIONAL_VALVE_MIN) / 4 + PROPORTIONAL_VALVE_MIN);
|
||
}
|
||
|
||
return f;
|
||
}
|
||
|
||
// 获取压力传感器的值
|
||
float32_t get_pressure_sensor_adc_in(int32_t adc_val)
|
||
{
|
||
/**
|
||
* DP-100压力范围-100-1000kPa,输出电流2.4-20mA
|
||
* 电流和压力关系 电流值 = (压力值 - 最小压力值) * (最大电流值 - 最小电流值) / (最大压力值 - 最小压力值) + 最小电流值 => mA = (p - -100) * (20 - 2.4) / (1000 - -100) + 2.4
|
||
* mA和DAC关系 mA = adc*3000/4096*10*15
|
||
* 推导关系转化 (p - PRESURE_SENSOR_MIN) * (20 - 2.4) / (PRESURE_SENSOR_MAX - PRESURE_SENSOR_MIN) + 2.4 = adc*3000/4096*10*15
|
||
* => p = (adc*3000/4096*10*15 - 2.4) * (PRESURE_SENSOR_MAX - PRESURE_SENSOR_MIN) / (20 - 2.4) + PRESURE_SENSOR_MIN
|
||
* 简化后的关系 p = (adc*30/6144 - 2.4) * (PRESURE_SENSOR_MAX - PRESURE_SENSOR_MIN) / 17.6 + PRESURE_SENSOR_MIN
|
||
*/
|
||
float32_t f;
|
||
float32 tmp = adc_val;
|
||
if (((tmp * 30) / 6144) < 2.3)
|
||
{
|
||
f.f = 0;
|
||
}
|
||
else
|
||
{
|
||
f.f = (int32_t)((tmp * 30 / 6144 - 2.4) * (PRESURE_SENSOR_MAX - PRESURE_SENSOR_MIN) / 17.6 + PRESURE_SENSOR_MIN);
|
||
}
|
||
if (f.f < 0)
|
||
{
|
||
f.f = 0;
|
||
}
|
||
return f;
|
||
}
|
||
|
||
// 获取小回路值
|
||
float32_t get_minor_loop_adc_in(int32_t adc_val)
|
||
{
|
||
float32_t f;
|
||
float32 tmp = adc_val;
|
||
f.f = tmp * 3 / 4096;
|
||
return f;
|
||
}
|
||
|
||
// 获取阀门种类对应的继电器状态
|
||
static uint8_t get_value_unit_state(unit_e unit)
|
||
{
|
||
uint8_t state = 0;
|
||
if (unit == UNIT_TWO_WAY_VALVE)
|
||
{
|
||
for (uint8_t i = 1; i < 9; i++)
|
||
{
|
||
switch (i)
|
||
{
|
||
case 1:
|
||
state = (app.relay.bits.r1 == 1) ? (state | 0x01) : (state & ~0x01);
|
||
break;
|
||
case 2:
|
||
state = (app.relay.bits.r2 == 1) ? (state | 0x02) : (state & ~0x02);
|
||
break;
|
||
case 3:
|
||
state = (app.relay.bits.r3 == 1) ? (state | 0x04) : (state & ~0x04);
|
||
break;
|
||
case 4:
|
||
state = (app.relay.bits.r6 == 1) ? (state | 0x08) : (state & ~0x08);
|
||
break;
|
||
case 5:
|
||
state = (app.relay.bits.r7 == 1) ? (state | 0x10) : (state & ~0x10);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else if (unit == UNIT_THREE_WAY_VALVE)
|
||
{
|
||
for (uint8_t i = 1; i < 9; i++)
|
||
{
|
||
switch (i)
|
||
{
|
||
case 1:
|
||
state = (app.relay.bits.r4 == 1) ? (state | 0x01) : (state & ~0x01);
|
||
break;
|
||
case 2:
|
||
state = (app.relay.bits.r5 == 1) ? (state | 0x02) : (state & ~0x02);
|
||
break;
|
||
case 3:
|
||
state = (app.relay.bits.r8 == 1) ? (state | 0x04) : (state & ~0x04);
|
||
break;
|
||
case 4:
|
||
state = (app.relay.bits.r9 == 1) ? (state | 0x08) : (state & ~0x08);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return state;
|
||
}
|
||
|
||
// 设置阀门状态
|
||
void set_valve_status(unit_e unit, uint8_t index, uint8_t status)
|
||
{
|
||
if (unit == UNIT_TWO_WAY_VALVE)
|
||
{
|
||
switch (index)
|
||
{
|
||
case 1:
|
||
app.relay.bits.r1 = status;
|
||
break;
|
||
case 2:
|
||
app.relay.bits.r2 = status;
|
||
break;
|
||
case 3:
|
||
app.relay.bits.r3 = status;
|
||
break;
|
||
case 4:
|
||
app.relay.bits.r6 = status;
|
||
break;
|
||
case 5:
|
||
app.relay.bits.r7 = status;
|
||
break;
|
||
}
|
||
}
|
||
else if (unit == UNIT_THREE_WAY_VALVE)
|
||
{
|
||
switch (index)
|
||
{
|
||
case 1:
|
||
app.relay.bits.r4 = status == 1 ? LEFT_VALVE : RIGHT_VALVE;
|
||
break;
|
||
case 2:
|
||
app.relay.bits.r5 = status == 1 ? LEFT_VALVE : RIGHT_VALVE;
|
||
break;
|
||
case 3:
|
||
app.relay.bits.r8 = status == 1 ? LEFT_VALVE : RIGHT_VALVE;
|
||
break;
|
||
case 4:
|
||
app.relay.bits.r9 = status == 1 ? LEFT_VALVE : RIGHT_VALVE;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
// 标定压力传感器
|
||
static void calibration_sensor_pressure(uint8_t bits)
|
||
{
|
||
for (uint8_t i = 0; i < 8; i++)
|
||
{
|
||
uint8_t bit = bits & (1 << i);
|
||
switch (bit)
|
||
{
|
||
case 1:
|
||
app.adc.presure_in7.is_open = true;
|
||
break;
|
||
case 2:
|
||
app.adc.presure_in8.is_open = true;
|
||
break;
|
||
case 3:
|
||
app.adc.presure_in9.is_open = true;
|
||
break;
|
||
case 4:
|
||
app.adc.presure_in10.is_open = true;
|
||
break;
|
||
case 5:
|
||
app.adc.presure_in11.is_open = true;
|
||
break;
|
||
case 6:
|
||
app.adc.presure_in12.is_open = true;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void calibration_sensor(query_data_t data)
|
||
{
|
||
uint8_t count = data.count;
|
||
for (uint8_t i = 0; i < count; i++)
|
||
{
|
||
uint8_t sensor_class = data.sensors[i].sensor_class;
|
||
uint8_t sensor_bits = data.sensors[i].sensor.data;
|
||
switch (sensor_class)
|
||
{
|
||
case SENSOR_PRESSURE:
|
||
calibration_sensor_pressure(sensor_bits);
|
||
break;
|
||
case SENSOR_FLOW:
|
||
#ifdef STM32
|
||
flowmeter_set_calibration_flag(sensor_bits);
|
||
#endif
|
||
break;
|
||
case SENSOR_LASER:
|
||
#ifdef STM32
|
||
// 激光传感器默认只有一个
|
||
laser_handle.state = LASER_IDEL;
|
||
#endif
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void get_sensor_pressure_data(const sensor_bits_e sensor_bits, float32_t *ptr)
|
||
{
|
||
uint8_t offset = 0;
|
||
if (sensor_bits.bits.sensor_1)
|
||
{
|
||
(ptr + offset)->f = get_pressure_sensor_adc_in(app.adc.presure_in7.original_value - app.adc.presure_in7.calibration_value).f;
|
||
offset++;
|
||
}
|
||
if (sensor_bits.bits.sensor_2)
|
||
{
|
||
(ptr + offset)->f = get_pressure_sensor_adc_in(app.adc.presure_in8.original_value - app.adc.presure_in8.calibration_value).f;
|
||
offset++;
|
||
}
|
||
if (sensor_bits.bits.sensor_3)
|
||
{
|
||
(ptr + offset)->f = get_pressure_sensor_adc_in(app.adc.presure_in9.original_value - app.adc.presure_in9.calibration_value).f;
|
||
offset++;
|
||
}
|
||
if (sensor_bits.bits.sensor_4)
|
||
{
|
||
(ptr + offset)->f = get_pressure_sensor_adc_in(app.adc.presure_in10.original_value - app.adc.presure_in10.calibration_value).f;
|
||
offset++;
|
||
}
|
||
if (sensor_bits.bits.sensor_5)
|
||
{
|
||
(ptr + offset)->f = get_pressure_sensor_adc_in(app.adc.presure_in11.original_value - app.adc.presure_in11.calibration_value).f;
|
||
offset++;
|
||
}
|
||
if (sensor_bits.bits.sensor_6)
|
||
{
|
||
(ptr + offset)->f = get_pressure_sensor_adc_in(app.adc.presure_in12.original_value - app.adc.presure_in12.calibration_value).f;
|
||
offset++;
|
||
}
|
||
}
|
||
|
||
static void get_sensor_flowmeter_data(sensor_bits_e sensor_bits, float32_t *ptr)
|
||
{
|
||
uint8_t offset = 0;
|
||
if (sensor_bits.bits.sensor_1)
|
||
{
|
||
#ifdef STM32
|
||
(ptr + offset)->f = flowmeter_get_flow(0);
|
||
#endif
|
||
offset++;
|
||
}
|
||
|
||
if (sensor_bits.bits.sensor_2)
|
||
{
|
||
#ifdef STM32
|
||
(ptr + offset)->f = flowmeter_get_flow(1);
|
||
#endif
|
||
offset++;
|
||
}
|
||
}
|
||
|
||
static float32_t *get_sensor_data(sensor_e sensor_class, sensor_bits_e sensor_bits)
|
||
{
|
||
static float32_t data[8];
|
||
float32_t *ptr = NULL;
|
||
#ifdef STM32
|
||
step_motor_t *step_motor;
|
||
#endif
|
||
|
||
// initialize data array to 0
|
||
osel_memset((uint8_t *)data, 0, sizeof(data));
|
||
ptr = data;
|
||
switch (sensor_class)
|
||
{
|
||
case SENSOR_PRESSURE:
|
||
// get pressure data
|
||
get_sensor_pressure_data(sensor_bits, ptr);
|
||
break;
|
||
case SENSOR_FLOW:
|
||
// get flowmeter data
|
||
get_sensor_flowmeter_data(sensor_bits, ptr);
|
||
break;
|
||
case SENSOR_TEMPERATURE:
|
||
#ifdef STM32
|
||
data[0] = ntc_get_temp(app.adc.ntc_in12.original_value);
|
||
#endif
|
||
break;
|
||
case SENSOR_LASER:
|
||
#ifdef STM32
|
||
// get laser distance
|
||
data[0].f = laser_handle.distance;
|
||
#endif
|
||
break;
|
||
case SENSOR_MINOR_LOOP:
|
||
#ifdef STM32
|
||
data[0] = get_minor_loop_adc_in(app.adc.minor_loop_in13.original_value);
|
||
#endif
|
||
break;
|
||
case SENSOR_STEP_MOTOR:
|
||
#ifdef STM32
|
||
step_motor = get_step_motor(STEP_MOTOR_1);
|
||
data[0].f = (int)(step_motor->attribute.add_pulse_count * MAX_STEP_ANGLE);
|
||
data[0].f = ABS(data[0].f); // 在当前项目中步进电机反转角度为正值
|
||
#endif
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return data;
|
||
}
|
||
|
||
// 串口发送数据
|
||
static void uart_send_data(uint8_t *data, uint16_t len)
|
||
{
|
||
#ifndef STM32
|
||
LOG_HEX(data, len);
|
||
#else
|
||
UartSend(UART_1, data, len);
|
||
#endif
|
||
}
|
||
|
||
static slave_request_done_t request_done(command_e command, void *data)
|
||
{
|
||
slave_request_done_t rsp;
|
||
osel_memset((uint8_t *)&rsp, 0, sizeof(slave_request_done_t));
|
||
|
||
switch (command)
|
||
{
|
||
case COMMAND_QUERY_IP_INPUT_CURRENT: // 读取电流
|
||
rsp.data.current.f = (uint32_t)get_ip_adc_in(app.adc.ip_in6.original_value).f;
|
||
rsp.default_value.f = ip_dac_value;
|
||
break;
|
||
case COMMAND_ADJUST_IP_INPUT_CURRENT: // 调节电流
|
||
rsp.data.current.f = *(float32 *)data;
|
||
ip_dac_value = (uint16_t)rsp.data.current.f;
|
||
|
||
if (ip_dac_value == 0) // 自动校准
|
||
{
|
||
#ifdef STM32
|
||
dac_init_flag_reset();
|
||
laser_zero_flag_reset();
|
||
#endif
|
||
}
|
||
break;
|
||
case COMMAND_QUERY_STATE: // 读取状态
|
||
|
||
{
|
||
uint8_t hi = 0, lo = 0;
|
||
osel_memcpy(rsp.data.query_state.code, (uint8_t *)PROJECT_NAME, 3);
|
||
version_split((uint8_t *)VERSION, &hi, &lo);
|
||
rsp.data.query_state.version.bits.hi = hi;
|
||
rsp.data.query_state.version.bits.lo = lo;
|
||
rsp.data.query_state.status = app.task_run_state;
|
||
rsp.data.query_state.process_index = app.process_state.process_index;
|
||
rsp.data.query_state.plan_index = app.process_state.plan_index;
|
||
rsp.data.query_state.action_index = app.process_state.action_index;
|
||
rsp.data.query_state.two_way_valve = get_value_unit_state(UNIT_TWO_WAY_VALVE);
|
||
rsp.data.query_state.three_way_valve = get_value_unit_state(UNIT_THREE_WAY_VALVE);
|
||
}
|
||
break;
|
||
case COMMAND_QUERY_PROCESS: // 读取流程
|
||
if (g_config != NULL)
|
||
{
|
||
osel_memcpy((uint8_t *)&rsp.data.config, (uint8_t *)g_config, sizeof(config_t));
|
||
}
|
||
break;
|
||
case COMMAND_CONFIG_PROCESS: // 配置流程
|
||
if (data != NULL)
|
||
{
|
||
osel_memcpy((uint8_t *)&rsp.data.config, (uint8_t *)data, sizeof(config_t));
|
||
flash_write_process_config(rsp.data.config);
|
||
}
|
||
break;
|
||
case COMMAND_EXECUTE_PROCESS: // 执行流程
|
||
if (data != NULL)
|
||
{
|
||
osel_memcpy((uint8_t *)&rsp.data.execute_process, (uint8_t *)data, sizeof(config_t));
|
||
if (app.task_run_state != RUN_STATE_EXECUTING)
|
||
{
|
||
app.task_run_state = RUN_STATE_READY_RUN;
|
||
}
|
||
}
|
||
break;
|
||
case COMMAND_STOP_PROCESS: // 停止流程
|
||
app.task_run_state = RUN_STATE_UNEXECUTED;
|
||
app.relay.data = 0;
|
||
break;
|
||
case COMMAND_QUERY_DATA: // 读取数据
|
||
{
|
||
if (data != NULL)
|
||
{
|
||
float32_t *f;
|
||
query_data_rsp_t *query_data_rsp = NULL;
|
||
osel_memcpy((uint8_t *)&rsp.data.query_data, (uint8_t *)data, sizeof(query_data_t));
|
||
query_data_rsp = (query_data_rsp_t *)osel_mem_alloc(rsp.data.query_data.count * sizeof(query_data_rsp_t)); // 申请内存,在query_data_convert_pbuf中释放
|
||
DBG_ASSERT(query_data_rsp != NULL __DBG_LINE);
|
||
|
||
for (uint8_t i = 0; i < rsp.data.query_data.count; i++)
|
||
{
|
||
query_data_rsp[i].sensor_class = rsp.data.query_data.sensors[i].sensor_class;
|
||
query_data_rsp[i].sensor.data = rsp.data.query_data.sensors[i].sensor.data;
|
||
query_data_rsp[i].count = get_bit_num(query_data_rsp[i].sensor.data);
|
||
f = get_sensor_data((sensor_e)query_data_rsp[i].sensor_class, query_data_rsp[i].sensor);
|
||
if (f != NULL)
|
||
{
|
||
osel_memcpy((uint8_t *)query_data_rsp[i].data, (uint8_t *)f, query_data_rsp[i].count * sizeof(float32_t));
|
||
}
|
||
}
|
||
|
||
rsp.data.query_data_rsp = query_data_rsp; // 需要手动释放
|
||
}
|
||
}
|
||
break;
|
||
case COMMAND_CONFIG_ADDRESS: // 配置地址
|
||
if (data != NULL)
|
||
{
|
||
osel_memcpy((uint8_t *)&rsp.data.config_address, (uint8_t *)data, sizeof(config_address_t));
|
||
app.device_address = B2S_UINT16(rsp.data.config_address.address);
|
||
// 写到flash中
|
||
flash_write_address();
|
||
}
|
||
break;
|
||
case COMMAND_QUERY_ADDRESS: // 读取地址
|
||
// TODO 从flash中读取地址
|
||
rsp.data.query_address.address = S2B_UINT16(app.device_address);
|
||
break;
|
||
case COMMAND_CALIBRATE_SENSOR:
|
||
if (data != NULL)
|
||
{
|
||
osel_memcpy((uint8_t *)&rsp.data.calibration_sensor, (uint8_t *)data, sizeof(calibration_sensor_t));
|
||
if (rsp.data.calibration_sensor.state == 0) // 0值
|
||
{
|
||
calibration_sensor(rsp.data.calibration_sensor.sensor_data);
|
||
}
|
||
else
|
||
{
|
||
// TODO ?
|
||
}
|
||
}
|
||
break;
|
||
case COMMAND_SET_VALVE: // 设置阀门
|
||
if (data != NULL)
|
||
{
|
||
osel_memcpy((uint8_t *)&rsp.data.set_valve, (uint8_t *)data, sizeof(set_valve_t));
|
||
set_valve_status((unit_e)rsp.data.set_valve.unit, rsp.data.set_valve.index, rsp.data.set_valve.status);
|
||
}
|
||
|
||
break;
|
||
case COMMAND_QUERY_VALVE: // 比例阀查询
|
||
rsp.data.valve_ratio.value.f = (uint32_t)get_proportional_valve_adc_in(app.adc.proportional_valve_in1.original_value).f;
|
||
rsp.default_value.f = proportional_valve_dac_value;
|
||
if (pid_pressure_flag)
|
||
{
|
||
rsp.data.valve_ratio.pid_sensor_class = SENSOR_PRESSURE;
|
||
rsp.data.valve_ratio.pid_sensor_no = pid_pressure_no.data;
|
||
}
|
||
else
|
||
{
|
||
rsp.data.valve_ratio.pid_sensor_class = SENSOR_PROPORTIONAL_VALVE;
|
||
rsp.data.valve_ratio.pid_sensor_no = 1;
|
||
}
|
||
break;
|
||
case COMMAND_SET_VALVE_RATIO: // 设置比例阀
|
||
if (data != NULL)
|
||
{
|
||
osel_memcpy((uint8_t *)&rsp.data.valve_ratio, (uint8_t *)data, sizeof(set_valve_ratio_t));
|
||
proportional_valve_dac_value = (uint16_t)rsp.data.valve_ratio.value.f;
|
||
if (rsp.data.valve_ratio.pid_sensor_class == SENSOR_PRESSURE)
|
||
{
|
||
pid_pressure_flag = true;
|
||
pid_pressure_no.data = rsp.data.valve_ratio.pid_sensor_no;
|
||
}
|
||
else
|
||
{
|
||
pid_pressure_flag = false;
|
||
pid_pressure_no.data = 0;
|
||
}
|
||
|
||
if (proportional_valve_dac_value == 0) // 自动校准
|
||
{
|
||
#ifdef STM32
|
||
dac_init_flag_reset();
|
||
#endif
|
||
app.adc.proportional_valve_in1.is_open = true;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case COMMAND_SET_STEPPER_MOTOR: // 设置步进电机
|
||
if (data != NULL)
|
||
{
|
||
osel_memcpy((uint8_t *)&rsp.data.stepper_motor, (uint8_t *)data, sizeof(stepper_motor_t));
|
||
#ifdef STM32
|
||
step_motor_t *step_motor = get_step_motor(STEP_MOTOR_1);
|
||
step_motor->interface.stop(STEP_MOTOR_1);
|
||
// 因为步进电机带动转盘,电机360度转一圈,转盘只转2度,所以需要乘以180
|
||
step_motor->interface.set_angle(STEP_MOTOR_1, (uint16_t)(rsp.data.stepper_motor.angle * ANGLE), (dir_e)rsp.data.stepper_motor.dir);
|
||
#endif
|
||
}
|
||
break;
|
||
case COMMAND_QUERY_IP_INPUT_PWM_DUTY:
|
||
{
|
||
float32_t f;
|
||
f.f = ip_pwm_duty;
|
||
f.c = S2B_UINT32(f.c);
|
||
rsp.data.query_ip_pwm_duty.frequency = app.ip_out_pwm_frequency;
|
||
rsp.data.query_ip_pwm_duty.percent = f.f;
|
||
LOG_PRINT("ip pwm duty:%f", rsp.data.query_ip_pwm_duty.percent);
|
||
break;
|
||
}
|
||
case COMMAND_ADJUST_IP_INPUT_PWM_DUTY:
|
||
if (data != NULL)
|
||
{
|
||
osel_memcpy((uint8_t *)&rsp.data.adjust_ip_pwm_duty, (uint8_t *)data, sizeof(adjust_ip_pwm_duty_t));
|
||
ip_pwm_duty = rsp.data.adjust_ip_pwm_duty.percent;
|
||
LOG_PRINT("ip pwm duty:%f", ip_pwm_duty);
|
||
}
|
||
break;
|
||
case COMMAND_SET_IP_MODE: // 设置IP模式
|
||
if (data != NULL)
|
||
{
|
||
osel_memcpy((uint8_t *)&rsp.data.set_ip_mode, (uint8_t *)data, sizeof(set_ip_mode_t));
|
||
app.ip_out_mode = rsp.data.set_ip_mode.mode;
|
||
app.ip_out_pwm_frequency = rsp.data.set_ip_mode.data.frequency;
|
||
flash_write_ip_mode();
|
||
flash_write_ip_pwm_frequency();
|
||
LOG_PRINT("ip mode:%d, ip frequency:%d", app.ip_out_mode, app.ip_out_pwm_frequency);
|
||
#ifdef STM32
|
||
ip_set_init((ip_out_mode_e)app.ip_out_mode, app.ip_out_pwm_frequency);
|
||
#endif
|
||
}
|
||
break;
|
||
case COMMAND_QUERY_IP_MODE: // 查询IP模式
|
||
{
|
||
rsp.data.query_ip_mode.mode = app.ip_out_mode;
|
||
if (app.ip_out_mode == 2)
|
||
{
|
||
rsp.data.query_ip_mode.data.frequency = app.ip_out_pwm_frequency;
|
||
rsp.data.query_ip_mode.data_length = 1;
|
||
}
|
||
else
|
||
{
|
||
rsp.data.query_ip_mode.data_length = 0;
|
||
}
|
||
|
||
break;
|
||
}
|
||
case COMMAND_RESET_DEVICE:
|
||
reset_flag = true;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
return rsp;
|
||
}
|
||
|
||
static void data_analysis_event(void)
|
||
{
|
||
uint8_t frame[UART_RXSIZE];
|
||
uint8_t data_head[3];
|
||
uint8_t crc[2];
|
||
uint16_t frame_len, out_frame_len;
|
||
data_read(UART_DATA_ANALYSIS_PORT, &data_head[0], 3);
|
||
osel_memcpy((uint8_t *)&frame_len, &data_head[1], 2);
|
||
|
||
frame_len = B2S_UINT16(frame_len) - 2; // 报文长度包含帧长,这里需要减2
|
||
if (frame_len > UART_RXSIZE)
|
||
{
|
||
lock_data(UART_DATA_ANALYSIS_PORT);
|
||
unlock_data(UART_DATA_ANALYSIS_PORT);
|
||
return;
|
||
}
|
||
|
||
out_frame_len = data_read(UART_DATA_ANALYSIS_PORT, frame, (uint16_t)frame_len);
|
||
if (out_frame_len != frame_len)
|
||
{
|
||
return;
|
||
}
|
||
out_frame_len = out_frame_len - 1; // 报文中包含帧尾,这里需要减1
|
||
|
||
// 校验CRC_16
|
||
uint16_t crc_16 = 0;
|
||
uint16_t crc16 = crc16_compute(&frame[0], out_frame_len - 2);
|
||
osel_memcpy(&crc[0], &frame[out_frame_len - 2], 2);
|
||
crc_16 = BUILD_UINT16(crc[1], crc[0]);
|
||
if (crc16 != crc_16)
|
||
{
|
||
return;
|
||
}
|
||
// CRC校验通过后将数据长度-2
|
||
out_frame_len -= 2;
|
||
|
||
pbuf_t *frm_buf = pbuf_allocz(out_frame_len __PLINE1);
|
||
DBG_ASSERT(frm_buf != NULL __DBG_LINE);
|
||
frm_buf->data_len = out_frame_len;
|
||
osel_memcpy(&frm_buf->data_p[0], frame, out_frame_len);
|
||
agreement_req_cb(&frm_buf->data_p[0], out_frame_len);
|
||
pbuf_freez(&frm_buf __PLINE2);
|
||
|
||
app.master_active = true; // 主机活跃
|
||
}
|
||
|
||
bool uart_init(agreement_req_cb_t cb)
|
||
{
|
||
DBG_ASSERT(cb != NULL __DBG_LINE);
|
||
// 注册数据解析
|
||
data_reg_t reg;
|
||
reg.sd.valid = true;
|
||
reg.sd.len = 1;
|
||
reg.sd.pos = 0;
|
||
reg.sd.data[0] = FRAME_HEAD;
|
||
reg.ld.len = 2;
|
||
reg.ld.pos = 2; // 报文长度包含帧长,这里需要设置偏移2
|
||
reg.ld.valid = true;
|
||
reg.ld.little_endian = false;
|
||
reg.argu.len_max = 1024;
|
||
reg.argu.len_min = 2;
|
||
reg.ed.valid = true;
|
||
reg.ed.len = 1;
|
||
reg.ed.data[0] = FRAME_TAIL;
|
||
reg.echo_en = false;
|
||
reg.func_ptr = data_analysis_event;
|
||
uart_data_analysis_cb = data_fsm_init(UART_DATA_ANALYSIS_PORT);
|
||
data_reg(UART_DATA_ANALYSIS_PORT, reg);
|
||
agreement_req_cb = cb;
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* @description: 应用层初始化
|
||
* @return {*}
|
||
*/
|
||
bool app_init(void)
|
||
{
|
||
app.task_run_state = RUN_STATE_UNEXECUTED;
|
||
|
||
if (!DBG_ASSERT(false != uart_init(agreement_slave_req) __DBG_LINE))
|
||
return false;
|
||
|
||
agreement_init_t agreement_init_param;
|
||
agreement_init_param.slave = 1;
|
||
agreement_init_param.response_call = uart_send_data;
|
||
agreement_init_param.slave_request_done_call = request_done;
|
||
if (!DBG_ASSERT(false != agreement_init(&agreement_init_param) __DBG_LINE))
|
||
return false;
|
||
|
||
sensor_init();
|
||
flash_load();
|
||
#ifdef STM32
|
||
// app.ip_out_mode = IP_OUT_PWM;
|
||
// app.ip_out_pwm_frequency = 32;
|
||
ip_set_init((ip_out_mode_e)app.ip_out_mode, app.ip_out_pwm_frequency);
|
||
ip_set_out(0);
|
||
#endif
|
||
return true;
|
||
}
|
||
|
||
// 串口接收到数据
|
||
void uart_recv_data(uint8_t *data, uint16_t len)
|
||
{
|
||
if (uart_data_analysis_cb != NULL)
|
||
{
|
||
for (uint16_t i = 0; i < len; i++)
|
||
{
|
||
uart_data_analysis_cb(UART_DATA_ANALYSIS_PORT, *(data + i));
|
||
}
|
||
}
|
||
}
|
||
|
||
void register_request_done(void)
|
||
{
|
||
handle.slave_request_done_call = request_done;
|
||
}
|