optimize: SPP Bluetooth -> BLE
This commit is contained in:
parent
3420bf4a4a
commit
64a4c8ae43
196
src/main.cpp
196
src/main.cpp
|
@ -1,5 +1,8 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <BluetoothSerial.h>
|
#include <BLEDevice.h>
|
||||||
|
#include <BLEServer.h>
|
||||||
|
#include <BLEUtils.h>
|
||||||
|
#include <BLE2902.h>
|
||||||
|
|
||||||
#define STATUS_LED 2
|
#define STATUS_LED 2
|
||||||
|
|
||||||
|
@ -38,15 +41,11 @@
|
||||||
#define TURN_RATIO 0.6 // 转向时的速度比例
|
#define TURN_RATIO 0.6 // 转向时的速度比例
|
||||||
#define SPEED_INCREMENT 10 // 速度增量
|
#define SPEED_INCREMENT 10 // 速度增量
|
||||||
|
|
||||||
// 全局变量
|
// Nordic UART Service UUID
|
||||||
int currentSpeed = 0; // 当前速度
|
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||||
int turnOffset = 0; // 转向偏移量 (-100 到 100)
|
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||||
bool isMoving = false; // 运动状态
|
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||||
bool isTurning = false; // 转向状态
|
|
||||||
|
|
||||||
BluetoothSerial SerialBT;
|
|
||||||
|
|
||||||
// 在全局变量定义区域添加以下内容
|
|
||||||
#define PACKET_R_HEAD 0x00
|
#define PACKET_R_HEAD 0x00
|
||||||
#define PACKET_R_TAIL 0xFF
|
#define PACKET_R_TAIL 0xFF
|
||||||
#define PACKET_T_HEAD 0x01
|
#define PACKET_T_HEAD 0x01
|
||||||
|
@ -59,6 +58,17 @@ BluetoothSerial SerialBT;
|
||||||
#define CMD_MOTOR_MOVE_CONTROL 0x20
|
#define CMD_MOTOR_MOVE_CONTROL 0x20
|
||||||
#define CMD_MOTOR_ROTATE_CONTROL 0x21
|
#define CMD_MOTOR_ROTATE_CONTROL 0x21
|
||||||
|
|
||||||
|
// 全局变量
|
||||||
|
int currentSpeed = 0; // 当前速度
|
||||||
|
int turnOffset = 0; // 转向偏移量 (-100 到 100)
|
||||||
|
bool isMoving = false; // 运动状态
|
||||||
|
bool isTurning = false; // 转向状态
|
||||||
|
|
||||||
|
// BLE 相关
|
||||||
|
BLEServer *pServer = nullptr;
|
||||||
|
BLECharacteristic *pTxCharacteristic = nullptr;
|
||||||
|
bool deviceConnected = false;
|
||||||
|
|
||||||
// 数据包缓冲区
|
// 数据包缓冲区
|
||||||
uint8_t packetBuffer[PACKET_MAX_LENGTH];
|
uint8_t packetBuffer[PACKET_MAX_LENGTH];
|
||||||
int packetIndex = 0;
|
int packetIndex = 0;
|
||||||
|
@ -69,6 +79,38 @@ bool isReceivingPacket = false;
|
||||||
unsigned long lastLedToggle = 0; // 上次LED切换状态的时间
|
unsigned long lastLedToggle = 0; // 上次LED切换状态的时间
|
||||||
bool ledState = false; // LED当前状态
|
bool ledState = false; // LED当前状态
|
||||||
|
|
||||||
|
void processSerialIncomingByte(uint8_t incomingByte, BLECharacteristic &characteristic);
|
||||||
|
|
||||||
|
class CarBLEServerCallbacks : public BLEServerCallbacks
|
||||||
|
{
|
||||||
|
void onConnect(BLEServer *pServer)
|
||||||
|
{
|
||||||
|
deviceConnected = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
void onDisconnect(BLEServer *pServer)
|
||||||
|
{
|
||||||
|
deviceConnected = false;
|
||||||
|
// 重新开始广播
|
||||||
|
pServer->getAdvertising()->start();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CarBLECharacteristicCallbacks : public BLECharacteristicCallbacks
|
||||||
|
{
|
||||||
|
void onWrite(BLECharacteristic *pCharacteristic)
|
||||||
|
{
|
||||||
|
std::string rxValue = pCharacteristic->getValue();
|
||||||
|
if (rxValue.length() > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < rxValue.length(); i++)
|
||||||
|
{
|
||||||
|
processSerialIncomingByte((uint8_t)rxValue[i], *pTxCharacteristic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void floatToBytes(float val, uint8_t *bytes)
|
void floatToBytes(float val, uint8_t *bytes)
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
|
@ -107,7 +149,6 @@ void motorControl(int pwmPin, int in1Pin, int in2Pin, int speed)
|
||||||
analogWrite(pwmPin, speed);
|
analogWrite(pwmPin, speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float getDistance()
|
float getDistance()
|
||||||
{
|
{
|
||||||
digitalWrite(HC_SR04_TRIG, HIGH);
|
digitalWrite(HC_SR04_TRIG, HIGH);
|
||||||
|
@ -118,18 +159,32 @@ float getDistance()
|
||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
u_char getSerialBTStatus()
|
|
||||||
{
|
|
||||||
return SerialBT.connected() ? 0x01 : 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
// 初始化串口
|
// 初始化串口
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
|
||||||
// 初始化蓝牙
|
// 初始化 BLE
|
||||||
SerialBT.begin("WhiteTiger");
|
BLEDevice::init("WhiteTiger");
|
||||||
|
pServer = BLEDevice::createServer();
|
||||||
|
pServer->setCallbacks(new CarBLEServerCallbacks());
|
||||||
|
|
||||||
|
BLEService *pService = pServer->createService(SERVICE_UUID);
|
||||||
|
|
||||||
|
// 创建 RX 特征值 (用于接收数据)
|
||||||
|
BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
|
||||||
|
CHARACTERISTIC_UUID_RX,
|
||||||
|
BLECharacteristic::PROPERTY_WRITE);
|
||||||
|
pRxCharacteristic->setCallbacks(new CarBLECharacteristicCallbacks());
|
||||||
|
|
||||||
|
// 创建 TX 特征值 (用于发送数据)
|
||||||
|
pTxCharacteristic = pService->createCharacteristic(
|
||||||
|
CHARACTERISTIC_UUID_TX,
|
||||||
|
BLECharacteristic::PROPERTY_NOTIFY);
|
||||||
|
pTxCharacteristic->addDescriptor(new BLE2902());
|
||||||
|
|
||||||
|
pService->start();
|
||||||
|
pServer->getAdvertising()->start();
|
||||||
|
|
||||||
// 设置引脚模式
|
// 设置引脚模式
|
||||||
pinMode(STATUS_LED, OUTPUT);
|
pinMode(STATUS_LED, OUTPUT);
|
||||||
|
@ -155,50 +210,49 @@ void setup()
|
||||||
pinMode(HC_SR04_ECHO, INPUT);
|
pinMode(HC_SR04_ECHO, INPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSerialPacket(uint8_t *packet, int length, Stream &serial)
|
void handleSerialPacket(uint8_t *packet, int length, BLECharacteristic &characteristic)
|
||||||
{
|
{
|
||||||
if (length < 4)
|
if (!deviceConnected || length < 4)
|
||||||
return; // 最小包长度:包头(1) + 长度(1) + 指令(1) + 包尾(1)
|
return;
|
||||||
|
|
||||||
uint8_t packetLength = packet[1]; // 获取长度
|
uint8_t packetLength = packet[1]; // 获取长度
|
||||||
uint8_t cmd = packet[2]; // 获取指令
|
uint8_t cmd = packet[2]; // 获取指令
|
||||||
uint8_t direction, speed, time;
|
uint8_t direction, speed, time;
|
||||||
float distance;
|
float distance;
|
||||||
|
uint8_t buffer[PACKET_MAX_LENGTH]; // 用于存储要发送的数据
|
||||||
uint8_t transmitBuffer[PACKET_MAX_LENGTH];
|
int bufferIndex = 0;
|
||||||
|
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case CMD_GET_BT_STATUS:
|
case CMD_GET_BT_STATUS:
|
||||||
Serial.println("CMD_GET_BT_STATUS");
|
Serial.println("CMD_GET_BT_STATUS");
|
||||||
// 回复状态
|
// 构建响应数据
|
||||||
serial.write(PACKET_T_HEAD);
|
buffer[0] = PACKET_T_HEAD;
|
||||||
serial.write(0x05); // 包体长度
|
buffer[1] = 0x05;
|
||||||
serial.write(CMD_GET_BT_STATUS);
|
buffer[2] = CMD_GET_BT_STATUS;
|
||||||
serial.write(getSerialBTStatus());
|
buffer[3] = (uint8_t)(deviceConnected ? 0x01 : 0x00);
|
||||||
serial.write(PACKET_T_TAIL);
|
buffer[4] = PACKET_T_TAIL;
|
||||||
|
characteristic.setValue(buffer, 5);
|
||||||
|
characteristic.notify();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_GET_DISTANCE:
|
case CMD_GET_DISTANCE:
|
||||||
Serial.println("CMD_GET_DISTANCE");
|
|
||||||
distance = getDistance();
|
distance = getDistance();
|
||||||
Serial.printf("distance = %f\n", distance);
|
Serial.println("CMD_GET_DISTANCE, distance: " + String(distance));
|
||||||
floatToBytes(distance, transmitBuffer);
|
// 构建响应数据
|
||||||
// 回复距离
|
buffer[0] = PACKET_T_HEAD;
|
||||||
serial.write(PACKET_T_HEAD);
|
buffer[1] = 0x08;
|
||||||
serial.write(0x08); // 包体长度
|
buffer[2] = CMD_GET_DISTANCE;
|
||||||
serial.write(CMD_GET_DISTANCE);
|
floatToBytes(distance, &buffer[3]);
|
||||||
serial.write(transmitBuffer, 4);
|
buffer[7] = PACKET_T_TAIL;
|
||||||
serial.write(PACKET_T_TAIL);
|
characteristic.setValue(buffer, 8);
|
||||||
|
characteristic.notify();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_MOTOR_MOVE_CONTROL:
|
case CMD_MOTOR_MOVE_CONTROL:
|
||||||
// 获取方向和速度
|
|
||||||
direction = packet[3];
|
direction = packet[3];
|
||||||
speed = packet[4];
|
speed = packet[4];
|
||||||
|
Serial.println("CMD_MOTOR_MOVE_CONTROL, direction: " + String(direction) + ", speed: " + String(speed));
|
||||||
Serial.printf("CMD_MOTOR_MOVE_CONTROL: direction = 0x%02X, speed = %d\n", direction, speed);
|
|
||||||
|
|
||||||
// 移动
|
// 移动
|
||||||
if (direction == 0x00)
|
if (direction == 0x00)
|
||||||
{
|
{
|
||||||
|
@ -207,64 +261,52 @@ void handleSerialPacket(uint8_t *packet, int length, Stream &serial)
|
||||||
motorControl(MOTOR_C_PWMA, MOTOR_C_AIN1, MOTOR_C_AIN2, 0);
|
motorControl(MOTOR_C_PWMA, MOTOR_C_AIN1, MOTOR_C_AIN2, 0);
|
||||||
motorControl(MOTOR_D_PWMB, MOTOR_D_BIN1, MOTOR_D_BIN2, 0);
|
motorControl(MOTOR_D_PWMB, MOTOR_D_BIN1, MOTOR_D_BIN2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 前进
|
// 前进
|
||||||
if (direction == 0x01)
|
else if (direction == 0x01)
|
||||||
{
|
{
|
||||||
motorControl(MOTOR_A_PWMA, MOTOR_A_AIN1, MOTOR_A_AIN2, speed);
|
motorControl(MOTOR_A_PWMA, MOTOR_A_AIN1, MOTOR_A_AIN2, speed);
|
||||||
motorControl(MOTOR_B_PWMB, MOTOR_B_BIN2, MOTOR_B_BIN1, speed);
|
motorControl(MOTOR_B_PWMB, MOTOR_B_BIN2, MOTOR_B_BIN1, speed);
|
||||||
motorControl(MOTOR_C_PWMA, MOTOR_C_AIN2, MOTOR_C_AIN1, speed);
|
motorControl(MOTOR_C_PWMA, MOTOR_C_AIN2, MOTOR_C_AIN1, speed);
|
||||||
motorControl(MOTOR_D_PWMB, MOTOR_D_BIN1, MOTOR_D_BIN2, speed);
|
motorControl(MOTOR_D_PWMB, MOTOR_D_BIN1, MOTOR_D_BIN2, speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 后退
|
// 后退
|
||||||
if (direction == 0x02)
|
else if (direction == 0x02)
|
||||||
{
|
{
|
||||||
motorControl(MOTOR_A_PWMA, MOTOR_A_AIN1, MOTOR_A_AIN2, -speed);
|
motorControl(MOTOR_A_PWMA, MOTOR_A_AIN1, MOTOR_A_AIN2, -speed);
|
||||||
motorControl(MOTOR_B_PWMB, MOTOR_B_BIN2, MOTOR_B_BIN1, -speed);
|
motorControl(MOTOR_B_PWMB, MOTOR_B_BIN2, MOTOR_B_BIN1, -speed);
|
||||||
motorControl(MOTOR_C_PWMA, MOTOR_C_AIN2, MOTOR_C_AIN1, -speed);
|
motorControl(MOTOR_C_PWMA, MOTOR_C_AIN2, MOTOR_C_AIN1, -speed);
|
||||||
motorControl(MOTOR_D_PWMB, MOTOR_D_BIN1, MOTOR_D_BIN2, -speed);
|
motorControl(MOTOR_D_PWMB, MOTOR_D_BIN1, MOTOR_D_BIN2, -speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_MOTOR_ROTATE_CONTROL:
|
case CMD_MOTOR_ROTATE_CONTROL:
|
||||||
// 获取方向和时间
|
|
||||||
direction = packet[3];
|
direction = packet[3];
|
||||||
time = packet[4];
|
time = packet[4];
|
||||||
|
Serial.println("CMD_MOTOR_ROTATE_CONTROL, direction: " + String(direction) + ", time: " + String(time));
|
||||||
// 原地旋转
|
|
||||||
Serial.printf("CMD_MOTOR_ROTATE_CONTROL: direction = 0x%02X, time = %d\n", direction, time);
|
|
||||||
// 顺时针
|
// 顺时针
|
||||||
if (direction == 0x00)
|
if (direction == 0x00)
|
||||||
{
|
{
|
||||||
// 左侧电机向前转
|
motorControl(MOTOR_A_PWMA, MOTOR_A_AIN1, MOTOR_A_AIN2, 255);
|
||||||
motorControl(MOTOR_A_PWMA, MOTOR_A_AIN1, MOTOR_A_AIN2, 255); // 左前
|
motorControl(MOTOR_B_PWMB, MOTOR_B_BIN2, MOTOR_B_BIN1, 255);
|
||||||
motorControl(MOTOR_B_PWMB, MOTOR_B_BIN2, MOTOR_B_BIN1, 255); // 左后
|
motorControl(MOTOR_C_PWMA, MOTOR_C_AIN2, MOTOR_C_AIN1, -255);
|
||||||
// 右侧电机向后转
|
motorControl(MOTOR_D_PWMB, MOTOR_D_BIN1, MOTOR_D_BIN2, -255);
|
||||||
motorControl(MOTOR_C_PWMA, MOTOR_C_AIN2, MOTOR_C_AIN1, -255); // 右后
|
|
||||||
motorControl(MOTOR_D_PWMB, MOTOR_D_BIN1, MOTOR_D_BIN2, -255); // 右前
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 逆时针
|
// 逆时针
|
||||||
if (direction == 0x01)
|
else if (direction == 0x01)
|
||||||
{
|
{
|
||||||
// 左侧电机向后转
|
motorControl(MOTOR_A_PWMA, MOTOR_A_AIN1, MOTOR_A_AIN2, -255);
|
||||||
motorControl(MOTOR_A_PWMA, MOTOR_A_AIN1, MOTOR_A_AIN2, -255); // 左前
|
motorControl(MOTOR_B_PWMB, MOTOR_B_BIN2, MOTOR_B_BIN1, -255);
|
||||||
motorControl(MOTOR_B_PWMB, MOTOR_B_BIN2, MOTOR_B_BIN1, -255); // 左后
|
motorControl(MOTOR_C_PWMA, MOTOR_C_AIN2, MOTOR_C_AIN1, 255);
|
||||||
// 右侧电机向前转
|
motorControl(MOTOR_D_PWMB, MOTOR_D_BIN1, MOTOR_D_BIN2, 255);
|
||||||
motorControl(MOTOR_C_PWMA, MOTOR_C_AIN2, MOTOR_C_AIN1, 255); // 右后
|
|
||||||
motorControl(MOTOR_D_PWMB, MOTOR_D_BIN1, MOTOR_D_BIN2, 255); // 右前
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// 未知指令处理
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void processSerialIncomingByte(uint8_t incomingByte, Stream &serial)
|
void processSerialIncomingByte(uint8_t incomingByte, BLECharacteristic &characteristic)
|
||||||
{
|
{
|
||||||
static uint8_t expectedLength = 0;
|
static uint8_t expectedLength = 0;
|
||||||
|
|
||||||
|
@ -294,7 +336,7 @@ void processSerialIncomingByte(uint8_t incomingByte, Stream &serial)
|
||||||
isReceivingPacket = false;
|
isReceivingPacket = false;
|
||||||
if (incomingByte == PACKET_R_TAIL)
|
if (incomingByte == PACKET_R_TAIL)
|
||||||
{
|
{
|
||||||
handleSerialPacket(packetBuffer, packetIndex + 1, serial);
|
handleSerialPacket(packetBuffer, packetIndex + 1, *pTxCharacteristic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,14 +349,12 @@ void processSerialIncomingByte(uint8_t incomingByte, Stream &serial)
|
||||||
|
|
||||||
void updateStatusLED()
|
void updateStatusLED()
|
||||||
{
|
{
|
||||||
if (SerialBT.connected())
|
if (deviceConnected)
|
||||||
{
|
{
|
||||||
// 蓝牙已连接,LED常亮
|
|
||||||
digitalWrite(STATUS_LED, HIGH);
|
digitalWrite(STATUS_LED, HIGH);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 蓝牙未连接,LED慢闪
|
|
||||||
unsigned long currentMillis = millis();
|
unsigned long currentMillis = millis();
|
||||||
if (currentMillis - lastLedToggle >= LED_FLASH_INTERVAL)
|
if (currentMillis - lastLedToggle >= LED_FLASH_INTERVAL)
|
||||||
{
|
{
|
||||||
|
@ -327,19 +367,5 @@ void updateStatusLED()
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
if (SerialBT.available())
|
updateStatusLED();
|
||||||
{
|
|
||||||
uint8_t incomingByte = SerialBT.read();
|
|
||||||
processSerialIncomingByte(incomingByte, SerialBT);
|
|
||||||
Serial.printf("BT Received: 0x%02X\n", incomingByte);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Serial.available())
|
|
||||||
{
|
|
||||||
uint8_t incomingByte = Serial.read();
|
|
||||||
processSerialIncomingByte(incomingByte, Serial);
|
|
||||||
Serial.printf("UART Received: 0x%02X\n", incomingByte);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateStatusLED(); // 更新LED状态
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue