update HardWareManager
This commit is contained in:
parent
f9521a72e7
commit
1a04ca2689
@ -90,7 +90,7 @@ target_link_libraries(cmvr_es PRIVATE
|
||||
cmvr_es::utils
|
||||
cmvr_es::service
|
||||
cmvr_es::monitor
|
||||
cmvr_es::hardware
|
||||
cmvr_es::hardware_manager
|
||||
cmvr_es::httpclient
|
||||
cmvr_es::device::canbus
|
||||
cmvr_es::device::ti5motor
|
||||
|
||||
@ -6,15 +6,16 @@
|
||||
#define CMVR_ES_CAN_GROUP_H
|
||||
|
||||
#include "motor_protocol/motorprotocolmanager.h"
|
||||
namespace cmvr::device
|
||||
namespace cmvr::hardware
|
||||
{
|
||||
class CanGroup
|
||||
{
|
||||
public:
|
||||
explicit CanGroup(const XmlNode &cfg);
|
||||
~CanGroup() = default;
|
||||
private:
|
||||
|
||||
|
||||
private:
|
||||
std::string id_;
|
||||
unsigned int channelId_;
|
||||
bool enable_;
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
#include "rapidxml/rapidxml.hpp"
|
||||
#include "can_group.h"
|
||||
namespace cmvr::device
|
||||
namespace cmvr::hardware
|
||||
{
|
||||
class CanManager
|
||||
{
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#define CMVR_ES_ABSTRACTMOTORPROTOCOL_H
|
||||
#include "rapidxml/xml_parser.h"
|
||||
|
||||
namespace cmvr::device
|
||||
namespace cmvr::hardware
|
||||
{
|
||||
class AbstractMotorProtocol
|
||||
{
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#include <memory>
|
||||
#include "abstractmotorprotocol.h"
|
||||
|
||||
namespace cmvr::device
|
||||
namespace cmvr::hardware
|
||||
{
|
||||
class MotorProtocolManager
|
||||
{
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#include "rapidxml/xml_parser.h"
|
||||
#include "abstractmotorprotocol.h"
|
||||
namespace cmvr::device{
|
||||
namespace cmvr::hardware{
|
||||
class Ti5MotorProtocol final : public AbstractMotorProtocol {
|
||||
public:
|
||||
explicit Ti5MotorProtocol(const XmlNode &cfg);
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#ifndef CMVR_ES_SERIAL_MANAGER_H
|
||||
#define CMVR_ES_SERIAL_MANAGER_H
|
||||
#include "rapidxml/xml_parser.h"
|
||||
namespace cmvr::device
|
||||
namespace cmvr::hardware
|
||||
{
|
||||
class SerialManager
|
||||
{
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#include "rapidxml/xml_parser.h"
|
||||
#include "hardware/can/can_manager.h"
|
||||
namespace cmvr::device {
|
||||
namespace cmvr::hardware {
|
||||
|
||||
class HardwareFactory {
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#include <mutex>
|
||||
#include "hardware_factory.h"
|
||||
#include "hardware/can/can_manager.h"
|
||||
namespace cmvr::device
|
||||
namespace cmvr::hardware
|
||||
{
|
||||
class HardWareManager
|
||||
{
|
||||
|
||||
@ -11,7 +11,7 @@ find_package(ALSA REQUIRED)
|
||||
add_library(cmvr::device::head_esp32 ALIAS head_esp32)
|
||||
|
||||
# 链接依赖库
|
||||
target_link_libraries(head_esp32 PRIVATE ALSA::ALSA )
|
||||
target_link_libraries(head_esp32 PRIVATE ALSA::ALSA cmvr_es::hardware::serial)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#define CMVR_ES_BIOHEAD_ESP32_H
|
||||
|
||||
#include "devices/abstract_biohead.h"
|
||||
#include "hardware/esp32_serial_port.h"
|
||||
#include "../../../../include/hardware/serial/RS485/esp32_serial_port.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
@ -4,4 +4,4 @@ target_include_directories(rh56dftp_dexhand PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_library(cmvr_es::device::rh56dftp_dexhand ALIAS rh56dftp_dexhand)
|
||||
|
||||
target_link_libraries(rh56dftp_dexhand PRIVATE cmvr_es::hardware -lmodbus)
|
||||
target_link_libraries(rh56dftp_dexhand PRIVATE cmvr_es::hardware_manager -lmodbus)
|
||||
@ -234,7 +234,32 @@ void RH56DFTPDexhand::init() {
|
||||
|
||||
LOG(INFO)<< "[RH56DFTPDexhand](init) sucess, id="<< id_;
|
||||
}
|
||||
std::vector<std::string> parse_error(unsigned char errorCode) {
|
||||
|
||||
std::vector<std::string> faults;
|
||||
|
||||
// 直接判断每一位是否为1
|
||||
if (errorCode & (1 << 0)) { // Bit0: 堵转故障
|
||||
faults.emplace_back("堵转故障");
|
||||
}
|
||||
|
||||
if (errorCode & (1 << 1)) { // Bit1: 过温故障
|
||||
faults.emplace_back("过温故障");
|
||||
}
|
||||
|
||||
if (errorCode & (1 << 2)) { // Bit2: 过流故障
|
||||
faults.emplace_back("过流故障");
|
||||
}
|
||||
|
||||
if (errorCode & (1 << 3)) { // Bit3: 电机异常
|
||||
faults.emplace_back("电机异常");
|
||||
}
|
||||
|
||||
if (errorCode & (1 << 4)) { // Bit4: 通讯故障
|
||||
faults.emplace_back("通讯故障");
|
||||
}
|
||||
return faults;
|
||||
}
|
||||
void RH56DFTPDexhand::updateState() {
|
||||
//读取数据,初始化
|
||||
std::vector<int> parsed_values;
|
||||
@ -320,36 +345,6 @@ void RH56DFTPDexhand::updateState() {
|
||||
}
|
||||
}
|
||||
}
|
||||
void printPinkySensorData(const HandTactileSensors& sensors) {
|
||||
// 打印小拇指指端数据
|
||||
std::cout << "=== 小拇指指端数据 (" << sensors.pinky.tip.rows << "x" << sensors.pinky.tip.cols << ") ===\n";
|
||||
for (const auto& row : sensors.pinky.tip.data) {
|
||||
for (TactilePoint value : row) {
|
||||
std::cout << std::setw(5) << value; // 每个值占5个字符宽度
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
// 打印小拇指指尖数据
|
||||
std::cout << "=== 小拇指指尖数据 (" << sensors.pinky.finger.rows << "x" << sensors.pinky.finger.cols << ") ===\n";
|
||||
for (const auto& row : sensors.pinky.finger.data) {
|
||||
for (TactilePoint value : row) {
|
||||
std::cout << std::setw(5) << value;
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
// 打印小拇指指腹数据
|
||||
std::cout << "=== 小拇指指腹数据 (" << sensors.pinky.pad.rows << "x" << sensors.pinky.pad.cols << ") ===\n";
|
||||
for (const auto& row : sensors.pinky.pad.data) {
|
||||
for (TactilePoint value : row) {
|
||||
std::cout << std::setw(5) << value;
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void RH56DFTPDexhand::updateSensorData() {
|
||||
//触觉传感器数据。
|
||||
|
||||
@ -11,9 +11,8 @@
|
||||
#include <condition_variable>
|
||||
#include <modbus/modbus.h>
|
||||
#include <boost/lockfree/spsc_queue.hpp>
|
||||
#include "../../../../include/utils/base/os.h"
|
||||
#include "utils/base/os.h"
|
||||
#include "devices/abstract_dexhand.h"
|
||||
#include "hardware/serial_interface.h"
|
||||
|
||||
namespace cmvr::device {
|
||||
|
||||
@ -67,8 +66,6 @@ namespace cmvr::device {
|
||||
int default_force_;//上电的力控阈值
|
||||
int default_speed_;//上电的自由角转动速度
|
||||
|
||||
std::shared_ptr<serial_interface> serial_;
|
||||
|
||||
std::string ip_address_;
|
||||
int port_;
|
||||
std::shared_ptr<ModbusController> controller_;
|
||||
|
||||
@ -1,18 +1,3 @@
|
||||
add_subdirectory(can)
|
||||
add_subdirectory(serial)
|
||||
|
||||
add_library(hardware SHARED
|
||||
esp32_serial_port.cpp
|
||||
serial_interface.cpp
|
||||
)
|
||||
|
||||
target_include_directories(hardware PUBLIC
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
target_link_libraries(hardware PRIVATE
|
||||
cmvr_es::can
|
||||
cmvr_es::serial
|
||||
)
|
||||
add_library(cmvr_es::hardware ALIAS hardware)
|
||||
|
||||
|
||||
@ -11,4 +11,4 @@ target_link_libraries(can PRIVATE
|
||||
cmvr_es::motor_protocol
|
||||
)
|
||||
|
||||
add_library(cmvr_es::can ALIAS can)
|
||||
add_library(cmvr_es::hardware::can ALIAS can)
|
||||
@ -5,7 +5,7 @@
|
||||
#include "hardware/can/can_group.h"
|
||||
#include <glog/logging.h>
|
||||
using namespace std;
|
||||
using namespace cmvr::device;
|
||||
using namespace cmvr::hardware;
|
||||
|
||||
CanGroup::CanGroup(const XmlNode &cfg)
|
||||
{
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#include <glog/logging.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace cmvr::device;
|
||||
using namespace cmvr::hardware;
|
||||
|
||||
CanManager::CanManager(const XmlNode& cfg)
|
||||
{
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
#include <glog/logging.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace cmvr::device;
|
||||
using namespace cmvr::hardware;
|
||||
|
||||
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
//
|
||||
|
||||
#include "hardware/can/motor_protocol/ti5motorprotocol.h"
|
||||
using namespace cmvr::device;
|
||||
using namespace cmvr::hardware;
|
||||
|
||||
Ti5MotorProtocol::Ti5MotorProtocol(const XmlNode &cfg):AbstractMotorProtocol(cfg)
|
||||
{
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
|
||||
#add_subdirectory(IO)
|
||||
add_subdirectory(RS485)
|
||||
|
||||
add_library(serial
|
||||
serial_manager.cpp
|
||||
)
|
||||
@ -5,7 +9,7 @@ add_library(serial
|
||||
target_include_directories(serial PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
||||
|
||||
target_link_libraries(serial PRIVATE
|
||||
protobuf::libprotobuf
|
||||
cmvr_es::hardware::rs485
|
||||
)
|
||||
|
||||
add_library(cmvr_es::serial ALIAS serial)
|
||||
add_library(cmvr_es::hardware::serial ALIAS serial)
|
||||
9
src/hardware/serial/RS485/CMakeLists.txt
Normal file
9
src/hardware/serial/RS485/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
||||
add_library(rs485 SHARED
|
||||
esp32_serial_port.cpp
|
||||
)
|
||||
|
||||
target_include_directories(rs485 PUBLIC
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
add_library(cmvr_es::hardware::rs485 ALIAS rs485)
|
||||
@ -1,5 +1,5 @@
|
||||
// esp32_serial_port.cpp
|
||||
#include "hardware/esp32_serial_port.h"
|
||||
#include "hardware/serial/RS485/esp32_serial_port.h"
|
||||
#include <iostream>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
@ -5,7 +5,7 @@
|
||||
#include "hardware/serial/serial_manager.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cmvr::device;
|
||||
using namespace cmvr::hardware;
|
||||
|
||||
SerialManager::SerialManager(const XmlNode &cfg)
|
||||
{
|
||||
|
||||
@ -1,512 +0,0 @@
|
||||
//
|
||||
// Created by xtkuang on 2025/5/6.
|
||||
//
|
||||
|
||||
#include "hardware/serial_interface.h"
|
||||
#include <iostream>
|
||||
#include <bitset>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <random>
|
||||
#include <chrono>
|
||||
#include <glog/logging.h>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
|
||||
using namespace boost::asio;
|
||||
|
||||
// 地址转换和二进制转十六进制函数
|
||||
std::string convertAddressToBinary_read(int address_dec, const std::string& id_value) {
|
||||
std::string address_bin = std::bitset<32>(address_dec).to_string();
|
||||
size_t first_one = address_bin.find('1');
|
||||
|
||||
if (first_one != std::string::npos) {
|
||||
address_bin = address_bin.substr(first_one);
|
||||
} else {
|
||||
address_bin = "0";
|
||||
}
|
||||
|
||||
std::string formatted_output = "0000000" + address_bin + "000000000000" + id_value;
|
||||
return formatted_output;
|
||||
}
|
||||
|
||||
std::string convertAddressToBinary_write(int address_dec, const std::string& id_value) {
|
||||
std::string address_bin = std::bitset<32>(address_dec).to_string();
|
||||
size_t first_one = address_bin.find('1');
|
||||
|
||||
if (first_one != std::string::npos) {
|
||||
address_bin = address_bin.substr(first_one);
|
||||
} else {
|
||||
address_bin = "0";
|
||||
}
|
||||
|
||||
std::string formatted_output = "0000010" + address_bin + "000000000000" + id_value;
|
||||
return formatted_output;
|
||||
}
|
||||
|
||||
std::string binaryToHex(const std::string& binary_string) {
|
||||
unsigned long decimal_value = std::stoul(binary_string, nullptr, 2);
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::uppercase << decimal_value;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// 处理十六进制数据的函数
|
||||
std::vector<unsigned char> processHexData(const std::string& hex_data) {
|
||||
std::string padded_hex = hex_data;
|
||||
if (padded_hex.length() < 8) {
|
||||
padded_hex = std::string(8 - padded_hex.length(), '0') + padded_hex;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> processed_data;
|
||||
|
||||
for (size_t i = padded_hex.length(); i > 0; i -= 2) {
|
||||
std::string byte_str = padded_hex.substr(i - 2, 2);
|
||||
unsigned char byte_value = static_cast<unsigned char>(std::stoi(byte_str, nullptr, 16));
|
||||
processed_data.push_back(byte_value);
|
||||
}
|
||||
|
||||
return processed_data;
|
||||
}
|
||||
|
||||
namespace cmvr {
|
||||
// 构造函数,初始化串口参数
|
||||
serial_interface::serial_interface(const std::string& port, unsigned int baudrate, CommunicationMode mode) : io(), comm_mode(mode),timer(io), timeout(false) {
|
||||
try {
|
||||
serial = std::make_shared<serial_port>(io, port);
|
||||
serial->set_option(serial_port_base::baud_rate(baudrate));
|
||||
serial->set_option(serial_port_base::character_size(8)); // 数据位
|
||||
serial->set_option(serial_port_base::parity(serial_port_base::parity::none)); // 无校验位
|
||||
serial->set_option(serial_port_base::stop_bits(serial_port_base::stop_bits::one)); // 1个停止位
|
||||
is_initialized = true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
is_initialized = false;
|
||||
LOG(ERROR) << "[serial_interface] ([serial_interface]): Failed to init serialport: " << e.what();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool serial_interface::isInitialized() {
|
||||
return is_initialized;
|
||||
}
|
||||
|
||||
void serial_interface::on_timeout(const boost::system::error_code& ec) {
|
||||
if (!ec) {
|
||||
timeout = true;
|
||||
serial->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void serial_interface::on_read_complete(const boost::system::error_code& ec, size_t bytes_transferred, boost::system::error_code* out_ec, size_t* out_bytes_transferred) {
|
||||
*out_ec = ec;
|
||||
*out_bytes_transferred = bytes_transferred;
|
||||
timer.cancel();
|
||||
}
|
||||
|
||||
// 向串口写入数据
|
||||
void serial_interface::write(const std::vector<unsigned char>& data) {
|
||||
if (comm_mode == CommunicationMode::RS485) {
|
||||
boost::asio::write(*serial, buffer(data));
|
||||
} else if (comm_mode == CommunicationMode::CAN) {
|
||||
// CAN模式下的写入逻辑,这里简化为和RS485相同,可根据实际情况修改
|
||||
boost::asio::write(*serial, buffer(data));
|
||||
}
|
||||
}
|
||||
|
||||
// 从串口读取指定长度的数据
|
||||
std::vector<unsigned char> serial_interface::read(size_t length) {
|
||||
std::vector<unsigned char> buffer(length);
|
||||
if (comm_mode == CommunicationMode::RS485) {
|
||||
boost::asio::read(*serial, boost::asio::buffer(buffer.data(), length));
|
||||
} else if (comm_mode == CommunicationMode::CAN) {
|
||||
timeout = false;
|
||||
int timeout_ms = 1000;
|
||||
timer.expires_after(std::chrono::milliseconds(timeout_ms));
|
||||
timer.async_wait(boost::bind(&serial_interface::on_timeout, this, boost::asio::placeholders::error));
|
||||
|
||||
boost::system::error_code ec;
|
||||
size_t bytes_transferred = 0;
|
||||
serial->async_read_some(boost::asio::buffer(buffer),
|
||||
boost::bind(&serial_interface::on_read_complete, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, &ec, &bytes_transferred));
|
||||
|
||||
io.run();
|
||||
io.reset();
|
||||
|
||||
if (timeout) {
|
||||
throw std::runtime_error("串口读取超时");
|
||||
}
|
||||
|
||||
if (ec) {
|
||||
throw boost::system::system_error(ec);
|
||||
}
|
||||
|
||||
buffer.resize(bytes_transferred);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
CommunicationMode serial_interface::getCommunicationMode()
|
||||
{
|
||||
return comm_mode;
|
||||
}
|
||||
// 根据寄存器名称获取地址
|
||||
int getAddressByName(const std::string& reg_name) {
|
||||
for (const auto& reg : regdict) {
|
||||
if (reg.name == reg_name) {
|
||||
return reg.address; // 返回匹配的地址
|
||||
}
|
||||
}
|
||||
return -1; // 未找到寄存器名称,返回 -1
|
||||
}
|
||||
|
||||
// 写寄存器函数
|
||||
void write_register(serial_interface& serial, int address_decimal, const std::string& id_value, const std::vector<int>& values_to_write) {
|
||||
if (values_to_write.size() > 6) {
|
||||
std::cerr << "超过允许的值数量,最多只能写入6个值!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (serial.getCommunicationMode() == CommunicationMode::RS485) {
|
||||
// RS485模式下的写寄存器逻辑
|
||||
std::vector<unsigned char> send_buffer;
|
||||
send_buffer.push_back(0xEB);
|
||||
send_buffer.push_back(0x90);
|
||||
send_buffer.push_back(static_cast<unsigned char>(std::stoi(id_value))); // 将 ID 转换为 unsigned char
|
||||
size_t num_values = values_to_write.size();
|
||||
auto data_length = static_cast<unsigned char>(num_values * 2 + 3);
|
||||
send_buffer.push_back(data_length);
|
||||
send_buffer.push_back(0x12); // 写寄存器命令
|
||||
send_buffer.push_back(static_cast<unsigned char>(address_decimal & 0xFF)); // 地址低八位
|
||||
send_buffer.push_back(static_cast<unsigned char>((address_decimal >> 8) & 0xFF)); // 地址高八位
|
||||
|
||||
// 将要写入的值添加到数据包中
|
||||
for (int value : values_to_write) {
|
||||
send_buffer.push_back(static_cast<unsigned char>(value & 0xFF)); // 写入值低八位
|
||||
send_buffer.push_back(static_cast<unsigned char>((value >> 8) & 0xFF)); // 写入值高八位
|
||||
}
|
||||
|
||||
// 计算校验和,从 ID 部分开始
|
||||
unsigned char checksum = 0;
|
||||
for (size_t k = 2; k < send_buffer.size(); ++k) {
|
||||
checksum += send_buffer[k];
|
||||
}
|
||||
|
||||
send_buffer.push_back(checksum & 0xFF); // 添加校验和
|
||||
|
||||
// // 输出发送的数据
|
||||
// std::cout << "发送的写入数据: ";
|
||||
// for (auto byte : send_buffer) {
|
||||
// std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)byte << " ";
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
|
||||
// 写入数据
|
||||
serial.write(send_buffer);
|
||||
|
||||
// 读取并丢弃写入后的响应
|
||||
try {
|
||||
std::vector<unsigned char> discard_buffer = serial.read(9);
|
||||
std::cout << "写操作后的响应数据已丢弃,字节数: " << discard_buffer.size() << std::endl;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "写操作后的响应数据读取失败: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
else if (serial.getCommunicationMode() == CommunicationMode::CAN) {
|
||||
// CAN模式下的写寄存器逻辑
|
||||
std::vector<int> first_chunk(values_to_write.begin(), values_to_write.begin() + std::min(4, (int)values_to_write.size()));
|
||||
std::vector<int> second_chunk(values_to_write.begin() + first_chunk.size(), values_to_write.end());
|
||||
|
||||
// 构造并发送第一段数据
|
||||
auto construct_and_send = [&](const std::vector<int>& chunk, int addr) {
|
||||
// 转换地址为二进制->十六进制
|
||||
std::string result_bin = convertAddressToBinary_write(addr, id_value);
|
||||
std::string result_hex = binaryToHex(result_bin);
|
||||
std::vector<unsigned char> processed_data = processHexData(result_hex);
|
||||
|
||||
// 构造数据帧
|
||||
std::vector<unsigned char> send_buffer;
|
||||
send_buffer.push_back(0xAA);
|
||||
send_buffer.push_back(0xAA);
|
||||
send_buffer.insert(send_buffer.end(), processed_data.begin(), processed_data.end());
|
||||
|
||||
// 写入值
|
||||
for (int value : chunk) {
|
||||
send_buffer.push_back(value & 0xFF); // 低八位
|
||||
send_buffer.push_back((value >> 8) & 0xFF); // 高八位
|
||||
}
|
||||
|
||||
while (send_buffer.size() < 14) {
|
||||
send_buffer.push_back(0x00);
|
||||
}
|
||||
|
||||
// 添加固定字节
|
||||
send_buffer.push_back(chunk.size() * 2); // 数据长度
|
||||
send_buffer.push_back(0x00);
|
||||
send_buffer.push_back(0x01);
|
||||
send_buffer.push_back(0x00);
|
||||
|
||||
// 计算校验和
|
||||
unsigned char checksum = 0;
|
||||
for (size_t k = 2; k < send_buffer.size(); ++k) {
|
||||
checksum += send_buffer[k];
|
||||
}
|
||||
send_buffer.push_back(checksum & 0xFF);
|
||||
send_buffer.push_back(0x55);
|
||||
send_buffer.push_back(0x55);
|
||||
|
||||
// 打印并发送
|
||||
// std::cout << "发送的完整数据: ";
|
||||
// for (auto byte : send_buffer) {
|
||||
// std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)byte << " ";
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
|
||||
serial.write(send_buffer);
|
||||
|
||||
// 读掉响应数据,不处理
|
||||
try {
|
||||
std::vector<unsigned char> discard_buffer = serial.read(32);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "写操作后的响应数据读取失败: " << e.what() << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
// 发送第一段
|
||||
construct_and_send(first_chunk, address_decimal);
|
||||
|
||||
// 如果有第二段值,发送第二段
|
||||
if (!second_chunk.empty()) {
|
||||
construct_and_send(second_chunk, address_decimal + 8); // 地址后移 8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 读寄存器函数
|
||||
std::vector<unsigned char> read_register(serial_interface& serial, int address_decimal, const std::string& id_value,
|
||||
size_t register_length, size_t length_to_read) {
|
||||
|
||||
std::vector<unsigned char> send_buffer;
|
||||
if (serial.getCommunicationMode() == CommunicationMode::RS485) {
|
||||
// RS485模式下的读寄存器逻辑
|
||||
send_buffer.push_back(0xEB);
|
||||
send_buffer.push_back(0x90);
|
||||
send_buffer.push_back(static_cast<unsigned char>(std::stoi(id_value))); // 将 ID 转换为 unsigned char
|
||||
send_buffer.push_back(0x04);
|
||||
send_buffer.push_back(0x11);
|
||||
send_buffer.push_back(static_cast<unsigned char>(address_decimal & 0xFF)); // 地址低八位
|
||||
send_buffer.push_back(static_cast<unsigned char>((address_decimal >> 8) & 0xFF)); // 地址高八位
|
||||
send_buffer.push_back(register_length); // 读取寄存器长度
|
||||
|
||||
// 计算校验和
|
||||
unsigned char checksum = 0;
|
||||
for (size_t k = 2; k < send_buffer.size(); ++k) {
|
||||
checksum += send_buffer[k];
|
||||
}
|
||||
|
||||
send_buffer.push_back(checksum & 0xFF);
|
||||
|
||||
// std::cout << "发送的完整数据: ";
|
||||
// for (auto byte : send_buffer) {
|
||||
// std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)byte << " ";
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
|
||||
serial.write(send_buffer); // 写入串口
|
||||
|
||||
// 读取响应数据
|
||||
std::vector<unsigned char> received_data = serial.read(length_to_read);
|
||||
|
||||
// // 打印接收到的原始响应数据
|
||||
// std::cout << "接收到的原始响应数据: ";
|
||||
// for (auto byte : received_data) {
|
||||
// std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)byte << " ";
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
|
||||
return received_data;
|
||||
}
|
||||
return send_buffer;
|
||||
}
|
||||
|
||||
std::vector<int> read_register_can(serial_interface& serial, int address_decimal, const std::string& id_value, size_t register_length, size_t length_to_read, bool parse_as_short) {
|
||||
std::vector<int> parsed_values;
|
||||
size_t bytes_read = 0;
|
||||
|
||||
while (bytes_read < register_length) {
|
||||
std::vector<unsigned char> send_buffer;
|
||||
|
||||
// 生成地址相关数据
|
||||
std::string result_bin = convertAddressToBinary_read(address_decimal, id_value);
|
||||
std::string result_hex = binaryToHex(result_bin);
|
||||
std::vector<unsigned char> processed_data = processHexData(result_hex);
|
||||
|
||||
// 动态计算数据长度控制字段(关键调整)
|
||||
size_t current_remaining = register_length - bytes_read;
|
||||
size_t data_length = (parse_as_short)
|
||||
? std::min(8UL, (current_remaining + 1) & ~1UL) // 按short对齐到偶数
|
||||
: std::min(8UL, current_remaining); // 按byte无需对齐
|
||||
|
||||
// 构建发送缓冲区
|
||||
send_buffer.push_back(0xAA);
|
||||
send_buffer.push_back(0xAA);
|
||||
send_buffer.insert(send_buffer.end(), processed_data.begin(), processed_data.end());
|
||||
send_buffer.push_back(static_cast<unsigned char>(data_length)); // 动态数据长度
|
||||
send_buffer.insert(send_buffer.end(), 7, 0x00);
|
||||
send_buffer.push_back(0x01);
|
||||
send_buffer.push_back(0x00);
|
||||
send_buffer.push_back(0x01);
|
||||
send_buffer.push_back(0x00);
|
||||
|
||||
// 计算校验和
|
||||
unsigned char checksum = 0;
|
||||
for (size_t k = 2; k < send_buffer.size(); ++k) {
|
||||
checksum += send_buffer[k];
|
||||
}
|
||||
send_buffer.push_back(checksum & 0xFF);
|
||||
send_buffer.push_back(0x55);
|
||||
send_buffer.push_back(0x55);
|
||||
|
||||
// 发送并接收数据
|
||||
serial.write(send_buffer);
|
||||
std::vector<unsigned char> received_data = serial.read(length_to_read);
|
||||
|
||||
// 定位有效数据起始位置
|
||||
size_t start_pos = 0;
|
||||
while (start_pos < received_data.size() && received_data[start_pos] != 0xAA) {
|
||||
start_pos++;
|
||||
}
|
||||
|
||||
// 根据解析类型处理数据
|
||||
if (parse_as_short) {
|
||||
size_t shorts_to_read = data_length / 2;
|
||||
for (size_t j = start_pos + 6; j < start_pos + 6 + data_length; j += 2) {
|
||||
if (j + 1 < received_data.size()) {
|
||||
int value = (received_data[j + 1] << 8) | received_data[j];
|
||||
if (value > 6000) value = 0;
|
||||
parsed_values.push_back(value);
|
||||
bytes_read += 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t j = start_pos + 6; j < start_pos + 6 + data_length; j++) {
|
||||
if (j < received_data.size()) {
|
||||
parsed_values.push_back(received_data[j]);
|
||||
bytes_read++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
address_decimal += static_cast<int>(data_length); // 地址后移8字节
|
||||
}
|
||||
|
||||
return parsed_values;
|
||||
}
|
||||
|
||||
|
||||
std::vector<unsigned char> read_register_can_single(serial_interface& serial, int address_decimal, const std::string& id_value, size_t register_length, size_t length_to_read) {
|
||||
std::vector<unsigned char> all_parsed_values;
|
||||
|
||||
size_t bytes_read = 0;
|
||||
while (bytes_read < register_length) {
|
||||
std::vector<unsigned char> send_buffer;
|
||||
std::vector<unsigned char> parsed_values;
|
||||
std::string result_bin = convertAddressToBinary_read(address_decimal, id_value);
|
||||
std::string result_hex = binaryToHex(result_bin);
|
||||
std::vector<unsigned char> processed_data = processHexData(result_hex);
|
||||
|
||||
send_buffer.push_back(0xAA);
|
||||
send_buffer.push_back(0xAA);
|
||||
send_buffer.insert(send_buffer.end(), processed_data.begin(), processed_data.end());
|
||||
send_buffer.push_back(0x08); // 数据长度控制
|
||||
send_buffer.insert(send_buffer.end(), 7, 0x00);
|
||||
send_buffer.push_back(0x01);
|
||||
send_buffer.push_back(0x00);
|
||||
send_buffer.push_back(0x01);
|
||||
send_buffer.push_back(0x00);
|
||||
|
||||
unsigned char checksum = 0;
|
||||
for (size_t k = 2; k < send_buffer.size(); ++k) {
|
||||
checksum += send_buffer[k];
|
||||
}
|
||||
send_buffer.push_back(checksum & 0xFF); // 添加校验和
|
||||
send_buffer.push_back(0x55);
|
||||
send_buffer.push_back(0x55);
|
||||
|
||||
serial.write(send_buffer);
|
||||
// 读取响应数据
|
||||
std::vector<unsigned char> received_data = serial.read(length_to_read);
|
||||
|
||||
// 找到第一个 0xAA 的位置
|
||||
size_t start_pos = 0;
|
||||
while (start_pos < received_data.size() && received_data[start_pos] != 0xAA) {
|
||||
start_pos++;
|
||||
}
|
||||
// 从第一个 0xAA 开始解析数据,每次最多读取 8 字节
|
||||
size_t bytes_to_read = std::min(8UL, register_length - bytes_read);
|
||||
for (size_t j = start_pos + 6; j < start_pos + 6 + bytes_to_read; j++) {
|
||||
if (j < received_data.size()) {
|
||||
parsed_values.push_back(received_data[j]);
|
||||
}
|
||||
}
|
||||
|
||||
all_parsed_values.insert(all_parsed_values.end(), parsed_values.begin(), parsed_values.end());
|
||||
bytes_read += parsed_values.size();
|
||||
address_decimal += 8; // 地址后移 8 字节
|
||||
}
|
||||
return all_parsed_values;
|
||||
}
|
||||
|
||||
std::vector<int> parse_register(const std::vector<unsigned char>& data,int start_byte, size_t register_length,int per_byte){
|
||||
|
||||
std::vector<int> parsed_values;
|
||||
for (size_t j = 7; j < register_length + 7; j += 2) {
|
||||
if (j + 1 < data.size()) {
|
||||
int value = 0;
|
||||
//根据数据位数获取数据
|
||||
if (per_byte == 1) {
|
||||
value = data[j];
|
||||
}
|
||||
else if (per_byte == 2) {
|
||||
value = (data[j + 1] << 8) | data[j];
|
||||
}
|
||||
|
||||
if (value > 6000) {
|
||||
value = 0;
|
||||
}
|
||||
parsed_values.push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
return parsed_values;
|
||||
}
|
||||
|
||||
std::vector<std::string> parse_error(unsigned char errorCode) {
|
||||
|
||||
std::vector<std::string> faults;
|
||||
|
||||
// 直接判断每一位是否为1
|
||||
if (errorCode & (1 << 0)) { // Bit0: 堵转故障
|
||||
faults.emplace_back("堵转故障");
|
||||
}
|
||||
|
||||
if (errorCode & (1 << 1)) { // Bit1: 过温故障
|
||||
faults.emplace_back("过温故障");
|
||||
}
|
||||
|
||||
if (errorCode & (1 << 2)) { // Bit2: 过流故障
|
||||
faults.emplace_back("过流故障");
|
||||
}
|
||||
|
||||
if (errorCode & (1 << 3)) { // Bit3: 电机异常
|
||||
faults.emplace_back("电机异常");
|
||||
}
|
||||
|
||||
if (errorCode & (1 << 4)) { // Bit4: 通讯故障
|
||||
faults.emplace_back("通讯故障");
|
||||
}
|
||||
return faults;
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,13 @@
|
||||
add_library(hardware_manager SHARED
|
||||
hardware_factory.cpp
|
||||
hardware_manager.cpp
|
||||
../hardware/can/can_manager.cpp
|
||||
../hardware/serial/serial_manager.cpp
|
||||
)
|
||||
|
||||
target_include_directories(hardware_manager PUBLIC
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
target_link_libraries(hardware_manager PRIVATE
|
||||
cmvr_es::hardware::can
|
||||
cmvr_es::hardware::serial
|
||||
)
|
||||
add_library(cmvr_es::hardware_manager ALIAS hardware_manager)
|
||||
@ -6,7 +6,7 @@
|
||||
#include <glog/logging.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace cmvr::device;
|
||||
using namespace cmvr::hardware;
|
||||
|
||||
template std::shared_ptr<CanManager> HardwareFactory::create<CanManager>(const XmlNode&);
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
#include "hardware_manager/hardware_manager.h"
|
||||
using namespace std;
|
||||
using namespace cmvr::device;
|
||||
using namespace cmvr::hardware;
|
||||
std::shared_ptr<HardWareManager> HardWareManager::instance_ = nullptr;
|
||||
|
||||
HardWareManager::HardWareManager(const XmlNode& cfg) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user