injectorCTL/protocol.c

1641 lines
46 KiB
C
Raw Normal View History

2024-12-10 12:01:16 +00:00
#include "protocol.h"
#include <string.h>
#ifndef USE_ELOG
void elog_hexdump(const char *name, uint8_t width, const void *buf, uint16_t size) {
printf("%s: ", name);
// 按width的宽度打印
for(uint16_t i = 0; i < size; i++) {
printf("%02X ", ((uint8_t*)buf)[i]);
if((i+1)%width == 0) {
printf("\r\n");
}
}
printf("\r\n");
}
#endif
2024-12-23 09:27:49 +00:00
DeviceStatus_t deviceStatus = {
2024-12-23 15:14:35 +00:00
.sensorStatus = 1,
.valves = {{210, 120}},
.pumps = {{0, 0},{50, 50}},
2024-12-13 08:00:24 +00:00
.bubbleStatus = 0,
.activityMeter = 0,
.estopStatus = 0,
2024-12-13 08:00:24 +00:00
.errorCode = 0,
.initStatus = 1
};
2024-12-23 15:14:35 +00:00
SystemStatus_t systemStatus = {
.valvesSpeed = {0},
.valvesPos = {0},
.valvesSpeedPercent = {0},
.pumpsSpeed = {0},
.pumpsPos = {0},
.pumpsSpeedPercent = {0},
.rst = 0
2024-12-23 15:14:35 +00:00
};
2024-12-13 08:00:24 +00:00
2024-12-23 15:14:35 +00:00
uint8_t isValveMovingBackToOrigin[2] = {0,0};
2024-12-23 07:52:28 +00:00
2024-12-23 09:27:49 +00:00
DeviceParam_t dp = {
2024-12-23 03:13:24 +00:00
.pump = {
{"pump1", 4, 60, 100, 100,40000,0},
{"pump2", 3, 10, 100, 100,40000,0}
2024-12-23 03:13:24 +00:00
},
.valve = {
{"valve1", 1, 10, 100, 100,47620,0},
{"valve2", 2, 10, 100, 100,47620,0}
2024-12-23 03:13:24 +00:00
}
};
2024-12-12 08:38:51 +00:00
2024-12-10 12:01:16 +00:00
// CRC16 查表法实现
static const uint16_t crcTable[] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
2024-12-13 08:31:59 +00:00
/**
2024-12-19 14:49:20 +00:00
* CRC16校验值,CRC16校验多项式为:X16+X15+X2+1
2024-12-13 08:31:59 +00:00
*
* @param data CRC的数据缓冲区
* @param length
* @return CRC16校验值
*/
2024-12-10 12:01:16 +00:00
uint16_t CalculateCRC16(uint8_t *data, uint16_t length) {
uint16_t crc = 0xFFFF;
2024-12-22 14:29:17 +00:00
if (!data) return 0;
2024-12-10 12:01:16 +00:00
for (uint16_t i = 0; i < length; i++) {
uint8_t index = (crc ^ data[i]) & 0xFF;
crc = (crc >> 8) ^ crcTable[index];
}
return crc;
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param status (线/线)
*/
// void updateDeviceStatus(SensorStatus status) {
// deviceStatus.sensorStatus = status;
// }
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index (12)
2024-12-13 09:08:28 +00:00
* @param angle (0-360)
2024-12-13 08:31:59 +00:00
*/
// void updateValveStatus(uint8_t index, ValveAngle angle) {
// if (index == 1) {
// deviceStatus.valves.angle1 = angle;
// } else if (index == 2) {
// deviceStatus.valves.angle2 = angle;
// }
// }
2024-12-10 12:01:16 +00:00
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index (12)
* @param speed (0-100%)
*/
// void updatePumpSpeedStatus(uint8_t index, uint8_t speed) {
// if (index == 1) {
// deviceStatus.pumps.speed1 = speed;
// } else if (index == 2) {
// deviceStatus.pumps.speed2 = speed;
// }
// }
2024-12-10 12:01:16 +00:00
2024-12-13 08:31:59 +00:00
/**
*
*
* @param value (/)
*/
// void updateBubbleSensor(BubbleStatus value) {
// deviceStatus.bubbleStatus = value;
// }
2024-12-10 12:01:16 +00:00
2024-12-13 08:31:59 +00:00
/**
*
*
* @param status (/)
*/
// void updateEmergencyStop(EstopStatus_t status) {
// deviceStatus.stopStatus = status;
// }
2024-12-13 08:31:59 +00:00
/**
*
*
* @param errorCode
*/
// void updateErrorCode(ErrorCode_t errorCode) {
// deviceStatus.errorCode = errorCode;
// }
2024-12-10 12:01:16 +00:00
2024-12-13 08:31:59 +00:00
/**
*
*
* @param status (//)
*/
// void updateInitStatus(InitStatus_t status) {
// deviceStatus.initStatus = status;
// }
2024-12-10 12:01:16 +00:00
2024-12-11 07:55:40 +00:00
2024-12-10 12:01:16 +00:00
2024-12-13 08:31:59 +00:00
/**
* ModBUS RTU写命令
* ModBUS RTU格式的命令
*
* systemStatus.rst
*
2024-12-13 08:31:59 +00:00
* @param txBuf
* @param txLen
2024-12-23 07:52:28 +00:00
* @return 0: :
2024-12-13 08:31:59 +00:00
*/
2024-12-23 07:52:28 +00:00
static uint8_t writeCMD(uint8_t *txBuf, uint16_t txLen) {
elog_hexdump("writeCMD", 16, txBuf, txLen);
2024-12-19 15:33:30 +00:00
transDataToMotorValve(txBuf, txLen);
uint8_t rxBuf[30] = {0};
2024-12-22 14:29:17 +00:00
uint16_t rxLen = txLen;
readDataFromMotorValve(rxBuf, rxLen, READ_ACK_TIMEOUT);
if(memcmp(rxBuf, txBuf, 2) != 0) {//正常情况下返回的前2个字节应与发送的相同
log_e("writeCMD error!");
elog_hexdump("writeCMD error", 16, rxBuf, rxLen);
systemStatus.rst += 1;//结果计数
2024-12-23 07:52:28 +00:00
return 1;
2024-12-19 15:33:30 +00:00
}
else {
log_i("writeCMD success!");
systemStatus.rst += 0;//结果计数
return 0;
}
2024-12-10 12:01:16 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param txBuf
* @param txLen
*/
void sendMsgToHost(uint8_t *txBuf, uint16_t txLen) {
// 发送数据
2024-12-23 07:52:28 +00:00
transDataToHost(txBuf, txLen);
2024-12-11 08:01:45 +00:00
}
2024-12-10 12:01:16 +00:00
// 判断系统大端序还是小端序
static uint8_t IsBigEndian() {
uint32_t num = 0x12345678;
return ((*(uint8_t*)&num) == 0x12);
}
// 将数据按大端序填充
2024-12-10 15:52:29 +00:00
static void FillBigEndian32(uint8_t *data, uint32_t value) {
2024-12-10 12:01:16 +00:00
if(!IsBigEndian()) {
2024-12-10 15:52:29 +00:00
for(uint16_t i = 0; i < 4; i++) {
data[i] = (value >> ((4 - i - 1) * 8)) & 0xFF;
}
}
else {
for(uint16_t i = 0; i < 4; i++) {
data[i] = (value >> (i * 8)) & 0xFF;
2024-12-10 12:01:16 +00:00
}
}
}
2024-12-10 15:52:29 +00:00
static void FillBigEndian16(uint8_t *data, uint16_t value) {
2024-12-10 12:01:16 +00:00
if(!IsBigEndian()) {
2024-12-10 15:52:29 +00:00
for(uint16_t i = 0; i < 2; i++) {
data[i] = (value >> ((2 - i - 1) * 8)) & 0xFF;
2024-12-10 12:01:16 +00:00
}
}
2024-12-10 15:52:29 +00:00
else {
for(uint16_t i = 0; i < 2; i++) {
data[i] = (value >> (i * 8)) & 0xFF;
}
}
}
2024-12-11 09:41:56 +00:00
/*
+----------+--------+------------+------------+------------+
| | | | | CRC校验值 |
+----------+--------+------------+------------+------------+
| 1 | 1 | 2 | 2 | 2 |
+----------+--------+------------+------------+------------+
*/
2024-12-11 07:55:40 +00:00
// pump 读寄存器
2024-12-23 09:27:49 +00:00
/**
* 0x031
* @param id id
* @param reg
* @param return
*/
uint16_t ReadPump1Reg(uint8_t id, uint16_t reg) {
2024-12-11 07:55:40 +00:00
uint8_t data[8] = {0};
2024-12-23 09:27:49 +00:00
data[0] = id;
2024-12-12 08:38:51 +00:00
data[1] = RTU_FUNC_READ_HOLD_REG;
2024-12-11 07:55:40 +00:00
FillBigEndian16(&data[2], reg);
2024-12-11 09:41:56 +00:00
FillBigEndian16(&data[4], 1);
2024-12-10 15:52:29 +00:00
2024-12-11 07:55:40 +00:00
uint16_t crc = CalculateCRC16(data, 6);
2024-12-11 08:01:45 +00:00
// 小端序填充
memcpy(&data[6], &crc, 2);
2024-12-12 08:38:51 +00:00
writeCMD(data, 8);
2024-12-22 14:29:17 +00:00
uint8_t rxBuf[30] = {0};
uint16_t rxLen = 8;
readDataFromMotorValve(rxBuf, rxLen, READ_ACK_TIMEOUT);
2024-12-22 14:29:17 +00:00
return rxBuf[3]<<8|rxBuf[4];
2024-12-12 08:38:51 +00:00
}
2024-12-23 09:27:49 +00:00
/**
* 0x032
* @param id id
* @param reg
* @param return
*/
uint32_t ReadPump2Reg(uint8_t id, uint16_t reg) {
2024-12-23 07:52:28 +00:00
uint8_t data[12] = {0};
2024-12-23 09:27:49 +00:00
data[0] = id;
2024-12-12 08:38:51 +00:00
data[1] = RTU_FUNC_READ_HOLD_REG;
FillBigEndian16(&data[2], reg);
FillBigEndian16(&data[4], 2);
uint16_t crc = CalculateCRC16(data, 6);
// 小端序填充
memcpy(&data[6], &crc, 2);
2024-12-10 15:52:29 +00:00
2024-12-23 07:52:28 +00:00
writeCMD(data, 12);
uint8_t rxBuf[30] = {0};
uint16_t rxLen = 12;
readDataFromMotorValve(rxBuf, rxLen, READ_ACK_TIMEOUT*2);
2024-12-23 07:52:28 +00:00
// 逻辑需进一步完善
return rxBuf[6]<<24|rxBuf[7]<<16|rxBuf[8]<<8|rxBuf[9];
2024-12-10 15:52:29 +00:00
}
2024-12-11 09:41:56 +00:00
/*
+----------+--------+------------+----------+------------+
| | | | | CRC校验值 |
2024-12-11 09:41:56 +00:00
+----------+--------+------------+----------+------------+
| 1 | 1 | 2 | 2 | 2 |
+----------+--------+------------+----------+------------+
*/
2024-12-11 07:55:40 +00:00
// 写泵1个寄存器
2024-12-22 14:29:17 +00:00
uint8_t WritePump1Reg(uint8_t id, uint16_t reg, int16_t value) {
2024-12-11 07:55:40 +00:00
// 写一个寄存器不需要指定寄存器长度
uint8_t data[8] = {0};
2024-12-22 14:29:17 +00:00
data[0] = id;
2024-12-12 08:38:51 +00:00
data[1] = RTU_FUNC_WRITE_REG;
2024-12-11 07:55:40 +00:00
FillBigEndian16(&data[2], reg);
FillBigEndian16(&data[4], value);
uint16_t crc = CalculateCRC16(data, 6);
2024-12-11 08:01:45 +00:00
// 小端序填充
memcpy(&data[6], &crc, 2);
2024-12-10 15:52:29 +00:00
2024-12-23 07:52:28 +00:00
return writeCMD(data, 8);
2024-12-10 12:01:16 +00:00
}
2024-12-11 09:41:56 +00:00
/*
+----------+--------+------------+------------+----------+----------+------------+
| | | | | | | CRC校验值 |
+----------+--------+------------+------------+----------+----------+------------+
| 1 | 1 | 2 | 2 | 1 | 4 | 2 |
+----------+--------+------------+------------+----------+----------+------------+
*/
2024-12-11 07:55:40 +00:00
// 写泵2个寄存器
2024-12-22 14:29:17 +00:00
uint8_t WritePump2Reg(uint8_t id , uint16_t reg, int32_t value) {
2024-12-11 07:55:40 +00:00
// 写2个寄存器需要指定寄存器长度
uint8_t data[13] = {0};
2024-12-22 14:29:17 +00:00
data[0] = id;
2024-12-12 08:38:51 +00:00
data[1] = RTU_FUNC_WRITE_MULTI_REG;
2024-12-11 07:55:40 +00:00
FillBigEndian16(&data[2], reg);
FillBigEndian16(&data[4], 2);
2024-12-22 14:29:17 +00:00
data[6] = 4;
2024-12-11 07:55:40 +00:00
FillBigEndian32(&data[7], value);
uint16_t crc = CalculateCRC16(data, 11);
2024-12-11 08:01:45 +00:00
// 小端序填充
memcpy(&data[11], &crc, 2);
2024-12-10 12:01:16 +00:00
2024-12-23 07:52:28 +00:00
return writeCMD(data, 13);
2024-12-11 07:55:40 +00:00
}
2024-12-10 12:01:16 +00:00
2024-12-11 07:55:40 +00:00
/*
+--------------+--------------------------------+
| jogging设置顺序 |
+--------------+--------------------------------+
| 1. | JAJLJS |
+--------------+--------------------------------+
| 2. | Jog-CJ |
+--------------+--------------------------------+
| 3. | Jog-SJ |
+--------------+--------------------------------+
*/
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param acc
* @return 0: :
*/
2024-12-13 09:08:28 +00:00
static uint8_t SetPumpJogAcc(uint8_t index, uint16_t acc) {
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_JA, acc*PUMP_ACCEL_RPS);
2024-12-11 07:55:40 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param dec
* @return 0: :
*/
2024-12-13 09:08:28 +00:00
static uint8_t SetPumpJogDec(uint8_t index, uint16_t dec) {
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_JL, dec*PUMP_DECEL_RPS);
2024-12-11 07:55:40 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param speed
* @return 0: :
*/
2024-12-13 09:08:28 +00:00
static uint8_t SetPumpJogSpeed(uint8_t index, uint16_t speed) {
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_JS, speed*PUMP_SPEED_RPS);
2024-12-11 07:55:40 +00:00
}
2024-12-10 12:01:16 +00:00
2024-12-11 07:55:40 +00:00
// Jog=慢跑
// CJ=start jogging
// 写入命令操作码寄存器(40125)数据0x0096(CJ)即执行启动Jog控制
2024-12-13 09:08:28 +00:00
static uint8_t StartPumpJog(uint8_t index) {
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_CO, 0x0096);
2024-12-11 07:55:40 +00:00
}
2024-12-10 12:01:16 +00:00
2024-12-11 07:55:40 +00:00
// SJ=stop jogging
// 写入命令操作码寄存器(40125)数据0x00D8(SJ)即执行停止Jog控制
2024-12-11 14:03:09 +00:00
// CJ与SJ一一对应单次SJ无法停止所有全部CJ
// 直接停止泵需要使用SK命令
2024-12-13 09:08:28 +00:00
static uint8_t StopPumpJog(uint8_t index) {
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_CO, 0x00D8);
2024-12-11 07:55:40 +00:00
}
2024-12-10 12:01:16 +00:00
2024-12-11 07:55:40 +00:00
/*
+--------------+--------------------------------+
| step设置顺序 |
+--------------+--------------------------------+
| 1. | ACDEVE |
+--------------+--------------------------------+
| 2. | DI |
+--------------+--------------------------------+
2024-12-13 08:31:59 +00:00
| 3. | FLFP |
2024-12-11 07:55:40 +00:00
+--------------+--------------------------------+
| 4. | SK |
+--------------+--------------------------------+
*/
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param acc
* @return 0: :
*/
2024-12-13 09:08:28 +00:00
static uint8_t SetPumpStepAcc(uint8_t index, uint16_t acc) {
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_AC, acc*PUMP_ACCEL_RPS);
2024-12-11 07:55:40 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param dec
* @return 0: :
*/
2024-12-13 09:08:28 +00:00
static uint8_t SetPumpStepDec(uint8_t index, uint16_t dec) {
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_DE, dec*PUMP_DECEL_RPS);
2024-12-11 07:55:40 +00:00
}
/**
*
*
* @param index
* @param speedPercent
* @return
*/
uint16_t transSpeedPercentToSpeed(uint8_t index, uint8_t speedPercent) {
return speedPercent * dp.pump[index].speed / 100;
}
/**
*
*
* @param index
* @param speed
* @return
*/
uint8_t transSpeedToSpeedPercent(uint8_t index, uint32_t speed) {
return speed * 100 / dp.pump[index].speed;
}
2024-12-13 08:31:59 +00:00
/**
*
*
*
* @param index
2024-12-22 14:29:17 +00:00
* @param speed
2024-12-13 08:31:59 +00:00
* @return 0: :
*/
2024-12-13 09:08:28 +00:00
static uint8_t SetPumpStepSpeed(uint8_t index, uint16_t speed) {
2024-12-22 14:29:17 +00:00
// 速度类寄存器参数设定值单位为 1/240 rps
speed = speed * PUMP_SPEED_RPS;
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_VE, speed);
2024-12-11 07:55:40 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param target
* @return 0: :
*/
2024-12-22 14:29:17 +00:00
static uint8_t SetPumpStepTarget(uint8_t index, int32_t target) {
2024-12-23 07:52:28 +00:00
return WritePump2Reg(dp.pump[index].id, RTU_PUMP_CMD_DI, target);
2024-12-11 07:55:40 +00:00
}
2024-12-10 12:01:16 +00:00
2024-12-13 08:31:59 +00:00
/**
2024-12-13 09:56:20 +00:00
*
2024-12-13 08:31:59 +00:00
* FL(feed length)
*
* @param index
* @return 0: :
*/
2024-12-13 09:56:20 +00:00
static uint8_t StartPumpRelativeMove(uint8_t index) {
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_CO, 0x0066);
2024-12-10 12:01:16 +00:00
}
2024-12-13 08:31:59 +00:00
/**
2024-12-13 09:56:20 +00:00
* 使
2024-12-13 08:31:59 +00:00
* FP(feed position)
*
* @param index
* @return 0: :
*/
2024-12-13 09:56:20 +00:00
static uint8_t StartPumpAbsoluteMove(uint8_t index) {
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_CO, 0x0067);
2024-12-11 07:55:40 +00:00
}
2024-12-11 02:32:35 +00:00
2024-12-13 08:31:59 +00:00
/**
*
* SK(Stop & Kill)
*
* @param index
* @return 0: :
*/
2024-12-11 07:55:40 +00:00
static uint8_t StopPump(uint8_t index) {
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_CO, 0x00E1);
2024-12-11 07:55:40 +00:00
}
2024-12-11 02:32:35 +00:00
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @return 0: :
*/
2024-12-13 09:08:28 +00:00
uint8_t ReadPumpHWReg(uint8_t index) {
2024-12-23 07:52:28 +00:00
return ReadPump1Reg(dp.pump[index].id, RTU_PUMP_CMD_HW);
2024-12-11 02:32:35 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param br
* @return 0: :
*/
2024-12-13 09:08:28 +00:00
uint8_t SetPumpBR(uint8_t index, uint16_t br) {
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_BR, br);
2024-12-11 09:41:56 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param pr
* @return 0: :
*/
2024-12-13 09:08:28 +00:00
uint8_t SetPumpPR(uint8_t index, uint16_t pr) {
2024-12-23 07:52:28 +00:00
return WritePump1Reg(dp.pump[index].id, RTU_PUMP_CMD_PR, pr);
2024-12-11 09:41:56 +00:00
}
2024-12-11 02:32:35 +00:00
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
*/
2024-12-22 14:29:17 +00:00
uint16_t ReadPumpStatus(uint8_t index) {
return ReadPump1Reg(dp.pump[index].id, RTU_PUMP_CMD_SC);
2024-12-11 02:32:35 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
*/
2024-12-22 14:29:17 +00:00
uint16_t ReadPumpAlarm(uint8_t index) {
return ReadPump1Reg(dp.pump[index].id, RTU_PUMP_CMD_AL);
2024-12-11 02:32:35 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
2024-12-13 08:31:59 +00:00
*
* @param reg4001
*/
2024-12-11 02:32:35 +00:00
void DecodePumpAlarmMsg(uint16_t reg4001) {
2024-12-22 14:29:17 +00:00
printf("reg4001: %x\r\n", reg4001);
2024-12-11 02:32:35 +00:00
static AlarmCode_t alarmCode = {0};
// 与上次告警信息相同,则不更新,仅打印一次
if (alarmCode.all == reg4001)
{
return;
2024-12-11 02:32:35 +00:00
}
alarmCode.all = reg4001;
if(alarmCode.all == 0) {
//暂时屏蔽,避免刷屏
// printf("\r\n%s无报警信息\r\n", pumpName[index]);
return;
2024-12-11 02:32:35 +00:00
}
// 打印表格头部
printf("\r\n+--------+------------------+\r\n");
printf("| 告警位 | 告警信息 |\r\n");
printf("+--------+------------------+\r\n");
for(uint16_t i = 0; i < 16; i++) {
if(alarmCode.all & (1 << i)) {
printf("| %6d | %-14s |\r\n", i, alarmInfo[i]);
printf("+--------+------------------+\r\n");
}
}
return;
2024-12-11 02:32:35 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param reg4002
*/
2024-12-11 02:32:35 +00:00
void DecodePumpStatusMsg(uint16_t reg4002) {
static StatusCode_t statusCode = {0};
// 与上次状态信息相同,则不更新,仅打印一次
if (statusCode.all == reg4002)
{
return 1;
}
statusCode.all = reg4002;
printf("\r\n+--------+------------------+\r\n");
printf("| 状态位 | 状态信息 |\r\n");
printf("+--------+------------------+\r\n");
for(uint16_t i = 0; i < 16; i++) {
if(statusCode.all & (1 << i)) {
printf("| %6d | %-14s |\r\n", i, statusInfo[i]);
printf("+--------+------------------+\r\n");
}
}
return 0;
}
/**
*
*
*/
void ReadPumpSpeedPos(void)
2024-12-23 09:27:49 +00:00
{
for(uint8_t index = 0; index < 2; index++) {
uint32_t pos = ReadPump2Reg(dp.pump[index].id,RTU_PUMP_CMD_POS);
systemStatus.pumpsPos[index] = pos;
log_d("%s pos = %d",dp.pump[index].name,pos);
uint16_t speed = ReadPump2Reg(dp.pump[index].id,RTU_PUMP_CMD_SPEED);
systemStatus.pumpsSpeed[index] = speed;
systemStatus.pumpsSpeedPercent[index] = (uint8_t)(speed * 100 / dp.pump[index].speed);
log_d("%s speed = %d",dp.pump[index].name,speed);
//判断正转、反转
if(speed > 0) {
if(ReadPump2Reg(dp.pump[index].id,RTU_PUMP_CMD_POS) > pos)
systemStatus.ds.pumps.status[index] = PUMP_STATUS_CLOCKWISE;
else
systemStatus.ds.pumps.status[index] = PUMP_STATUS_ANTICLOCKWISE;
} else {
systemStatus.ds.pumps.status[index] = PUMP_STATUS_STOP;
}
}
2024-12-23 09:27:49 +00:00
}
2024-12-13 09:08:28 +00:00
/**
*
*
2024-12-13 09:08:28 +00:00
*/
void updatePumpStatus(void) {
2024-12-13 09:08:28 +00:00
// 更新设备状态
for(uint8_t index = 0; index < 2; index++) {
uint16_t reg4001 = ReadPumpAlarm(index);
DecodePumpAlarmMsg(reg4001);
uint16_t reg4002 = ReadPumpStatus(index);
DecodePumpStatusMsg(reg4002);
}
2024-12-13 09:08:28 +00:00
}
/**
*
*
*
* @return 0: :
*/
uint8_t InitPump(void) {
// 初始化泵
log_i("InitPump");
for(uint8_t index = 0; index < 2; index++) {
uint8_t rst = systemStatus.rst;
SetPumpJogAcc(index, dp.pump[index].accel);
SetPumpJogDec(index, dp.pump[index].decel);
SetPumpJogSpeed(index, dp.pump[index].speed*dp.pump[index].speedPercent/100);
SetPumpStepAcc(index, dp.pump[index].accel);
SetPumpStepDec(index, dp.pump[index].decel);
SetPumpStepSpeed(index, dp.pump[index].speed*dp.pump[index].speedPercent/100);
if (rst != systemStatus.rst)
{
log_e("InitPump %s failed!", dp.pump[index].name);
systemStatus.ds.initStatus = INIT_FAILED;
return 1;
}
}
return 0;
2024-12-13 09:08:28 +00:00
}
2024-12-11 15:32:34 +00:00
// valve
/*
# 轮廓位置模式,配置流程
1.
00B1h=0 03C2h=0x01使
2024-12-12 08:44:18 +00:00
1.1( CIA402 )
1.2()
2024-12-11 15:32:34 +00:00
2.
2024-12-12 08:44:18 +00:00
2.1 (03E7h)()
2.2 (03F8h) (/s)
2.3 (03FCh)(/s2)
2.4 (03FEh)(/s2)
2024-12-11 15:32:34 +00:00
3.使使
2024-12-12 08:44:18 +00:00
(0380h)= 0x060x07 0x0F使
2024-12-23 15:14:35 +00:00
4.使<EFBFBD><EFBFBD>
2024-12-12 08:44:18 +00:00
(0380h)= 0x2F0x3F
2024-12-11 15:32:34 +00:00
5.
2024-12-12 08:44:18 +00:00
(03C8h) ()
2024-12-11 15:32:34 +00:00
# 堵转找寻原点方式,配置流程
1.
2024-12-12 08:44:18 +00:00
(0416h)=37;17=18=
2024-12-11 15:32:34 +00:00
2.
2024-12-12 08:44:18 +00:00
(0170h)=300(0172h)=50
2024-12-11 15:32:34 +00:00
3.
2024-12-12 08:44:18 +00:00
(00B1h)=0 (03C2h)=0x06使
2024-12-11 15:32:34 +00:00
4.
2024-12-12 08:44:18 +00:00
(0417h)= 10000 (0419h)=1000;
2024-12-11 15:32:34 +00:00
5.
2024-12-12 08:44:18 +00:00
(041Bh)=200000
2024-12-11 15:32:34 +00:00
6.
(0380h)= 0x060x070x0F0x1F
*/
2024-12-11 02:32:35 +00:00
2024-12-12 03:35:40 +00:00
// 与pump通用
2024-12-23 15:14:35 +00:00
uint8_t (*writeValve1Reg)(uint8_t index, uint16_t reg, uint16_t value) = WritePump1Reg;
uint8_t (*writeValve2Reg)(uint8_t index, uint16_t reg, uint32_t value) = WritePump2Reg;
uint8_t (*readValve1Reg)(uint8_t index, uint16_t reg) = ReadPump1Reg;
uint8_t (*readValve2Reg)(uint8_t index, uint16_t reg) = ReadPump2Reg;
2024-12-12 03:35:40 +00:00
2024-12-23 07:52:28 +00:00
/**
* 1
*
2024-12-23 09:37:25 +00:00
* @param id id
2024-12-23 07:52:28 +00:00
* @param reg
* @return
*/
2024-12-23 09:37:25 +00:00
uint16_t ReadValve1InputReg(uint8_t id, uint16_t reg)
2024-12-23 07:52:28 +00:00
{
uint8_t data[8] = {0};
2024-12-23 09:37:25 +00:00
data[0] = id;
2024-12-23 07:52:28 +00:00
data[1] = RTU_FUNC_READ_INPUT_REG;
FillBigEndian16(&data[2], reg);
FillBigEndian16(&data[4], 1);
uint16_t crc = CalculateCRC16(data, 6);
// 小端序填充
memcpy(&data[6], &crc, 2);
writeCMD(data, 8);
uint8_t rxBuf[30] = {0};
uint16_t rxLen = 8;
uint8_t rst = HAL_UART_Receive(&huart2, rxBuf, rxLen, READ_ACK_TIMEOUT);
return rxBuf[3]<<8|rxBuf[4];
}
/**
* 2
*
2024-12-23 09:37:25 +00:00
* @param id id
2024-12-23 07:52:28 +00:00
* @param reg
* @return
*/
2024-12-23 09:37:25 +00:00
uint32_t ReadValve2InputReg(uint8_t id, uint16_t reg)
2024-12-23 07:52:28 +00:00
{
uint8_t data[8] = {0};
2024-12-23 09:37:25 +00:00
data[0] = id;
2024-12-23 07:52:28 +00:00
data[1] = RTU_FUNC_READ_INPUT_REG;
FillBigEndian16(&data[2], reg);
FillBigEndian16(&data[4], 2);
uint16_t crc = CalculateCRC16(data, 6);
// 小端序填充
memcpy(&data[6], &crc, 2);
writeCMD(data, 8);
uint8_t rxBuf[30] = {0};
uint16_t rxLen = 9;
uint8_t rst = HAL_UART_Receive(&huart2, rxBuf, rxLen, READ_ACK_TIMEOUT);
return rxBuf[3]<<24|rxBuf[4]<<16|rxBuf[5]<<8|rxBuf[6];
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param mode (CIA402模式)
* @return 0: :
*/
2024-12-12 03:35:40 +00:00
static uint8_t SetValveCOMMMode(uint8_t index, uint16_t mode) {
2024-12-23 15:14:35 +00:00
return writeValve1Reg(dp.valve[index].id, RTU_VALVE_CMD_CTL_MODE, mode);
2024-12-11 15:32:34 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param mode (HMPP)
* @return 0: :
*/
2024-12-11 15:32:34 +00:00
static uint8_t SetValveRunMode(uint8_t index, uint16_t mode) {
2024-12-23 15:14:35 +00:00
return writeValve1Reg(dp.valve[index].id, RTU_VALVE_CMD_RUN_MODE, mode);
2024-12-11 15:32:34 +00:00
}
2024-12-11 02:32:35 +00:00
2024-12-11 15:32:34 +00:00
// PP=轮廓位置模式
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param pos ()
* @return 0: :
*/
2024-12-12 07:40:28 +00:00
static uint8_t SetValvePPPos(uint8_t index, uint32_t pos) {
2024-12-23 07:52:28 +00:00
return writeValve2Reg(dp.valve[index].id, RTU_VALVE_CMD_PP_POS, pos);
2024-12-11 15:32:34 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param speed (/s)
* @return 0: :
*/
2024-12-12 07:40:28 +00:00
static uint8_t SetValvePPSpeed(uint8_t index, uint32_t speed) {
2024-12-23 07:52:28 +00:00
return writeValve2Reg(dp.valve[index].id, RTU_VALVE_CMD_PP_SPEED, speed);
2024-12-11 15:32:34 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param acc (/s²)
* @return 0: :
*/
2024-12-12 07:40:28 +00:00
static uint8_t SetValvePPAcc(uint8_t index, uint32_t acc) {
2024-12-23 07:52:28 +00:00
return writeValve2Reg(dp.valve[index].id, RTU_VALVE_CMD_PP_ACCEL, acc);
2024-12-11 15:32:34 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param dec (/s²)
* @return 0: :
*/
2024-12-12 07:40:28 +00:00
static uint8_t SetValvePPDec(uint8_t index, uint32_t dec) {
2024-12-23 07:52:28 +00:00
return writeValve2Reg(dp.valve[index].id, RTU_VALVE_CMD_PP_DECEL, dec);
2024-12-11 15:32:34 +00:00
}
// HM=原点回归模式
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param mode ()
* @return 0: :
*/
2024-12-12 03:35:40 +00:00
static uint8_t SetValveHomeDetectMode(uint8_t index, uint16_t mode) {
2024-12-23 07:52:28 +00:00
return writeValve1Reg(dp.valve[index].id, RTU_VALVE_CMD_HOME_MODE, mode);
2024-12-12 03:35:40 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param speed
* @return 0: :
*/
2024-12-12 07:40:28 +00:00
static uint8_t SetValveHomeSwtSpeed(uint8_t index, uint32_t speed) {
2024-12-23 07:52:28 +00:00
return writeValve2Reg(dp.valve[index].id, RTU_VALVE_CMD_HOME_SWT_SPEED, speed);
2024-12-11 15:32:34 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param speed
* @return 0: :
*/
2024-12-12 07:40:28 +00:00
static uint8_t SetValveHomeOriSpeed(uint8_t index, uint32_t speed) {
2024-12-23 07:52:28 +00:00
return writeValve2Reg(dp.valve[index].id, RTU_VALVE_CMD_HOME_ORI_SPEED, speed);
2024-12-11 15:32:34 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param acc
* @return 0: :
*/
2024-12-12 07:40:28 +00:00
static uint8_t SetValveHomeAcc(uint8_t index, uint32_t acc) {
2024-12-23 07:52:28 +00:00
return writeValve2Reg(dp.valve[index].id, RTU_VALVE_CMD_HOME_ACCEL, acc);
2024-12-11 15:32:34 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param func (使)
* @return 0: :
*/
2024-12-11 15:32:34 +00:00
static uint8_t SetValveFunc(uint8_t index, uint16_t func) {
2024-12-23 07:52:28 +00:00
return writeValve1Reg(dp.valve[index].id, RTU_VALVE_CMD_FUNC, func);
2024-12-12 03:35:40 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param torque 3030%
2024-12-13 08:31:59 +00:00
* @return 0: :
*/
2024-12-12 03:35:40 +00:00
static uint8_t SetValveHomeTorque(uint8_t index, uint16_t torque) {
2024-12-23 07:52:28 +00:00
return writeValve1Reg(dp.valve[index].id, RTU_VALVE_CMD_HOME_TORQUE, torque*10);
2024-12-12 03:35:40 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
* @param time (ms)55ms
2024-12-13 08:31:59 +00:00
* @return 0: :
*/
2024-12-12 03:35:40 +00:00
static uint8_t SetValveHomeTime(uint8_t index, uint16_t time) {
2024-12-23 07:52:28 +00:00
return writeValve1Reg(dp.valve[index].id, RTU_VALVE_CMD_HOME_TIME, time*10);
2024-12-12 03:35:40 +00:00
}
2024-12-23 07:52:28 +00:00
/**
*
*
* @param index
* @return ()
*/
static uint32_t ReadValvePos(uint8_t index) {
2024-12-23 09:37:25 +00:00
return ReadValve2InputReg(dp.valve[index].id, RTU_VALVE_CMD_POS);
2024-12-23 07:52:28 +00:00
}
/**
*
*
* @param index
* @return (/s)
2024-12-23 07:52:28 +00:00
*/
static uint32_t ReadValveSpeed(uint8_t index) {
return ReadValve2InputReg(dp.valve[index].id, RTU_VALVE_CMD_SPEED);
2024-12-23 07:52:28 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
*
*
*
2024-12-13 08:31:59 +00:00
* @param index
* @param direction
2024-12-13 08:31:59 +00:00
*/
void ValveBackToOrigin(uint8_t index,int8_t direction) {
uint8_t rst = systemStatus.rst;
2024-12-12 03:35:40 +00:00
// 1.设置原点回归方式
2024-12-12 08:44:18 +00:00
// (0416h)=37;17=负限位18=正限位
if(direction > 0) {
log_i("back to Origin, +\r\n");
2024-12-22 14:29:17 +00:00
SetValveHomeDetectMode(index, 37);//正方向堵转
}
else {
log_i("back to Origin, -\r\n");
2024-12-22 14:29:17 +00:00
SetValveHomeDetectMode(index, 38);//反方向堵转
}
2024-12-12 03:35:40 +00:00
// 2.设置堵转检测力矩和堵转检测时间
2024-12-12 08:44:18 +00:00
// (0170h)=300(0172h)=50
SetValveHomeTorque(index, 30);//30%
SetValveHomeTime(index, 5);//50ms
2024-12-12 08:44:18 +00:00
// 3.写 (00B1h)=0、运行模式 (03C2h)=0x06使其工作在原点回归模式
2024-12-23 03:13:24 +00:00
SetValveCOMMMode(index, RTU_VALVE_CFG_COMM_CIA402);
SetValveRunMode(index, RTU_VALVE_CFG_MODE_HM);
2024-12-12 08:44:18 +00:00
// 4.写寻找限位开关速度和寻找原点信号速度(0417h)= 10000 (0419h)=1000;
2024-12-22 14:29:17 +00:00
// SetValveHomeSwtSpeed(index, 20000);
SetValveHomeOriSpeed(index, 20000);
2024-12-12 03:35:40 +00:00
// 5.设置回零加速度
SetValveHomeAcc(index, 200000);
// 6.写控制字
// (0380h)= 0x06→0x07→0x0F→0x1F电机运行
2024-12-23 03:13:24 +00:00
SetValveFunc(index, RTU_VALVE_CFG_PREPARE);
SetValveFunc(index, RTU_VALVE_CFG_DISABLE);
SetValveFunc(index, RTU_VALVE_CFG_ENABLE);
2024-12-12 03:35:40 +00:00
SetValveFunc(index, RTU_VALVE_CFG_RUN_ORIGIN);
2024-12-23 16:00:46 +00:00
if(rst != systemStatus.rst) {
log_e("ValveBackToOrigin[%d] failed!",index);
systemStatus.ds.initStatus = INIT_FAILED;
}
2024-12-23 16:00:46 +00:00
// 2,3,4,5设置过后可不再设置
// 1,6为必须
// 堵转点即为原点读位置应为0或小于200
// 不同在于负堵转时目标位置10000为正0x2710正堵转时目标位置为负0xffffd8f0
2024-12-11 15:32:34 +00:00
}
2024-12-11 02:32:35 +00:00
/**
*
* @param index
* @return 0: 1: 2:
*/
static void valveCheckBTOResult(uint8_t index)
{
static uint8_t retryCnt = 0;
uint8_t isSuccess = 0;
uint16_t rst = ReadValve1InputReg(dp.valve[index].id,RTU_VALVE_CMD_SC);
// 如果原点回归完成状态字第12位会从0变为1
// 如果原点回归失败状态字第13位会从0变为1。
// 此外也可以附加判断电机当前位置是否在0附近的200个脉冲以内。
if(rst & 0x0001<<12) {
// 成功
uint32_t pos = ReadValvePos(index);
if(pos > 200 || pos < (VALVE_PULSE_PER_ROUND-200)) {
// 位置超出范围
isSuccess = 0;
}
else {
isSuccess = 1;
}
}
if(rst & 0x0001<<13) {
// 失败
isSuccess = 0;
}
if (isSuccess)
{
retryCnt = 0;
systemStatus.ds.initStatus = INIT_SUCCESS;
return;
}
else {
retryCnt++;
if(retryCnt > 2) {//执行两次回归,都失败则认为初始化失败
systemStatus.ds.initStatus = INIT_FAILED;
retryCnt = 0;
return;
}
ValveBackToOrigin(index, -1);
}
}
2024-12-13 08:31:59 +00:00
/**
*
*
*
* @param index
* @return 0: :
*/
2024-12-23 07:52:28 +00:00
uint8_t ValvePPInit(uint8_t index) {
uint8_t rst = systemStatus.rst;
log_i("set mode to PP\r\n");
2024-12-12 07:40:28 +00:00
// 1.配置模式:
// 00B1h=0、运行模式 03C2h=0x01使设备工作在轮廓位置模式
SetValveCOMMMode(index, RTU_VALVE_CFG_COMM_CIA402);
SetValveRunMode(index, RTU_VALVE_CFG_MODE_PP);
2024-12-12 08:44:18 +00:00
// 2.2写当前段位移指令匀速运行速度 (03F8h) (用户单位/s)
2024-12-12 08:38:51 +00:00
SetValvePPSpeed(index, 10000);
2024-12-12 08:44:18 +00:00
// 2.3设置位移的加速度 (03FCh)(用户单位/s2)
2024-12-12 08:38:51 +00:00
SetValvePPAcc(index, 40000);
2024-12-12 08:44:18 +00:00
// 2.4设置位移的减速度 (03FEh)(用户单位/s2)
2024-12-12 08:38:51 +00:00
SetValvePPDec(index, 40000);
2024-12-12 07:40:28 +00:00
// 3.写控制字使电机使能
2024-12-13 02:54:29 +00:00
// (0380h)= 0x06→0x07→ 0x0F 电机使能:
2024-12-12 08:38:51 +00:00
SetValveFunc(index, RTU_VALVE_CFG_PREPARE);
2024-12-12 07:40:28 +00:00
SetValveFunc(index, RTU_VALVE_CFG_DISABLE);
2024-12-12 08:38:51 +00:00
SetValveFunc(index, RTU_VALVE_CFG_ENABLE);
if (rst != systemStatus.rst)
{
log_e("ValvePPInit[%d] failed!",index);
systemStatus.ds.initStatus = INIT_FAILED;
}
2024-12-12 08:38:51 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param index
2024-12-13 09:08:28 +00:00
* @param angle 0-360
2024-12-13 08:31:59 +00:00
* @return 0: :
*/
2024-12-12 08:38:51 +00:00
uint8_t ValveRunToAngle(uint8_t index, uint32_t angle) {
uint8_t rst = systemStatus.rst;
log_i("set angel to %d\r\n",angle);
2024-12-13 09:08:28 +00:00
// 限制角度的逻辑不在这里,此处只执行控制逻辑
if(angle > 360) {
log_e("阀门角度设置错误");
2024-12-12 08:38:51 +00:00
return 1;
}
2024-12-13 09:08:28 +00:00
2024-12-12 08:38:51 +00:00
// 其它配置不变的情况下只需要写3个控制字
SetValvePPPos(index, (uint32_t)(angle*dp.valve[index].fullCount/360+dp.valve[index].offsetPos));
2024-12-12 08:38:51 +00:00
// 电机以绝对位置,立即更新的方式运行
2024-12-12 08:44:18 +00:00
// (电机是以控制字 6040h(0380h)的 bit4 的上升沿接收新的位置命令,
// 所以每次执行完一次运行后需 要把此位清零。)
2024-12-12 07:40:28 +00:00
SetValveFunc(index, 0x2F);
SetValveFunc(index, 0x3F);
if(rst != systemStatus.rst) {
log_e("ValveRunToAngle[%d] failed!",index);
systemStatus.ds.initStatus = INIT_FAILED;
}
2024-12-12 07:40:28 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
* PP
2024-12-13 08:31:59 +00:00
*
* @return 0: :
*/
2024-12-12 08:38:51 +00:00
uint8_t InitValve(void) {
2024-12-23 03:13:24 +00:00
printf("InitValve\n");
2024-12-12 08:38:51 +00:00
2024-12-23 15:14:35 +00:00
ValvePPInit(0);
// ValvePPInit(1);
2024-12-12 08:38:51 +00:00
}
void ReadValveSpeedPos(void)
{
for(uint8_t index = 0; index < 2; index++) {
systemStatus.valvesSpeed[index] = ReadValveSpeed(index);
// systemStatus.valvesSpeedPercent[index] = transSpeedToSpeedPercent(index, systemStatus.valvesSpeed[index]);
systemStatus.valvesPos[index] = ReadValvePos(index);
systemStatus.ds.valves.angle[index] = systemStatus.valvesPos[index]*360/dp.valve[index].fullCount;
}
}
/**
*
*/
void updateValveStatus(void)
{
valveCheckBTOResult(0);
valveCheckBTOResult(1);
//alarm
}
/**
*
*
* @param index
*/
void stopValve(uint8_t index) {
SetValveFunc(index, RTU_VALVE_CFG_DISABLE);
SetValveFunc(index, RTU_VALVE_CFG_ENABLE);
}
2024-12-13 08:31:59 +00:00
/**
*
* 线
*/
// void InitDeviceStatus() {
// // 初始化泵
2024-12-13 02:54:29 +00:00
2024-12-11 02:32:35 +00:00
// // 更新设备状态
// updateDeviceStatus(SENSOR_ONLINE);
// updateValveStatus(1, 120);
// updateValveStatus(2, 210);
// updatePumpStatus(1, PUMP_CLOCKWISE);
// updatePumpStatus(2, PUMP_ANTICLOCKWISE);
// updatePumpSpeedStatus(1, 100);
// updatePumpSpeedStatus(2, 100);
// updateBubbleSensor(BUBBLE_DETECTED);
// updateEmergencyStop(ESTOP_NORMAL);
// updateInitStatus(INIT_SUCCESS);
// }
2024-12-13 08:31:59 +00:00
2024-12-23 09:27:49 +00:00
/**
* valve和pump的信息
*
2024-12-23 09:27:49 +00:00
*/
void updateVPInfo(void)
2024-12-23 07:52:28 +00:00
{
// 获取回归状态
2024-12-23 07:52:28 +00:00
// 获取泵实时速度、位置
ReadPumpSpeedPos();
2024-12-23 07:52:28 +00:00
// 获取阀门实时速度、位置
ReadValveSpeedPos();
2024-12-23 07:52:28 +00:00
}
2024-12-23 09:27:49 +00:00
//在主循环中调用
/**
*
*/
void updateSystemStatus(void)
{
updateVPInfo();
updatePumpStatus();
updateValveStatus();
2024-12-23 09:27:49 +00:00
}
2024-12-23 15:14:35 +00:00
/**
*
* HOST_CMD_SYSTEM_INIT=0x0007
2024-12-23 15:14:35 +00:00
*/
void initCTLSystem(void)
2024-12-23 15:14:35 +00:00
{
systemStatus.ds = deviceStatus;
systemStatus.ds.initStatus = INIT_IN_PROGRESS;
systemStatus.rst = 0;
2024-12-23 15:14:35 +00:00
InitValve();
InitPump();
2024-12-23 15:14:35 +00:00
}
/**
*
* :+(2Byte)+(1Byte)+(NByte)+CRC16校验位+
*
* @param funcCode
*/
static void packMsgToHost(uint16_t funcCode, uint8_t isOK) {
// 实现打包消息到上位机逻辑
// 帧头+功能码(2Byte)+数据长度(1Byte)+ 具体数据(NByte)+CRC16校验位+帧尾
uint8_t msgBuf[64];//最大为4+2+1+15+2+4=28
uint8_t len = 0;
uint8_t dlen = 0;
uint8_t index = 0;
FillBigEndian32(msgBuf, FRAME_HEADER);
FillBigEndian16(msgBuf+sizeof(FRAME_HEADER), funcCode);
if(funcCode == HOST_CMD_STATUS_QUERY) {
dlen = sizeof(DeviceStatus_t);
index = sizeof(FRAME_HEADER)+2;
msgBuf[index] = dlen;
index += 1;
memcpy(msgBuf+index, &deviceStatus, dlen);
index += dlen;
uint16_t crc = CalculateCRC16(msgBuf+4, index-4);//不包含帧头
FillBigEndian16(msgBuf+index, crc);
index += 2;
FillBigEndian32(msgBuf+index, FRAME_TAIL);
len = index+4;
}
else {
dlen = 1;
index = sizeof(FRAME_HEADER)+2;
msgBuf[index] = dlen;
index += 1;
msgBuf[index] = isOK;
index += 1;
uint16_t crc = CalculateCRC16(msgBuf+4, index-4);//不包含帧头
FillBigEndian16(msgBuf+index, crc);
index += 2;
FillBigEndian32(msgBuf+index, FRAME_TAIL);
len = index+4;
}
// 发送数据
sendMsgToHost(msgBuf, len);
}
2024-12-10 12:01:16 +00:00
// 初始化处理
2024-12-13 02:54:29 +00:00
static uint8_t HandleInit(void) {
2024-12-10 12:01:16 +00:00
// 实现初始化逻辑
2024-12-23 07:52:28 +00:00
// 1.更新状态为“初始化中”
// 2.执行默认的初始化内容,此步骤系统上电后会自动执行
// 3.执行协议初始化流程
// 4.检查初始化结果,更新状态“成功”或“失败”
// 3.协议要求内容为2个三通阀步进电机堵转找原点重复至少2次然后各自转至120°。
systemStatus.ds.initStatus = INIT_IN_PROGRESS;
systemStatus.rst = 0;
initCTLSystem();
ValveBackToOrigin(0,-1);
ValveBackToOrigin(1,-1);
if(systemStatus.rst != 0) {
log_e("系统初始化失败");
systemStatus.ds.initStatus = INIT_FAILED;
return ACK_FAILED;
}
return ACK_OK;
2024-12-11 02:32:35 +00:00
}
// 状态查询处理
2024-12-13 08:31:59 +00:00
/**
*
*
* @return 0: :
*/
static void HandleStatusQuery(void) {
packMsgToHost(HOST_CMD_STATUS_QUERY, ACK_OK);
2024-12-11 02:32:35 +00:00
}
// 三通阀控制处理
2024-12-13 08:31:59 +00:00
/**
*
2024-12-13 08:31:59 +00:00
*
* @param Buff
* @param len
* @return 0: :
*/
2024-12-11 02:32:35 +00:00
static uint8_t HandleValveControl(uint8_t *Buff, uint8_t len) {
// 实现三通阀控制逻辑
if(len != 8) {
2024-12-13 02:54:29 +00:00
log_e("三通阀控制错误");
return 1;
2024-12-11 02:32:35 +00:00
}
// for
2024-12-11 02:32:35 +00:00
uint8_t index = Buff[0];
2024-12-13 09:08:28 +00:00
uint8_t direction = Buff[1];//此状态位无效目前三通阀有硬件限位且指定角度必须为120或210
2024-12-11 02:32:35 +00:00
uint16_t angle = (Buff[2]<<8) | Buff[3];
if (angle > 360 || angle != VALVE_ANGLE_120 || angle != VALVE_ANGLE_210) {
2024-12-13 02:54:29 +00:00
log_e("三通阀控制错误");
2024-12-11 02:32:35 +00:00
return 1;
}
// 具体实现
2024-12-13 09:08:28 +00:00
ValveRunToAngle(index,angle);
2024-12-11 02:32:35 +00:00
return 0;
}
// 泵时长控制处理
2024-12-13 08:31:59 +00:00
/**
*
*
* @param Buff
2024-12-13 08:31:59 +00:00
* @param len
* @return 0: :
*/
2024-12-11 02:32:35 +00:00
static uint8_t HandlePumpTimeControl(uint8_t *Buff, uint8_t len) {
// 实现泵时长控制逻辑方向1字节时长2字节。全FF跳过
// 1表示启动泵顺时针转动2表示启动泵的逆时针转动0表示停止泵
// 时间为0则表示一直转
uint8_t rst = systemStatus.rst;
for(uint8_t index = 0; index < len; index++) {
2024-12-11 02:32:35 +00:00
if(memcmp(Buff+index*3, "\xFF\xFF\xFF", 3) == 0) {
continue;
}
int8_t direction = Buff[index*3];
if(direction == 0) {
StopPump(index);
continue;
}
if(direction == 2) {
direction = -1;
}
uint16_t time = (Buff[index*3+1]<<8) | Buff[index*3+2];
if(time == 0) {
// 方向控制办法待确定
StartPumpJog(index);
continue;
}
// 使用步数方式更靠谱,通过时间和速度计算步数,结束时不用发送停止命令
int32_t step = direction*time*dp.pump[index].speed*dp.pump[index].speedPercent/100;
SetPumpStepTarget(index, step);
StartPumpRelativeMove(index);
if(rst != systemStatus.rst) {
log_e("泵时长控制错误");
return ACK_FAILED;
}
}
return ACK_OK;
2024-12-11 02:32:35 +00:00
}
// 泵速度设置处理
2024-12-13 08:31:59 +00:00
/**
*
*
* @param Buff
* @param len
* @return 0: :
*/
2024-12-11 02:32:35 +00:00
static uint8_t HandlePumpSpeedControl(uint8_t *Buff, uint8_t len) {
// 1个字节为速度百分比全FF跳过
for (size_t index = 0; index < len; index++)
{
uint8_t rst = systemStatus.rst;
uint8_t speedPercent = Buff[index];
if (speedPercent == 0xFF)
{
continue;
}
if (speedPercent > 100) {
log_e("泵速度设置错误");
return ACK_FAILED;
}
//更新参数
systemStatus.ds.pumps.speed[index] = speedPercent;
// 写入指令
uint16_t speed = transSpeedPercentToSpeed(index, speedPercent);
SetPumpJogSpeed(index, speed);
SetPumpStepSpeed(index, speed);
2024-12-11 02:32:35 +00:00
if(rst != systemStatus.rst) {
log_e("泵速度设置错误");
return ACK_FAILED;
}
}
return ACK_OK;
2024-12-11 02:32:35 +00:00
}
2024-12-13 08:31:59 +00:00
// 泵步进控制处理
/**
*
*
* @param Buff
* @param len
* @return 0: :
*/
2024-12-11 02:32:35 +00:00
static uint8_t HandlePumpStepControl(uint8_t *Buff, uint8_t len) {
// 4字节步进全FF跳过
for (size_t index = 0; index < len; index++)
{
if(memcmp(Buff+index*4, "\xFF\xFF\xFF\xFF", 4) == 0) {
continue;
}
uint8_t rst = systemStatus.rst;
uint8_t index = Buff[index*4];
int32_t step = (Buff[index*4+1]<<24) | (Buff[index*4+2]<<16) | (Buff[index*4+3]<<8) | Buff[index*4+4];
SetPumpStepTarget(index, step);
StartPumpRelativeMove(index);
if(rst != systemStatus.rst) {
log_e("泵步进设置错误");
return ACK_FAILED;
}
2024-12-11 02:32:35 +00:00
}
return ACK_OK;
2024-12-10 12:01:16 +00:00
}
2024-12-13 08:31:59 +00:00
/**
*
*
* @param rxBuf
* @param rxLen
* @return 0: 1:
*/
2024-12-11 02:32:35 +00:00
static uint8_t HandleSoftStop(uint8_t *rxBuf, uint16_t rxLen) {
if(rxLen != 1) {
2024-12-13 02:54:29 +00:00
log_e("软急停设置错误");
return ACK_FAILED;
2024-12-11 02:32:35 +00:00
}
// 实现软急停功能逻辑
if(rxBuf[0] == 0) {
// 正常状态
systemStatus.ds.estopStatus = ESTOP_NORMAL;
2024-12-11 02:32:35 +00:00
}
else {
// 急停状态
uint8_t rst = systemStatus.rst;
2024-12-11 07:55:40 +00:00
StopPump(0);
StopPump(1);
2024-12-13 09:56:20 +00:00
// StopPumpJog(0);
// StopPumpJog(1);
stopValve(0);
stopValve(1);
if(rst != systemStatus.rst) {
log_e("软急停错误");
return ACK_FAILED;
}
systemStatus.ds.estopStatus = ESTOP_PRESSED;
2024-12-13 08:00:24 +00:00
}
return ACK_OK;
2024-12-13 08:00:24 +00:00
}
2024-12-11 02:32:35 +00:00
2024-12-13 08:31:59 +00:00
/**
*
*
* @param rxBuf
* @param rxLen
* @return
*/
2024-12-19 14:49:20 +00:00
CmdFrameError_t checkHostCmd(uint8_t *rxBuf, uint8_t rxLen) {
2024-12-11 02:32:35 +00:00
// 检查命令是否正确
2024-12-13 08:31:59 +00:00
// FRAME_HEADER是按小端序存储的而rxBuf是按大端序存的
2024-12-13 09:08:28 +00:00
uint8_t header[sizeof(FRAME_HEADER)];
FillBigEndian32(header, FRAME_HEADER);
uint8_t tail[sizeof(FRAME_TAIL)];
FillBigEndian32(tail, FRAME_TAIL);
2024-12-13 08:00:24 +00:00
2024-12-13 09:08:28 +00:00
if(memcmp(rxBuf, header, sizeof(FRAME_HEADER)) != 0)
2024-12-11 02:32:35 +00:00
{
log_e("CMD_FRAME_HEADER_ERROR\r\n");
2024-12-11 02:32:35 +00:00
return CMD_FRAME_HEADER_ERROR;
}
2024-12-13 08:00:24 +00:00
2024-12-13 09:08:28 +00:00
if (memcmp(rxBuf + rxLen - sizeof(FRAME_TAIL), tail, sizeof(FRAME_TAIL)) != 0)
2024-12-11 02:32:35 +00:00
{
log_e("CMD_FRAME_TAIL_ERROR\r\n");
2024-12-11 02:32:35 +00:00
return CMD_FRAME_TAIL_ERROR;
}
2024-12-19 14:49:20 +00:00
uint16_t crc = CalculateCRC16(rxBuf+sizeof(FRAME_HEADER), rxLen - sizeof(FRAME_HEADER)-sizeof(FRAME_TAIL)-2); // 计算crc不包含帧头和帧尾和crc自身
if (((rxBuf[rxLen-sizeof(FRAME_TAIL)-2]<<8) | rxBuf[rxLen-sizeof(FRAME_TAIL)-1]) != crc)
2024-12-11 02:32:35 +00:00
{
log_e("CMD_FRAME_CHECK_ERROR\r\n");
2024-12-11 02:32:35 +00:00
return CMD_FRAME_CHECK_ERROR;
}
return CMD_FRAME_OK;
}
2024-12-13 08:31:59 +00:00
/**
*
* ,modbus协议
*
* @param rxBuf
* @param rxLen
* @return
*/
void ProcessHostCommand(uint8_t *rxBuf, uint8_t rxLen) {
2024-12-11 02:32:35 +00:00
if (checkHostCmd(rxBuf, rxLen) != CMD_FRAME_OK)
2024-12-11 02:32:35 +00:00
{
log_e("命令错误");
return;
2024-12-11 02:32:35 +00:00
}
uint8_t error = 0;
2024-12-11 02:32:35 +00:00
uint16_t cmdCode = (rxBuf[sizeof(FRAME_HEADER)] << 8) | rxBuf[sizeof(FRAME_HEADER)+1];//提取命令码
uint8_t dataLen = rxBuf[sizeof(FRAME_HEADER)+2];//提取数据长度
uint8_t *data = &rxBuf[sizeof(FRAME_HEADER)+3];//提取数据
2024-12-10 12:01:16 +00:00
switch(cmdCode) {
2024-12-13 08:00:24 +00:00
case HOST_CMD_STATUS_QUERY:
HandleStatusQuery();
2024-12-10 12:01:16 +00:00
break;
2024-12-13 08:00:24 +00:00
case HOST_CMD_VALVE_CTRL:
2024-12-11 02:32:35 +00:00
error = HandleValveControl(data, dataLen);
packMsgToHost(HOST_CMD_VALVE_CTRL, error);
2024-12-10 12:01:16 +00:00
break;
2024-12-13 08:00:24 +00:00
case HOST_CMD_PUMP_RUN_TIME:
2024-12-11 02:32:35 +00:00
error = HandlePumpTimeControl(data, dataLen);
packMsgToHost(HOST_CMD_PUMP_RUN_TIME, error);
2024-12-10 12:01:16 +00:00
break;
2024-12-13 08:00:24 +00:00
case HOST_CMD_PUMP_RUN_SPEED:
2024-12-11 02:32:35 +00:00
error = HandlePumpSpeedControl(data, dataLen);
packMsgToHost(HOST_CMD_PUMP_RUN_SPEED, error);
2024-12-10 12:01:16 +00:00
break;
2024-12-13 08:00:24 +00:00
case HOST_CMD_SOFT_STOP:
2024-12-11 02:32:35 +00:00
error = HandleSoftStop(data, dataLen);
packMsgToHost(HOST_CMD_SOFT_STOP, error);
2024-12-10 12:01:16 +00:00
break;
2024-12-13 08:00:24 +00:00
case HOST_CMD_PUMP_RUN_STEP:
error = HandlePumpStepControl(data, dataLen);
packMsgToHost(HOST_CMD_PUMP_RUN_STEP, error);
2024-12-10 12:01:16 +00:00
break;
2024-12-13 08:00:24 +00:00
case HOST_CMD_SYSTEM_INIT:
2024-12-13 02:54:29 +00:00
error = HandleInit();
packMsgToHost(HOST_CMD_SYSTEM_INIT, error);
2024-12-10 12:01:16 +00:00
break;
default:
2024-12-11 02:32:35 +00:00
error = CMD_FRAME_CMD_ERROR;
2024-12-10 12:01:16 +00:00
break;
}
2024-12-11 02:32:35 +00:00
return error;
2024-12-13 02:54:29 +00:00
}
2024-12-19 14:49:20 +00:00
void runPumpDemo(void) {
2024-12-22 14:29:17 +00:00
printf("runPumpDemo\r\n");
// printf("InitPump\n");
2024-12-23 09:27:49 +00:00
InitPump();
2024-12-19 14:49:20 +00:00
// 泵1正转100步
printf("SetPumpStepTarget(0, 100)\n");
2024-12-22 14:29:17 +00:00
SetPumpStepTarget(0, 200000);
2024-12-19 14:49:20 +00:00
printf("StartPumpRelativeMove(0)\n");
StartPumpRelativeMove(0);
2024-12-23 03:13:24 +00:00
// HAL_Delay(1000);
2024-12-19 14:49:20 +00:00
// 泵1反转100步
printf("SetPumpStepTarget(0, -100)\n");
2024-12-22 14:29:17 +00:00
SetPumpStepTarget(1, -300000);
2024-12-19 14:49:20 +00:00
printf("StartPumpRelativeMove(0)\n");
2024-12-22 14:29:17 +00:00
StartPumpRelativeMove(1);
2024-12-23 03:13:24 +00:00
// HAL_Delay(1000);
2024-12-23 09:27:49 +00:00
// printf("StopPump(0)\n");
// StopPump(0);
2024-12-23 03:13:24 +00:00
// HAL_Delay(1000);
2024-12-22 14:29:17 +00:00
}
void runValveDemo(void) {
printf("runValveDemo\r\n");
ValveBackToOrigin(0,-1);
HAL_Delay(5000);
2024-12-22 14:29:17 +00:00
// 阀门1正转120度
printf("ValveRunToAngle(0, 120)\n");
2024-12-23 07:52:28 +00:00
ValvePPInit(0);
2024-12-22 14:29:17 +00:00
ValveRunToAngle(0, 120);
}