TLC5940 working with IR remote

I was looking to incorporate TLC5940 into my IR remote project. After some careful reading on the TLC5940 library page on the playground (Arduino Playground - TLC5940), I realized that TIMER2 is used in both TLC5940 library and IR remote library (A Multi-Protocol Infrared Remote Library for the Arduino).

I wish I knew how to make changes or evaluate whether changes can be made to accommodate both but I'm clueless. Can someone give me some idea? Thanks.

BTW, are there any simpler LED drives that don't employ PWM but just has on/off instead? I just want something basic. I've done plenty 595 shift registers but they need too many resistors.

I realized that TIMER2 is used in both TLC5940 library and IR remote library

Considered using 2 Arduino's ?

With the latest version of the library (found here: GitHub - Arduino-IRremote/Arduino-IRremote: Infrared remote library for Arduino: send and receive infrared signals with multiple protocols) you can select which timer to use.

Go into IRremoteInt.h and find

// define which timer to use
//
// Uncomment the timer you wish to use on your board.  If you
// are using another library which uses timer2, you have options
// to switch IRremote to use a different timer.

// Arduino Mega
#if defined(__AVR_ATmega1280__)
  //#define IR_USE_TIMER1   // tx = pin 11
  #define IR_USE_TIMER2     // tx = pin 9
  //#define IR_USE_TIMER3   // tx = pin 5
  //#define IR_USE_TIMER4   // tx = pin 6
  //#define IR_USE_TIMER5   // tx = pin 46

// Teensy 1.0
#elif defined(__AVR_AT90USB162__)
  #define IR_USE_TIMER1     // tx = pin 17

// Teensy 2.0
#elif defined(__AVR_ATmega32U4__)
  //#define IR_USE_TIMER1   // tx = pin 14
  //#define IR_USE_TIMER3   // tx = pin 9
  #define IR_USE_TIMER4_HS  // tx = pin 10

// Teensy++ 1.0 & 2.0
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
  //#define IR_USE_TIMER1   // tx = pin 25
  #define IR_USE_TIMER2     // tx = pin 1
  //#define IR_USE_TIMER3   // tx = pin 16

// Sanguino
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
  //#define IR_USE_TIMER1   // tx = pin 13
  #define IR_USE_TIMER2     // tx = pin 14

// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc
#else
  //#define IR_USE_TIMER1   // tx = pin 9
  #define IR_USE_TIMER2     // tx = pin 3
#endif

And change it to what ever you want.

BTW, are there any simpler LED drives that don't employ PWM but just has on/off instead?

TLC5916
TLC5925
M5450 - 34 outputs on this one
M5451 - 35 outputs on this one

Rob,

That could be an option, or the other way around I can design a TLC5940 shield with onboard atmega328 so the user can use all timers on the arduino and just use serial to change TLC5940. I've seen one TLC5940 shield but I don't think it has onboard MCU (it's using the same lib, Shirriff's).

Targettio,

Thanks. I will have that in mind for the IR remote + tones project I'm doing too :slight_smile: I think the TLC 5940 uses both timers on my atmega328 so changing the IR remote library settings is not useful in this case.

Mike,

Thanks. I will look into those other chips.

Just tried to switch to TIMER1 for IRremote lib but same problem happened, 392hz, 440hz and their multiples won't play, just two weak "dah" instead. I tried the speaker and without IR lib it plays all frequencies. I changed remote key assignment for tones and still these frequencies don't play. I wish I could check if TIMER1 is really used. I changed all defs to use TIMER1, programmer's superstition. Here is the code:

#include <IRremote.h>

#define buzzer 16
int RECV_PIN = 17;
int tones[]={262,294,330,350,392,440,494,523,588,659,698,784,880,988,131,147,165,175,196,220,247};

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

void loop() {
  if (irrecv.decode(&results)) {
    byte ret=find_key(results.value);
    Serial.println(ret);
    if ((ret<='9')&&(ret>='1'))
    {
      tone(buzzer, tones[ret-'1']);
      delay(500);
      noTone(buzzer);
      delay(1);
      irrecv.enableIRIn(); // Start the receiver
    }
    else irrecv.resume(); // Receive the next value
  }
}

char codes[]="ML1470ST258-Iv369TPVUCcR";
char find_key(unsigned long code)
{
  static byte last=0;
  byte col, row, temp;
  if (code==0xffffffff) return (last); // Repeat
  temp=lowByte((code-0x40BF00FF)/0x7f8)<<3;
  for (byte i=0;i<8;i++)
  {
    bitWrite(col,i,bitRead(temp,7-i));
  }
  row=col>>2;
  col=col&B11;
  return (last=codes[col*6+row]);
}

Hello,

if you need timer2 for remote control, you can move TLC5940 timer2 usage to e.g. timer5
Timer5 is free in most other applications:

Changes in TLC5940.cpp:

#if TLC_TIMER5 == 0
/* Timer 2 - GSCLK */

TCCR2A = _BV(COM2B1) // set on BOTTOM, clear on OCR2A (non-inverting),
// output on OC2B
| _BV(WGM21) // Fast pwm with OCR2A top
| _BV(WGM20); // Fast pwm with OCR2A top
TCCR2B = _BV(WGM22); // Fast pwm with OCR2A top
OCR2B = 0; // duty factor (as short a pulse as possible)
OCR2A = TLC_GSCLK_PERIOD; // see tlc_config.h
TCCR2B |= _BV(CS20); // no prescale, (start pwm output)
#else
/* Timer 5 - GSCLK */

TCCR5A = _BV(COM5B1) // set on BOTTOM, clear on OCR2A (non-inverting),
// output on OC2B
| _BV(WGM51) // Fast pwm with OCR2A top
| _BV(WGM50); // Fast pwm with OCR2A top
TCCR5B = _BV(WGM52) // Fast pwm with OCR2A top
| _BV(WGM53); // Fast pwm with OCR2A top /* This line is new to get Timer 5 in same Mode like Timer2 */
OCR5B = 0; // duty factor (as short a pulse as possible)
OCR5A = TLC_GSCLK_PERIOD; // see tlc_config.h
TCCR5B |= _BV(CS50); // no prescale, (start pwm output)
#endif

Set the Port correctly:

#if TLC_TIMER5 == 0
GSCLK_DDR |= _BV(GSCLK_PIN);
#else
GSCLK2_DDR |= _BV(GSCLK2_PIN); // Pin 45 ist OCR5B
#endif

and add to Arduino_mega.h:

/** OC2B (Mega pin 9) -> GSCLK (TLC pin 18) */
#define GSCLK_PIN PH6
#define GSCLK_PORT PORTH
#define GSCLK_DDR DDRH

/** OC5B (Mega pin 45) -> GSCLK (TLC pin 18) */
#define GSCLK2_PIN PL4
#define GSCLK2_PORT PORTL
#define GSCLK2_DDR DDRL

I added a define in tlc_config.h:
#define TLC_TIMER5 1 // 0 uses Timer2 GSCLK Pin9 1 uses Timer 5 GSCLK Pin45

The old code you can find strapped with TLC_TIMER5 == 0.
I hope his helps.

Regards
Andreas