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.
Attachments
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 uint16_t kbrd_kodi[] = { HID_KEY_P, HID_KEY_X, HID_KEY_SPACE, HID_KEY_F, HID_KEY_R, HID_KEY_0, HID_KEY_M, HID_KEY_BACKSPACE, HID_KEY_LEFT, HID_KEY_RIGHT, HID_KEY_UP, HID_KEY_DOWN, HID_KEY_ENTER, HID_KEY_DOT, HID_KEY_COMMA, HID_KEY_S, HID_KEY_I, HID_KEY_T, HID_KEY_L, (uint16_t(HID_LEFT_CTRL) << 8)| HID_KEY_T, HID_KEY_V, HID_KEY_Z, HID_KEY_W, HID_KEY_C };
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};