Infrared Receiving Module
Module Source
Purchase link: https://detail.tmall.com/item.htm?_u=72t4uge51318&id=548393997684&skuId=4361372496386 Materials download link: https://pan.baidu.com/s/1dEWVMIFDWb7k1NcsRy5hHA Materials extraction code: uucv
Specifications
View Materials
In the spectrum, electromagnetic waves with wavelengths from 760nm to 400um are called infrared rays; they are a type of invisible light. We should all be familiar with examples of infrared communication. Currently, almost all commonly used home appliances can be controlled via infrared remote control, such as TVs, air conditioners, projectors, etc., where the presence of infrared remote control can be seen. This technology is widely used, and the corresponding application devices are very inexpensive, making infrared remote control an ideal method for daily device control.
Infrared Communication Principle
Infrared light is emitted in the form of pulses at a specific frequency. After the receiving end receives the signal, it decodes according to the agreed protocol to complete data transmission. In consumer electronics products, the pulse frequency generally uses the 30KHz to 60KHz band; the frequency of the NEC protocol is 38KHz. Emitting at a specific frequency can actually be understood as turning on a light - don't be stumped by complex vocabulary. It's just controlling the blinking frequency (on/off) of the light, the same meaning as when you first learned microcontrollers to make a blinking LED, except the light has changed to a different type - it's still a light.
Principle of the receiving end: The chip at the receiving end is sensitive to this infrared light and can output high or low levels based on the presence or absence of light. If the blinking frequency of the transmitting end is regular, the high and low levels output by the receiving end after reception will also correspond regularly. As long as the transmitting end and the receiving end agree, data transmission can be performed.
The infrared transmission protocol can be said to be the lowest-cost and most convenient transmission protocol among all wireless transmission protocols, but it also has disadvantages: the distance is not long enough and the speed is not fast enough. Of course, each transmission protocol has a different application environment and different positioning, so the pros and cons cannot be compared. You need to choose the appropriate communication method according to your actual scenario.
NEC Protocol Introduction
The NEC protocol is one of many infrared protocols (here, "protocol" means their data frame format definitions are different, but the data transmission principle is the same). The universal remote controllers we buy, the mini remote controllers bought on Taobao, TVs, and projectors almost all use the NEC protocol. Devices like Gree air conditioners and Midea air conditioners use other protocol formats, not the NEC protocol. However, as long as you learn one protocol parsing method and understand the infrared transmission principle, other remote controller protocols can also be decoded.
A complete NEC protocol transmission includes: leader code, 8-bit address code, 8-bit address inverse code, 8-bit command code, and 8-bit command inverse code. Here we mainly explain how to receive the NEC protocol content sent by the infrared transmitter.
Leader code: composed of 9ms low level + 4.5ms high level.
4 bytes of data: address code + address inverse code + command code + command inverse code. The inverse code here can be used to verify whether the data was transmitted correctly and whether there was packet loss.
Key point: When the NEC protocol transmits data bits, the distinction between 0 and 1 is based on the duration of the received high and low levels. This is the key to decoding. Data sends 0 code: 0.56ms low level + 0.56ms high level.
Data sends 1 code: 0.56ms low level + 1.68ms high level
Therefore, the complete time representation for receiving a data bit is as follows: Received data bit 0: 0.56ms low level + 0.56ms high level Received data bit 1: 0.56ms low level + 1.68ms high level
There is also a repeat code, which is composed of a 9ms low level and a 2.5ms high level. When an infrared signal is sent continuously, it can be sent quickly by sending repeat codes.
Porting Process
Pin Selection
When the infrared receiver detects infrared light, it outputs a low level; when no infrared light is detected, it outputs a high level. Therefore, we configure the infrared pin as an external interrupt triggered on the falling edge. When the infrared pin has a falling edge, we immediately enter the processing function and receive the infrared signal.
Port to Project
Our goal is to port the example to the ESP32-S3 dev board. Complete driver code has been provided for you. Follow the steps below to complete the porting.
For detailed instructions on creating folders and new .c and .h files, refer to section 1.4.2 in the [DHT11 Temperature and Humidity Sensor] chapter; we will not repeat it here.
However, here we replace the file names bsp_dht11.c and bsp_dht11.h with bsp_ir_receiver.c and bsp_ir_receiver.h, and change the folder name to infraredReceiver.
Write Code
Write into bsp_ir_receiver.c:
/*
* LCSC-Openkits (LCKFB) software and hardware materials and related expansion board software and hardware materials are all open source on the official website.
* Dev board official website: www.lckfb.com
* Technical support resides on the forum; any technical questions are welcome for exchange and learning at any time.
* LCKFB Forum: club.szlcsc.com
* Follow our Bilibili account: [LCSC-Openkits (LCKFB)] to keep up with our latest updates!
* We do not make money by selling boards; we take cultivating engineers as our mission.
* Change Logs:
* Date Author Notes
* 2024-01-12 LCKFB-lp first version
*/
#include "bsp_ir_receiver.h"
#include "stdio.h"
typedef struct INFRARED_DATA{
uint8_t AddressCode; //Address code
uint8_t AddressInverseCode; //Address inverse code
uint8_t CommandCode; //Command code
uint8_t CommandInverseCode; //Command inverse code
}_INFRARED_DATA_STRUCT_;
_INFRARED_DATA_STRUCT_ InfraredData;
static void delay_ms(unsigned int ms)
{
vTaskDelay(ms / portTICK_PERIOD_MS);
}
static void delay_us(unsigned int us)
{
ets_delay_us(us);
}
static void delay_1ms(unsigned int ms)
{
vTaskDelay(ms / portTICK_PERIOD_MS);
}
static void delay_1us(unsigned int us)
{
ets_delay_us(us);
}
//Infrared pin initialization
void infrared_goio_config(void)
{
gpio_config_t lll_config = {
.pin_bit_mask = (1ULL<<IR_PIN), //Configure pin
.mode =GPIO_MODE_INPUT, //Input mode
.pull_up_en = GPIO_PULLUP_ENABLE, //Enable pull-up
.pull_down_en = GPIO_PULLDOWN_DISABLE, //Disable pull-down
.intr_type = GPIO_INTR_DISABLE //Disable pin interrupt
};
gpio_config(&lll_config);
}
//Get infrared low level time
//Using microseconds (us) as time reference
void get_infrared_low_time( uint32_t *low_time )
{
uint32_t time_val = 0;
while( gpio_get_level(IR_PIN) == 0 )
{
if( time_val>= 500 )
{
*low_time = time_val;
return;
}
delay_1us(20);
time_val++;
}
*low_time = time_val;
}
//Get infrared high level time
//Using microseconds (us) as time reference
void get_infrared_high_time(uint32_t *high_time)
{
uint32_t time_val = 0;
while( gpio_get_level(IR_PIN) == 1 )
{
if( time_val >= 250 )
{
*high_time = time_val;
return;
}
delay_1us(20);
time_val++;
}
*high_time = time_val;
}
/******************************************************************
* Function Name: guide_and_repeat_code_judgment
* Function Description: Leader and repeat code judgment
* Function Parameters: None
* Function Return: 1: Not leader code 2: Repeat code 0: Leader code
* Author: LC
* Notes: Using 20 microseconds (us) as time reference
Leader code: composed of a 9ms low level and a 4.5ms high level
Repeat code: composed of a 9ms low level and a 2.5ms high level
******************************************************************/
uint8_t guide_and_repeat_code_judgment(void)
{
uint32_t out_time=0;
get_infrared_low_time(&out_time);
//time>10ms time <8ms
if((out_time > 500) || (out_time < 400))
{
return 1;
}
get_infrared_high_time(&out_time);
// x>5ms or x<2ms
if((out_time > 250) || (out_time < 100))
{
return 1;
}
//If it is a repeat code 2ms < time < 3ms
if((out_time > 100) && (out_time < 150))
{
return 2;
}
return 0;
}
//Infrared data correctness judgment
uint8_t infrared_data_true_judgment(uint8_t *value)
{
//Check if address code is correct
if( value[0] != (uint8_t)(~value[1]) ) return 0;
//Check if command code is correct
if( value[2] != (uint8_t)(~value[3]) ) return 1;
printf("%x %x %x %x\r\n",value[0],value[1],value[2],value[3]);
//Save correct data
InfraredData.AddressCode = value[0];
InfraredData.AddressInverseCode = value[1];
InfraredData.CommandCode = value[2];
InfraredData.CommandInverseCode = value[3];
return 0;
}
//Receive infrared data
void receiving_infrared_data(void)
{
uint16_t group_num = 0,data_num = 0;
uint32_t time=0;
uint8_t bit_data = 0;
uint8_t ir_value[5] = {0};
uint8_t guide_and_repeat_code = 0;
if( gpio_get_level( IR_PIN ) == 1 )
{
return;
}
//Wait for leader code
guide_and_repeat_code = guide_and_repeat_code_judgment();
//If it is not the leader code, end parsing
if( guide_and_repeat_code == 1 )
{
return;
}
//Total 4 groups of data
//Address code + address inverse code + command code + command inverse code
for(group_num = 0; group_num < 4; group_num++ )
{
//Receive one group of 8-bit data
for( data_num = 0; data_num < 8; data_num++ )
{
//Receive low level
get_infrared_low_time(&time);
//If not within 0.56ms low level, data error
if((time > 60) || (time < 20))
{
return ;
}
time = 0;
//Receive high level
get_infrared_high_time(&time);
//If in the range of 1200us<t<2000us, judge as 1
if((time >=60) && (time < 100))
{
bit_data = 1;
}
//If in the range of 200us<t<1000us, judge as 0
else if((time >=10) && (time < 50))
{
bit_data = 0;
}
//groupNum indicates which group of data
ir_value[ group_num ] <<= 1;
//The first received value is the high level; in the second for loop, the data will be shifted right 8 times
ir_value[ group_num ] |= bit_data;
//After use, the time must be reset
time=0;
}
}
//Check if data is correct, if correct, save data
infrared_data_true_judgment(ir_value);
}
//Get the command sent by infrared
uint8_t get_infrared_command(void)
{
return InfraredData.CommandCode;
}
//Clear the data sent by infrared
void clear_infrared_command(void)
{
InfraredData.CommandCode = 0x00;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
Write into bsp_ir_receiver.h:
/*
* LCSC-Openkits (LCKFB) software and hardware materials and related expansion board software and hardware materials are all open source on the official website.
* Dev board official website: www.lckfb.com
* Technical support resides on the forum; any technical questions are welcome for exchange and learning at any time.
* LCKFB Forum: club.szlcsc.com
* Follow our Bilibili account: [LCSC-Openkits (LCKFB)] to keep up with our latest updates!
* We do not make money by selling boards; we take cultivating engineers as our mission.
* Change Logs:
* Date Author Notes
* 2024-01-12 LCKFB-lp first version
*/
#ifndef _BSP_IR_RECEIVER_H__
#define _BSP_IR_RECEIVER_H__
#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "driver/i2c.h"
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "freertos/queue.h"
#include <inttypes.h>
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "rom/ets_sys.h"
#include "esp_system.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "driver/spi_common.h"
#include "hal/gpio_types.h"
#include "string.h"
// OUT pin
#define IR_PIN 1
void infrared_goio_config(void);
uint8_t get_infrared_command(void);
void clear_infrared_command(void);
void receiving_infrared_data(void);
void clear_infrared_command(void);
#endif2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Porting Verification
In the main function of your own project, write the following code.
/*
* LCSC-Openkits (LCKFB) software and hardware materials and related expansion board software and hardware materials are all open source on the official website.
* Dev board official website: www.lckfb.com
* Technical support resides on the forum; any technical questions are welcome for exchange and learning at any time.
* LCKFB Forum: club.szlcsc.com
* Follow our Bilibili account: [LCSC-Openkits (LCKFB)] to keep up with our latest updates!
* We do not make money by selling boards; we take cultivating engineers as our mission.
* Change Logs:
* Date Author Notes
* 2024-01-12 LCKFB-lp first version
*/
#include <stdio.h>
#include "bsp_ir_receiver.h"
#include "string.h"
#include "esp_private/esp_task_wdt.h"
#include "esp_private/esp_task_wdt_impl.h"
int app_main(void)
{
esp_task_wdt_deinit();
//Infrared receiver initialization
infrared_goio_config();
printf("Start......\r\n");
while(1)
{
receiving_infrared_data(); // Receive one data
//If the [1] button on the remote is pressed
if( get_infrared_command() == 0xA2 )
{
clear_infrared_command();
printf("Press the 1 button \r\n");
}
vTaskDelay(1 / portTICK_PERIOD_MS);
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Power-on effect:
Driver code:
File Download
📌 Materials Download Center (click to jump)
📌 In the Materials Download Center -> Module Porting Materials Download, inside the compressed package of this chapter.