The Arduino code presented below works well on Gemma v2 and Trinket Mini. But if you have an M0 board you must use the CircuitPython code on the next page of this guide, no Arduino IDE required!

IR Reader

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.

IR Remote Speaker

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

The IR Codes in the code below were for a test remote and not the Adafruit mini remote. Use the codes you obtained in the Decoding IR Codes section for your own project.
// SPDX-FileCopyrightText: 2018 Mikey Sklar 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);
          }  
}

This guide was first published on Sep 27, 2013. It was last updated on Sep 27, 2013.

This page (Arduino Code) was last updated on Jan 09, 2023.

Text editor powered by tinymce.