IR module detection

Hey i have a 38kHz ir receiver module. I create the signal for the module with a circuit i made, 2 555 oscillator circuits, 1 creates the 38khz carrier frequency and the second modulates at 1.88Hz. I want a program that looks for a signal at 1.88Hz and when found lights a Led. The problem is i have no clue on how to do this.
my setup link: Ir proximity with 38kHz module n 2 555's - YouTube
I was thinking something like:
If input high, set counter 1, delay for 1 period of 1.88Hz, if input high again, set counter 2, delay for 1 period of 1.88Hz, if input high again, set counter 3.

If counter 3 set output high.

I tried this but im not sure if i tried it right. Any help really appreciated.

What if the input stays high? What difference does that make? You need to know transitions from high to low. Try reading up on interrupts. Or for 1.88 Hz (which is really slow) you could just test in the main loop. You need to detect transitions (ie. it is now high when it was previously low, or vice-versa). When you get a transition remember the time (using millis () or micros () ). By comparing the time from one transition to the next you get the period, and the inverse of the period is the frequency.

That is, 1/1.88 is 0.53191489361702, therefore if the time between transition is 531914 microseconds (or thereabouts of course) then you have a frequency of 1.88 Hz. Depending on your margin for error (eg 5%) you would allow for 5% less than 531914 and 5% greater than 531914, and check the period fell somewhere in that range.

Actually I think period is the time between the same transitions (eg. low to high) but not both, so if you are measuring a single transition (low/high or high/low) then the period would be half of what I said above. That is, for 1.88 Hz the signal would transition every 265957 microseconds (low/high) and then again 265957 microseconds (high/low) later, giving a total of 531914 microseconds for the whole cycle.

Ok so i can use hardware interrupt on change to detect the switch between high and low, but i don't get how I can record the time between each switch?

Edit:
nvm - i didnt notice you actually told me "using millis () or micros ()".

So i'm doing something wrong here...
my code is:

#include <SimpleTimer.h>
int IR = 0;
int internalLed = 13;
int t=0;
volatile int counter=0;

SimpleTimer timer;

void Timer() {
t = t+1;
}


void setup () {
timer.setInterval(1, Timer);
pinMode(internalLed, OUTPUT);
Serial.begin(9600);
//Attach interrupt
attachInterrupt(IR, count, RISING);
}

void count () {
counter++;

}


void loop() {
  
  timer.run();
  if(counter == 4) {
Serial.print(t/4);
Serial.print(" miliseconds ");
counter=0;
t=0;
      }
 }

and my serial output is:
251 miliseconds 2 miliseconds 2 miliseconds 66 miliseconds 1 miliseconds 1 miliseconds 2 miliseconds 4 miliseconds 32 miliseconds 737 miliseconds 21 miliseconds 2 miliseconds 3 miliseconds 61 miliseconds 2 miliseconds 1 miliseconds 2 miliseconds

my frequency is: 1.87161 Hz
and with a :80.2% duty cycle
and period of 0.53318727 seconds
high period should be 0.42765 seconds
and low should be 0.10553 seconds
so my program isnt working and i dont know why..
my timeing code is from...
http://www.arduino.cc/playground/Code/SimpleTimer

sorry for double post but discovered something very useful.

And this is why i love this sexy thing that is called Arduino!!!!!
its a pre-defined function called PulseIn http://arduino.cc/en/Reference/PulseIn.
It records the time between 2 highs or lows and outputs it in microseconds its basically everything ive been trying to do so far in 1 command.

int pin = 7;
int count = 0;
int avg=0;
unsigned long duration;

void setup()
{
  pinMode(pin, INPUT);
  Serial.begin(9600);
}

void loop()
{
  duration = pulseIn(pin, HIGH);
  Serial.print(duration);
  Serial.print(" us ");
  avg = avg + duration;
  count++;
 if (count == 10) {
 count = 0;
 Serial.println(" Average = ");
 Serial.print(avg/10);
 Serial.print(" us ");
 avg = 0;
 } 
}

so problem... im not getting regular results so i have a problem with my circuit and am going to have to try to (too many to's) get hold of an oscilloscope to see whats going on.

Okay so i ditched the second 555 and now i'm modulating through the arduino, i kept 1 555 for the 38khz carrier signal, i used this code now...

void setup () {


}

void loop () {
analogWrite(3, 128);
delay(30);
analogWrite(3, 0);
delay(30);
}

is there a way i can calculate the modulation period in that? or would it just be 60 ms?..
(it doesnt work with just delay on normal input mode and doesnt work with PWM without delays either have no clue why.)

Er, you just want it on or off right? So you want digitalWrite. AnalogWrite does pulse-width modulation. Also you need to set the pin mode to output. You are roughly right about the frequency but the instructions themselves, and the loop, take a small amount of time so it won't be exact. Closer to this:

void setup () {
  pinMode (3, OUTPUT);
}

void loop () {
  digitalWrite(3, HIGH);
  delay(30);
  digitalWrite(3, LOW);
  delay(30);
}

Testing that I get 60.12345 (lol) mS between two on/off pulses (giving a frequency of 16.63 Hz). So the 0.12345 mS is the overhead of the instructions and the looping.

Testing that I get 60.12345 (lol) mS between two on/off pulses

Are you really able to measure the time to within 0.00001 milliseconds?

Let's see. The logic analyzer was set to sample at 24 MHz, so each sample was 1/24000000 seconds apart, namely 0.000000041 seconds (every 41 nanoseconds). So a resolution of 10 nS was perhaps a bit optimistic. But that was what the screen said (and I laughed because of the "12345" part of it).

Just to compare I hooked up the Logic16 analyzer which can sample at 100 MHz, and measured that. That gave me 60.1141200 mS between on/off pulses, which is slightly different. That should have given me a resolution of 0.000000010 seconds (10 nS).

PaulS:
Are you really able to measure the time to within 0.00001 milliseconds?

Yes, just. :slight_smile: But in my first post I hadn't because I used the Logic8 analyzer. And I admit there is probably some sort of error margin there if you try to sample too close to the frequency in question.

would it be okay if i used delay() and pulseIn() functions together or will it start to get iffy, maybe better to use milli()?
Im not sure if the pulseIn() function and milli() use the same timers there might be a problem if if they do.
I have the MEGA if it makes a difference

How would you use them together? Looking at the source, it looks like pulseIn simply loops, adding one to a counter, until the pulse is over. Then it converts the count to microseconds.

I would have thought you would have got a similar result by my suggested technique of looking for the pulse start, noting the time with micros (), and then looking for the pulse end. Get the time with micros () again, and subtract one from the other. Since pulseIn doesn't (appear to) use timers it won't clash (per se) with millis ().

For me the problem with pulseIn is that it waits for the pulse to finish, and for a 1.88 Hz pulse that is quite a wait (half a second). If you check for transitions inside loop, and just time them, you can be doing other things.

Ok i got back to this project.
I've replaced the second 555 with a NAND oscillator.
I'm using this circuit..

With this i have a much more stable modulation so I managed to find a range that only looks for my transmitter.

I wrote this code with it..

int in=12;
int out=13;
unsigned long duration=0;



void setup() {
  pinMode(in, INPUT);
  pinMode(out, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  
  duration = pulseIn(in, HIGH);
  
    if(duration >= 1121 && duration <= 1439) { // range of 1121 microsecs to 1439 microsecs
    digitalWrite(out, HIGH);}
    else { digitalWrite(out, LOW); }
   
    if(duration >= 1121 && duration <= 1439) {
      Serial.write("Ok ");
      Serial.print(duration);
      Serial.write(" \n");
     }
    else  if (duration > 0) {
    Serial.write("Time in Microsecs: ");
    Serial.print(duration);
    Serial.write(" \n");
    Serial.write("Frequency: ");
    Serial.print(1000000/(duration));
    Serial.write("Hz \n");
    }
    
   
}

It works, but theres random anomalies in the pulseIn results that causes flashing of LED 13 at times when put further away.
I was thinking if i used averages of my durations instead i could sorta smudge these bad results into my range.
Also sometimes led 13 gets stuck in low state and i have to cover the receiver and uncover to get it to work again. (The transmitter runs smoothly seems to be bad coding problem.)

My question is how can I improve this code to work more efficiently... my goal overall is to make a proximity sensor..(so if a IR source of defined frequency is detected.. set of an alarm).
could anyone help?