IR receiver without library

Hello, I made a challenge for me to use a IR receiver without the IRremote library. Could anyone help
understand how an IR receiver works and how to write the code. Thank you

Just open up the library source and see how Ken Shirriff did it in the first place.

You can earn an entry in the hall of fame if you manage to write a library with integer only arithmetic, i.e. based on multiples of 50µs.

I decided that I am gonna use the RC 5 protocol. I know how it works ,but I don't know how to write it in arduino code.

Well you can do it the way Ken did, or you can use pin change interrupts to detect when the receiver starts/stops receiving a signal, and use a timer to keep track of the pulse length.

I looked at the IR library but I don't understand the getrclevel function.

Could you gie me the code that uses pin change interrupts to detect when the receiver starts/stops receiving a signal.

harryprogram:
Could you gie me the code that uses pin change interrupts to detect when the receiver starts/stops receiving a signal.

This isn't meant to be a putdown at all so please don't take it as one- but if you're just asking for the code then why not just use the IRremote library?
If you actually do want to do it yourself then I can give you some pointers and walk you through the way that I've done it.
This page has some excellent information on interrupts and how to use them.
To read what's coming off the IR receiver you can have pin change interrupt that it triggered by the receiver. You also use a timer to get the pulse length values- choose one that won't clash with any other libraries you're using.
Each time the interrupt fires you can record the value of the timer, and whether the pin is going high or low. You can also keep a count of the amount of pulses that have come in if you're looking for that.
Then you reset the timer and exit the ISR.

Thank you. I am gonna try it.

I have never used timers only the delay function. How can use timers?

Would this work?

////////////////////////////////////////////
#include

int IRpin = 13;

volatile string pulse;
volatile string timer;
int previousstate = 0;

//records time
void time() {
int time = 0;
int currentstate = digitalread(IRpin);
while(previoustate != currenstate) {
delay(1);
time++;
}
timer.push_back(time);
previousstate = currentstate;
}

//records binary pulses values 1 or 0
void recieveIR() {
cli();
time();
int val = digitalRead(IRpin);
pulse.push_back(val);
sei();
}

void setup() {
Serial.begin(9600);
pinMode(IRpin, INPUT);
attachInterrupt(digitalPinToInterrupt(IRpin,recieveIR , CHANGE)
}

//prints time and binary values of the pulses
void loop() {
Serial.println(timer);
Serial.println(pulse);
}

harryprogram:
I have never used timers only the delay function. How can use timers?

Here is a good link to what timers are and how they work. As an aside, if you ever want a good explanation of something to do with the Arduino microcontroller make Nick Gammon's site your first port of call. Chances are he has covered it at some point.
Having thought about it though, for your skill level it would probably be better to stay away from directly manipulating the timer registers and just use the millis() method instead.

harryprogram:
Would this work?
(snip)

No, because you're trying to use delay() inside an ISR which will never work. But you're having a go so good on you. And you've got the right general idea- have an ISR which is triggered whenever the pin changes state, record that state, then try to record how long it stays that way.
Let's have a look at some details.

harryprogram:
#include

volatile string pulse;
volatile string timer;

There's no need for these to be strings, or to use strings at all. Just for the sake of clarity I wouldn't use a variable named timer since you want to work with timers- I'd call it timerValue or something like that.

harryprogram:
//records time
void time() {
int time = 0;
int currentstate = digitalread(IRpin);
while(previoustate != currenstate) {
delay(1);
time++;
}
timer.push_back(time);
previousstate = currentstate;
}

This were most of the problem lies. First off, since this function is only ever called from the ISR there's no need to have it separate to the ISR- just have it all as part of the ISR.
Secondly, it is try to use delay() inside the ISR, which just doesn't work. You'd also only be reading every other state, since the whole ISR checks for the state to change again before exiting. This might be what you want- you might only care about the low pulses and not about the high pulses for example- but just be aware of that.

This is more like what I'd do. This is just pseudo code but it isn't too complicated.

//records binary pulses values 1 or 0
void recieveIR() 
{
    unsigned long pulseEnd = millis()
    pulseLength[i] = (pulseEnd - pulseStart)
    i++    
}

You'd need to declare the following volatile variable at the top of your code too:

volatile unsigned long pulseLength[]
volatile byte i

You can make the pulseLength array as big as you'd like to handle as many pulses as you need to.
You could also optimise it a fair bit- if you know that the pulse length is going to be less than 65,535 milliseconds then you could change pulseLength from an unsigned long to an unsigned int. Or if it is always going to be less than 255 milliseconds then you could change it to a byte.
You could also have a separate array for high pulses and low pulses, and load length of the pulse into the correct variable by checking if the pin is high or low at the start of the ISR.

harryprogram:

//prints time and binary values of the pulses

void loop() {
  Serial.println(timer);
  Serial.println(pulse);
}

using Serial to print the values will typically be too slow. A better way is to use your loop() to check the amount of pulses that have come in (ie, the 'i' variable in my above example) and then print the values in the pulseLength array once you have a certain amount of pulses come in.

I have made use of the mills(); function.
Is this one better?

//////////////////////////////////////////////////////////////////////////
volatile unsigned int pulseLength[];
volatile unsigned int values[];
volatile int counter = 0;
int IRpin = 13;

void recieverIR() {
//switches off interrupt
cli();
//records pulse
int values[counter] = digitalRead(IRpin);
unsigned int time;
bool loop = true;
unsigned int start = millis();
while(loop) {
if(values[countr] != digitalRead(IRpin)) {
pulseLength[counter] = millis() - start;
loop = false;
}
}
counter++;
//switches on interrupt
sei();

}

void setup() {
Serial.begin(9600);
pinMode(IRpin, INPUT);
attachInterrupt(digitalPinToInterrupt(IRpin, recieverIR), CHANGE);
}

void loop() {
if(counter == 32) {
cli();
}
Serial.println(pulseLength);
Serial.println(values);
}