Monday, April 2, 2018

ESP8266 IR Receiver

The project I have in mind has to mimic IR signals from remote control devices for audio/video devices like TV, receiver, set top box, etc. The IR signals have to be sent out in formats specific to each device. In order to send the IR signals, the first step is to receive sample signals and analyse them. This is what this post is about.

I am looking at using a NodeMcu Devkit for the ESP8266 and an IR sensor to capture the IR signal format. The ESP8266 also has a web server running and the UI uses this. The raw IR data is then sent to a browser on request. The analysis is done on the browser and the results displayed.

IR Signal format

I have analysed IR signals in the past - some of the results have been blogged before. Briefly, the parameters are as follows:

  • Wavelength
  • Carrier frequency
  • Coding scheme (Mark/Space/Both /Phase/Quad) [C]
  • No. of data bits
  • Header mark/space [H]
  • Data bit timings [T]
  • Pause [P]
  • Stop mark/space [S]
  • End [E]
  • Gap [G]
  • Repeat signal

Once of the biggest IR signal collection is the irdb. It uses the IRP format. You can read an exhaustive and exhausting definition here. A few examples can be found here. This seems a bit too complex to implement for now. I have used my own internal format to define each IR format. I may move to the IRP spec some day.

The internal format used is as below.

C=S,12;H=2200,1100;T=550,1100,550,,;P=455;S=50,50;E=550;G=22000;
 C = coding scheme
  S - space encoding. Values are M(ark), S(pace), B(oth), P(hase), Q(uad)
  12 – data bits
 H = header mark and space values
 T = timings interpreted according to the coding scheme
 P = pause
 S = stop mark and space values
 E = end
 G = gap

Timings
M – 0 mark, 1 mark, space
S – mark, 0 space, 1 space
B – 0 mark, 0 space, 1 mark, 1 space
P – mark/space
Q – mark, 00 space, 01 space, 10 space, 11 space

All timings are in µs. Some timings are optional and can be left out or set to 0. The commas are still put in even if the values are not applicable. The wavelength and carrier frequency are not captured and, fortunately, are not critical. As part of a URL, most of the delimiters need to be URI encoded. To avoid it, it may be sent as below.

C~S_12-H~2200_1100-T~550_1100_550__-P~455-S~50_50-E~550-G~22000-

ESP8266 Code

The hardware is pretty trivial. The only component is the TSOP38238 and it is connected to GPIO5. It is an IR sensor and a preamp in a single 3 pin package. It detects IR signals with a carrier frequency around 38Khz and provides a clean digital signal.

To capture the IR signal, I turned to some sample code for the NEC remote. The GPIO connected to the TSOP38238 is set to input. An interrupt is set up to trigger on both the rising and falling edges.

enum mgos_app_init_result mgos_app_init(void) {
 ...
 mgos_gpio_set_mode(INPUT_PIN, MGOS_GPIO_MODE_INPUT);
 mgos_gpio_set_pull(INPUT_PIN, MGOS_GPIO_PULL_UP);
 mgos_gpio_set_int_handler_isr(INPUT_PIN, MGOS_GPIO_INT_EDGE_ANY, 
  irrecv_handler, NULL);
 ...
 return MGOS_APP_INIT_SUCCESS;
}

An internal timer keeps track of the time since the last reboot. At each interrupt, check the timer and store the difference since the last interrupt in an array. At timeout, send the contents of the entire array in response to a /cgi/Read request.

static void irrecv_handler(int pin, void *arg) {
 if (bufInx >= BUF_SIZE) {
  return;
 }
 uint32_t now = 1000000 * mgos_uptime();
 buffer[bufInx] = now - timer;
 timer = now;
 if (mgos_gpio_read(INPUT_PIN) == 0) {
  buffer[bufInx] = -buffer[bufInx];
 }
 bufInx++;

 (void) pin;
 (void) arg;
}

Web interface

Here is a screenshot of the web page used to drive the whole thing.

On top is the waveform received reconstructed from the simple signal capture logic above. Then come all the parameters extracted from the raw signal. The captured signal is for a Sony TV and the button press is for Volume+. The logic to extract the parameters from the raw signal is relatively complex. So I have chosen to implement it in javascript and runs on the browser instead of the ESP8266. As you can see, it still needs work as the parameters have a few problems. But with the signal trace in a scrollable section showing multiple pulse trains, it is not hard to debug or simply fine tune the parameters. Ah, the joys of a proper browser based UI!

On pressing the Learn button, the page makes an Ajax call /cgi/Learn. This triggers the data acquisition on the ESP8266. A 10 second timer is kicked off and the data on the IR input is captured and stored in a buffer. The browser periodically checks the progress of the data acquisition by calling /cgi/Read. During the 10 second period, the ESP8266 returns an almost empty array. Once the timer has triggered, the ESP8266 returns the acquired raw data. The javascript analyses this data and determines the IR signal parameters. It displays the raw data as a waveform and populates the parameters in the fields. The Send button is there for future functionality.

No comments:

Post a Comment