Attiny85 interrupt conflic

Hi

I have one personal project where I try to control an RGB LED with an IR sensor and an Attiny85 processor.

The idea is to have a PWM in PB0, PB1 and PB4.

But I have noticed that the IR Library that I'm using (IRremote_Attiny modified to accept Samsung codes) is usint the Timer2 to control the IR Sensor.

So, that causes problems with the PB0 and PB1.

I'm a newbie, specialy in interupt questions, and I'll try to explain what I have understand of all the posts, and web pages I have read.

Tha Attiny85 has only 2 timers and one is used for the IRremote library, so the other can controll 2 of the PB. Now is controlling the PB4, and the PWM is working on PB4.

I think there are some solutions (it doesn'nt mean that I know how to do it)

1 - Change the IRremote library to use the other timer and this way I will have a PWM on PB0 and PB1, probably I lose the PWM on PB4 but I'm not sure that will be happen.

2 - Change the IRremote library to manage the PWM on PB0 and PB1 at the same time of the IR sensor (I don't know if this is possible or not).

3 - Change the desing and try to do it in a different way. Try to use PWM with PB3 and PB4, and use the PB2 to read the IRR code.

The part of the code that I thing I need to modify is

// initialization
void IRrecv::enableIRIn() {
  // setup pulse clock timer interrupt
  TCCR0A = 0;  // normal mode

  //Prescale /8 (16M/8 = 0.5 microseconds per tick)
  // Therefore, the timer interval can range from 0.5 to 128 microseconds
  // depending on the reset value (255 to 0)
  cbi(TCCR0B,CS02);
  sbi(TCCR0B,CS01);
  cbi(TCCR0B,CS00);

  //Timer2 Overflow Interrupt Enable
  sbi(TIMSK,TOIE0);
  RESET_TIMER2;

  sei();  // enable interrupts

  // initialize state machine variables
  irparams.rcvstate = STATE_IDLE;
  irparams.rawlen = 0;

  // set pin modes
  pinMode(irparams.recvpin, INPUT);
}

// TIMER2 interrupt code to collect raw data.
// Widths of alternating SPACE, MARK are recorded in rawbuf.
// Recorded in ticks of 50 microseconds.
// rawlen counts the number of entries recorded so far.
// First entry is the SPACE between transmissions.
// As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues.
// As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts
ISR(TIMER0_OVF_vect)
{
  RESET_TIMER2;

  uint8_t irdata = (uint8_t)digitalRead(irparams.recvpin);

  irparams.timer++; // One more 50us tick
  if (irparams.rawlen >= RAWBUF) {
    // Buffer overflow
    irparams.rcvstate = STATE_STOP;
  }
  switch(irparams.rcvstate) {
  case STATE_IDLE: // In the middle of a gap
    if (irdata == MARK) {
      if (irparams.timer < GAP_TICKS) {
        // Not big enough to be a gap.
        irparams.timer = 0;
      }
      else {
        // gap just ended, record duration and start recording transmission
        irparams.rawlen = 0;
        irparams.rawbuf[irparams.rawlen++] = irparams.timer;
        irparams.timer = 0;
        irparams.rcvstate = STATE_MARK;
      }
    }
    break;
  case STATE_MARK: // timing MARK
    if (irdata == SPACE) {   // MARK ended, record time
      irparams.rawbuf[irparams.rawlen++] = irparams.timer;
      irparams.timer = 0;
      irparams.rcvstate = STATE_SPACE;
    }
    break;
  case STATE_SPACE: // timing SPACE
    if (irdata == MARK) { // SPACE just ended, record it
      irparams.rawbuf[irparams.rawlen++] = irparams.timer;
      irparams.timer = 0;
      irparams.rcvstate = STATE_MARK;
    }
    else { // SPACE
      if (irparams.timer > GAP_TICKS) {
        // big SPACE, indicates gap between codes
        // Mark current code as ready for processing
        // Switch to STOP
        // Don't reset timer; keep counting space width
        irparams.rcvstate = STATE_STOP;
      }
    }
    break;
  case STATE_STOP: // waiting, measuring gap
    if (irdata == MARK) { // reset gap timer
      irparams.timer = 0;
    }
    break;
  }
}

To compile all the project I use the Arduino 1.0.5-r2 with the IRremote_Attiny library to optimize the code.

Thanks for your time and any help is wellcome.

Sorry for my english, but I'm not a native speaker :frowning:

cr_bb_samsung_85_01.ino (7.99 KB)

IRremote.zip (5.42 KB)

I didn't write the code, but I have used it in a project:

http://www.technoblogy.com/show?LE0

At most one could have 2 pwm channels and IR remote control on a tiny85 (this is what you would be using my core, since it uses timer1 for 2 channels, and timer0 for one).

You cant get pwm and use times for irremote, the tiny85 has only two timers, and each timer an control, at most, two pwm channels.

I cant think of any attiny that I know irremote works on that would still give you 3 pwm channels (I've been meaning to reimplement it the Right Way - that would make it work on the t841, and on the new tinyAVR 0/1-series (including the 412/402, the 8-pin ones; sadly there is no 8-pin one with 8k flash) , and work better in general everywhere - but like, realistically theres little chance of that happening before August considering my to-do list!)

Thanks for your replies.

ChrisTenone, it was in that page where I realized that I have a problem with the timers.

DrAzzy, you have confirmed what I was thinking. There has to be a timer for the IRremote library and there is no posibility to do what I want with the other one.

Thanks for your time.

So I have considered a drastic change of my point of view. I will have a working version of my code without PWM, so I can manage a RGB led with 7 colors, but I need a new vision on how to develop the next version.

I have found this code:

IR Remote Control Detective

I see that the code used is not working with timers. It works with interrupts. So I think that I can develop a new version of my code using that example.

When I finish my project I would like to share it, because it can be helpful for other newbies like me.

And finaly thanks for your idea to reimplement the irremote library, DrAzzy. Most of the information about this library is a little old, so this will be very helpful for the newbies like me. Thanks again.

Does it not also use the timer?

IIRC most of those libraries take over a timer, and either put an interrupt on the timer overflow vector and check the pin at that time, or an interrupt on the pin where they check the timer count value at that time.

Either one of those is going to be a problem though

(Also - just realized why you were getting a timer interrupt vector conflict; the millis timer uses Timer0. With my core, if you disabled millis (this is controlled by a tools submenu when an applicable part is selected using my core, or at least recent versions of it), it actually might work... (depending on implementation)