|
本帖最后由 vany5921 于 2020-5-8 15:55 编辑
在上一篇中讲解了如何收发红外遥控,我们不得不通过串口监视器了解当前状态,同时一旦我们断电,我们学习的编码因为无法保存而丢失。为了解决这些问题我们对之前的代码进行补充,通过AtomMatrix的LED进行显示,并存储学习后的红外编码
====创建LED显示==========================================
我创建了三个学习遥控器的指示:1.尚未学习接收遥控信号的状态 2.等待接收遥控信号 3.学习遥控信号后等待发送
我们可以通过AtomPixelTool进行创建,下载连接https://github.com/m5stack/M5Atom
当启动AtomPixelTool后,将会有如下显示
右侧是5x5的矩阵,通过修改左侧的H和W来修改垂直和水平的显示像素数。我设置为水平15像素,垂直5像素
点击工具并选择保存,生成的发光数据将以c文件的形式导出
[mw_shl_code=arduino,true]
// File URLC:/Users/iCloudDrive/mp3/IRremoteLED.c
// Image Size: width=15,height=5
// Data Size: 227
const unsigned char image_IRremoteLED[227]=
{
/* width 015 */ 0x0f,
/* height 005 */ 0x05,
/* Line 000 */ 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x55,0xff,0x7f, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0xff,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, //
/* Line 001 */ 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0xff,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, //
/* Line 002 */ 0x00,0x00,0x00, 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x55,0xff,0xff, 0x55,0xff,0xff, 0x00,0xff,0xff, 0x55,0xff,0xff, 0x00,0xff,0xff, //
/* Line 003 */ 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0xff,0xff, 0x00,0xff,0xff, 0x00,0xff,0xff, 0x00,0x00,0x00, //
/* Line 004 */ 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x55,0xff,0x7f, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0xff,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, //
};[/mw_shl_code]
查看输出文件,它是一个一维数组,第一元素是宽度,第二元素是高度,第三元素是RGB的值,每个像素都有RGB三个元素,数组元素总个数为1+1+15x5x3 = 227
屏幕上的一行对应数组里的一行,通过Line xxx可以查看一行中包含的数据
void displaybuff(uint8_t *buffptr, int8_t offsetx = 0, int8_t offsety = 0)用于LED的显示,buffptr是图像数据的数组。offsetx和offsety是偏移位置,例如
图像数据数组是
displaybuf((uint8_t*)image_IRremoteLED, 0, 0)会显示
displaybuf((uint8_t*)image_IRremoteLED, -5, 0)将显示
接下来将我们上节的代码插入灯光
[mw_shl_code=arduino,true]#define FASTLED_INTERNAL
#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
const unsigned char image_IRremoteLED[227]=
{
/* width 015 */ 0x0f,
/* height 005 */ 0x05,
/* Line 000 */ 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x55,0xff,0x7f, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0xff,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, //
/* Line 001 */ 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0xff,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, //
/* Line 002 */ 0x00,0x00,0x00, 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x55,0xff,0xff, 0x55,0xff,0xff, 0x00,0xff,0xff, 0x55,0xff,0xff, 0x00,0xff,0xff, //
/* Line 003 */ 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0xff,0xff, 0x00,0xff,0xff, 0x00,0xff,0xff, 0x00,0x00,0x00, //
/* Line 004 */ 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xf0,0x14,0xff, 0x00,0x00,0x00, 0x55,0xff,0x7f, 0x55,0xff,0x7f, 0x55,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0xff,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, //
};
void setup() {
M5.begin(true, false, true); // SerialEnable = true, I2CEnable = false, DisplayEnable = true);
Serial.printf("\n\n### IR Remote Controller ###\n");
Serial.printf("IR Sensor Pin Number =%d \n", kRecvPin);
irrecv.setUnknownThreshold(kMinUnknownSize);
irsend.begin();
M5.dis.displaybuff((uint8_t*)image_IRremoteLED, 0, 0);
}
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");
M5.dis.displaybuff((uint8_t*)image_IRremoteLED, -10, 0);
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();
M5.dis.displaybuff((uint8_t*)image_IRremoteLED, -5, 0);
}
}
}[/mw_shl_code]
====SPIFFS存储==============================================
SPIFFS(SPI Flash文件系统)是一个库,允许用户将数据保存到flash中。我们可以通过查看ArduinoIDE中的SPIFFS示例来了解。
要使用SPIFFS,必须先装载文件系统。上述程序中第162行的SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)是其中一部分,如果首次使用SPIFFS,需要进行格式化操作。当begin参数为true,则进行格式化操作。第40行到第70行是读取和写入文件的示例。
操作步骤
・将SPIFFS中存储文件的完整路径定义为/irdata。
・作为LED上显示的图形,添加显示图案。
・准备一个数组保存红外数据。
・在setup()中进行以下操作
・挂载SPIFFS。挂载时执行格式后会等待10秒左右,因此,显示一个表示初始化的图案。
・试着从SPIFFS内的/irdata文件向RAM读入遥控信号。
・读取成功后,在LED上显示圆圈,读取失败后在LED上显示叉。
・在loop()内进行下述操作
・点击按钮后
・如果是等待遥控器信号接收的状态,则解除等待状态,删除SPIFFS内的文件,在LED上显示叉。
・在通常的状态下,并且如果有遥控信号数据则发送。
・长按按钮的话
・在LED上显示下箭头,进入等待接收状态
・收到遥控信号后
・取出接收到的遥控信号数据写入RAM
・将写入RAM中的遥控信号数据写入SPIFFS
・在LED上显示圆圈。
最终代码
[mw_shl_code=arduino,true]#define FASTLED_INTERNAL
#include <M5Atom.h>
//=== IRremoteESP8266 files
#include <IRrecv.h>
#include <IRremoteESP8266.h>
#include <IRac.h>
#include <IRtext.h>
#include <IRutils.h>
//=== SPIFFS files
#include "FS.h"
#include "SPIFFS.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 Tunable 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
//=== SPIFFS parameters
#define FORMAT_SPIFFS_IF_FAILED true
const char *FILE_NAME = "/irdata";
//== instances for receiving and sending IR messages
IRrecv irrecv(kRecvPin, kCaptureBufferSize, kTimeout, true);
decode_results results; // Somewhere to store the results
IRsend irsend(IR_LED);
//== IR message container
#define BUFFER_SIZE 1024
uint16_t rawData[BUFFER_SIZE]; // IR message container
uint16_t dataLength = 0; // IR message length
//== variable for remembering mode
bool receiving = false;
const unsigned char matrix_image[302]=
{
/* width 020 */ 0x14,
/* height 005 */ 0x05,
/* Line 000 */ 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0x00,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xff,0x00,0xff, 0x00,0x00,0x00, 0x00,0xff,0x00, 0x00,0xff,0x00, 0x00,0xff,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x55,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, //
/* Line 001 */ 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0x00,0x00,0x00, 0xff,0x00,0xff, 0x00,0x00,0x00, 0xff,0x00,0xff, 0x00,0x00,0x00, 0x00,0xff,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0xff,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x55,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, //
/* Line 002 */ 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xff,0x00,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0xff,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0xff,0x00, 0x00,0x55,0xff, 0x00,0x55,0xff, 0x00,0x55,0xff, 0x00,0x55,0xff, 0x00,0x55,0xff, //
/* Line 003 */ 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0x00,0x00,0x00, 0xff,0x00,0xff, 0x00,0x00,0x00, 0xff,0x00,0xff, 0x00,0x00,0x00, 0x00,0xff,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0xff,0x00, 0x00,0x00,0x00, 0x00,0x55,0xff, 0x00,0x55,0xff, 0x00,0x55,0xff, 0x00,0x00,0x00, //
/* Line 004 */ 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0xff,0x7f, 0xff,0x00,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xff,0x00,0xff, 0x00,0x00,0x00, 0x00,0xff,0x00, 0x00,0xff,0x00, 0x00,0xff,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x55,0xff, 0x00,0x00,0x00, 0x00,0x00,0x00, //
};
void setup() {
M5.begin(true, false, true); //SerialEnable = true, I2CEnable = false, DisplayEnable = true);
Serial.printf("\n\n### IR Remote Controller ###\n");
Serial.printf("IR Sensor Pin Number =%d \n", kRecvPin);
irrecv.setUnknownThreshold(kMinUnknownSize);
irsend.begin();
Serial.print("Initializeing SPIFFS....");
M5.dis.displaybuff((uint8_t*)matrix_image, 0, 0);
SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED); // activate SPIFFS
Serial.println("Done.");
readRawDataFromSPIFFS(); // read data if available
if (dataLength > 0) {
M5.dis.displaybuff((uint8_t*)matrix_image, -10, 0);
} else {
M5.dis.displaybuff((uint8_t*)matrix_image, -5, 0);
}
}
void loop() {
M5.update();
if (M5.Btn.wasReleased()) {
Serial.print("Button wasReleased(): ");
if (receiving) {
irrecv.disableIRIn();
receiving = false;
deleteRawDataInSPIFFS();
dataLength = 0;
M5.dis.displaybuff((uint8_t*)matrix_image, -5, 0);
} else 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();
receiving = true;
Serial.println("M5.Btn.pressedFor(500): waiting for IR signal");
M5.dis.displaybuff((uint8_t*)matrix_image, -15, 0);
while (! M5.Btn.wasReleased()) {
delay(50);
M5.update();
}
} else {
if (irrecv.decode(&results)) {
uint16_t *rawData_tmp;
irrecv.disableIRIn();
receiving = false;
if (results.overflow)
Serial.printf(D_WARN_BUFFERFULL "\n", kCaptureBufferSize);
rawData_tmp = resultToRawArray(&results);
dataLength = getCorrectedRawLength(&results);
Serial.printf("rawData[%d] : ", dataLength);
for (int i = 0; i < dataLength; i++) {
rawData = rawData_tmp;
Serial.printf("%d, ", rawData);
}
delete[] rawData_tmp;
Serial.println();
writeRawDataToSPIFFS();
M5.dis.displaybuff((uint8_t*)matrix_image, -10, 0);
yield(); // Feed the WDT (again)
}
}
}
void readRawDataFromSPIFFS() {
Serial.printf("reading rawData from SPIFF file: %s \n", FILE_NAME);
fs::FS fs = SPIFFS;
File file;
if (fs.exists(FILE_NAME)) {
file = fs.open(FILE_NAME);
} else {
Serial.printf("file \"%s\" not found in SPIFFS\n", FILE_NAME);
return;
}
int i = 0;
uint8_t *rawData8 = (uint8_t *)rawData;
while (file.available()) {
rawData8 = file.read();
Serial.printf("%d ", rawData8);
i++;
}
Serial.println();
dataLength = i / 2;
file.close();
Serial.printf("dataLength = %d\n", dataLength);
for (int j = 0; j < dataLength; j++) {
Serial.printf("%d", rawData[j]);
Serial.print(" ");
}
Serial.println("done");
}
void writeRawDataToSPIFFS() {
fs::FS fs = SPIFFS;
Serial.println("writing data to SPIFF");
File file = fs.open(FILE_NAME, FILE_WRITE);
file.write((uint8_t *)rawData, dataLength * 2);
file.close();
Serial.println("done");
}
void deleteRawDataInSPIFFS() {
Serial.printf("Deleting rawData in SPIFFS: %s\r\n", FILE_NAME);
fs::FS fs = SPIFFS;
if (fs.remove(FILE_NAME)) {
Serial.println("- file deleted");
} else {
Serial.println("- deletion failed");
}
}[/mw_shl_code]
|
|