Home > Arduino, Guides, TKJ Electronics > ATtinyRemote

ATtinyRemote

I have previous thought about buying a universal remote like this one, as I was tired of grabbing my JVC remote for my stereo everytime I had to turn it on, off or turn the volume up or down. But then I discovered Ken Shirriff’s IR Library for the Arduino. Normally the library didn’t support neither the Panasonic or JVC protocol, but I discovered that somebody else had already added them. See the forked github library. At first I simple downloaded the library and tested whenever it could decode the Panasonic protocol and send commands to my JVC stereo. It had to tweak the library a bit, but then it worked just fine.
I thought it would be a bit overkill to use an Arduino and I didn’t want to rewrite the whole library, so I decided to use another AVR’s but in a much smaller package, the ATtiny85. Which is 8-pin AVR.

Development
I the beginning I thought about writing everything in C and then compile and upload everything using the terminal, but then I discovered that one can easily use the Arduino IDE to compile and upload the code.

To use an ATtiny85 with the Arduino IDE, you simple download the ATtiny core for Arduino. Then move the content to a folder called “hardware” inside the Arduino sketchbook folder (you can find it’s location in the preferences dialog in the Arduino software). If the hardware folder doesn’t already exist, just create a new folder called “hardware” in the sketchbook folder. After that simply restart the Arduino IDE. Now you can select “ATtiny85 @ 16 MHz (external crystal; 4.3 V BOD)” in Tools>Board menu.

But you can’t simply upload the program to the ATtiny85 as you normally would, you have to use a programmer. The good thing about AVR’s is that you don’t have to spend another cent if you already own an Arduino, as you can use the Arduino itself as a programmer. To use the Arduino as an ISP see my previous post for more information or see this video by MAKE Magazine which describes the basics in detail: http://youtu.be/30rPt802n1k.

I had some problems with the Arduino ISP sketch in the Arduino IDE version 1.0, but the one in version 0.22 works just fine. So go and download the old IDE, if you can’t get it working.

Then connect the Arduino to the ATtiny85, with some jumper wires, as follows:

ATtiny85       -   Arduino
PIN 8 (VCC)    -   5V
PIN 4 (GND)    -   GND
PIN 1 (RESET)  -   PIN 10 (Slave Reset)
PIN 5 (MOSI)   -   PIN 11 (MOSI)
PIN 6 (MISO)   -   PIN 12 (MISO)
PIN 7 (SCK)    -   Pin 13 (SCK)

For some reason I couldn’t burn the fuses using the Arduino IDE, but it’s pretty simple to use the terminal too. To set the fuses you should download AVRDude or you could simple download WinAVR if you are running windows or CrossPack if your are running MAC OS X, as it contains a GNU compiler suite, a C library for the AVR, the AVRDude uploader, and other AVR development tools.

After you have downloaded the program, go ahead an open a terminal. In windows open run and type cmd, or in MAC OS X simply open the terminal application.

After that you simply type

avrdude -p t85 -P /dev/tty.usb* -c avrisp -b 19200

To check if the communication is working. If you are running Windows, you should replace “/dev/tty.usb*” with the COM-port of your Arduino ISP.

The terminal will then print out something like this:

avrdude: please define PAGEL and BS2 signals in the configuration file for part ATtiny85
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.25s

avrdude: Device signature = 0x1e930b

avrdude: safemode: Fuses OK

avrdude done. Thank you.

You can just ignore the first line.
If it didn’t work, double check all the connection, remember you should also connect 5V and GND to the ATtiny85.

If that’s works, you simple set the fuses like so:

avrdude -p t85 -P /dev/tty.usb* -c avrisp -b 19200 -U lfuse:w:0xff:m -U hfuse:w:0xd4:m -U efuse:w:0xff:m

This will print out something like this:

avrdude: please define PAGEL and BS2 signals in the configuration file for part ATtiny85
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.13s

avrdude: Device signature = 0x1e930b
avrdude: reading input file "0xff"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.05s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xff:
avrdude: load data lfuse data from input file 0xff:
avrdude: input file 0xff contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.03s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified
avrdude: reading input file "0xd4"
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.05s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xd4:
avrdude: load data hfuse data from input file 0xd4:
avrdude: input file 0xd4 contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.05s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: reading input file "0xff"
avrdude: writing efuse (1 bytes):

Writing | ################################################## | 100% 0.03s

avrdude: 1 bytes of efuse written
avrdude: verifying efuse memory against 0xff:
avrdude: load data efuse data from input file 0xff:
avrdude: input file 0xff contains 1 bytes
avrdude: reading on-chip efuse data:

Reading | ################################################## | 100% 0.05s

avrdude: verifying ...
avrdude: 1 bytes of efuse verified

avrdude: safemode: Fuses OK

avrdude done. Thank you.

This will set the ATtiny85 to use an external crystal at 8MHz or above, the start-up time is set to 16K CK/14 CK + 65ms, brown-out detection is set to 4.3, the EEPROM is preserved though chip erase cycle, and the SPI is enabled.
NB: You should be very careful when written the fuses, as you can BRICK your chip, if you for instance disable the SPI interface or disable the reset pin.
For more information see ladyada’s excellent tutorial. Also see the datasheet at page 25 for more information.
If your are going to set some different fuses, I recommend the Engbedded Atmel AVR® Fuse Calculator.

If you don’t like using the command line, you can download the following program: AVRFuses, for both Windows and MAC OS X. If you are running Windows, you can also just download AVR Studio which will include all you will ever need for AVR’s.

The reason why I decided to use an external crystal was because the timing has to be very precise when sending the IR commands. I know that you could properly just use the internal clock inside the ATtiny85. It could be achieved by tuning the internal clock using the following sketch: TinyTuner. But as I don’t care that much about production cost, it would be easier just to use an external 16MHz crystal, as I had some of them laying around.

You should connect the crystal as follows:

Where C1 and C2 are 22pF capacitors.

The next thing you will need is a IR LED to send the commands, I used one I had in my drawer, but any IR LED just like this one could be used. You might also want some with a wider angle, so you can combine these two types, if you are going to mount it permanently. The wider angle ones are usually blue/violet.

The next thing you will need is a IR receiver. I used a TSOP4838, but you could use any one you like. I recommend getting a 38kHz one, as this is the most common, but check the frequency of your the IR protocol you want to decode before buying one. See the LIRC page for more information.

The code
The next thing I had to do, was to write the code itself.
The receiving code is based around Adafruit’s IR-Commander sketch while the decoding of the Panasonic protocol and sending of the JVC commands are based upon a forked version of Ken Shirriff’s library.

The finished code can be found at github: ATtinyRemote.

Update
I have now created a highly optimized new version of the code. Instead of using a timeroverflow to measure the pulses and then save them in a buffer, which you have to do if you want to compare the data to a lot of different protocols, you could just use a interrupt and then a timer to measure the time of the pulse, if you only need to compare it against one protocol. The outcome is that the code is much faster – the ATtiny now react instantly, there is no noticeable delay at all.
The new updated version can be found at github as well: https://github.com/TKJElectronics/ATtinyRemote/tree/master/ATtinyRemoteVer2.

The functionality is pretty simply, if I press the red button it turns my stereo on/off, the green button mutes and unmutes the stereo, and finally the yellow and blue bottom respectively turns the volume down and up. The stereo will also turn on/off whenever I turn my TV on/off. Finally the power button in the bottom left disables/enables the ATtinyRemote. This allows the user to use the color buttons as you use them very rarely to change settings.

I have used the port registers as much as possible, so it would be easy to port it to other AVR’s. The only thing I used from the Arduino IDE, is the delay functionality, as I discovered that the delay microseconds function in the popular AVR Libc library isn’t precise enough for the sending functionality.
If you want to port the code to another AVR, that’s not supported in the Arduino IDE, you could just copy the delayMicroseconds() from the Arduino IDE as I couldn’t get it working properly with the delay function from AVR Libc.

The PCB
I decided to use an IR emitter, also known as an IR blaster, and an IR receiver cable from ebay. They can simply be connected to the PCB with a normal 3.5mm Jack plug.

I decided this to be my final design, as I didn’t like the ATtinyRemote to be visible to the user. By having the cables, I could mount the PCB on the back of my tv, while getting power from the USB port at the same time. By doing that, only the cables would be visible. Also I would save power, as it’s only turned on, while my TV is also turned on.

The schematic for the PCB can be seen below:

And the finished PCB from Dorkbotpdx can be seen below:

The PCB is available at Github as well.

You might have noticed that the protecting resistor is only 22Ω for the IR emitter, but the thing is that a IR LED can actually handle up to approximately 1A depending of the type – but only for a few milliseconds! This is not a problem when using it for IR communication, as it toggles at a frequency of 38kHz (this change depending on the specific protocol), but if you turn it on constantly you might damage the IR LED, so while prototyping I recommend a larger value protecting resistor. See this page for more information.

Since I didn’t know the exact specs for the IR emitter, I just decided the following values for my circuit: a forward voltage of 1.1V and a 22Ω protecting resistor. By using Ohm’s lov one can calculate that the current through the LED is 177.3mA ((5V-1.1V)/22Ω).

Get one
If you would like a kit, please send me an email at kristianl@tkjelectronics.dk.

For information on how to implement your own IR protocol, I recommend the following pages

If you don’t own a ATtiny85 and want to control you JVC or Panasonic device, check out my forked repository at github: https://github.com/TKJElectronics/Arduino-IRremote as I added the protocols to Ken Shirriff’s original library.

In the case you missed it here is a link to the final source code: ATtinyRemote.

For more information about PWM see the following pages:

If you got problems uploading to the ATtiny, then see the following sites:

For more information about how IR works:

Categories: Arduino, Guides, TKJ Electronics Tags:
  1. Moe
    January 3rd, 2014 at 21:25 | #1

    Just wanted to thank you for putting very good comments on your GitHub code.

  2. January 4th, 2014 at 03:57 | #2

    @Moe
    You are welcome :)

  3. Karo Minkkinen
    March 24th, 2014 at 03:33 | #3

    Thank’s for this great article!
    Two years has passed and it’s still the most valid information for working with IR and ATTiny85.
    I’m not so skilled with coding and I’m getting gray hair trying to extract the sending part of you code. I simply have to send few (long) raw ir-codes with ATTiny85, nothing else to maximize the memory left for the other part of the application. I’m looking for to command my heat pump with this. Could you give a little help?
    Thank’s

  4. March 28th, 2014 at 00:55 | #4

    @Karo Minkkinen
    Yes of course. What typo of device is it? Have you checked that it is not already supported by the IRremote library: https://github.com/shirriff/Arduino-IRremote? If it is, then it should be much easier to implement support for it.

  5. Karo Minkkinen
    March 28th, 2014 at 21:20 | #5

    I’m having just barebones attiny85 with 16mhz crystal. Hardware is working, my ir timings are working with arduino and libraries.
    With Attiny, IRremote gave me plenty of errors that maybe could be fixed by changing the timers etc. The problem is that I’m getting lost with those libraries and I guess it’s eating more memory? Also to learn, could be better to start from naked sketch…?

  6. Jack
    March 29th, 2014 at 02:14 | #6

    First off, Thank you for your awesome code. Second I’m a little stuck on how to change your send codes from JVC to NEC. I have compared it with https://github.com/shirriff/Arduino-IRremote and am still stuck (beginner here, sorry =). Any advice to send NEC instead? -Thanks, Jack

  7. March 29th, 2014 at 12:23 | #7

    @Karo Minkkinen
    You can just use an Uno or similar to find out if your protocol is supported by the IRremote library, then it will be much easier to implement it on the ATTiny85.

    @Jack
    I guess you have already studied the decodeNEC function: https://github.com/shirriff/Arduino-IRremote/blob/master/IRremote.cpp#L454-L500?

    Here is a site that described the NEC protocol in more detail: http://www.sbprojects.com/knowledge/ir/nec.php.

  8. Karo Minkkinen
    March 30th, 2014 at 11:42 | #8

    @Lauszus
    Would be too easy…
    I have long 288 bits code sent twice with long pause between. From raw timings I can read headers, mark and spaces. From thereon I could obviously calculate binary data. But I don’t know how to send it with attiny85.
    If I could just extract that sending part of you code and use it to send raw timings or even in binary…

  9. March 31st, 2014 at 09:51 | #9

    @Karo Minkkinen
    Okay. First of all you need to read and understand these blog posts: http://www.sbprojects.com/knowledge/ir/index.php and http://www.righto.com/2009/07/secrets-of-arduino-pwm.html.
    Also please read the datasheet for the ATtiny85 starting from page 83-94: http://www.atmel.com/Images/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf.

    Then finally try to understand the sending part of the code: https://github.com/TKJElectronics/ATtinyRemote/blob/master/ATtinyRemoteVer2/ATtinyRemoteVer2.ino#L185-L209. Please note that you will properly need to modify this code to reflect your IR protocol. Also just assume that nrRepeats is 0, as it this was specific for my device.

  10. Aki
    April 5th, 2014 at 15:47 | #10

    I have been working on sending an IR single using an attiny 85 for a couple of days now and i still i haven’t come up with anything. I consider my self a beginner to this kind of stuff. I have read and tried every piece of code there is in the internet and i still can’t seem to send a single. every time a try a code i get a kind of error.

    Finally i came across your code…when i tried to upload it to my attiny it worked like a charm with no errors at all….but then i took a look at your circuit and code and couldn’t understand a thing.

    So i was wondering if it possible to make your code dead simple….like hooking up an IR to a attiny and make it send any single.

    your help will be really appreciated.
    love your work btw

  11. April 5th, 2014 at 16:35 | #11

    @Aki
    Are you looking at version 1 og version 2 of the code?
    Version 1 is a lot slower, but is also easier to understand. If that is not simple enough, then am I afraid that you need to spent some more hours studying the code ;)

  12. Karo Minkkinen
    April 8th, 2014 at 22:27 | #12

    I red all the links you gave me, thank’s for those! Little step forward, the problem is that I should study basic coding more than else… Basically I need something like Aki was asking above:)

    Anyway I wanted to ask about that duty cycle, thing that is rarely mentioned: How can I know if it should be 1/3 or 1/4 or something else, how much it has importance?

  13. April 9th, 2014 at 00:08 | #13

    @Karo Minkkinen
    It depends on the protocol, but normally it is 1/3.
    If you got a scope you can measure it if you want.

Comment pages
1 2 2070
  1. No trackbacks yet.