38KHz IR Proximity sensor with ATTINY45

Hello!

I am trying to make an infrared proximity sensor using an Attiny45. The circuit must sense when an object is in front of the IR receiver and turn on an maintain the on state of a light while the object remains in front of the sensor. The first time I uploaded a sketch on Arduino Uno(REV 3) and it worked just fine. This is the code, but the pin numbers are assigned for Attiny 45.

#define output 0
#define irRxPin 1          
#define irTxPin 2       

void setup()
{
  pinMode(output, OUTPUT);
  pinMode(irRxPin, INPUT);
  pinMode(irTxPin, OUTPUT);
}

void loop()
{  
  int halfPeriod = 13; 
  int cycles = 38; 
  int i;
  for (i=0; i <=cycles; i++)
  {
    digitalWrite(irTxPin, HIGH); 
    delayMicroseconds(halfPeriod);
    digitalWrite(irTxPin, LOW); 
    delayMicroseconds(halfPeriod - 1);         
  }
  digitalWrite(output, digitalRead(irRxPin)); 
  delay(10); 
}

The code outputs a "LOW" value when the object is in proximity of the sensor and a "HIGH" value otherwise.

I am using the Attiny at 1MHz internal. But the program doesn't run properly. It only detects when the object is swept very fast from side to side, but not from the front, and if it detects it doesn't maintain the "LOW" value.

The original code is Arduino Playground - PanasonicIrSensor.

What should I do in order to make the code run on Attiny 45 like it runs on Arduino?

THANKS,
DANIEL ZAMFIR

You might want to add some BlinkWithoutDelay code to insure that the processor is running at the speed you expect. If your clock speed is off that would explain why it isn't acting the same as on the UNO.

An interesting & unusual use of an IR receiver - using a signal of 1ms to activate the receiver and then rely on the lag from the IR receiver to capture the IR signal immediately after the loop.... = clever!.

There are dedicated 'presence' IR receivers for these types of applications (google Vishay IR receivers), but the code would be much different.

What model IR receiver are you using. If its diferent from the original article, it may have different timing characteristics which could be part of your problem. But you say it works with a UNO @16Mhz.

The next thing to consider assuming the clock & Fuses on the ATTiny45 are correctly set for 1Mhz, is that the speed of the digitalRead may be slower by up to a factor of 16 (or maybe even more - not certain). If this is true you may be just missing the end of the signal.

One thing to try is to rewrite the for loop as follows:

  for (i=0; i <=cycles; i++)
  {
    delayMicroseconds(halfPeriod - 1); //put this line first*********
    digitalWrite(irTxPin, HIGH); 
    delayMicroseconds(halfPeriod);
    digitalWrite(irTxPin, LOW); 
    ///////////////////////////////////delayMicroseconds(halfPeriod - 1); //moved up above     
  }

This avoids the wait for 12 uSecs on the last iteration of the for loop. Hopefully this will help.

If all fails then in addition, you could look at direct port access to read the 'irRxPin', which would be much faster. You would need to search for & read up on this.

Finally, if I was coding this from scratch I would use interrupts to capture the event & PWM to generate the 38kHz moulated IR signal.

Thanks for your help! Rewriting the for loop did the trick. Now I'm also using the 8MHz internal osc. Everything is working just fine.

Best regards,

Daniel Zamfir

Great!

Did it not work at 1MHz even with the code change?

It worked at 1MHz but wasn't very stable. Sometimes it missed the pulse and acted as before.