понедельник, 18 апреля 2022 г.

IR remote + STM32 to usb, decoding IR data

Here we couldn't found a standard solution, because all firms was invented their own IR controllers with their own codes. But why not to try to decode codes from IRs from my basement.

For that experiment we need:

Main idea is in collecting data from IR and sending the stream with it to PC. Then a program with graphical interface will show time diagram of IR signal. By the diagram we can guess about coding type we have and write a decoding program. Of course the simplest solution in this case was in making own IR remote on microcontroller. But usually simpler to use the same IR for all equipment rather then separate one for every one. For example my friend could use the same IR for speaker system and player on PC.

RAW ir data grabber

Just replace in USB-COM example UART RX functions by timer based interrupt, collecting data from GPIO, connected to IR. Experimental I figure out that frequency is 5kHz provides enough precision. In that case datastream in 5 kBytes/sec is easily supported by STM MCU and serial module in the QT framework.

Simplest QT interface

In my daily life I prefer lightweight applications written in GTK or wxwidgets. But if i need a GUI in one evening, QT framework will fits perfectly. So in that 200-lines program you can see:

  • Data acquisition pause button and rewind buttons.  
  • Graphical view of a signal with a scale graduated in milliseconds. 
  • List of obtained IR codes.

Decoding

All of the previous stages was for prepairing to decoding. Decoding algoritm is primitive and consists of several ifs.

  • A counter nulls and ones. Provides to know about a period of pulse.
  • // edge detector if(rxBuf[i] == 1) ++oneCnt; else oneCnt = 0; if(rxBuf[i] == 0) ++nullCnt; else nullCnt = 0; prev = rxBuf[i];

  • Edge detectors. Can recognize start bits or data bits, using time of pulse information.
  • // detect start bit if((prev == 0) && (rxBuf[i] == 1) && (nullCnt > 20)) { isStart = true; bitCnt = 0; word = 0; } // detect one if((prev == 1) && (rxBuf[i] == 0) && (isStart == true) && (oneCnt > 7) && (oneCnt < 11)) { word += 1<<bitCnt; ++bitCnt; } // detect null if((prev == 1) && (rxBuf[i] == 0) && (isStart == true) && (oneCnt < 7)) { ++bitCnt; }

  • All data bits detected condition. Will check and show an obtained code if all of its bits are detected.
  • if((bitCnt >= 32) && ((word & 0xff) == (~(word >> 8) & 0xff)) && \ ((word >> 16 & 0xff) == (~(word >> 24) & 0xff))) { addr = (uint8_t)word; command = (uint8_t)(word >> 16); isStart = false; bitCnt = 0; word = 0; }

  • Null condition. Resets all information about the package if there isn't any data on port.

if(bitCnt >= 32) { bitCnt = 0; isStart = false; word = 0; }

That simple algorithm perfectly recognizes NEC ir codes, which are explained in the third chapter of pdf provided by IR receiver IC vendor. In total I catch all packages from two IR's what I have. IR from microlab speaker system and from samsung VHS player. 

But if you need some additional information, see that website. For information about IR keyboard receiver firmware see the next post.

2 комментария :