添加蓝牙功能
This commit is contained in:
13
.vscode/settings.json
vendored
13
.vscode/settings.json
vendored
@ -56,5 +56,16 @@
|
||||
"C_Cpp_Runner.useLeakSanitizer": false,
|
||||
"C_Cpp_Runner.showCompilationTime": false,
|
||||
"C_Cpp_Runner.useLinkTimeOptimization": false,
|
||||
"C_Cpp_Runner.msvcSecureNoWarnings": false
|
||||
"C_Cpp_Runner.msvcSecureNoWarnings": false,
|
||||
"files.associations": {
|
||||
"optional": "cpp",
|
||||
"istream": "cpp",
|
||||
"ostream": "cpp",
|
||||
"system_error": "cpp",
|
||||
"array": "cpp",
|
||||
"functional": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp"
|
||||
}
|
||||
}
|
||||
BIN
VSMD通信协议整理.pdf
Normal file
BIN
VSMD通信协议整理.pdf
Normal file
Binary file not shown.
@ -1,65 +1,73 @@
|
||||
{
|
||||
"cmd": "cfg",
|
||||
"params": {
|
||||
"cfg zmd": 1,
|
||||
"cfg snr": 0,
|
||||
"cfg osv": 0,
|
||||
"cfg zsd": 1200,
|
||||
"cfg zsp": 2400,
|
||||
"cfg dmd": 2,
|
||||
"cfg dar": 5,
|
||||
"cfg msr": 1,
|
||||
"cfg msv": 1,
|
||||
"cfg psr": 1,
|
||||
"cfg psv": 1,
|
||||
"cfg bdr": 115200,
|
||||
"cfg cid": 1,
|
||||
"cfg mcs": 5,
|
||||
"cfg spd": 1200,
|
||||
"cfg acc": 12000,
|
||||
"cfg dec": 12000,
|
||||
"cfg cra": 0.8,
|
||||
"cfg crn": 0.4,
|
||||
"cfg crh": 0.0
|
||||
},
|
||||
"actions": [
|
||||
{
|
||||
"cmd": "ena"
|
||||
},
|
||||
{
|
||||
"cmd": "off"
|
||||
},
|
||||
{
|
||||
"cmd": "mov"
|
||||
},
|
||||
{
|
||||
"cmd": "pos",
|
||||
"value": 10000
|
||||
},
|
||||
{
|
||||
"cmd": "rmv",
|
||||
"value": -6400
|
||||
},
|
||||
{
|
||||
"cmd": "pps"
|
||||
},
|
||||
{
|
||||
"cmd": "pps",
|
||||
"value": 12800
|
||||
},
|
||||
{
|
||||
"cmd": "org"
|
||||
},
|
||||
{
|
||||
"cmd": "stp"
|
||||
},
|
||||
{
|
||||
"cmd": "zero",
|
||||
"value": "start"
|
||||
},
|
||||
{
|
||||
"cmd": "zero",
|
||||
"value": "stop"
|
||||
}
|
||||
]
|
||||
}
|
||||
{"command": "cfg"}
|
||||
{"command": "ena"}
|
||||
{"command": "off"}
|
||||
{"command": "mov"}
|
||||
{"command": "org"}
|
||||
{"command": "dev"}
|
||||
{"command": "sts"}
|
||||
{"command": "zero_start"}
|
||||
{"command": "zero_stop"}
|
||||
{"command": "sav"}
|
||||
|
||||
{"command": "pos", "PA": {"value": 1000}}
|
||||
{"command": "rmv", "PA": {"value": 500}}
|
||||
{"command": "pps", "PA": {"value": 1000}}
|
||||
{"command": "stp", "PA": {"value": 1}}
|
||||
|
||||
{"command": "cfg_bdr", "PA": {"value": 115200}}
|
||||
{"command": "cfg_mcs", "PA": {"value": 5}}
|
||||
{"command": "cfg_spd", "PA": {"value": 10000}}
|
||||
{"command": "cfg_acc", "PA": {"value": 100000}}
|
||||
{"command": "cfg_dec", "PA": {"value": 100000}}
|
||||
{"command": "cfg_cra", "PA": {"value": 1.5}}
|
||||
{"command": "cfg_crn", "PA": {"value": 1.0}}
|
||||
{"command": "cfg_crh", "PA": {"value": 0.5}}
|
||||
|
||||
{"command": "cfg_zmd", "PA": {"value": 2}}
|
||||
{"command": "cfg_snr", "PA": {"value": 1}}
|
||||
{"command": "cfg_osv", "PA": {"value": 0}}
|
||||
{"command": "cfg_zsd", "PA": {"value": 5000}}
|
||||
{"command": "cfg_zsp", "PA": {"value": 100}}
|
||||
|
||||
{"command": "cfg_dmd", "PA": {"value": 1}}
|
||||
{"command": "cfg_dar", "PA": {"value": 30}}
|
||||
|
||||
{"command": "cfg_msr", "PA": {"value": 3}}
|
||||
{"command": "cfg_msv", "PA": {"value": 0}}
|
||||
{"command": "cfg_psr", "PA": {"value": 4}}
|
||||
{"command": "cfg_psv", "PA": {"value": 1}}
|
||||
|
||||
//编码器配置命令
|
||||
{"command": "cfg_pae", "PA": {"value": 1}}
|
||||
{"command": "cfg_emod", "PA": {"value": 2}}
|
||||
{"command": "cfg_elns", "PA": {"value": 1000}}
|
||||
{"command": "cfg_estp", "PA": {"value": 200}}
|
||||
{"command": "cfg_erty", "PA": {"value": 3}}
|
||||
{"command": "cfg_edir", "PA": {"value": 0}}
|
||||
{"command": "cfg_ez", "PA": {"value": 5}}
|
||||
{"command": "cfg_ewr", "PA": {"value": 1}}
|
||||
|
||||
//S3-S6传感器触发事件配置命令
|
||||
{"command": "cfg_s3f", "PA": {"value": 5}}
|
||||
{"command": "cfg_s3r", "PA": {"value": 6}}
|
||||
{"command": "cfg_s4f", "PA": {"value": 7}}
|
||||
{"command": "cfg_s4r", "PA": {"value": 8}}
|
||||
{"command": "cfg_s5f", "PA": {"value": 9}}
|
||||
{"command": "cfg_s5r", "PA": {"value": 0}}
|
||||
{"command": "cfg_s6f", "PA": {"value": 1}}
|
||||
{"command": "cfg_s6r", "PA": {"value": 2}}
|
||||
|
||||
{"command": "cfg_s3", "PA": {"value": 1}}
|
||||
{"command": "cfg_s4", "PA": {"value": 0}}
|
||||
{"command": "cfg_s5", "PA": {"value": 1}}
|
||||
{"command": "cfg_s6", "PA": {"value": 0}}
|
||||
|
||||
//S3-S6端口输出控制命令
|
||||
{"command": "s3_on"}
|
||||
{"command": "s3_off"}
|
||||
{"command": "s4_on"}
|
||||
{"command": "s4_off"}
|
||||
{"command": "s5_on"}
|
||||
{"command": "s5_off"}
|
||||
{"command": "s6_on"}
|
||||
{"command": "s6_off"}
|
||||
|
||||
2278
src/VSMD_command_handler.cpp
Normal file
2278
src/VSMD_command_handler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
138
src/VSMD_command_handler.h
Normal file
138
src/VSMD_command_handler.h
Normal file
@ -0,0 +1,138 @@
|
||||
#ifndef VSMD_COMMAND_HANDLER_H
|
||||
#define VSMD_COMMAND_HANDLER_H
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include "vsmd_parser.h"
|
||||
|
||||
// 外部变量声明
|
||||
extern bool deviceEnabled;
|
||||
extern int32_t pulsePerSecond;
|
||||
extern uint8_t sendBuffer[];
|
||||
extern int32_t packedLength;
|
||||
extern VSMDParser parser;
|
||||
|
||||
// 串口通信函数
|
||||
void send_vsmd_cmd(const char* cmd, int value = -1);
|
||||
// send_vsmd_cmd("dev"); // 不带参数,使用默认值-1
|
||||
// send_vsmd_cmd("pos", value); // 带参数
|
||||
|
||||
// 打印Serial串口收到的原始数据
|
||||
void printSerialRawData(const uint8_t* buffer, int bytesRead);
|
||||
//VSMD串口数据解析
|
||||
String readAndParseSerialData();
|
||||
|
||||
// JSON响应函数
|
||||
void sendJsonResponse(const char* command, const char* status, int value = -1);
|
||||
// 打包并发送字符串响应
|
||||
void sendStringResponse(const char* response);
|
||||
|
||||
// JSON命令处理函数
|
||||
void processJsonCommand(const char* jsonString);
|
||||
// 处理字符串命令
|
||||
void processStringCommand(const char* stringData);
|
||||
|
||||
//获取参数值
|
||||
void handle_cfg_cmd();
|
||||
//握手,获取型号和版本号
|
||||
void handle_dev_cmd();
|
||||
//获取运行状态(速度、位置、状态)
|
||||
void handle_sts_cmd();
|
||||
//电机使能
|
||||
void handle_ena_cmd();
|
||||
//电机脱机
|
||||
void handle_off_cmd();
|
||||
//以指定速度连续运转
|
||||
void handle_mov_cmd();
|
||||
//移动到指定位置
|
||||
void handle_pos_cmd(int value);
|
||||
//相对移动
|
||||
void handle_rmv_cmd(int value);
|
||||
//移动到预设位置,有value时,预设目标位置
|
||||
void handle_pps_cmd(int value = -1);
|
||||
//指定当前位置位原点
|
||||
void handle_org_cmd();
|
||||
//停止
|
||||
void handle_stp_cmd(int value = 0);
|
||||
//执行归零
|
||||
void handle_zero_start_cmd();
|
||||
//停止归零
|
||||
void handle_zero_stop_cmd();
|
||||
//设置波特率
|
||||
void handle_cfg_bdr_cmd(int baudrate);
|
||||
//设置微步细分
|
||||
void handle_cfg_mcs_cmd(int value);
|
||||
//设置速度
|
||||
void handle_cfg_spd_cmd(int value);
|
||||
//设置加速速度
|
||||
void handle_cfg_accSpeed_cmd(int value);
|
||||
//设置减速度
|
||||
void handle_cfg_decSpeed_cmd(int value);
|
||||
//设置加速时电流
|
||||
void handle_cfg_cra_cmd(float value);
|
||||
//设置匀速时电流
|
||||
void handle_cfg_crn_cmd(float value);
|
||||
//设置HOLD电流
|
||||
void handle_cfg_crh_cmd(float value);
|
||||
|
||||
// ***************************SENSOR事件、工作模式处理**********************/
|
||||
void handle_cfg_sensor_cmd(const char* sensorType, int value);
|
||||
// ***************************SENSOR端口输出控制处理**********************/
|
||||
void handle_port_output_cmd(const char* portType, const char* action);
|
||||
|
||||
// //设置S1下降沿触发事件
|
||||
// void handle_cfg_s1f_cmd(int value);
|
||||
// //设置S1上升沿触发事件
|
||||
// void handle_cfg_s1r_cmd(int value);
|
||||
// //设置S2下降沿触发事件
|
||||
// void handle_cfg_s2f_cmd(int value);
|
||||
// //设置S2上升沿触发事件
|
||||
// void handle_cfg_s2r_cmd(int value);
|
||||
|
||||
//设置归零功能
|
||||
void handle_cfg_zmd_cmd(int value);
|
||||
//设置归零用传感器
|
||||
void handle_cfg_snr_cmd(int value);
|
||||
//设置归零传感器OPEN时电平
|
||||
void handle_cfg_osv_cmd(int value);
|
||||
//设置归零速度
|
||||
void handle_cfg_zsd_cmd(int value);
|
||||
//设置归零后的安全位置
|
||||
void handle_cfg_zsp_cmd(int value);
|
||||
//设置离线运行模式
|
||||
void handle_cfg_dmd_cmd(int value);
|
||||
//设置无握手启动时间
|
||||
void handle_cfg_dar_cmd(int value);
|
||||
//设置负极限传感器
|
||||
void handle_cfg_msr_cmd(int value);
|
||||
//设置负极限触发电平
|
||||
void handle_cfg_msv_cmd(int value);
|
||||
//设置正极限传感器
|
||||
void handle_cfg_psr_cmd(int value);
|
||||
//设置正极限触发电平
|
||||
void handle_cfg_psv_cmd(int value);
|
||||
//设置上电使能
|
||||
void handle_cfg_pae_cmd(int value);
|
||||
|
||||
//***************************编码器相关配置*********************************/
|
||||
|
||||
// 编码器模式
|
||||
void handle_cfg_emod_cmd(int value);
|
||||
// 编码器线数
|
||||
void handle_cfg_elns_cmd(int value);
|
||||
// 电机每圈整步数
|
||||
void handle_cfg_estp_cmd(int value);
|
||||
// 堵转后重试次数
|
||||
void handle_cfg_erty_cmd(int value);
|
||||
// 编码器方向
|
||||
void handle_cfg_edir_cmd(int value);
|
||||
// 编码器灵敏度
|
||||
void handle_cfg_ez_cmd(int value);
|
||||
// 堵转后动作
|
||||
void handle_cfg_ewr_cmd(int value);
|
||||
//*********************************************************************/
|
||||
|
||||
|
||||
//保存参数到FLASH
|
||||
void handle_sav_cmd();
|
||||
|
||||
#endif
|
||||
310
src/bluetooth_handler.cpp
Normal file
310
src/bluetooth_handler.cpp
Normal file
@ -0,0 +1,310 @@
|
||||
#include "bluetooth_handler.h"
|
||||
#include "VSMD_command_handler.h"
|
||||
#include "IRIS_Method.h"
|
||||
|
||||
// 添加缺失的常量定义
|
||||
#define BUFFER_SIZE 1024
|
||||
#define JSON_BUFFER_SIZE 512
|
||||
|
||||
// 蓝牙服务和特征值UUID
|
||||
#define BT_SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||
#define BT_CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||
#define BT_CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||
|
||||
// 全局变量
|
||||
BLEServer* btServer = nullptr;
|
||||
BLECharacteristic* btCharacteristicTX = nullptr;
|
||||
BLECharacteristic* btCharacteristicRX = nullptr;
|
||||
bool bluetoothConnected = false;
|
||||
bool bluetoothDataReceived = false;
|
||||
|
||||
// 蓝牙接收缓冲区和数据包重组
|
||||
#define BT_BUFFER_SIZE 1024
|
||||
#define BT_PACKET_TIMEOUT 1000 // 1秒超时
|
||||
uint8_t btReceiveBuffer[BT_BUFFER_SIZE];
|
||||
size_t btDataLength = 0;
|
||||
uint8_t btPacketBuffer[BT_BUFFER_SIZE]; // 数据包重组缓冲区
|
||||
size_t btPacketLength = 0;
|
||||
unsigned long lastPacketTime = 0;
|
||||
bool isReceivingPacket = false;
|
||||
|
||||
// 外部变量声明
|
||||
extern uint8_t receiveBuffer[BUFFER_SIZE];
|
||||
extern uint8_t sendBuffer[BUFFER_SIZE];
|
||||
extern uint8_t responseBuffer[BUFFER_SIZE];
|
||||
extern uint8_t command;
|
||||
extern int32_t bytesProcessed;
|
||||
extern int32_t unpackResult;
|
||||
extern int32_t packedLength;
|
||||
extern HardwareSerial DebugSerial;
|
||||
|
||||
// 数据包是否完整(检查IRIS协议的头部和长度,支持CRC校验)
|
||||
bool isPacketComplete(const uint8_t* buffer, size_t length) {
|
||||
if (length < 7) return false; // 最小包长度:头部(2) + 命令(1) + 长度(2) + CRC(2)
|
||||
|
||||
// 检查包头 0x55 0xAA
|
||||
if (buffer[0] != 0x55 || buffer[1] != 0xAA) return false;
|
||||
|
||||
// 获取数据长度字段(第3和第4字节)
|
||||
uint16_t dataLen = (buffer[3] << 8) | buffer[4];
|
||||
|
||||
// 计算期望的总包长度:头部(2字节) + 命令(1字节) + 长度(2字节) + 数据长度 + CRC(2字节)
|
||||
size_t expectedLength = 5 + dataLen + 2;
|
||||
|
||||
if (length < expectedLength) {
|
||||
return false; // 数据包还不完整
|
||||
}
|
||||
|
||||
if (length >= expectedLength &&
|
||||
buffer[expectedLength-2] == 0xEE &&
|
||||
buffer[expectedLength-1] == 0xEE) {
|
||||
return true; // 无校验包,直接返回完整
|
||||
}
|
||||
|
||||
// 对于有校验的包,验证CRC
|
||||
if (length >= expectedLength) {
|
||||
// 计算数据部分的CRC(从第5字节开始,长度为dataLen)
|
||||
uint16_t calculatedCRC = IRIS_calcCRC(buffer + 5, dataLen);
|
||||
|
||||
uint16_t packetCRC = (buffer[expectedLength-2] << 8) | buffer[expectedLength-1];
|
||||
|
||||
if (calculatedCRC == packetCRC) {
|
||||
return true;
|
||||
} else {
|
||||
DebugSerial.print("CRC err: calculated=0x");
|
||||
DebugSerial.print(calculatedCRC, HEX);
|
||||
DebugSerial.print(", packet=0x");
|
||||
DebugSerial.println(packetCRC, HEX);
|
||||
return false; // CRC校验失败
|
||||
}
|
||||
}
|
||||
|
||||
return false; // 默认返回不完整
|
||||
}
|
||||
|
||||
// 重置数据包接收状态
|
||||
void resetPacketReceiving() {
|
||||
isReceivingPacket = false;
|
||||
btPacketLength = 0;
|
||||
lastPacketTime = 0;
|
||||
}
|
||||
|
||||
// 处理接收到的数据片段
|
||||
void processBluetoothFragment(const uint8_t* data, size_t length) {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
// 检查超时
|
||||
if (isReceivingPacket && (currentTime - lastPacketTime > BT_PACKET_TIMEOUT)) {
|
||||
DebugSerial.println("Bluetooth packet timeout, resetting...");
|
||||
resetPacketReceiving();
|
||||
}
|
||||
|
||||
// 如果缓冲区空间不足,重置
|
||||
if (btPacketLength + length > BT_BUFFER_SIZE) {
|
||||
DebugSerial.println("Bluetooth packet buffer overflow, resetting...");
|
||||
resetPacketReceiving();
|
||||
}
|
||||
|
||||
// 将新数据添加到包缓冲区
|
||||
memcpy(btPacketBuffer + btPacketLength, data, length);
|
||||
btPacketLength += length;
|
||||
lastPacketTime = currentTime;
|
||||
isReceivingPacket = true;
|
||||
|
||||
DebugSerial.print("Ble rec: ");
|
||||
DebugSerial.print(length);
|
||||
DebugSerial.print(" bytes, total: ");
|
||||
DebugSerial.println(btPacketLength);
|
||||
|
||||
// 检查数据包是否完整
|
||||
if (isPacketComplete(btPacketBuffer, btPacketLength)) {
|
||||
//DebugSerial.println("Complete packet received via Bluetooth");
|
||||
|
||||
// 复制完整数据包到接收缓冲区
|
||||
memcpy(btReceiveBuffer, btPacketBuffer, btPacketLength);
|
||||
btDataLength = btPacketLength;
|
||||
bluetoothDataReceived = true;
|
||||
|
||||
// 重置包接收状态
|
||||
resetPacketReceiving();
|
||||
}
|
||||
}
|
||||
|
||||
// 服务器回调类
|
||||
class BluetoothServerCallbacks : public BLEServerCallbacks {
|
||||
void onConnect(BLEServer* pServer) {
|
||||
bluetoothConnected = true;
|
||||
DebugSerial.println("Bluetooth Client Connected");
|
||||
resetPacketReceiving(); // 连接时重置状态
|
||||
}
|
||||
|
||||
void onDisconnect(BLEServer* pServer) {
|
||||
bluetoothConnected = false;
|
||||
bluetoothDataReceived = false;
|
||||
DebugSerial.println("Bluetooth Client Disconnected");
|
||||
resetPacketReceiving(); // 断开时重置状态
|
||||
|
||||
// 重新开始广播
|
||||
delay(500);
|
||||
pServer->startAdvertising();
|
||||
DebugSerial.println("Bluetooth advertising restarted");
|
||||
}
|
||||
};
|
||||
|
||||
// 特征值回调类
|
||||
class BluetoothCharacteristicCallbacks : public BLECharacteristicCallbacks {
|
||||
void onWrite(BLECharacteristic* pCharacteristic) {
|
||||
std::string rxValue = pCharacteristic->getValue();
|
||||
|
||||
if (rxValue.length() > 0) {
|
||||
// 处理接收到的数据片段
|
||||
processBluetoothFragment((const uint8_t*)rxValue.c_str(), rxValue.length());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void initBluetooth() {
|
||||
//DebugSerial.println("Initializing Bluetooth...");
|
||||
|
||||
// 初始化BLE设备
|
||||
BLEDevice::init("VSMD_Controller");
|
||||
|
||||
// 创建BLE服务器
|
||||
btServer = BLEDevice::createServer();
|
||||
btServer->setCallbacks(new BluetoothServerCallbacks());
|
||||
|
||||
// 创建BLE服务
|
||||
BLEService* btService = btServer->createService(BT_SERVICE_UUID);
|
||||
|
||||
// 创建TX特征值(用于发送数据到客户端)
|
||||
btCharacteristicTX = btService->createCharacteristic(
|
||||
BT_CHARACTERISTIC_UUID_TX,
|
||||
BLECharacteristic::PROPERTY_NOTIFY
|
||||
);
|
||||
btCharacteristicTX->addDescriptor(new BLE2902());
|
||||
|
||||
// 创建RX特征值(用于接收来自客户端的数据)
|
||||
btCharacteristicRX = btService->createCharacteristic(
|
||||
BT_CHARACTERISTIC_UUID_RX,
|
||||
BLECharacteristic::PROPERTY_WRITE
|
||||
);
|
||||
btCharacteristicRX->setCallbacks(new BluetoothCharacteristicCallbacks());
|
||||
|
||||
// 启动服务
|
||||
btService->start();
|
||||
|
||||
// 开始广播
|
||||
BLEAdvertising* btAdvertising = BLEDevice::getAdvertising();
|
||||
btAdvertising->addServiceUUID(BT_SERVICE_UUID);
|
||||
btAdvertising->setScanResponse(false);
|
||||
btAdvertising->setMinPreferred(0x0);
|
||||
BLEDevice::startAdvertising();
|
||||
|
||||
DebugSerial.println("VSMD_Ble_Controller initialized");
|
||||
|
||||
// 初始化包接收状态
|
||||
resetPacketReceiving();
|
||||
}
|
||||
|
||||
void handleBluetoothData() {
|
||||
if (!bluetoothDataReceived) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 复制数据到主接收缓冲区
|
||||
memcpy(receiveBuffer, btReceiveBuffer, btDataLength);
|
||||
|
||||
DebugSerial.print("Total: ");
|
||||
DebugSerial.print(btDataLength);
|
||||
DebugSerial.println(" bytes");
|
||||
|
||||
// 处理数据(使用与DebugSerial相同的处理逻辑)
|
||||
bytesProcessed = IRIS_Cut_Befor_Header(receiveBuffer, btDataLength);
|
||||
|
||||
if (bytesProcessed > 0) {
|
||||
unpackResult = IRIS_STM32_Protocol_Unpack(receiveBuffer, bytesProcessed, &command, responseBuffer);
|
||||
|
||||
if (unpackResult >= 0) {
|
||||
// 根据命令类型处理数据
|
||||
switch (command) {
|
||||
case 0x00: { // JSON数据
|
||||
char jsonString[JSON_BUFFER_SIZE];
|
||||
memcpy(jsonString, responseBuffer, unpackResult);
|
||||
jsonString[unpackResult] = '\0';
|
||||
|
||||
DebugSerial.print("Bluetooth JSON: ");
|
||||
DebugSerial.println(jsonString);
|
||||
|
||||
processJsonCommand(jsonString);
|
||||
//BLE Notify
|
||||
sendBluetoothData(sendBuffer, packedLength);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x01: { // 字符串数据
|
||||
char stringData[BUFFER_SIZE];
|
||||
memcpy(stringData, responseBuffer, unpackResult);
|
||||
stringData[unpackResult] = '\0';
|
||||
|
||||
DebugSerial.print("Bluetooth String: ");
|
||||
DebugSerial.println(stringData);
|
||||
|
||||
processStringCommand(stringData);
|
||||
break;
|
||||
}
|
||||
|
||||
default: { // 自定义二进制数据
|
||||
DebugSerial.print("Bluetooth Binary Data, Command: 0x");
|
||||
DebugSerial.print(command, HEX);
|
||||
DebugSerial.print(", Length: ");
|
||||
DebugSerial.println(unpackResult);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DebugSerial.print("Bluetooth unpack failed, error code: ");
|
||||
DebugSerial.println(unpackResult);
|
||||
}
|
||||
}
|
||||
|
||||
// 重置标志
|
||||
bluetoothDataReceived = false;
|
||||
}
|
||||
|
||||
void sendBluetoothData(const uint8_t* data, size_t length) {
|
||||
if (bluetoothConnected && btCharacteristicTX != nullptr) {
|
||||
// BLE特征值有最大传输长度限制,通常为20字节
|
||||
const size_t maxChunkSize = 20;
|
||||
size_t offset = 0;
|
||||
|
||||
// DebugSerial.println("Sending ");
|
||||
// DebugSerial.print(length);
|
||||
// DebugSerial.println(" bytes via Bluetooth in chunks:");
|
||||
|
||||
while (offset < length) {
|
||||
size_t chunkSize = min(maxChunkSize, length - offset);
|
||||
btCharacteristicTX->setValue((uint8_t*)(data + offset), chunkSize);
|
||||
btCharacteristicTX->notify();
|
||||
|
||||
// DebugSerial.print(" Chunk ");
|
||||
// DebugSerial.print(offset/maxChunkSize + 1);
|
||||
// DebugSerial.print(": ");
|
||||
// DebugSerial.print(chunkSize);
|
||||
// DebugSerial.println(" bytes");
|
||||
|
||||
offset += chunkSize;
|
||||
|
||||
// 短暂延迟以确保数据传输稳定
|
||||
if (offset < length) {
|
||||
delay(20); // 增加延迟确保接收端有时间处理
|
||||
}
|
||||
}
|
||||
|
||||
//DebugSerial.println("Bluetooth transmission complete");
|
||||
}
|
||||
}
|
||||
|
||||
bool isBluetoothConnected() {
|
||||
return bluetoothConnected;
|
||||
}
|
||||
27
src/bluetooth_handler.h
Normal file
27
src/bluetooth_handler.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef BLUETOOTH_HANDLER_H
|
||||
#define BLUETOOTH_HANDLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <BLEDevice.h>
|
||||
#include <BLEUtils.h>
|
||||
#include <BLEServer.h>
|
||||
#include <BLECharacteristic.h>
|
||||
#include <BLE2902.h>
|
||||
|
||||
// 蓝牙状态
|
||||
extern bool bluetoothConnected;
|
||||
extern bool bluetoothDataReceived;
|
||||
|
||||
// 蓝牙初始化
|
||||
void initBluetooth();
|
||||
|
||||
// 蓝牙数据处理
|
||||
void handleBluetoothData();
|
||||
|
||||
// 蓝牙发送数据
|
||||
void sendBluetoothData(const uint8_t* data, size_t length);
|
||||
|
||||
// 蓝牙连接状态
|
||||
bool isBluetoothConnected();
|
||||
|
||||
#endif
|
||||
377
src/main.cpp
377
src/main.cpp
@ -1,19 +1,19 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include "IRIS_Method.h"
|
||||
#include "vsmd_parser.h"
|
||||
#include "VSMD_command_handler.h"
|
||||
#include "bluetooth_handler.h" // 添加蓝牙模块
|
||||
|
||||
VSMDParser parser;
|
||||
|
||||
#define DEBUG_TX_PIN 17 // TX
|
||||
#define DEBUG_RX_PIN 16 // RX
|
||||
|
||||
|
||||
HardwareSerial DebugSerial(1); // 使用UART1
|
||||
|
||||
#define BUFFER_SIZE 1024
|
||||
#define JSON_BUFFER_SIZE 512
|
||||
|
||||
// 全局变量声明
|
||||
HardwareSerial DebugSerial(1); // 使用UART1
|
||||
|
||||
// 全局变量
|
||||
uint8_t receiveBuffer[BUFFER_SIZE]; // 接收缓冲区
|
||||
uint8_t sendBuffer[BUFFER_SIZE]; // 发送缓冲区
|
||||
uint8_t responseBuffer[BUFFER_SIZE]; // 响应缓冲区
|
||||
@ -24,86 +24,54 @@ int32_t packedLength; // 打包后的数据长度
|
||||
|
||||
// 设备状态变量
|
||||
bool deviceEnabled = false;
|
||||
int32_t currentPosition = 0;
|
||||
int32_t targetPosition = 0;
|
||||
int32_t pulsePerSecond = 1200;
|
||||
bool isMoving = false;
|
||||
bool isBackZero = false;
|
||||
int32_t pulsePerSecond;
|
||||
|
||||
// 设备配置参数
|
||||
struct DeviceConfig {
|
||||
int zmd = 1; // cfg zmd
|
||||
int snr = 0; // cfg snr
|
||||
int osv = 0; // cfg osv
|
||||
int zsd = 1200; // cfg zsd
|
||||
int zsp = 2400; // cfg zsp
|
||||
int dmd = 2; // cfg dmd
|
||||
int dar = 5; // cfg dar
|
||||
int msr = 1; // cfg msr
|
||||
int msv = 1; // cfg msv
|
||||
int psr = 1; // cfg psr
|
||||
int psv = 1; // cfg psv
|
||||
int bdr = 115200; // cfg bdr
|
||||
int cid = 1; // cfg cid
|
||||
int mcs = 5; // cfg mcs
|
||||
int spd = 1200; // cfg spd
|
||||
int acc = 12000; // cfg acc
|
||||
int dec = 12000; // cfg dec
|
||||
float cra = 0.8; // cfg cra
|
||||
float crn = 0.4; // cfg crn
|
||||
float crh = 0.0; // cfg crh
|
||||
} deviceConfig;
|
||||
|
||||
|
||||
void processJsonCommand(const char* jsonString);
|
||||
void processStringCommand(const char* stringData);
|
||||
void sendJsonResponse(const char* cmd, const char* status, int value = -1);
|
||||
void sendStringResponse(const char* response);
|
||||
void handle_cfg_cmd();
|
||||
void handle_ena_cmd();
|
||||
void handle_off_cmd();
|
||||
void handle_mov_cmd();
|
||||
void handle_pos_cmd(int value);
|
||||
void handle_rmv_cmd(int value);
|
||||
void handle_pps_cmd(int value = -1);
|
||||
void handle_org_cmd();
|
||||
void handle_stp_cmd();
|
||||
void handle_zero_cmd(const char* value);
|
||||
void handle_dev_cmd();
|
||||
void printDeviceStatus();
|
||||
void handleSerialData();
|
||||
|
||||
void printDeviceStatus() {
|
||||
DebugSerial.println("\n=== Device Status ===");
|
||||
DebugSerial.print("Enabled: ");
|
||||
DebugSerial.println(deviceEnabled ? "Yes" : "No");
|
||||
DebugSerial.print("Bluetooth: ");
|
||||
DebugSerial.println(isBluetoothConnected() ? "Connected" : "Disconnected");
|
||||
DebugSerial.println("==================\n");
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// 调试串口
|
||||
DebugSerial.begin(115200, SERIAL_8N1, DEBUG_RX_PIN, DEBUG_TX_PIN);
|
||||
DebugSerial.setTimeout(1);
|
||||
|
||||
// 主串口(用于数据通信)
|
||||
// 电机数据通信串口
|
||||
Serial.begin(115200);
|
||||
Serial.setTimeout(100);
|
||||
|
||||
DebugSerial.println("VSMD INIT");
|
||||
DebugSerial.println("Commands:dev, cfg, ena, off, mov, pos, rmv, pps, org, stp, zero");
|
||||
DebugSerial.println("CMD: dev, sts, cfg, ena, off, mov, pos, rmv, pps, org, stp, zero, sav");
|
||||
DebugSerial.println("cfg CMD: bdr, mcs, spd, acc, dec, cra, crn, crh, s1f, s1r, s2f, s2r, zmd, snr, osv, zsd, zsp, dmd, dar, msr, msv, psr, psv");
|
||||
|
||||
// 初始化蓝牙
|
||||
initBluetooth();
|
||||
|
||||
printDeviceStatus();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// 处理串口数据
|
||||
handleSerialData();
|
||||
|
||||
// 处理蓝牙数据
|
||||
handleBluetoothData();
|
||||
|
||||
// 短暂延迟
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void handleSerialData() {
|
||||
if (DebugSerial.available() > 0) {
|
||||
int bytesRead = DebugSerial.readBytes(receiveBuffer, sizeof(receiveBuffer));
|
||||
|
||||
// // 添加调试信息
|
||||
// DebugSerial.print("Bytes read: ");
|
||||
// DebugSerial.println(bytesRead);
|
||||
// DebugSerial.print("Raw data: ");
|
||||
// for(int i = 0; i < bytesRead; i++) {
|
||||
// DebugSerial.print(receiveBuffer[i], HEX);
|
||||
// DebugSerial.print(" ");
|
||||
// }
|
||||
// DebugSerial.println();
|
||||
|
||||
// bytesProcessed = IRIS_Cut_Befor_Header(receiveBuffer, bytesRead);
|
||||
|
||||
// // 添加更多调试信息
|
||||
// DebugSerial.print("Bytes after header cut: ");
|
||||
// DebugSerial.println(bytesProcessed);
|
||||
|
||||
bytesProcessed = IRIS_Cut_Befor_Header(receiveBuffer, bytesRead);
|
||||
|
||||
if (bytesProcessed > 0) {
|
||||
@ -115,12 +83,11 @@ void loop() {
|
||||
case 0x00: { // JSON数据
|
||||
char jsonString[JSON_BUFFER_SIZE];
|
||||
memcpy(jsonString, responseBuffer, unpackResult);
|
||||
jsonString[unpackResult] = '\0'; // 确保字符串以null结尾
|
||||
|
||||
DebugSerial.print("Received JSON: ");
|
||||
DebugSerial.println(jsonString);
|
||||
jsonString[unpackResult] = '\0';
|
||||
|
||||
processJsonCommand(jsonString);
|
||||
//BLE Notify
|
||||
sendBluetoothData(sendBuffer, packedLength);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -136,7 +103,7 @@ void loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
default: { // 自定义二进制数据 (0x02-0xff)
|
||||
default: { // 自定义二进制数据
|
||||
DebugSerial.print("Received Binary Data, Command: 0x");
|
||||
DebugSerial.print(command, HEX);
|
||||
DebugSerial.print(", Length: ");
|
||||
@ -155,267 +122,3 @@ void loop() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void processJsonCommand(const char* jsonString) {
|
||||
StaticJsonDocument<JSON_BUFFER_SIZE> doc;
|
||||
DeserializationError error = deserializeJson(doc, jsonString);
|
||||
|
||||
if (error) {
|
||||
DebugSerial.print("JSON parsing failed: ");
|
||||
DebugSerial.println(error.c_str());
|
||||
sendJsonResponse("error", "JSON_PARSE_ERROR");
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用 command 字段替代 cmd
|
||||
const char* command = doc["command"];
|
||||
if (command == nullptr) {
|
||||
sendJsonResponse("error", "NO_COMMAND_FIELD");
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取 PA 参数对象(可选)
|
||||
JsonObject params = doc["PA"];
|
||||
|
||||
// 根据command执行相应操作
|
||||
if (strcmp(command, "cfg") == 0) {
|
||||
handle_cfg_cmd();
|
||||
} else if (strcmp(command, "ena") == 0) {
|
||||
handle_ena_cmd();
|
||||
} else if (strcmp(command, "off") == 0) {
|
||||
handle_off_cmd();
|
||||
} else if (strcmp(command, "mov") == 0) {
|
||||
handle_mov_cmd();
|
||||
} else if (strcmp(command, "pos") == 0) {
|
||||
// 修正:正确的类型转换
|
||||
int value = params.containsKey("value") ? params["value"].as<int>() : 0;
|
||||
handle_pos_cmd(value);
|
||||
} else if (strcmp(command, "rmv") == 0) {
|
||||
int value = params.containsKey("value") ? params["value"].as<int>() : 0;
|
||||
handle_rmv_cmd(value);
|
||||
} else if (strcmp(command, "pps") == 0) {
|
||||
if (params.containsKey("value")) {
|
||||
int value = params["value"].as<int>();
|
||||
handle_pps_cmd(value);
|
||||
} else {
|
||||
handle_pps_cmd();
|
||||
}
|
||||
} else if (strcmp(command, "org") == 0) {
|
||||
handle_org_cmd();
|
||||
} else if (strcmp(command, "stp") == 0) {
|
||||
handle_stp_cmd();
|
||||
} else if (strcmp(command, "zero") == 0) {
|
||||
// 修正:正确的字符串类型转换
|
||||
const char* value = params.containsKey("value") ? params["value"].as<const char*>() : "";
|
||||
handle_zero_cmd(value);
|
||||
} else if (strcmp(command, "dev") == 0) {
|
||||
handle_dev_cmd();
|
||||
} else {
|
||||
sendJsonResponse(command, "UNKNOWN_COMMAND");
|
||||
}
|
||||
}
|
||||
|
||||
void processStringCommand(const char* stringData) {
|
||||
// 处理字符串命令
|
||||
String response = "Echo: " + String(stringData);
|
||||
sendStringResponse(response.c_str());
|
||||
}
|
||||
|
||||
void sendJsonResponse(const char* command, const char* status, int value) {
|
||||
StaticJsonDocument<JSON_BUFFER_SIZE> responseDoc;
|
||||
|
||||
// 修改:使用新的JSON格式
|
||||
responseDoc["command"] = command; // 使用 command 替代 cmd
|
||||
responseDoc["ST"] = status; // 使用 ST 替代 status
|
||||
|
||||
// 如果有参数值,添加到 PA 对象中
|
||||
if (value != -1) {
|
||||
JsonObject params = responseDoc.createNestedObject("PA");
|
||||
params["value"] = value;
|
||||
}
|
||||
|
||||
// 可选:添加其他信息
|
||||
responseDoc["Other"] = "";
|
||||
|
||||
char jsonResponse[JSON_BUFFER_SIZE];
|
||||
serializeJson(responseDoc, jsonResponse, sizeof(jsonResponse));
|
||||
|
||||
// 打包并发送JSON响应
|
||||
DebugSerial.print("JSON Response: ");
|
||||
packedLength = IRIS_Protocol_Pack(0x00, strlen(jsonResponse), (uint8_t*)jsonResponse, sendBuffer);
|
||||
DebugSerial.write(sendBuffer, packedLength);
|
||||
|
||||
// DebugSerial.println();
|
||||
|
||||
// DebugSerial.print("Sent JSON Response: ");
|
||||
// DebugSerial.println(jsonResponse);
|
||||
}
|
||||
|
||||
void sendStringResponse(const char* response) {
|
||||
// 打包并发送字符串响应
|
||||
packedLength = IRIS_Protocol_Pack(0x01, strlen(response), (uint8_t*)response, sendBuffer);
|
||||
DebugSerial.write(sendBuffer, packedLength);
|
||||
|
||||
DebugSerial.print("Sent String Response: ");
|
||||
DebugSerial.println(response);
|
||||
}
|
||||
|
||||
void handle_cfg_cmd() {
|
||||
DebugSerial.println("cfg requested");
|
||||
Serial.println("cfg\n");
|
||||
// 返回配置相关信息
|
||||
sendJsonResponse("cfg", "OK");
|
||||
}
|
||||
|
||||
void handle_dev_cmd() {
|
||||
DebugSerial.println("dev_requested");
|
||||
Serial.println("dev\n");
|
||||
|
||||
// vsmd test data
|
||||
uint8_t testData[] = {
|
||||
0xFF, 0x00, 0x01, 0x56, 0x53, 0x4D, 0x44, 0x31, 0x34, 0x32, 0x2D, 0x30, 0x32, 0x35, 0x54, 0x2D,0x31, 0x2E, 0x31, 0x2E, 0x30, 0x32, 0x30, 0x2E, 0x32, 0x31, 0x31, 0x31, 0x31, 0x35, 0x00, 0x42, 0xFE
|
||||
};
|
||||
|
||||
// parseInfo获取解析结果
|
||||
String deviceInfo = parser.parseInfo(testData, sizeof(testData));
|
||||
|
||||
// 创建带有解析数据的JSON响应
|
||||
StaticJsonDocument<JSON_BUFFER_SIZE> responseDoc;
|
||||
responseDoc["command"] = "dev";
|
||||
responseDoc["ST"] = "OK";
|
||||
responseDoc["Other"] = deviceInfo;
|
||||
|
||||
char jsonResponse[JSON_BUFFER_SIZE];
|
||||
serializeJson(responseDoc, jsonResponse, sizeof(jsonResponse));
|
||||
|
||||
// 打包并发送JSON响应
|
||||
packedLength = IRIS_Protocol_Pack(0x00, strlen(jsonResponse), (uint8_t*)jsonResponse, sendBuffer);
|
||||
DebugSerial.write(sendBuffer, packedLength);
|
||||
|
||||
DebugSerial.println();
|
||||
|
||||
DebugSerial.print("Sent JSON Response: ");
|
||||
DebugSerial.println(jsonResponse);
|
||||
}
|
||||
|
||||
void handle_ena_cmd() {
|
||||
deviceEnabled = true;
|
||||
DebugSerial.println("Device enabled");
|
||||
Serial.print("ena\n");
|
||||
sendJsonResponse("ena", "OK");
|
||||
}
|
||||
|
||||
void handle_off_cmd() {
|
||||
deviceEnabled = false;
|
||||
isMoving = false;
|
||||
DebugSerial.println("Device disabled");
|
||||
Serial.print("off\n");
|
||||
sendJsonResponse("off", "OK");
|
||||
}
|
||||
|
||||
void handle_mov_cmd() {
|
||||
if (!deviceEnabled) {
|
||||
sendJsonResponse("mov", "DEVICE_DISABLED");
|
||||
return;
|
||||
}
|
||||
|
||||
isMoving = true;
|
||||
DebugSerial.println("Starting movement");
|
||||
Serial.print("mov\n");
|
||||
sendJsonResponse("mov", "OK");
|
||||
}
|
||||
|
||||
void handle_pos_cmd(int value) {
|
||||
if (!deviceEnabled) {
|
||||
sendJsonResponse("pos", "DEVICE_DISABLED");
|
||||
return;
|
||||
}
|
||||
|
||||
targetPosition = value;
|
||||
currentPosition = value; // 模拟立即到达
|
||||
DebugSerial.print("Position set to: ");
|
||||
DebugSerial.println(value);
|
||||
sendJsonResponse("pos", "OK", value);
|
||||
}
|
||||
|
||||
void handle_rmv_cmd(int value) {
|
||||
if (!deviceEnabled) {
|
||||
sendJsonResponse("rmv", "DEVICE_DISABLED");
|
||||
return;
|
||||
}
|
||||
|
||||
currentPosition += value;
|
||||
DebugSerial.print("Relative move by: ");
|
||||
DebugSerial.print(value);
|
||||
DebugSerial.print(", new position: ");
|
||||
DebugSerial.println(currentPosition);
|
||||
sendJsonResponse("rmv", "OK", currentPosition);
|
||||
}
|
||||
|
||||
void handle_pps_cmd(int value) {
|
||||
if (value == -1) {
|
||||
// SET PPS
|
||||
Serial.print("pps\n");
|
||||
sendJsonResponse("pps", "OK", pulsePerSecond);
|
||||
} else {
|
||||
// 设置PPS值
|
||||
pulsePerSecond = value;
|
||||
DebugSerial.print("Pulse per second set to: ");
|
||||
DebugSerial.println(value);
|
||||
sendJsonResponse("pps", "OK", value);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_org_cmd() {
|
||||
if (!deviceEnabled) {
|
||||
sendJsonResponse("org", "DEVICE_DISABLED");
|
||||
return;
|
||||
}
|
||||
|
||||
currentPosition = 0;
|
||||
targetPosition = 0;
|
||||
DebugSerial.println("Returned to origin");
|
||||
Serial.print("org\n");
|
||||
sendJsonResponse("org", "OK", 0);
|
||||
}
|
||||
|
||||
void handle_stp_cmd() {
|
||||
isMoving = false;
|
||||
DebugSerial.println("Movement stopped");
|
||||
Serial.print("stp\n");
|
||||
sendJsonResponse("stp", "OK");
|
||||
}
|
||||
|
||||
void handle_zero_cmd(const char* value) {
|
||||
if (strcmp(value, "start") == 0) {
|
||||
Serial.print("zero start\n");
|
||||
isBackZero = true;
|
||||
DebugSerial.println("Zero started");
|
||||
sendJsonResponse("zero", "ZERO_STARTED");
|
||||
} else if (strcmp(value, "stop") == 0) {
|
||||
Serial.print("zero stop\n");
|
||||
isBackZero = false;
|
||||
currentPosition = 0;
|
||||
DebugSerial.println("Zero completed");
|
||||
sendJsonResponse("zero", "ZERO_COMPLETED");
|
||||
} else {
|
||||
sendJsonResponse("zero", "INVALID_VALUE");
|
||||
}
|
||||
}
|
||||
|
||||
void printDeviceStatus() {
|
||||
DebugSerial.println("\n=== Device Status ===");
|
||||
DebugSerial.print("Enabled: ");
|
||||
DebugSerial.println(deviceEnabled ? "Yes" : "No");
|
||||
DebugSerial.print("Current Position: ");
|
||||
DebugSerial.println(currentPosition);
|
||||
DebugSerial.print("Target Position: ");
|
||||
DebugSerial.println(targetPosition);
|
||||
DebugSerial.print("Pulse Per Second: ");
|
||||
DebugSerial.println(pulsePerSecond);
|
||||
DebugSerial.print("Moving: ");
|
||||
DebugSerial.println(isMoving ? "Yes" : "No");
|
||||
DebugSerial.print("Zero Backing: ");
|
||||
DebugSerial.println(isBackZero ? "Yes" : "No");
|
||||
DebugSerial.println("==================\n");
|
||||
}
|
||||
@ -185,7 +185,8 @@ String VSMDParser::parseInfo(uint8_t* data, int size) {
|
||||
result += (char)data[i];
|
||||
}
|
||||
} else {
|
||||
result = "数据长度不足";
|
||||
result = "Not enough data";
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user