From fc0aac6803587619ab46b9afe45466a1c862f73b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=96=E5=8F=81?= Date: Fri, 27 Dec 2024 11:32:09 +0800 Subject: [PATCH] feat: basic ir mode --- README.md | 8 +++++++- include/consts.example.h | 8 ++++++++ include/handlers.h | 1 + include/ir.h | 33 +++++++++++++++++++++++++++++++++ packet.md | 13 ++++++++++--- src/handlers.cpp | 26 ++++++++++++++------------ src/ir.cpp | 28 ++++++++++++++++++++++++++++ src/main.cpp | 4 ++++ src/transmit.cpp | 34 +++++++++++++++++++++------------- 9 files changed, 126 insertions(+), 29 deletions(-) create mode 100644 include/ir.h create mode 100644 src/ir.cpp diff --git a/README.md b/README.md index 74284e8..3ee8084 100644 --- a/README.md +++ b/README.md @@ -46,4 +46,10 @@ git clone https://github.com/colour93/esp32-car.git 同时一些状态信息会主动发送。 -[数据包格式](./packet.md) \ No newline at end of file +[数据包格式](./packet.md) + +## Android APP + +这是一个配套的 Android APP,基于 Kotlin + Compose,通信协议使用上面的 BLE 串口通信协议。 + +[colour93/esp32-car-android](https://github.com/colour93/esp32-car-android) diff --git a/include/consts.example.h b/include/consts.example.h index 7bed484..48de5e0 100644 --- a/include/consts.example.h +++ b/include/consts.example.h @@ -15,6 +15,14 @@ #define HC_SR04_TRIG 23 #define HC_SR04_ECHO 22 +// 红外循迹模块引脚 +// 模式选择 +#define IR_MODE IRMode::IR_MODE_GPIO +// GPIO 模式 +#define IR_PINS {34, 35, 12, 13, 15} +// 串口模式 +// #define IR_PINS {34, 35} + // TB6612 #1 控制 A B 电机 // A 电机 左前轮 #define MOTOR_A_PWMA 21 // 电机 A PWM diff --git a/include/handlers.h b/include/handlers.h index 2956088..7289ded 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -7,6 +7,7 @@ #include "ultrasound.h" #include "transmit.h" #include "pid.h" +#include "ir.h" #include "utils.h" // 指令定义 diff --git a/include/ir.h b/include/ir.h new file mode 100644 index 0000000..1b064f1 --- /dev/null +++ b/include/ir.h @@ -0,0 +1,33 @@ +#ifndef IR_H +#define IR_H + +#include + +enum IRMode +{ + IR_MODE_GPIO, + IR_MODE_UART +}; + +struct IRConfig +{ + IRMode mode; + uint8_t pins[5]; +}; + +struct IRData +{ + uint8_t length; + uint8_t data[8]; +}; + +class IR +{ +public: + static IRConfig config; + static IRData data; + static void init(IRConfig config); + static void update(); +}; + +#endif \ No newline at end of file diff --git a/packet.md b/packet.md index b19185e..60280b2 100644 --- a/packet.md +++ b/packet.md @@ -132,8 +132,15 @@ ## 状态回报 -### 电机状态汇报 `0xE0` +### 设备状态回报 `0xE0` -包体 `01 0C E0 电机A_IN_1_2 电机A_PWM 电机B_IN_1_2 电机B_PWM 电机C_IN_1_2 电机C_PWM 电机D_IN_1_2 电机D_PWM FE` +包体 `01 0E E0 电机A_IN_1_2 电机A_PWM 电机B_IN_1_2 电机B_PWM 电机C_IN_1_2 电机C_PWM 电机D_IN_1_2 电机D_PWM 红外引脚数量 红外数据 FE` -示例 `01 0C E0 01 FF 02 FF 02 FF 01 FF FE` +| 数据 | 类型 | 表示 | +| -------- | ---- | ---- | +| IN_1_2 | 无符号整数 | 按位表示 IN1 IN2 的值, 0000 00 IN2 IN1 | +| PWM | 无符号整数 | - | +| 红外引脚数量 | 无符号整数 | - | +| 红外数据 | 无符号整数 | 按位表示红外循迹模块数据, 0001 1111 | + +示例 `01 0E E0 01 FF 02 FF 02 FF 01 FF 05 1F FE` diff --git a/src/handlers.cpp b/src/handlers.cpp index da76975..502e267 100644 --- a/src/handlers.cpp +++ b/src/handlers.cpp @@ -18,27 +18,29 @@ void Handlers::getBTStatus(BLECharacteristic &characteristic) void Handlers::getSPIFFSStatus(BLECharacteristic &characteristic) { Serial.println("CMD_GET_SPIFFS_STATUS"); + uint8_t bufferIndex = 0; // 构建响应数据 - buffer[0] = PACKET_T_HEAD; - buffer[1] = 0x05; - buffer[2] = CMD_GET_SPIFFS_STATUS; - buffer[3] = (uint8_t)(Storage::isMounted ? 0x01 : 0x00); - buffer[4] = PACKET_T_TAIL; - characteristic.setValue(buffer, 5); + buffer[bufferIndex++] = PACKET_T_HEAD; + buffer[bufferIndex++] = 0x05; + buffer[bufferIndex++] = CMD_GET_SPIFFS_STATUS; + buffer[bufferIndex++] = (uint8_t)(Storage::isMounted ? 0x01 : 0x00); + buffer[bufferIndex++] = PACKET_T_TAIL; + characteristic.setValue(buffer, bufferIndex); characteristic.notify(); } void Handlers::getDistance(BLECharacteristic &characteristic) { float distance = Ultrasonic::getDistance(); + uint8_t bufferIndex = 0; Serial.println("CMD_GET_DISTANCE, distance: " + String(distance)); // 构建响应数据 - buffer[0] = PACKET_T_HEAD; - buffer[1] = 0x08; - buffer[2] = CMD_GET_DISTANCE; - floatToBytes(distance, &buffer[3]); - buffer[7] = PACKET_T_TAIL; - characteristic.setValue(buffer, 8); + buffer[bufferIndex++] = PACKET_T_HEAD; + buffer[bufferIndex++] = 0x08; + buffer[bufferIndex++] = CMD_GET_DISTANCE; + floatToBytes(distance, &buffer[bufferIndex]); + buffer[bufferIndex++] = PACKET_T_TAIL; + characteristic.setValue(buffer, bufferIndex); characteristic.notify(); } diff --git a/src/ir.cpp b/src/ir.cpp new file mode 100644 index 0000000..fc2d89b --- /dev/null +++ b/src/ir.cpp @@ -0,0 +1,28 @@ +#include "ir.h" + +IRConfig IR::config; +IRData IR::data; + +void IR::init(IRConfig config) +{ + IR::config = config; + if (config.mode == IRMode::IR_MODE_GPIO) + { + data.length = 5; + for (int i = 0; i < 5; i++) + { + pinMode(config.pins[i], INPUT); + } + } +} + +void IR::update() +{ + if (config.mode == IRMode::IR_MODE_GPIO) + { + for (int i = 0; i < 5; i++) + { + data.data[i] = digitalRead(config.pins[i]); + } + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 2b269f4..03bd83e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include "storage.h" #include "ble.h" #include "led.h" +#include "ir.h" #include "consts.h" void setup() @@ -24,6 +25,9 @@ void setup() {MOTOR_C_PWMA, MOTOR_C_AIN1, MOTOR_C_AIN2}, {MOTOR_D_PWMB, MOTOR_D_BIN1, MOTOR_D_BIN2}); + // 初始化红外循迹模块 + IR::init({IR_MODE, IR_PINS}); + // 初始化状态灯 if (STATUS_LED_ENABLE) { diff --git a/src/transmit.cpp b/src/transmit.cpp index bae7cf2..088574a 100644 --- a/src/transmit.cpp +++ b/src/transmit.cpp @@ -115,19 +115,27 @@ void sendStatus(BLECharacteristic &characteristic) lastMotorStatusUpdate = currentMillis; uint8_t buffer[PACKET_MAX_LENGTH]; - buffer[0] = PACKET_T_HEAD; - buffer[1] = 0x0C; - buffer[2] = CMD_STATUS_MOTOR; - buffer[3] = (MotorController::getMotorStatus('A').in2 << 1) | MotorController::getMotorStatus('A').in1; - buffer[4] = MotorController::getMotorStatus('A').pwm; - buffer[5] = (MotorController::getMotorStatus('B').in2 << 1) | MotorController::getMotorStatus('B').in1; - buffer[6] = MotorController::getMotorStatus('B').pwm; - buffer[7] = (MotorController::getMotorStatus('C').in2 << 1) | MotorController::getMotorStatus('C').in1; - buffer[8] = MotorController::getMotorStatus('C').pwm; - buffer[9] = (MotorController::getMotorStatus('D').in2 << 1) | MotorController::getMotorStatus('D').in1; - buffer[10] = MotorController::getMotorStatus('D').pwm; - buffer[11] = PACKET_T_TAIL; - characteristic.setValue(buffer, 12); + uint8_t bufferIndex = 0; + buffer[bufferIndex++] = PACKET_T_HEAD; + buffer[bufferIndex++] = 0x0C; + buffer[bufferIndex++] = CMD_STATUS_MOTOR; + buffer[bufferIndex++] = (MotorController::getMotorStatus('A').in2 << 1) | MotorController::getMotorStatus('A').in1; + buffer[bufferIndex++] = MotorController::getMotorStatus('A').pwm; + buffer[bufferIndex++] = (MotorController::getMotorStatus('B').in2 << 1) | MotorController::getMotorStatus('B').in1; + buffer[bufferIndex++] = MotorController::getMotorStatus('B').pwm; + buffer[bufferIndex++] = (MotorController::getMotorStatus('C').in2 << 1) | MotorController::getMotorStatus('C').in1; + buffer[bufferIndex++] = MotorController::getMotorStatus('C').pwm; + buffer[bufferIndex++] = (MotorController::getMotorStatus('D').in2 << 1) | MotorController::getMotorStatus('D').in1; + buffer[bufferIndex++] = MotorController::getMotorStatus('D').pwm; + buffer[bufferIndex++] = IR::data.length; + uint16_t irData = 0; + for (uint8_t i = 0; i < IR::data.length; i++) + { + irData |= (IR::data.data[i] << (i * 2)); + } + buffer[bufferIndex++] = irData; + buffer[bufferIndex++] = PACKET_T_TAIL; + characteristic.setValue(buffer, bufferIndex); characteristic.notify(); } } \ No newline at end of file