Go Down

Topic: TLC5940 working with IR remote (Read 4554 times) previous topic - next topic

liuzengqiang

I was looking to incorporate TLC5940 into my IR remote project. After some careful reading on the TLC5940 library page on the playground (http://www.arduino.cc/playground/Learning/TLC5940), I realized that TIMER2 is used in both TLC5940 library and IR remote library (http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html).

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.
Serial LCD keypad panel,phi_prompt user interface library,SDI-12 USB Adapter

robtillaart

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

Considered using 2 Arduino's ? 
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Targettio

With the latest version of the library (found here: https://github.com/shirriff/Arduino-IRremote) you can select which timer to use.

Go into  IRremoteInt.h and find
Code: [Select]

// 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.

Grumpy_Mike

Quote
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

liuzengqiang

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).

http://www.practicalmaker.com/tlc5940/arduino-tlc5940-shield-demo

Targettio,

Thanks. I will have that in mind for the IR remote + tones project I'm doing too :) 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.
Serial LCD keypad panel,phi_prompt user interface library,SDI-12 USB Adapter

liuzengqiang

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:

Code: [Select]


#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]);
}
Serial LCD keypad panel,phi_prompt user interface library,SDI-12 USB Adapter

odysee_2002

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

Go Up