Attiny Pulling my hair out!! HELP PLEASE

So I am trying to make a intervalometer/remote shutter for my camera (Pentax X5) using a Attiny85.

I found a library HERE some guy created that triggers camera shutters via ir. I have tested his library on an Uno and it works! but when I try it on a attiny it doesn't. The signals on a o-scope look similar.

Also if I use the IR remote library using the IRrecord sketch on an Uno, according to the serial output the siganls are the same and if I tell it to transmit the signal that it recorded from the attiny running the camera trigger sketch it triggers the camera.

I tried with the attiny set to 1mhz & 8mhz. If I try and run at 16Mhz it doesn't do anything, not even blink an LED. I tried following this guys tutorial for calibration, running tinytuner, got an OSCCAL of 87, still no working.

What is going on!! I've been working on this for around 2 days now. I'm really frustrated.

Please help.

Some versions of the Shirriff IRremote library has some wrong definitions for the ATtiny85. They are setting the wrong registers for the IR PWM frequency.

You can try these changes in the IRremoteInt.h file:

// defines for timer1 (8 bits)
#elif defined(IR_USE_TIMER1_8)
#define TIMER_RESET
#define TIMER_ENABLE_PWM     (TCCR1 |= _BV(COM1A1))
#define TIMER_DISABLE_PWM    (TCCR1 &= ~(_BV(COM1A1)))
#define TIMER_ENABLE_INTR    (TIMSK |= _BV(OCIE1A))
#define TIMER_DISABLE_INTR   (TIMSK &= ~(_BV(OCIE1A)))
#define TIMER_INTR_NAME      TIMER1_COMPA_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint8_t pwmval = SYSCLOCK / 2000 / (val) - 1; \
  TCCR1 = _BV(PWM1A) | _BV(CS10); \
  OCR1A = pwmval; \
  OCR1C = pwmval * 2; \
})
#define TIMER_COUNT_TOP      (SYSCLOCK * USECPERTICK / 1000000)
#if (TIMER_COUNT_TOP < 256)
#define TIMER_CONFIG_NORMAL() ({ \
  TCCR1 = _BV(CS10); \
  OCR1A = TIMER_COUNT_TOP; \
  TCNT1 = 0; \
})
#else
#define TIMER_CONFIG_NORMAL() ({ \
  TCCR1 = _BV(CS11); \
  OCR1A = TIMER_COUNT_TOP / 8; \
  TCNT1 = 0; \
})
#endif
#if defined(CORE_OC1A_PIN)
#define TIMER_PWM_PIN        CORE_OC1A_PIN  /* Teensy */
#else
#define TIMER_PWM_PIN        1  /* Arduino Duemilanove, Diecimila, LilyPad, etc */
#endif

Actually, depending on which IRremote version you have, here is the complete IRremoteInt.h file that has the support for the attiny85. See attachment.

IRremoteInt.h (16.4 KB)

So I've narrowed it down to the raw code that transmits the IR code. I can confirm this code works on an Uno but not on a Attiny. Whats the deal?

const int IR_pin = 2; // IR transmiter pin
int freq = 38;

void wait(unsigned int time){
  unsigned long start = micros();
  while(micros()-start<=time){
  }
}

void high(unsigned int time, int freq){
  int pause = (1000/freq/2)-4;
  unsigned long start = micros();
  while(micros()-start<=time){
    digitalWrite(IR_pin,HIGH);
    delayMicroseconds(pause);
    digitalWrite(IR_pin,LOW);
    delayMicroseconds(pause);
  }
}

void shutterNow() {
  high(13000,freq);
  wait(3000);
  for (int i=0;i<7;i++){
    high(1000,freq);
    wait(1000);
  };
}

void setup() {
  // put your setup code here, to run once:
  // initialize the LED pin as an output:
  pinMode(IR_pin, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  shutterNow();
  delay(1000);              // wait for a second
}

So I've narrowed it down to an issue with the math...lol

1000/38=26.31578947

Apparently the attiny hates fractions (don't we all!)

If I do the calculations for my tiny and enter in 9, the result of the following line.

int pause = (1000/freq/2)-4;

It works!!

Is there any way to fix this for the whole library instead of manually entering the numbers?

const int freq = 38;
void high(unsigned int time){
  static const int pause = (1000/freq/2)-4;
...

Wait sorry

I'm wrong. I simplify the code too much and forgot something else. It's not the equation. I checked the output via serial on my attiny. It does come out to 9.

The error for sure comes from his wait function. I find it quite odd that insted of using delayMicroseconds or delay he wrote a whole entire function! 6 lines of code instead of 1 line.

His "high" function doesn't work either because it uses the same

unsigned long start = micros();
  while(micros()-start<=time){

method of programming.

If I change it to "millis();" it works.

Here is the code that I have found to work!

const int IR_pin = 2; // IR transmiter pin
int freq = 38;

void high(unsigned int time, int freq){
  int pause = (1000/freq/2)-4;
  unsigned long start = millis();
  while(millis()-start<=time){
    digitalWrite(IR_pin,HIGH);
    delayMicroseconds(pause);
    digitalWrite(IR_pin,LOW);
    delayMicroseconds(pause);
  }
}

void shutterNow() {
  high(13,freq);
  delayMicroseconds(3000);
  for (int i=0;i<7;i++){
    high(1,freq);
    delayMicroseconds(1000);
  };
}

void setup() {
  // put your setup code here, to run once:
  // initialize the LED pin as an output:
  pinMode(IR_pin, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  shutterNow();
  delay(1000);              // wait for a second
}

..may be of interest to you.

It is tuned for 16Mhz, but as you have an oscilloscope it should be relatively easy to 'tune' for 8Mhz etc.