Falling in Stm32: Remote Control for Home Media Center

Introduction: Falling in Stm32: Remote Control for Home Media Center

This is a complete prototype for home media center remote control based on smt32 micro controller, stm32f103c8t6 known as 'bluepill' board. Suppose, you are using a PC for home media center. It is very flexible solution, which allows you to place huge video library into internal hard drive, or you can play video from the network, for example youtube or so, you have no trouble with codecs or video playing at all, because it is very easy to update the software player any time. The main disadvantage of this solution is that you should use mouse and keyboard to control your playback. The IR remote control is much mode convenient for this.

In this article i will show how to create own remote control using chip bluepill board.

Step 1: The Idea

The main idea is very simple: the bluepill board has embedded usb port and can act as USB HID keyboard. If we attach IR receiver to the board, it could translate the command from your IR remote control to 'key press' of the virtual keyboard. No additional drivers are required!

There are many IR protocols in the world around us. Each TV of VCS vendor has its own IR protocol. But all these protocols have some thing common: they use pulse-modulation to encode the signal. Usually, there is some preamble: long impulse before the first bit in the packet. Then IR control transmits entire packet with 0 and 1 and finalizes the transmission with finish long pulse. To decode the bit we need to measure the length pulse and length of the peak. Usually, the peak length of logic 0 and logic 1 are the same, the difference is in the complete pulse length.

The stm32 micro controllers have embedded feature to capture PWM signal. Near every timer of the micro controller can be put in the 'PWM signal capture more' when the channel variables of the timer save the total length of the pulse and its peak length. Here i must highlight the little detail: when IR receiver catch the signal, the voltage on its working pin become 0 and in the idle state the voltage in the working pin is a 5 or 3.3 volts depending on the IR receiver supply voltage. I.e., the receiver 'inverts' the signal.

With PWM capture mode the stm32 micro controller can be easily turned into a IR remote translator from IR remote to the keyboard codes. Then you can start your favorite visualizing software, for example Kodi of VLC to play your favorite movie on the media center.

Step 2: Creating the Controller

To program stm32 micro controller i would like to recommend the free software from STM: system workbench (aka ac6) and the board configuration tool cubeMX. To upload the software into the micro controller the chip clone of ST-Link V2 adapter can be used. The system workbench project files attached to this step, F1-IR_remote.zip file.

The board configuration tool simplifies the process of initial hardware configuration of our micro controller.

If you are using the system workbench tool, you can just use the downloaded project. But if you wish to investigate the project in more details, you can create the board configuration in the cubeMX:

  • Create new project and select board stm32f103c8
  • Select 'Crystal/Ceramic Resonator' for the 'High Speed Clock (HSE)' item in the RCC menu.
  • Select 'Serial Wire' for the 'Debug' item in the SYS menu.
  • Configure the timer #2 (TIM2 menu) in PWM capture mode as shown on the picture:
    • Slave Mode -> Reset Mode
    • Trigger Source -> TI1FP1
    • Clock Source -> Internal Clock
    • Channel1 -> Input Capture direct mode
  • Set checkbox 'Device (FS) in USB menu
  • Select 'Human Interface Device Class (HID)' pull-down menu element in the 'Class of FS IP' item in USB_DEVICE menu
  • In the clock configuration panel, make sure to provide 72 MHz to the timer #2 because we need timer count at each 1 mks.
  • In the configuration panel configure USB device as shown in the picture
  • In the configuration panel configure timer#2 as following:

    • Prescaller - 71 (from 0 to 71) - 1 micro second tick!
    • Counter Mode - Up
    • Counter Period - 39999 (we should be able to measure the long pulse)
    • Input capture channel1 - Falling Edge (remember that the signal from IR receiver is inverted)

In the PWM capture mode the timer#2 would works the following:

When the falling front detected, the timer counter would be saved in the channel1 register and the timer counter would be reset with 0. Then the timer would continue to count up direction. So we can easily measure the pulse length in micro seconds.

By default the STM32 USB HID class simulates the USB mouse. Here you can find the instruction to turn the controller into keyboard.

Step 3: Tailoring the Controller

The project works with Panasonic remote control and Kodi media center. To tailor the project for your own controller you should add the code array for your remote control as i did for panasonic remote control (panasonicCode) to the Inc/code.h header. As you can see, every command have unique ID (in the IRcommmand enum). There are 24 commands (0-23) recognized by the project. The command are sorted by the relevance.

typedef enum {
IR_play = 0, IR_stop, IR_pause, IR_forward, IR_rewind, IR_last_channel, IR_OSD, IR_prevous_menu, IR_left, IR_right, IR_up, IR_down, IR_enter, IR_chapter_next, IR_chapter_previous, IR_info, IR_subtitle, IR_nxt_subtitle, IR_pos_subtitle, IR_teletext, IR_zoom, IR_mark_watched, IR_playlist, IR_power, IR_unknown } IRcommand;


const uint32_t panasonicCode[] = { 0xd00505d, 0xd00000d, 0xd00606d, 0xd00525f, 0xd00929f, 0x100eced, 0xd00101d, 0x1002b2a, 0x1007273, 0x100f2f3, 0x1005253, 0x100d2d3, 0x1009293, 0x1002c2d, 0x100acad, 0x1009c9d, 0x1008e8f, 0x1004e4f, 0x100cecf, 0x1000e0f, 0x180c041, 0x1801091, 0x180a021, 0xd00bcb1 };

Then you should add your own remote control in the init() method in the IR.cpp with addRemote() function. The function arguments are:

  • Number of bits in the packet
  • The packet Header length
  • 'Zero' bit length
  • 'One' bit length
  • Pointer to the code array
  • Number elements of the array

void IRcmd::init(void) {
addRemote(48, 5252, 902, 1755, panasonicCode, sizeof(panasonicCode)/sizeof(uint32_t));


Also the file contains another table to convert commands into keyboard codes. The kbdr_kodi array contains the key codes for Kodi media center. You can add another array for your own media center program, for example, vlc player. If you would add another media center application table, you would create another object KBD, and initialize it in the main.cpp.

Step 4: Tools to Simplify Tailoring

There are two another projects in the repository

  • IR investigate - allowing to measure the timing parameters of the signals of your remote.
  • IR_capture - allowing to capture the HEX codes of your remote control.

Just load IR investigate project and connect USB port of bluepill board into your computer. Then launch any terminal program on the virtual serial port device, corresponding to the stm32 board. While you press the buttons on you remote, the program would measure the received pulses and prints the average times for different pulse. It should simplify to detect the pulse length for the packet header, zero and one bits.

In the IR investigate project the timer #2 is working in the PWM capture mode with two channels: channel one captures whole pulse length and channel2 captures the peak length. When the falling signal edge detected, the timer value saved into the channel one register and the timer reset with 0. When the rising edge of the signal detected, the timer counter saved to the channel 2 register.

To capture the button codes of your own remote control, the IR_capture project can be used. In the main.c file you should add the remote definition like this one:

IRcode panasonic = {
.hdr = 5252, .bits = 48, .zero = 902, .one = 1755, .dev = 60 };

  • .hdr - the header length in mks
  • .bits - the number of bits in the packet
  • .zero - the length of the zero bit
  • .one - the length one the one bit
  • .dev - the deviation (the difference in times that can be accepted). Usually it is 1/10 of the smallest length.

Then add your remote to the list of supported remotes:

const IRcode* remote[2] = {&panasonic, &pioneer};



    • Metalworking Contest

      Metalworking Contest
    • Fix It! Contest

      Fix It! Contest
    • Creative Misuse Contest

      Creative Misuse Contest

    7 Discussions


    4 months ago

    Hello. I repeated your project. The only clear example of decoding the codes of the console that I found. I made it work. Just answer please why your ready project perfectly recognizes commands from the console, and the project for capturing remote control codes very badly reads them (from 8-10 times). I checked everything on one board and remote control. Unfortunately your main object is written in c ++, I do not understand it well, could you translate it simply to c? I can not yet, just do not have enough knowledge.

    2 replies


    Nice to hear that you have repeated the project.

    Sorry, probably i have hot understood correctly about capturing program. Do you mean the one in F1-IR_Capture.zip archive? But this program written in pure C. There are a list of 'remote control' structures that describes the parameters of the rempte control codes: length of ZERO and ONE codes and so on. You must correctly initialize the IRcode array with your owr remote controll. Or you ment something different?

    I apologize if you do not understand, I'm writing through an interpreter. I mean the program F1-IR_capture.zip. If you compile by default the HEC parameters of the console, then there is practically no capture. You have to press 15 times or more to work. I changed parameters and the program a little, now it works almost always. I'll attach the archive please see if you can still improve the capture. Although the program F1-IR_remote.zip perfectly captures the codes of the NEC console by default, naturally after adding an array with codes. That's what I do not understand why F1-IR_remote.zip works well and F1-IR_capture.zip almost does not work. I work in Keil uVision5.


    Alguien sabe como hacer esto usando arduino IDE 1.

    2 replies

    As far as i understand, arduino IDE for stm32 is not so flexible. Of ourse, you can use direct acess to the registers but this requires deeper knowledge of the architecture.

    Gracias!!! use varias librerias y ciertamente no lo logré con Arduino. Seguiré como lo has hecho tú. Usando el CubeMX pero por lo pronto no tengo el ST-LINK :( para programarlo por esa vía.

    Hey, nice to see one more fellow bluepill enthusiast. I see you're using CubeMX. Been meaning to use this forever, I heard it greatly simplifies setting up the complex hardware ecosystem of STM32. Maybe after reading your instructable I'll finally give it a try!