Electronic – arduino – ATTiny IR receiver logging erratic values, but works consitently on Arduino Uno

arduinoattiny

I am making a an ATTiny85 IR receiver, programmed with an Arduino Uno.

I'm using a modified version of this code (because the other IR libraries I found weren't compatible).

It's working… sort of. It will respond to anything out of my Universal remote, but I would like it to only respond to one button.

I have the IR sensor connected to 5V, Ground, and ATTiny pin 1 (literally 6), and an LED with capacitor to 4 (literally 3) and ground. 99% percent sure it's not an issue with the components.

If I run the code with the same sensors on my Arduino Uno, it works flawlessly and consistently. The key printed to Serial when I press the power button, for example, is always 2704.

With the ATTiny85, I get values all over the place. From the 0 to thousands. I pressed the power button two dozen times and got 2704 once.

So the variable here is the chip.

I have a hunch it has to do with the ATTiny being unable to measure the times between pulses accurately, but I don't really know how to fix this (calibration? A better external crystal?) and would like some input before I order and then sit around waiting for more components.

It seems possible, because this person built a robot that is controlled with the D-pad on a remote control—but they didn't post their code, schematic, or explain how they made it in very much detail. Other people have asked.

Thank you very much!

Also, here is my code:

int ir_pin = 1;                         //Sensor pin 1 wired through a 220 ohm resistor
int led_pin = 4; //"Ready to Receive" flag, not needed but nice
int start_bit = 2000;                   //Start bit threshold (Microseconds)
int bin_1 = 1000;                           //Binary 1 threshold (Microseconds)
int bin_0 = 400; //Binary 0 threshold (Microseconds)

int led_state = HIGH;

void setup() {
  pinMode(led_pin, OUTPUT);             //This shows when we're ready to receive
  pinMode(ir_pin, INPUT);
  digitalWrite(led_pin, led_state);
  Serial.begin(9600);

}

void loop() {
int key = getIRKey();             //Fetch the key
  if ( key != -1) {
    Serial.println(key);
    //if (key == 2704) {
       led_state = !led_state;
       digitalWrite(led_pin, led_state);
       delay(1000);
    //}
  }
}

int getIRKey() {
int data[12];
while(pulseIn(ir_pin, LOW) < 2200) { //Wait for a start bit
}
data[0] = pulseIn(ir_pin, LOW);       //Start measuring bits, I only want low pulses
data[1] = pulseIn(ir_pin, LOW);
data[2] = pulseIn(ir_pin, LOW);
data[3] = pulseIn(ir_pin, LOW);
data[4] = pulseIn(ir_pin, LOW);
data[5] = pulseIn(ir_pin, LOW);
data[6] = pulseIn(ir_pin, LOW);
data[7] = pulseIn(ir_pin, LOW);
data[8] = pulseIn(ir_pin, LOW);
data[9] = pulseIn(ir_pin, LOW);
data[10] = pulseIn(ir_pin, LOW);
data[11] = pulseIn(ir_pin, LOW);

for(int i=0;i<=11;i++) {                 //Parse them
  if(data[i] > bin_1) {                 //is it a 1?
      data[i] = 1;
  }  else {
      if(data[i] > bin_0) {           //is it a 0?
        data[i] = 0;
      } else {
       data[i] = 2;                     //Flag the data as invalid; I don't know what it is!
      }
  }
}

for(int i=0;i<=11;i++) {                 //Pre-check data for errors
  if(data[i] > 1) {
      return -1;                           //Return -1 on invalid data
  }
}

int result = 0;
int seed = 1;
for(int i=11;i>=0;i--) {                //Convert bits to integer
  if(data[i] == 1) {
      result += seed;
  }
  seed = seed * 2;
}

return result;                             //Return key number
}

Best Answer

Chances are that your attiny runs with the default 1MHz internal clock. Because it works flawlessly on your Arduino, you could start by changing the fuse settings of your tiny AVR to also run at 16MHz.