Atom发送红外编码(一)-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2711|回复: 0

Atom发送红外编码(一)

[复制链接]
发表于 2020-5-8 15:03 | 显示全部楼层 |阅读模式
M5Stack的几款主机都集成了红外发射二极管,用于对家电进行遥控,之前也提供了一些应用示例,这次再重新对红外发射和接收的程序进行梳理,深入了解IRremote8266这个库的使用,虽然库名字带有8266但是支持ESP32。

===接收红外信号==========================================================
在IRremoteESP8266的参考示例中提供了IRrecvDumpV2这样一个程序,整个程序用于接收红外信号、分析内容并将结果输出到串行监视器
在Atom中使用该示例需要对程序进行一定的修改。
7b9fb12d0159c4943f7ac6856660f1d8.png
在27行中,Arduino.h要被改为M5Atom.h
在第38行中,将红外传感器连接的GPIO14改为M5Stack IR-Unit对应引脚,在IR-Unit的背面是这样写的
IMG_1952-680x1024.jpeg
将它连接到Atom,找到对应的端口号
IMG_1965-768x849.jpeg
现在我们可以看出来接收引脚连接的是32,发射引脚接的是26(Atom内置的IR发射引脚为12)。
现在更改第27行和第38行
e6a0aba40ed310f11d8dea6983aaecb3.png
接下来是setup,在修改前是这样的
873d2f80460df9363505843cb9f9a728.png
第112行之后,对Atom进行初始化过程
M5.begin(true, fasle, false);//是否启用串行通讯、是否启用I2C、是否启用屏幕
加上M5.begin()的程序设这样的
248e60c20324efe0440f5eb05a737cd4.png
运行程序后,串口监视器打印以下内容
未命名.png
如果此时向IR Unit发送遥控信号,串口监视器会显示
未命名.png
从图中看到遥控器使用了NEC协议,
rawData是接收红外开/关时间的原始数据。
address、command、data是对协议原始数据分析的结果
如果我们事先知道遥控的协议可以直接使用对应的函数进行发送,如对于NEC协议使用sendNEC
如果我们不知道协议,则需要使用sendRaw(*)将原始数据作为参宿进行传递。创建学习遥控器时使用sendRaw()很容易,我们不需要知道遥控器的协议,但是缺点也明显,我们需要记住原始数据并消耗大量内存。比如发送空调遥控器信号,数据很长,需要大量内存。

====发送红外信号======================================================
对于发送红外信号来说,Atom Matrix和Atom Lite都带有红外传输LED
IMG_1959-1.jpeg

在Arduino示例中有一个名为IRsendDemo的程序,我们可以通过修改此程序完成IR的发送
9a9d6ca1c3b509da3b4856c8a46dc123.png
第35行代码是用于红外传输的LED引脚编号,我们在Atom标签上也能看到
IMG_1977.jpeg
第37行创建了一个IRsend对象,传递第35行定义的引脚
在第40到46行中,使用了IRrecvDumpV2分析的红外信号原始数据。
setup()中的第53行通过调用IRsend对象的begin()启动。
第62和63行是使用NEC协议发送红外信号的示例。使用irsend.sendNEC()将unit64_t类型的数据传递给参数(实际只传32位),例如
未命名.png
通过查看Protocol,可以看到是NEC协议,code为sendNEC()的参数0x419F58A7。在程序的63行示例中,由于数字文本作为参数直接传递给sendNEC(),因此添加"UL",调整长度
如果协议是SONY,使用sendSONY(),如第66行所示。传入三个参数。
第68-69行是发送rawData[]的示例。使用名为sendRaw()的函数,第一个参数是指向rawData数组的指针,第二个参数是rawData数组中的元素数,第三个参数是IR LED开/关频率
第67行是irsend.sendRaw(rawData, 67, 38),其中67指第40行数组的元素个数,38为IR的频率,通常遥控器使用的是38khz

分析完后,修改IRremoteESP8266示例,使用Atom发送红外信号。主要修改内容:
•加载Atom头文件
•更改红外LED引脚为12
•从IRrecvDumpV2程序中拷出原始数据和数据行
•在setup()中初始化Atom
•按下按钮时调用sendRaw()或sendNEC()
改造后的程序
[mw_shl_code=arduino,true]
#include <M5Atom.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>

const uint16_t kIrLed = 12; // M5Atom IR LED GPIO pin

IRsend irsend(kIrLed);  // Set the GPIO to be used to sending the message.

// Example of data captured by IRrecvDumpV2.ino
uint16_t rawData[67] = {9030, 4480,  588, 536,  584, 1628,  612, 536,
                        586, 536,  586, 538,  562, 564,  560, 562,
                        560, 1652,  610, 1652,  564, 560,  584, 540,
                        564, 1672,  584, 1652,  586, 1626,  610, 1628,
                        610, 1632,  606, 538,  562, 1654,  586, 560,
                        562, 1674,  586, 1652,  586, 538,  560, 562,
                        586, 538,  562, 1676,  586, 538,  566, 1672,
                        584, 540,  584, 538,  586, 1628,  610, 1626,
                        612, 1642,  588};  // NEC 419F58A7

uint64_t data = 0x419F58A7;

void setup() {
  M5.begin(true, false, false);
  irsend.begin();
}

void loop() {
  M5.update();
  if (M5.Btn.wasReleased()) {
    Serial.println("Button pressed");
   
    Serial.println("sendRaw");
    irsend.sendRaw(rawData, 67, 38);  // Send a raw data capture at 38kHz.
   
    // Serial.println("sendNEC()");
    // irsend.sendNEC(data);
  }
}[/mw_shl_code]
此程序调用sendRaw(),请将第10到第20行替换为你自己的原始数据,将第33行中的67更改为你自己的原始数据元素个数

=====创建学习型遥控==============================================================
下面我们将演示如何将上述两个代码融合,做到学习红外信号并进行发送
对应发送的信号可能有两种数据,一种是uint16_t rawData[],一种是根据协议传递数据(NEC和uint64_t数据)
对于rawData有以下优缺点:
•优点:控制信号可以在任何协议中传输 •缺点:数据量增加导致需要较大内存
对应根据协议传递的数据来说:
•优点:传递数据流较小 •缺点:必须根据协议对发送函数进行划分,并且无法处理没有发送函数的协议
考虑到学习型遥控器的用途,我们事先不确定遥控器的协议,因此传递rawData是恰当的方法。

现在我们来构建一下整个遥控器的功能,通过使用正面的按钮实现单击、双击、长按来操作遥控器。
[mw_shl_code=arduino,true]void loop() {
  M5.update();
  if (M5.Btn.wasReleased()) {// 单击/发送信号
  } else  if (M5.Btn.pressedFor(300)) { // 长按/启用接收
    while (! M5.Btn.wasReleased()) { // 等待按键松开
      delay(50);
      M5.update();
    }
  } else {
    if (收到红外信号) {
取出信号
}
  }
}[/mw_shl_code]
取出信号不是在长按过程中,而是在最后,信号接收处理是异步的
最终代码
[mw_shl_code=arduino,true]
#include <M5Atom.h>
#include <IRrecv.h>
#include <IRremoteESP8266.h>
#include <IRac.h>
#include <IRtext.h>
#include <IRutils.h>

// Select IR_LED in M5Atom or M5Stack IR Unit
#define IR_LED 12  // IR LED in M5Atom
//#define IR_LED 26  // IR LED in the M5Stack IR Unit

// ============ IRremoteESP8266 TUNEABLE PARAMETERS ================
const uint16_t kRecvPin = 32;
const uint32_t kBaudRate = 115200;
const uint16_t kCaptureBufferSize = 1024;
#if DECODE_AC
const uint8_t kTimeout = 50;
#else   // DECODE_AC
const uint8_t kTimeout = 15;
#endif  // DECODE_AC
const uint16_t kMinUnknownSize = 12;
#define LEGACY_TIMING_INFO false
// =================================================================

IRrecv irrecv(kRecvPin, kCaptureBufferSize, kTimeout, true);
decode_results results;  // Somewhere to store the results
IRsend irsend(IR_LED);

uint16_t *rawData;        // IR message container
uint16_t dataLength = 0;  // IR message length

void setup() {
  M5.begin(true, false, false); // SerialEnable = true, I2CEnable = false, DisplayEnable = false);
  Serial.printf("\n\n### IR Remote Controller ###\n");
  Serial.printf("IR Sensor Pin Number =%d \n", kRecvPin);
  irrecv.setUnknownThreshold(kMinUnknownSize);
  irsend.begin();
}

void loop() {
  M5.update();
  if (M5.Btn.wasReleased()) {
    Serial.print("Button wasReleased(): ");
    if (dataLength > 0) {
      Serial.printf("send rawData[%d]\n", dataLength);
      irsend.sendRaw(rawData, dataLength, 38);
    } else {
      Serial.println("rawData[] is empty. Skip sending");
    }
  } else if (M5.Btn.pressedFor(300)) {
    irrecv.enableIRIn();
    Serial.println("M5.Btn.pressedFor(300): waiting for IR signal");
    while (! M5.Btn.wasReleased()) {
      delay(50);
      M5.update();
    }
  } else {
    if (irrecv.decode(&results)) {
      irrecv.disableIRIn();
      if (results.overflow)
        Serial.printf(D_WARN_BUFFERFULL "\n", kCaptureBufferSize);
      rawData = resultToRawArray(&results);
      dataLength = getCorrectedRawLength(&results);
      Serial.printf("rawData[%d] : ", dataLength);
      for (int i = 0; i < dataLength; i++) {
        Serial.printf("%d, ", rawData);
      }
      Serial.println();
    }
  }
}[/mw_shl_code]



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 02:31 , Processed in 0.080127 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表