LIRC with Arduino-GIRS Infrared Transceiver

February 13, 2025   

TL;DR:

Infrared RCU Capture & Playback with Arduino-Girs and LIRC ( with both hardware and software reproducibility ).

History

See this blog post for my adventure with IrDroid-USB and Iguanaworks USB-IR with LIRC here.

I wanted to have a LIRC compatible hardware that I can reproduce by myself. I have found perfect one in the past ( IrDroid-USB) but it was not possible to buy it anymore since the developer is not accessible.

As you may see from above blog post, I was interested in this for long time: Original blog post on harctoolbox for arduino

I followed the tutorial and created following hardware:

How ?

This blog post has mainly two sections:

  • how I built the hardware ?
  • how did I configure my Ubuntu Desktop PC with LIRC

Hardware Prerequisities

  • Simple hardware & soldering experience
  • Arduino Nano
  • 2pcs Infrared Transmitter ( I used TSAL6200 and TSAL6400 )
  • 3pcs visible light LEDs ( RED, YELLOW, GREEN )
  • 1x Infrared Receiver ( I used TSOP4038 )

Software Prerequisites

  • Debian Like ( Such as Ubuntu ) OS
  • LIRC must be installed in your host ( sudo apt install lirc )
  • Ability to edit text files on your host ( such as: sudo vi /etc/lirc/lirc_options.conf )

Hardware differences to the original blog post

As you may have noticed, original blog post has slightly different hardware components than mine. The reason is, I could only find these equipments in the local market.

One example is non-demodulating sensor: I couldn’t find it, and for my simple IR RCU learning purposes, I think it wasn’t needed.

Another critical point is, original blog post used a very small resistor to avoid huge currents to flow across the IR Transmitter LEDs, but I tried even a 10ohm resistor , which has reduced signal intensity ( power ) of my IR LEDs dramatically. So I decided to connect two IR Transmitter LEDs directy to the GPIO output of Arduino-Nano, and I am happy with the performance so far.

Current setup is still not as powerful as IrDroid-USB, but I think it is enough for my purposes.

Maybe in future, I can consider adding a (fast) transistor to drive the IR Transmitter LEDS to increase the power even more.

I think currently my arduinos are pushing 40mA to the GPIO D3 pin, so if we check the datasheet of TSAL6400 or TSAL6200 , they can happily work at 100mA.

The rest of the circuit is exactly same as the original post.

For some hardware configuration details, read part-2 of the original post.

IrScrunitizer with Arduino-GIRS

Installing GirsLite firmware to Arduino-Nano

When you insert your Arduino-Nano to your USB port of your PC, it is detected as a USB-Serial (USBTTY)device:

[ 5095.574091] usb 1-2: new full-speed USB device number 5 using xhci_hcd
[ 5095.876218] usb 1-2: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.54
[ 5095.876224] usb 1-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 5095.876227] usb 1-2: Product: USB2.0-Ser!
[ 5095.917538] usbcore: registered new interface driver ch341
[ 5095.917556] usbserial: USB Serial support registered for ch341-uart
[ 5095.917578] ch341 1-2:1.0: ch341-uart converter detected
[ 5095.929202] ch341-uart ttyUSB1: break control not supported, using simulated break
[ 5095.929276] usb 1-2: ch341-uart converter now attached to ttyUSB1

So it is detected at /dev/ttyUSB1 !!

  • Download latest firmware installer bash script here:

https://github.com/bengtmartensson/AGirs/releases

I downloaded this one: https://github.com/bengtmartensson/AGirs/releases/download/Version-1.0.5/GirsLite-1.0.5-nano-flasher.sh

  • Install the firmware as follows:
stulluk amdpc ~/Downloads $  ./GirsLite-1.0.5-nano-flasher.sh /dev/ttyUSB1
./GirsLite-1.0.5-nano-flasher.sh: 32: [: Linux: unexpected operator

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/etc/avrdude.conf"
         User configuration file is "/home/stulluk/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyUSB1
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 3
         Firmware Version: 4.4
         Vtarget         : 0.3 V
         Varef           : 0.3 V
         Oscillator      : 28.800 kHz
         SCK period      : 3.3 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: safemode: lfuse reads as 0
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: reading input file "/tmp/flasher11385"
avrdude: writing flash (11448 bytes):

Writing | ################################################## | 100% 2.16s

avrdude: 11448 bytes of flash written
avrdude: verifying flash memory against /tmp/flasher11385:
avrdude: load data flash data from input file /tmp/flasher11385:
avrdude: input file /tmp/flasher11385 contains 11448 bytes
avrdude: reading on-chip flash data:

Reading | ##                                                 | 3% 0.05s
avrdude: stk500_paged_load(): (a) protocol error, expect=0x10, resp=0x47
Reading | ##                                                 | 4% 1.34savrdude: stk500_cmd(): programmer is out of sync
avr_read(): error reading address 0x0000
    read operation not supported for memory "flash"
avrdude: failed to read all of flash memory, rc=-2

avrdude: stk500_cmd(): programmer is out of sync
avrdude: stk500_cmd(): programmer is out of sync
avrdude: stk500_cmd(): programmer is out of sync
avrdude: stk500_cmd(): programmer is out of sync
avrdude: safemode: Sorry, reading back fuses was unreliable. I have given up and exited programming mode
avrdude: stk500_disable(): protocol error, expect=0x14, resp=0x74

avrdude done.  Thank you.

stulluk amdpc ~/Downloads $  ./GirsLite-1.0.5-nano-flasher.sh /dev/ttyUSB1
./GirsLite-1.0.5-nano-flasher.sh: 32: [: Linux: unexpected operator

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/etc/avrdude.conf"
         User configuration file is "/home/stulluk/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyUSB1
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 3
         Firmware Version: 4.4
         Vtarget         : 0.3 V
         Varef           : 0.3 V
         Oscillator      : 28.800 kHz
         SCK period      : 3.3 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: safemode: lfuse reads as 0
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: reading input file "/tmp/flasher11581"
avrdude: writing flash (11448 bytes):

Writing | ################################################## | 100% 2.16s

avrdude: 11448 bytes of flash written
avrdude: verifying flash memory against /tmp/flasher11581:
avrdude: load data flash data from input file /tmp/flasher11581:
avrdude: input file /tmp/flasher11581 contains 11448 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 1.62s

avrdude: verifying ...
avrdude: 11448 bytes of flash verified

avrdude: safemode: lfuse reads as 0
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: safemode: Fuses OK (E:00, H:00, L:00)

avrdude done.  Thank you.

stulluk amdpc ~/Downloads $  

As you noticed above, programming Atmega328p microcontroller didn’t went well on the 1st try, but it succeeded in my 2nd test.

Please pay attention to this situation.

Using Arduino-Girs with IrScrunitizer

  • Download latest APPIMAGE for IrScrunitizer here:

https://github.com/bengtmartensson/IrScrutinizer/releases

  • Main UI of the app is shown in below screenshot:

As you see from the picture:

  • I selected /dev/ttyUSB1
  • This printed device as “GirsLite 1.0.5” as the firmware version
  • And I clicked to “Use Receive for Capture”

Now we can use IrScrunitizer to “learn” our IR Remote keycodes and create a “LIRC compatible” configuration file here as follows:

  • Go to “Scrunitize remote” tab:

Here, when you press a remote contol button, the protocol ( “NEC” here ) and corresponding keycodes are printed ina new line.

On the “Name” tab, you need to enter your key names: I suggest to prefix them with “KEY_” , so that lirc server won’t complain about namespace

When you finish your work, press “Export” button, so it will save your LIRC compliant config file under your Documents/IrScrunitizer/lirc_…conf file.

Now you can copy this file to /etc/lirc/lircd.conf.d/ directory with a proper name.

Please note that, sometimes I see that IrScrunitizer messes up the file, so you need to check the file consistency / correctness via manually checking the lines. Especially, IrScrunitizer sometimes adds a keycode line without a KEY_XXX line.. This causes LIRCD to crash.

Here are some more screenshots from IrScrunitizer:

LIRC configuration

LIRC Remote Configuration

Each remote control configuration should reside in /etc/lirc/lircd.conf.d directory. So you can just copy your newly created lircd_your_fancy_remote.conf file to this directory.

Lirc Daemon Configuration

stulluk amdpc /etc/lirc $  diff lirc_options.conf lirc_options.conf.orig 
11,12c11,12
< driver          = girs
< device          = /dev/arduino_nano_qinheng
---
> driver          = default
> device          = auto
stulluk amdpc /etc/lirc $ 

I hope this is clear. Where did the “/dev/arduino_nano_qinheng” came from ? See below.

UDEV configuration

Here is my single line udev rule, that triggers when I insert my Arduino-Girs to one of my USB ports of my PC:

stulluk amdpc /etc/lirc $  cat /etc/udev/rules.d/96-arduino.rules 
ACTION=="add", SUBSYSTEM=="tty", ATTRS{idProduct}=="7523", ATTRS{idVendor}=="1a86", SYMLINK+="arduino_nano_qinheng", RUN+="/usr/bin/kill_lircd.sh"
stulluk amdpc /etc/lirc $  

Here is some explanation:

  • When I insert my arduino, a SYMLINK under /dev with name arduino_nano_qinheng is created. This file is symlinked to ttyUSB1 for example
  • When I insert my device, kill_lircd.sh script is triggered:
stulluk amdpc /etc/lirc $  cat /usr/bin/kill_lircd.sh 
#!/bin/bash

logger "[UDEV] Killing lircd process..."
/usr/bin/kill -9 $(/usr/bin/pidof lircd) | true
logger "[UDEV] lircd killed successfully."

exit 0

stulluk amdpc /etc/lirc $ 

Why I needed to kill lircd? See below:

Fixing LIRC-Daemon hanging issue

I guess this is a bug in lircd. Somehow, if I insert my arduino for the 1st time, lircd systemd service was working perfectly. But if I disconnect my arduino and reinsert again, the irsend command was just hanging, and even systemctl restart lircd was hanging too.

So I ended up killing the process totally.

After this, when you execute irsend , it automatically triggers the socket, which in turn triggers the lircd service to restart the lircd daemon.

My LIRC configuration files repository

IIUC, upstream lircd remote files should be committed to this repo:

https://sourceforge.net/projects/lirc-remotes/

However, I saw this repo wasn’t maintained for a while, and there are pending merge requests for more than 3 years.

So I decided to push my configurations to this public repo:

https://gitlab.com/stulluk/my-lirc-configs

Feel free to use it at your will.

Closing words

I achieved a fully reproducible way to create a hardware and software to both capture & play infrared remote signals with very cheap hardware & software configuration.



comments powered by Disqus