The sketch for reading the IR codes for a new remote is below. We will be using Wiring Diagram#the The earlier Gemma v2 and Trinket Mini do not have a built-in hardware serial so we will be using Wiring Diagram #2 Gemma v2 with the USB to TTL Serial Cable. Be sure the Arduino serial console (Putty or screen also work) to 9600 baud, use 8 bits, 1 stop bit, no parity.
Plug in Gemma v2 to your computer with a USB cable and load up the following:
// SPDX-FileCopyrightText: 2018 Limor Fried/ladyada for Adafruit Industries
//
// SPDX-License-Identifier: CC-BY-SA-3.0
/* Trinket/Gemma compatible Raw IR decoder sketch
This sketch/program uses an Adafruit Trinket or Gemma
ATTiny85 based mini microcontroller and a PNA4602 to
decode IR received. This can be used to make a IR receiver
(by looking for a particular code) or transmitter
(by pulsing an IR LED at ~38KHz for the durations pulse_index
Based on Adafruit tutorial http://learn.adafruit.com/ir-sensor/using-an-ir-sensor
and ATTiny program by TinyPCRemote Nathan Chantrell http://nathan.chantrell.net
under Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) license
SendSoftwareSerial Lirary modification by Nick Gammon from NewSoftwareSerial code
GNU Lesser General Public License as published by the Free Software Foundation version 2.1
at http://gammon.com.au/Arduino/SendOnlySoftwareSerial.zip
*/
#include <SoftwareSerial.h> // use if you do not wish to use the lightweight library
SoftwareSerial Serial(0,1); // Receive, Transmit (Receive not used)
// We need to use the 'raw' pin reading methods because timing is very important here
// and the digitalRead() procedure is slower!
#define IRpin_PIN PINB // ATTiny85 had Port B pins
#define IRpin 2
#define MAXPULSE 12000 // the maximum pulse we'll listen for - 5 milliseconds
#define NUMPULSES 34 // max IR pulse pairs to sample
#define RESOLUTION 2 // time between IR measurements
#define STORED_BUTTON_CODES 4 // remote control codes stored
// we will store up to 100 pulse pairs (this is -a lot-)
uint16_t pulses[NUMPULSES]; // high and low pulses
uint16_t pulse_index = 0; // index for pulses we're storing
uint32_t irCode = 0;
void setup(void) {
Serial.begin(9600);
Serial.println();
Serial.println("Ready to decode IR!");
pinMode(IRpin, INPUT); // Listen to IR receiver on Trinket/Gemma pin D2
}
void loop(void) {
// Wait for an IR Code
uint16_t numpulse=listenForIR();
// Process the pulses to get a single number representing code
for (int i = 0; i < NUMPULSES; i++) {
Serial.print(pulses[i]);
Serial.print(", ");
}
Serial.println("\n");
}
uint16_t listenForIR() { // IR receive code
pulse_index = 0;
while (1) {
unsigned int highpulse, lowpulse; // temporary storage timing
highpulse = lowpulse = 0; // start out with no pulse length
while (IRpin_PIN & _BV(IRpin)) { // got a high pulse
highpulse++;
delayMicroseconds(RESOLUTION);
if (((highpulse >= MAXPULSE) && (pulse_index != 0))|| pulse_index == NUMPULSES) {
return pulse_index;
}
}
pulses[pulse_index] = highpulse;
while (! (IRpin_PIN & _BV(IRpin))) { // got a low pulse
lowpulse++;
delayMicroseconds(RESOLUTION);
if (((lowpulse >= MAXPULSE) && (pulse_index != 0))|| pulse_index == NUMPULSES) {
return pulse_index;
}
}
pulses[pulse_index] = lowpulse;
pulse_index++;
}
}
Now that we have a way capture IR data, you can write your own program which uses these codes to do great things.
The demonstration uses a piezo speaker to make different beep tones depending based on four captured codes. This code is based on Wiring Diagram #3 - Trinket 5v with FTDI Friend.
// SPDX-FileCopyrightText: 2018 Anne Barela and Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT
/* Trinket/Gemma compatible IR read sketch
This sketch/program uses an Adafruit Trinket or Gemma
ATTiny85 based mini microcontroller and a PNA4602 or TSOP38238 to
read an IR code and perform a function. In this
test program, tones are generated to a piezo speaker
but you can use codes to trigger any function you wish.
Based on Adafruit tutorial http://learn.adafruit.com/ir-sensor/using-an-ir-sensor
and http://learn.adafruit.com/trinket-gemma-mini-theramin-music-maker
*/
// We need to use the 'raw' pin reading methods because timing is very important here
// and the digitalRead() procedure is slower!
#define IRpin_PIN PINB // ATTiny85 had Port B pins
#define IRpin 2 // IR sensor - TSOP38238 on Pin GPIO #2 / D2
#define SPEAKERPIN 1 // Piezo speaker on Trinket/Gemma Pin GPIO #1/D1
#define MAXPULSE 5000 // the maximum pulse we'll listen for - 5 milliseconds
#define NUMPULSES 100 // max IR pulse pairs to sample
#define RESOLUTION 2 // // time between IR measurements
// we will store up to 100 pulse pairs (this is -a lot-, reduce if needed)
uint16_t pulses[100][2]; // pair is high and low pulse
uint16_t currentpulse = 0; // index for pulses we're storing
uint32_t irCode = 0;
void setup() {
pinMode(IRpin, INPUT); // Listen to IR receiver on Trinket/Gemma pin D2
pinMode(SPEAKERPIN, OUTPUT); // Output tones on Trinket/Gemma pin D1
}
void loop() {
irCode=listenForIR(); // Wait for an IR Code
// Process the pulses to get our code
for (int i = 0; i < 32; i++) {
irCode=irCode<<1;
if((pulses[i][0] * RESOLUTION)>0&&(pulses[i][0] * RESOLUTION)<500) {
irCode|=0;
} else {
irCode|=1;
}
}
if(irCode==0xe0c8A2DD) { // "1" on my remote, USE YOUR CODE HERE
beep(SPEAKERPIN,400,500); } // Make a 400 Hz beep
else if (irCode==0xe0c8a3dc) { // "2", USE YOUR OWN HEX CODE HERE
beep(SPEAKERPIN,500,500); } // Make a 500 Hz beep
else if (irCode==0xe0c8a41b) { // "3", USE YOUR OWN HEX CODE HERE
beep(SPEAKERPIN,600, 500); } // Make a 600 Hz beep
else if (irCode==0xe0c8a29d) { // "4", USE YOUR OWN HEX CODE HERE
beep(SPEAKERPIN, 700, 500); // Make a 700 Hz beep
}
} // end loop
uint16_t listenForIR() { // IR receive code
currentpulse = 0;
while (1) {
unsigned int highpulse, lowpulse; // temporary storage timing
highpulse = lowpulse = 0; // start out with no pulse length
while (IRpin_PIN & _BV(IRpin)) { // got a high pulse
highpulse++;
delayMicroseconds(RESOLUTION);
if (((highpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
return currentpulse;
}
}
pulses[currentpulse][0] = highpulse;
while (! (IRpin_PIN & _BV(IRpin))) { // got a low pulse
lowpulse++;
delayMicroseconds(RESOLUTION);
if (((lowpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
return currentpulse;
}
}
pulses[currentpulse][1] = lowpulse;
currentpulse++;
}
}
// Generate a tone on speakerPin - Trinket/Gemma/ATTiny85 compatible
void beep (unsigned char speakerPin, int frequencyInHertz, long timeInMilliseconds)
{ // http://web.media.mit.edu/~leah/LilyPad/07_sound_code.html
int x;
long delayAmount = (long)(1000000/frequencyInHertz);
long loopTime = (long)((timeInMilliseconds*1000)/(delayAmount*2));
for (x=0;x<loopTime;x++)
{
digitalWrite(speakerPin,HIGH);
delayMicroseconds(delayAmount);
digitalWrite(speakerPin,LOW);
delayMicroseconds(delayAmount);
}
}
Page last edited December 09, 2025
Text editor powered by tinymce.