修复红外的兼容性问题
This commit is contained in:
405
ir_control.cpp
405
ir_control.cpp
@@ -1,169 +1,323 @@
|
||||
#include "ir_control.h"
|
||||
|
||||
void initIRControl() {
|
||||
pinMode(IR_RECEIVE_PIN, INPUT);
|
||||
pinMode(IR_SEND_PIN, OUTPUT);
|
||||
digitalWrite(IR_SEND_PIN, LOW);
|
||||
// 配置RMT发送通道
|
||||
rmt_config_t rmt_tx_config = RMT_DEFAULT_CONFIG_TX((gpio_num_t)IR_SEND_PIN, RMT_TX_CHANNEL);
|
||||
rmt_tx_config.clk_div = RMT_CLK_DIV;
|
||||
rmt_tx_config.mem_block_num = RMT_MEM_BLOCK_NUM;
|
||||
rmt_tx_config.tx_config.carrier_en = RMT_TX_CARRIER_EN;
|
||||
rmt_tx_config.tx_config.carrier_freq_hz = RMT_TX_CARRIER_FREQ_HZ;
|
||||
rmt_tx_config.tx_config.carrier_duty_percent = RMT_TX_CARRIER_DUTY_PERCENT;
|
||||
rmt_tx_config.tx_config.carrier_level = RMT_TX_CARRIER_LEVEL;
|
||||
rmt_tx_config.tx_config.idle_level = RMT_IDLE_LEVEL;
|
||||
rmt_tx_config.tx_config.idle_output_en = true;
|
||||
|
||||
Serial.println("红外控制模块初始化完成");
|
||||
Serial.print("接收引脚: ");
|
||||
Serial.println(IR_RECEIVE_PIN);
|
||||
Serial.print("发送引脚: ");
|
||||
Serial.println(IR_SEND_PIN);
|
||||
esp_err_t err = rmt_config(&rmt_tx_config);
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("RMT发送通道配置失败: %s\n", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
|
||||
err = rmt_driver_install(RMT_TX_CHANNEL, 0, 0);
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("RMT发送驱动安装失败: %s\n", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// 配置RMT接收通道
|
||||
rmt_config_t rmt_rx_config = RMT_DEFAULT_CONFIG_RX((gpio_num_t)IR_RECEIVE_PIN, RMT_RX_CHANNEL);
|
||||
rmt_rx_config.clk_div = RMT_CLK_DIV;
|
||||
rmt_rx_config.mem_block_num = RMT_MEM_BLOCK_NUM;
|
||||
rmt_rx_config.rx_config.filter_en = RMT_RX_FILTER_EN;
|
||||
rmt_rx_config.rx_config.filter_ticks_thresh = RMT_RX_FILTER_THRESH_US;
|
||||
rmt_rx_config.rx_config.idle_threshold = RMT_RX_IDLE_THRESH_US;
|
||||
|
||||
err = rmt_config(&rmt_rx_config);
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("RMT接收通道配置失败: %s\n", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
|
||||
err = rmt_driver_install(RMT_RX_CHANNEL, 1000, 0);
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("RMT接收驱动安装失败: %s\n", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("红外控制模块初始化完成 (使用RMT)");
|
||||
Serial.printf("发送引脚: %d (RMT通道: %d)\n", IR_SEND_PIN, RMT_TX_CHANNEL);
|
||||
Serial.printf("接收引脚: %d (RMT通道: %d)\n", IR_RECEIVE_PIN, RMT_RX_CHANNEL);
|
||||
Serial.printf("载波频率: %d Hz\n", RMT_TX_CARRIER_FREQ_HZ);
|
||||
Serial.printf("时钟分辨率: %d us\n", RMT_CLK_DIV);
|
||||
}
|
||||
|
||||
bool checkIRSignalStart() {
|
||||
return (digitalRead(IR_RECEIVE_PIN) == LOW);
|
||||
// 使用RMT检查是否有信号开始
|
||||
// 启动接收并检查是否立即有数据
|
||||
rmt_rx_start(RMT_RX_CHANNEL, true);
|
||||
|
||||
// 等待短时间检查是否有信号
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
|
||||
// 获取RMT环形缓冲区句柄
|
||||
RingbufHandle_t rb = NULL;
|
||||
esp_err_t err = rmt_get_ringbuf_handle(RMT_RX_CHANNEL, &rb);
|
||||
if (err != ESP_OK) {
|
||||
rmt_rx_stop(RMT_RX_CHANNEL);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查RMT接收缓冲区是否有数据
|
||||
size_t rx_size = 0;
|
||||
rmt_item32_t* items = (rmt_item32_t*)xRingbufferReceive(rb, &rx_size, 0);
|
||||
|
||||
bool hasSignal = (items != nullptr && rx_size > 0);
|
||||
|
||||
if (items) {
|
||||
vRingbufferReturnItem(rb, (void*)items);
|
||||
}
|
||||
|
||||
rmt_rx_stop(RMT_RX_CHANNEL);
|
||||
|
||||
return hasSignal;
|
||||
}
|
||||
|
||||
IRSignal receiveIRSignal() {
|
||||
IRSignal signal;
|
||||
signal.data = nullptr;
|
||||
signal.length = 0;
|
||||
signal.markTimes = nullptr;
|
||||
signal.spaceTimes = nullptr;
|
||||
signal.markCount = 0;
|
||||
signal.spaceCount = 0;
|
||||
signal.carrierFreq = IR_CARRIER_FREQ;
|
||||
signal.isValid = false;
|
||||
|
||||
Serial.println("开始接收红外信号...");
|
||||
Serial.println("开始接收红外信号 (使用RMT)...");
|
||||
|
||||
// 分配内存存储信号数据
|
||||
signal.data = (unsigned int*)malloc(MAX_SIGNAL_LENGTH * sizeof(unsigned int));
|
||||
if (signal.data == nullptr) {
|
||||
Serial.println("内存分配失败");
|
||||
// 启动RMT接收
|
||||
rmt_rx_start(RMT_RX_CHANNEL, true);
|
||||
|
||||
// 获取RMT环形缓冲区句柄
|
||||
RingbufHandle_t rb = NULL;
|
||||
esp_err_t err = rmt_get_ringbuf_handle(RMT_RX_CHANNEL, &rb);
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("获取RMT缓冲区句柄失败: %s\n", esp_err_to_name(err));
|
||||
rmt_rx_stop(RMT_RX_CHANNEL);
|
||||
return signal;
|
||||
}
|
||||
|
||||
unsigned long startTime = micros();
|
||||
unsigned long lastChange = startTime;
|
||||
bool currentState = HIGH;
|
||||
bool lastState = HIGH;
|
||||
// 等待接收数据
|
||||
size_t rx_size = 0;
|
||||
rmt_item32_t* items = (rmt_item32_t*)xRingbufferReceive(rb, &rx_size, pdMS_TO_TICKS(RECEIVE_TIMEOUT_US / 1000));
|
||||
|
||||
// 等待信号开始(第一个低电平)
|
||||
while (digitalRead(IR_RECEIVE_PIN) == HIGH && (micros() - startTime) < RECEIVE_TIMEOUT_US) {
|
||||
delayMicroseconds(10);
|
||||
}
|
||||
|
||||
if ((micros() - startTime) >= RECEIVE_TIMEOUT_US) {
|
||||
Serial.println("等待信号超时");
|
||||
free(signal.data);
|
||||
signal.data = nullptr;
|
||||
if (items == nullptr || rx_size == 0) {
|
||||
Serial.println("RMT接收超时或无数据");
|
||||
rmt_rx_stop(RMT_RX_CHANNEL);
|
||||
return signal;
|
||||
}
|
||||
|
||||
Serial.println("检测到信号开始");
|
||||
lastChange = micros();
|
||||
lastState = LOW;
|
||||
signal.length = 0;
|
||||
// 计算接收到的项目数量
|
||||
size_t item_count = rx_size / sizeof(rmt_item32_t);
|
||||
Serial.printf("接收到 %d 个RMT项目\n", item_count);
|
||||
|
||||
// 接收信号数据
|
||||
while (signal.length < MAX_SIGNAL_LENGTH) {
|
||||
currentState = digitalRead(IR_RECEIVE_PIN);
|
||||
if (item_count == 0) {
|
||||
Serial.println("接收到的数据为空");
|
||||
vRingbufferReturnItem(rb, (void*)items);
|
||||
rmt_rx_stop(RMT_RX_CHANNEL);
|
||||
return signal;
|
||||
}
|
||||
|
||||
// 分配临时数组存储时序数据
|
||||
unsigned int* tempData = (unsigned int*)malloc(item_count * 2 * sizeof(unsigned int));
|
||||
if (tempData == nullptr) {
|
||||
Serial.println("临时数据内存分配失败");
|
||||
vRingbufferReturnItem(rb, (void*)items);
|
||||
rmt_rx_stop(RMT_RX_CHANNEL);
|
||||
return signal;
|
||||
}
|
||||
|
||||
int tempLength = 0;
|
||||
|
||||
// 解析RMT数据项
|
||||
for (size_t i = 0; i < item_count; i++) {
|
||||
// 每个RMT项目包含两个时间段:level0的持续时间和level1的持续时间
|
||||
if (items[i].duration0 > 0 && tempLength < item_count * 2) {
|
||||
tempData[tempLength++] = items[i].duration0;
|
||||
}
|
||||
if (items[i].duration1 > 0 && tempLength < item_count * 2) {
|
||||
tempData[tempLength++] = items[i].duration1;
|
||||
}
|
||||
}
|
||||
|
||||
// 释放RMT缓冲区
|
||||
vRingbufferReturnItem(rb, (void*)items);
|
||||
rmt_rx_stop(RMT_RX_CHANNEL);
|
||||
|
||||
if (tempLength > 0) {
|
||||
// 分离mark和space时间
|
||||
signal.markCount = (tempLength + 1) / 2; // 奇数索引是mark
|
||||
signal.spaceCount = tempLength / 2; // 偶数索引是space
|
||||
|
||||
if (currentState != lastState) {
|
||||
// 状态改变,记录持续时间
|
||||
unsigned long duration = micros() - lastChange;
|
||||
signal.data[signal.length] = duration;
|
||||
signal.length++;
|
||||
// 分配mark时间数组
|
||||
if (signal.markCount > 0) {
|
||||
signal.markTimes = (unsigned int*)malloc(signal.markCount * sizeof(unsigned int));
|
||||
if (signal.markTimes == nullptr) {
|
||||
Serial.println("mark时间数组内存分配失败");
|
||||
free(tempData);
|
||||
return signal;
|
||||
}
|
||||
|
||||
lastState = currentState;
|
||||
lastChange = micros();
|
||||
// 复制mark时间(从索引0开始,每隔2个取一个)
|
||||
for (int i = 0; i < signal.markCount; i++) {
|
||||
signal.markTimes[i] = tempData[i * 2];
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否信号结束(高电平持续时间过长)
|
||||
if (currentState == HIGH && (micros() - lastChange) > SIGNAL_END_TIMEOUT_US) {
|
||||
Serial.println("检测到信号结束");
|
||||
break;
|
||||
// 分配space时间数组
|
||||
if (signal.spaceCount > 0) {
|
||||
signal.spaceTimes = (unsigned int*)malloc(signal.spaceCount * sizeof(unsigned int));
|
||||
if (signal.spaceTimes == nullptr) {
|
||||
Serial.println("space时间数组内存分配失败");
|
||||
if (signal.markTimes != nullptr) {
|
||||
free(signal.markTimes);
|
||||
signal.markTimes = nullptr;
|
||||
}
|
||||
free(tempData);
|
||||
return signal;
|
||||
}
|
||||
|
||||
// 复制space时间(从索引1开始,每隔2个取一个)
|
||||
for (int i = 0; i < signal.spaceCount; i++) {
|
||||
signal.spaceTimes[i] = tempData[i * 2 + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// 总体超时检查
|
||||
if ((micros() - startTime) > RECEIVE_TIMEOUT_US) {
|
||||
Serial.println("接收总体超时");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (signal.length > 0) {
|
||||
signal.isValid = true;
|
||||
Serial.print("信号接收成功,长度: ");
|
||||
Serial.println(signal.length);
|
||||
|
||||
// 重新分配内存以节省空间
|
||||
signal.data = (unsigned int*)realloc(signal.data, signal.length * sizeof(unsigned int));
|
||||
if (signal.data == nullptr) {
|
||||
Serial.println("内存重新分配失败");
|
||||
signal.isValid = false;
|
||||
signal.length = 0;
|
||||
}
|
||||
Serial.printf("RMT信号接收成功,mark数量: %d, space数量: %d\n", signal.markCount, signal.spaceCount);
|
||||
} else {
|
||||
Serial.println("未接收到有效信号");
|
||||
free(signal.data);
|
||||
signal.data = nullptr;
|
||||
Serial.println("未接收到有效的RMT信号数据");
|
||||
}
|
||||
|
||||
free(tempData);
|
||||
return signal;
|
||||
}
|
||||
|
||||
// generateCarrier函数已被RMT模块替代,不再需要
|
||||
|
||||
bool sendIRSignal(const IRSignal& signal) {
|
||||
if (!isValidIRSignal(signal)) {
|
||||
Serial.println("信号无效,无法发送");
|
||||
return false;
|
||||
}
|
||||
|
||||
Serial.println("开始发送红外信号...");
|
||||
Serial.print("信号长度: ");
|
||||
Serial.println(signal.length);
|
||||
Serial.println("开始发送红外信号 (使用RMT)...");
|
||||
Serial.printf("载波频率: %d Hz\n", signal.carrierFreq);
|
||||
Serial.printf("mark数量: %d, space数量: %d\n", signal.markCount, signal.spaceCount);
|
||||
|
||||
// 禁用中断以确保精确的时序
|
||||
noInterrupts();
|
||||
// 计算需要的RMT项目数量
|
||||
int maxCount = max(signal.markCount, signal.spaceCount);
|
||||
size_t item_count = maxCount;
|
||||
|
||||
bool state = LOW; // 红外信号通常以低电平开始
|
||||
|
||||
for (int i = 0; i < signal.length; i++) {
|
||||
digitalWrite(IR_SEND_PIN, state);
|
||||
delayMicroseconds(signal.data[i]);
|
||||
state = !state; // 切换状态
|
||||
// 分配RMT项目数组
|
||||
rmt_item32_t* items = (rmt_item32_t*)malloc(item_count * sizeof(rmt_item32_t));
|
||||
if (items == nullptr) {
|
||||
Serial.println("RMT项目内存分配失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 确保最后是低电平
|
||||
digitalWrite(IR_SEND_PIN, LOW);
|
||||
// 构建RMT数据项
|
||||
for (int i = 0; i < maxCount; i++) {
|
||||
items[i].level0 = 1; // mark期间为高电平(载波调制)
|
||||
items[i].duration0 = (i < signal.markCount) ? signal.markTimes[i] : 0;
|
||||
|
||||
items[i].level1 = 0; // space期间为低电平(无载波)
|
||||
items[i].duration1 = (i < signal.spaceCount) ? signal.spaceTimes[i] : 0;
|
||||
}
|
||||
|
||||
// 重新启用中断
|
||||
interrupts();
|
||||
// 发送RMT数据
|
||||
esp_err_t err = rmt_write_items(RMT_TX_CHANNEL, items, item_count, true);
|
||||
|
||||
Serial.println("信号发送完成");
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("RMT发送失败: %s\n", esp_err_to_name(err));
|
||||
free(items);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 等待发送完成
|
||||
err = rmt_wait_tx_done(RMT_TX_CHANNEL, pdMS_TO_TICKS(1000));
|
||||
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("RMT发送等待超时: %s\n", esp_err_to_name(err));
|
||||
free(items);
|
||||
return false;
|
||||
}
|
||||
|
||||
free(items);
|
||||
Serial.println("RMT信号发送完成");
|
||||
return true;
|
||||
}
|
||||
|
||||
void freeIRSignal(IRSignal& signal) {
|
||||
if (signal.data != nullptr) {
|
||||
free(signal.data);
|
||||
signal.data = nullptr;
|
||||
if (signal.markTimes != nullptr) {
|
||||
free(signal.markTimes);
|
||||
signal.markTimes = nullptr;
|
||||
}
|
||||
signal.length = 0;
|
||||
if (signal.spaceTimes != nullptr) {
|
||||
free(signal.spaceTimes);
|
||||
signal.spaceTimes = nullptr;
|
||||
}
|
||||
signal.markCount = 0;
|
||||
signal.spaceCount = 0;
|
||||
signal.carrierFreq = 0;
|
||||
signal.isValid = false;
|
||||
}
|
||||
|
||||
IRSignal copyIRSignal(const IRSignal& source) {
|
||||
IRSignal copy;
|
||||
copy.data = nullptr;
|
||||
copy.length = 0;
|
||||
copy.markTimes = nullptr;
|
||||
copy.spaceTimes = nullptr;
|
||||
copy.markCount = 0;
|
||||
copy.spaceCount = 0;
|
||||
copy.carrierFreq = 0;
|
||||
copy.isValid = false;
|
||||
|
||||
if (!isValidIRSignal(source)) {
|
||||
return copy;
|
||||
}
|
||||
|
||||
// 分配内存
|
||||
copy.data = (unsigned int*)malloc(source.length * sizeof(unsigned int));
|
||||
if (copy.data == nullptr) {
|
||||
Serial.println("复制信号时内存分配失败");
|
||||
return copy;
|
||||
// 复制mark时间数组
|
||||
if (source.markCount > 0 && source.markTimes != nullptr) {
|
||||
copy.markTimes = (unsigned int*)malloc(source.markCount * sizeof(unsigned int));
|
||||
if (copy.markTimes == nullptr) {
|
||||
Serial.println("复制mark时间数组时内存分配失败");
|
||||
return copy;
|
||||
}
|
||||
|
||||
for (int i = 0; i < source.markCount; i++) {
|
||||
copy.markTimes[i] = source.markTimes[i];
|
||||
}
|
||||
copy.markCount = source.markCount;
|
||||
}
|
||||
|
||||
// 复制数据
|
||||
for (int i = 0; i < source.length; i++) {
|
||||
copy.data[i] = source.data[i];
|
||||
// 复制space时间数组
|
||||
if (source.spaceCount > 0 && source.spaceTimes != nullptr) {
|
||||
copy.spaceTimes = (unsigned int*)malloc(source.spaceCount * sizeof(unsigned int));
|
||||
if (copy.spaceTimes == nullptr) {
|
||||
Serial.println("复制space时间数组时内存分配失败");
|
||||
if (copy.markTimes != nullptr) {
|
||||
free(copy.markTimes);
|
||||
copy.markTimes = nullptr;
|
||||
copy.markCount = 0;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
for (int i = 0; i < source.spaceCount; i++) {
|
||||
copy.spaceTimes[i] = source.spaceTimes[i];
|
||||
}
|
||||
copy.spaceCount = source.spaceCount;
|
||||
}
|
||||
|
||||
copy.length = source.length;
|
||||
copy.carrierFreq = source.carrierFreq;
|
||||
copy.isValid = true;
|
||||
|
||||
return copy;
|
||||
@@ -176,33 +330,56 @@ void printIRSignal(const IRSignal& signal, int maxPrint) {
|
||||
}
|
||||
|
||||
Serial.println("=== 红外信号数据 ===");
|
||||
Serial.print("信号长度: ");
|
||||
Serial.println(signal.length);
|
||||
Serial.print("载波频率: ");
|
||||
Serial.print(signal.carrierFreq);
|
||||
Serial.println(" Hz");
|
||||
Serial.print("mark数量: ");
|
||||
Serial.println(signal.markCount);
|
||||
Serial.print("space数量: ");
|
||||
Serial.println(signal.spaceCount);
|
||||
Serial.print("信号有效: ");
|
||||
Serial.println(signal.isValid ? "是" : "否");
|
||||
|
||||
int printCount = (maxPrint == 0) ? signal.length : min(maxPrint, signal.length);
|
||||
|
||||
Serial.println("原始数据 (微秒):");
|
||||
for (int i = 0; i < printCount; i++) {
|
||||
Serial.print("Index ");
|
||||
// 打印mark时间
|
||||
int markPrintCount = (maxPrint == 0) ? signal.markCount : min(maxPrint, signal.markCount);
|
||||
Serial.println("Mark时间 (微秒):");
|
||||
for (int i = 0; i < markPrintCount; i++) {
|
||||
Serial.print("Mark ");
|
||||
Serial.print(i);
|
||||
Serial.print(": ");
|
||||
Serial.print(signal.data[i]);
|
||||
Serial.print(" us (");
|
||||
Serial.print((i % 2 == 0) ? "LOW" : "HIGH");
|
||||
Serial.println(")");
|
||||
Serial.print(signal.markTimes[i]);
|
||||
Serial.println(" us");
|
||||
}
|
||||
|
||||
if (printCount < signal.length) {
|
||||
if (markPrintCount < signal.markCount) {
|
||||
Serial.print("... 还有 ");
|
||||
Serial.print(signal.length - printCount);
|
||||
Serial.println(" 个数据点未显示");
|
||||
Serial.print(signal.markCount - markPrintCount);
|
||||
Serial.println(" 个mark数据点未显示");
|
||||
}
|
||||
|
||||
// 打印space时间
|
||||
int spacePrintCount = (maxPrint == 0) ? signal.spaceCount : min(maxPrint, signal.spaceCount);
|
||||
Serial.println("Space时间 (微秒):");
|
||||
for (int i = 0; i < spacePrintCount; i++) {
|
||||
Serial.print("Space ");
|
||||
Serial.print(i);
|
||||
Serial.print(": ");
|
||||
Serial.print(signal.spaceTimes[i]);
|
||||
Serial.println(" us");
|
||||
}
|
||||
|
||||
if (spacePrintCount < signal.spaceCount) {
|
||||
Serial.print("... 还有 ");
|
||||
Serial.print(signal.spaceCount - spacePrintCount);
|
||||
Serial.println(" 个space数据点未显示");
|
||||
}
|
||||
|
||||
Serial.println("==================");
|
||||
}
|
||||
|
||||
bool isValidIRSignal(const IRSignal& signal) {
|
||||
return (signal.data != nullptr && signal.length > 0 && signal.isValid);
|
||||
return (signal.isValid &&
|
||||
((signal.markTimes != nullptr && signal.markCount > 0) ||
|
||||
(signal.spaceTimes != nullptr && signal.spaceCount > 0)) &&
|
||||
signal.carrierFreq > 0);
|
||||
}
|
||||
Reference in New Issue
Block a user