The Girs driver

The Arduino platform has gained an incredible popularity the last few years. One of the main reasons is the availability of "far-east" clones, often to the price of a hamburger or less. LEDs (for IR or for visible light), as well as IR detectors and receivers, can be soldered directly to these PCBs.

Up until now, usage of the Arduino platform was not supported in Lirc.

The present document requires a fair amount of prerequisite knowledge both on soft- and hardware. Easier to read documents are planned.

Girs (General InfraRed Server Command Language) is the attempt to specify a general communication language for IR servers, in a wide sense. AGirs is an implementation of Girs for the Arduino. (The name "ArduinoGirs" or such was avoided for legal reasons.) It consists of a library, GirsLib, with which different "programs" ("sketches") can be written. As in the Girs specification, there is a number of different, optional modules. These are selected at compile time through defining certain C preprocessor symbols in a configuration file. Also the hardware layout is defined in configuration files.

The AGirs package is available on Github. Currently, the user is supposed to clone that repository, to compile and upload the GirsLite sketch himself/herself. See the Arduino site for instructions on how to do this.

This guide covers both the firmware and the driver. The next chapter covers the firmware; in Arduino lingo, the "sketch" GirsLite. The chapter following deals with the Lirc driver.

The firmware GirsLite

GirsLite is a light-weight configuration of AGirs, intended for usage with IrScrutinizer, and with Lirc, using the driver girs. However, using a decoding receiver (TSOP-*) only, it cannot determine the modulation frequency of a measured signal, nor can it capture signals with a modulation frequency "too" different from the nominal frequency of the demodulator. (A 38kHz demodulator TSOP-*38 in practice works well for the commonly used frequencies 36--40 kHz. For optimal performance, select the "right" one.)

Hardware requirements and configuration

All components are optional. The sketch can be configured for sending and/or receiving, optionally supporting signaling LEDs and an I2C-connected LCD display. Sending of non-modulated signals, e.g. using an RF sender like TX-433, is supported. Thanks to the module command of Girs, the driver at run-time informs itself about the capacities of the current hardware, and informs Lirc in its turn.

Configuration is done by adapting the file config.h, selecting the desired components and their parameters. By convention, it includes a hardware configuration file, where the actual pin configuration is defined. Either use an existing one, or create your own. The Arduino can either be connected over USB, or, if equipped with suitable (W5100-compatible, like the official Ethernet shield) Ethernet shield, accessed over Ethernet using TCP sockets.

A more detailed configuration guide for AGirs is planned.


For sending, define the C preprocessor symbol TRANSMIT. Connect a suitable IR LED to the sending pin (pin 9 on Mega2560 and Leonardo/Mini, pin 3 on most others), using suitable resistor and/or driver transistor.

Sending non-demodulating signals

If NON_MOD is defined, and a suitable sender is connected to pin with the number NON_MOD_PIN, it will be possible to send non-modulated signals. This can be another IR LED, but more interestingly, it can be an RF sender, used for controlling e.g. remotely controlled power outlets etc. (Signals can be generated by IrScrutinizer, using e.g. the arctech protocol.) If the frequency of a signal is 0, the signal is sent to the non modulating receiver at NON_MOD_PIN, otherwise the normal, modulating, sender will be used.

Having the user select transmitter manually (e.g. irsend SET_TRANSMITTERS ...) might have been a cleaner solution than the auto-routing -- but definitely less convenient. Opinions are welcome.

Until recently, lircd parsed remotes having no explicit frequency as having frequency 0 (ticket). To avoid problems, make sure that all used remotes have explicit frequencies in their lircd.conf. (If unsure, just add "frequency 38000" to the preamble of each remote.)


For receiving, define RECEIVE. Use a demodulating receiver, TSOP*, with the data pin connected to IRSENSOR_1_PIN. (Warning: Different receivers look similar, but have different pin-outs. Check their data sheet, or be prepared to fry the components.)

LEDs (for visible light)

For using attached LEDs, define the symbol LED. If desired, define one as COMMANDLED, another as RECEIVELED, and a third one as TRANSMITLED.

This behavior is the same as in IrScrutinizer.

LEDs with build-in resistor are recommended. Otherwise, be sure to include a resistor of a few hundred ohms up to a few kilo-ohms (depending to desired brightness and the type of the LED) in series with the LED. Also note that "multicolored" LEDs (which is nothing but several LEDs within one package), can be used in creative ways.

LCD display

If the use of an I2C connected LCD display is desired, define I2C_LCD. This will be used during start-up to signalize the current firmware version.

As an extra feature, a received signal will be decoded using the decoder of Girs. This currently identifies NEC and RC5 signals. The outcome of the decoding is displayed, but (at least currently) not sent to Lirc.

Self test

As a simple self test, when starting the sketch, all the LEDs come on. If an LCD display is connected, it will show the name and version of the firmware.

Future development

AGirs is work in development, and may change, including the interface, at any time.

The girs driver

Using the modules command of Girs, the driver informs itself during runtime of the capacities of the firmware, and informs Lircd in its turn. For example, if TRANSMIT is not defined in the firmware, Lircd knows that it cannot send. This may lead to a performance improvement.

Driver parameters

There are a few parameter with which the user can customize the behavior of the driver. They are given at the command line to Lircd (alternatively in the file lirc_options.conf). For the syntax, see the documentation for Lircd. The parameters are:

(Only relevant for USB connected Arduinos) If non-zero, the "DTR line" will be lowered for 100 ms when making the first connect, causing most Arduinos to reset (see Arduino documentaton, paragraph "Automatic (Software) Reset").

The device name

As previously mentioned, the driver support both USB- as well as Ethernet connected operation. For the latter case, the "device" is interpreted as a hostname/IP number, optionally followed by a colon (":") and port number (default 33333). The exact rules are: If the device name

the device is assumed to be a connected with a USB-serial connection, otherwise it is assumed to be a hostname/portnumber.

(USB-)Serial connection

If an absolute file name was given, it is used as entered. Otherwise, the Lirc device enumeration is used to locate the device, using the globbing patterns /dev/ttyACM*, /dev/ttyUSB*, /dev/arduino*.

Linux (the subsystem udev really) assigns a connected Arduino a device file name of the form /dev/ttyACMn, in some cases /dev/ttyUSBn, where n is the smallest non-negative integer not yet taken. This can cause unpredictable behavior, not only when using several Arduino, but also in context of other device using the same names, like IrToys. By using custom rules to udev this difficulty can in general be circumvented.

Since there are so many different manufacturers of "Arduino-compatible" hardware, "all" having different vendor id and product id, there is no single simple answer. Some comes with a unique serial, cheaper clones in general not. As a guide to the reader, not as a definite answer, this is my /etc/udev/rules.d/10-arduino.rules. It can be used on Fedora, and probably most other modern Linuxes.

SUBSYSTEMS=="usb", ATTRS{idProduct}=="0043", ATTRS{idVendor}=="2341", SYMLINK+="arduino arduino_uno arduino_uno_$attr{serial}"
SUBSYSTEMS=="usb", ATTRS{idProduct}=="7523", ATTRS{idVendor}=="1a86", SYMLINK+="arduino arduino_nano_qinheng"
SUBSYSTEMS=="usb", ATTRS{idProduct}=="2303", ATTRS{idVendor}=="067b", SYMLINK+="arduino arduino_nano_prolific"
SUBSYSTEMS=="usb", ATTRS{idProduct}=="6001", ATTRS{idVendor}=="0403", SYMLINK+="arduino arduino_nano_ftdi arduino_nano_ftdi_$attr{serial}"
SUBSYSTEMS=="usb", ATTRS{idProduct}=="8037", ATTRS{idVendor}=="2341", SYMLINK+="arduino arduino_micro"
SUBSYSTEMS=="usb", ATTRS{idProduct}=="8036", ATTRS{idVendor}=="2341", SYMLINK+="arduino arduino_leonardo"
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0042", ATTRS{idVendor}=="2341", SYMLINK+="arduino arduino_mega arduino_mega_$attr{serial}"
Access rights

The thus created device files in general are accessible only for root and for members of a group like dialout (system dependent). To allow yourself, or a Lirc user, access to that device, make that user a member of the said group, using for example a command like sudo usermod -a -G dialout $USER.

Ethernet TCP connection

If the device name given is not interpreted as a serial device, it is assumed to denote a host name, optionally with a port number. If the string contains a comma (":"), the substring up to the comma is assumed to be the host name, the substring after the comma the port number. The "hostname" can be either a numerical IP4 address (like, or anything that the name resolver on the host can resolve. The default port number is 33333.


Is there a forum for AGirs?

Unfortunately not (yet). Issues with the Arduino firmware should be raised here, while problems with the driver can be posted to the Lirc mailing list, or, issued here.

Does this driver need to be run as root?

No, provided that the device file and the lock directory (on e.g. Fedora this is /var/run/lock/lockdev) are accessible by the current user. (On most systems, this means that the current user should be a member of the group lock and/or dialout.) Lircd itself may need privileges e.g. for creating lock files and pipes, but this is outside of the scope of the present document.

Why is the receive LED coming on for a short time before transmitting, and when Lircd is executing commands like "version"?

Because Lirc was designed that way; ask Christoph... It is not in the driver. If Lirc was designed today, this would probably have been done differently. Having said that, if using the hardware only for sending, consider disabling the receive feature in the Arduino sketch. This might improve the total systems robustness and performance.

I am looking for a hardware guide for "dummies".

See this guide, and possibly its second part.

What is Infrared4Arduino

Infrared4Arduino is a low-level library for IR signals on the Arduino, on which (the "high level") AGirs is built. It is hosted on Github. API documentation is found here. It is known to the Arduino library manager, so it can/should be installed using it (Sketch -> Include library -> Manage libraries; select Topic "Other" and Type "Contributed!, scroll down to "Infrared").

Why is the Arduino taking so long on its start?

Recently (2017-03-11), the selftest time was reduced from 2 seconds to 0.2 seconds. You may also disable the Arduino bootloader by programming the sketch using an external programmer connected to the ICSP header. (It can easily be restored from the Arduino IDE, using the programmer.) Also, consider adding the flag --immediate-init to the options to lircd.

I have seen a document saying that I should use "Girs4Lirc"; what is that?

Girs4Lirc has been replaced by GirsLite, which now works with both Lirc and IrScrutinizer.

How is "Girs" to be pronounced?

Who cares?