top of page
  • Writer's picturesmashteevee

Getting Attiny85 (attinycore) to work with Servos, Serial output and IRMP

Updated: Jan 23, 2022

I've recently been learning about Arduino and AVR chips, so trying to do something I originally thought would be simple turned out to be a learning exercise on the topic of timers and interrupts. This brief post describes what I learned so that it can help others in the future - I had trouble finding this info in the usual forums.


My original goal was to make a switchbot (like this) so my kids could use an old IR Remote to switch on their room light from their bunkbed.


Having quickly hacked together something that worked on my Uno, I thought I could do a quick miniaturization and port to the tiny Attiny85, using the popular attinycore library, its built-in Servo library, and the Tiny IR Remote library. I had used each of these in the past with success. I also wanted to debug with Serial, as attinycore has a nice software implementation built-in.


The key parts of my circuit were:

* Attiny85-20PU

* TSOP4838 IR receiver

* SG90 servo

* cheapo IR remote I had left over from a toy (NEC protocol)


The IR receiver and Attiny85 were powered by 5V via USB. The SG90 was powered separately by 4 AA batteries in serial - the ground was shared between the two.


Maybe later I'll post the schematic and code - at the moment it's a work-in-progress. But for now, I wanted to share my biggest learning, which was finding the right combos of libraries to support Attiny85 Serial output with IR receiving with Servo control!


While I had no compile issues, my resulting circuit was a glitchy mess. My TSOP4838 IR receiver was responding to my button presses - but only when I suppressed my debug Serial messages. Depending on what library I included, the servo would only sometimes respond on the remote button press, and only if I held my IR button down, would it sometimes properly move. I wasn't sure if it was the Servo code, the IR library, the Serial output - so I had to do some Datasheet studying (no more postponing diving into the 200+ page PDF!), reading helpful blog posts, like this one, and walking through attinycore Servo source and IRMP source, the IR library I eventually settled on. What made it more confusing were the various options some libraries offered and their pin usage constraints. I experimented with the Servo 8-bit library, as well, adding to my confusion.


It came down to Timers:


The Attinycore uses Timer1 for its Servo control. It supports the ability to send control signals on most any IO pin. PB0 and PB1 are reserved for Serial Tx/Rx in Attinycore's built-in Serial Software. I chose to output Servo signal to PB4.


I chose IRMP to handle IR duty because of its compact footprint, support for AVR Tinies, its support of different config flags, it's actively maintained, and other reasons (see comparison chart). But the most important was the ability to use Pin change interrupts instead of relying on Timer polling (IRMP defaults to using Timer1) to receive IR codes. Setting the following flag tells IRMP to compile using Pin change interrupt:



#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT

Without setting this flag, you will NOT be able to use IRMP with Attinycore and its built-in Servo library as both use Timer1!


A few other things of note, particularly with IRMP as I had to search its repository to figure things out:


* IRMP comes with a handy way to ignore repeated IR codes (I previously rolled my own handler), where you just use the flag IRMP_FLAG_REPETITION, as in:


if !(irmp_data.flags & IRMP_FLAG_REPETITION) {
    // your code here to handle the IR code
}

* Because it's a Pin Change interrupt, you can theoretically specify any of the PCINT pins as your IRMP input Pin. I was not sure what happens if I used PCINT0/1 as the pins are also used by Attinycore Serial, so I avoided those and used PB2. Also, IRMP uses Arduino pin numbers in its code and it's easy to mix things up. Be sure to use the Attinycore's Port Pin notation (eg, PIN_Pxn) for clarity:



#define IRMP_INPUT_PIN   PIN_PB2 // port 

* IRMP comes with some good sample code- however, the samples do include their own Software Serial output code. If you're testing out the code with Attinycore and want to keep Attinycore's Serial library, you'll need to comment out the one included in IRMP samples:



// #include"ATtinySerialOut.h"   <-- not used as we prefer Attinycore Serial library

* Don't forget to use at least 8MHz CPU frequency with IRMP and declare as such in your code:



Happy IR-remote-control-of-your-servos-with-Attiny85-using-attinycore-and-Serial-debug!

bottom of page