IR Sensor and ServoMotor

Sir, I have a challenge I've been trying to fix. I want to mount an IR receiver sensor on a cylindrical shaft (plastic but 3D printed) which will be mounted on a servomotor. The servo is to be rotating the IR sensor while it listens for IR signals from nearby transmitters. Each transmitter sends a unique code. I want the servo to rotate by an increment of 1degree and at the same time, the IR sensor should be listening for a unique code, such that once that unique code is detected, the servo is to stop rotating and give the value of its current servo position. I am having difficulty doing that...

Below is a code I wrote to do that but it is badly written. because it is no responding well.

#include <IRremote.h>

#include <Servo.h>
Servo IRservomotor;

#define motorspin 5
int angle = 0;
int current_angle;

int RECV_PIN = 3;
IRrecv irrecv(RECV_PIN);
decode_results results;

int phi1, phi2, phi3;

int detecting_beacon1();
int detecting_beacon2();
int detecting_beacon3();
void detect_IR_Signal();
int detect_beacons();

void setup()
{
  Serial.begin(9600);
  Serial.println("Starting");
  irrecv.enableIRIn();
  irrecv.blink13(true);

  IRservomotor.attach(5);
}

int detecting_beacon1()
{
  for(angle = 0; angle >= 180; angle += 1)
  {
    IRservomotor.write(angle);
    detect_IR_Signal();
    if(results.value == 0x18b){break;}
  }
  current_angle = angle;
  phi1 = 2*current_angle;
  delay(20);
  return phi1;
}

int detecting_beacon2()
{
  for(angle = 0; angle >= 180; angle += 1)
  {
    IRservomotor.write (angle);
    detect_IR_Signal();
    if(results.value == 0x58b){break;}
  }
  current_angle = angle;
  phi2 = 2*current_angle;
  return phi2;
}

int detecting_beacon3()
{
  for(angle = 0; angle >= 180; angle += 1)
  {
    IRservomotor.write(angle);
    detect_IR_Signal();
    if(results.value == 0x98b){break;}
  }
  current_angle = angle;
  phi3 = 2*current_angle;
  return phi3;
}


void detect_IR_Signal()
{
  if (irrecv.decode(&results))
  {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
  delay(10);
}

void return_servoPos()
{
  for(angle = current_angle; angle == 0; angle -= 5)
  {
   IRservomotor.write(angle);
    delay(20);
  }
}


/*
void loop()
{
  for(angle = 0; results.value != 0x18b; angle += PI/180)
  {
    IRservomotor.write(angle);
    detect_IR_Signal();
    current_angle = angle;
  }
  Serial.println("Wow... I have detected beacon1... Praise God!!! Alleluia");
  phi1 = 2*current_angle;
  Serial.println("And the current servo position is = ");
  Serial.print(phi1);
  delay(10000);
}

void loop()
{
  for(angle = 0.0; results.value == 0x18b; angle += 2.0)
  {
    IRservomotor.write(angle);
//    detect_IR_Signal();
//    current_angle = angle;
    delay(100);
  }
  Serial.println("Wow... I have detected beacon1... Praise God!!! Alleluia");
  phi1 = 2*current_angle;
  Serial.println("And the current servo position is = ");
  Serial.print(phi1);
  delay(10000);
}*/

void loop()
{
  for(angle = 0; angle >= 180; angle += 1)
  {
    IRservomotor.write(angle);
    detect_IR_Signal();
    if(results.value == 0x18b){break;}
  }
  current_angle = angle;
  phi1 = 2*current_angle;
  delay(20);
  return phi1;
}

I really need help

Lines like this (it occurs in more than one place) are going to get you into trouble:

  for(angle = 0; angle >= 180; angle += 1)

You set angle to zero, then you evaluate whether angle is greater than or equal to 180. It is not, so the for loop is immediately exited.

You probably intended:

  for (angle = 0; angle < 180; angle++)

angle++ and angle+=1 are identical for all practical purposes. I just think that angle++ looks nicer.

By the way, not equal is represented by != which you will need in at least one place.

Thanks a lot for the correction....

What I want the servo to do is move by an increment of a degree, then the IR sensor should listen for IR signal from a transmitter (The transmitter is an IR LED) somewhere after a degree move by the servo. (the IR LED has its own control by another arduino).
All I want is to obtain the angle the servo moved up to the instant the IR signal was detected by the IR sensor.

what i am having right now it the servo isn't turning. its just stiff.

Anybody with any suggestion?

oyegbadetunde:
what i am having right now

If "right now"means since you changed the code for the >= vs < thing, it would help for you to post that new code.

The Servo now rotates but doesn't still do as I want it to do. It completes the rotation to 180degrees then starts from zero again.

This is the code

#include <IRremote.h>

#include <Servo.h>
Servo IRservomotor;

#define motorspin 5
int angle = 0;
int current_angle;

int RECV_PIN = 3;
IRrecv irrecv(RECV_PIN);
decode_results results;

int phi1, phi2, phi3;


void detect_IR_Signal();

void setup()
{
  Serial.begin(9600);
  Serial.println("Starting");
  irrecv.enableIRIn();
  irrecv.blink13(true);

  IRservomotor.attach(5);
}


void detect_IR_Signal()
{
  if (irrecv.decode(&results))
  {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
  delay(10);
}


void loop()
{
  for(angle = 0; angle <= 180; angle++)
  {
    IRservomotor.write(angle);
    detect_IR_Signal();
    if(results.value == 0x18b){break;}
    delay(100);
  }
  current_angle = angle;
  phi1 = 2*current_angle;
  delay(20);
  Serial.println("...The value of phi1 is = ");
  Serial.print(phi1);
  delay(5000);
}

The Serial Monitor reads

Starting
DDE32E9D
4CB0FADF
3C4CE05A
686A18A9
FCABFFBF
F2ED9859
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
75C0FF8
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
D1E20CDD
90112230
0
D7E5424B
F380F7B8
...The value of phi1 is =
362

This is the Transmitter code I sent

#include <IRremote.h>

IRsend irsend;

void setup()
{
}

void loop()
{
  for (int i = 0; i < 3; i++)
  {
    irsend.sendSony(0x18b, 20);
    delay(4);
  }
  delay(10); 
}

The Servo now rotates but doesn't still do as I want it to do. It completes the rotation to 180degrees then starts from zero again.

Which means what?- it's not registering the presence of the ir beacon?

You list the serial output... cool, I was busy typing to ask you to do exactly that :wink:

So you need to be a bit clearer on what the problem is. Is that serial output what it's supposed to be or not? If not then that's not going to have anything to do with the servo code. The other part I was busy typing was to ask if you're 100% happy with the IR side of things, disregarding the servo stuff.

Are you 100% happy with the IR side or do we need to sort something there first?

PS to the above- I don't see anywhere in the serial output where it's getting an 18b?

And the 362 for phi1 is presumably when it falls through the for loop with an angle of 181, not having found the code it was hoping for, and you then double that, hence 362.

So to me, so far, it's working as advertised since you aren't sending an 18b as far as I can see.

You probably don't want the part where it prints phi1 is.... to work if it falls through the for loop, only if it got the right code?

manor_royal:
Which means what?- it's not registering the presence of the ir beacon?

Yes it is not able to determine the unique code the IR LED is sending which is (0x18b)

manor_royal:
You list the serial output... cool, I was busy typing to ask you to do exactly that :wink:

Thanks a lot.

manor_royal:
So you need to be a bit clearer on what the problem is. Is that serial output what it's supposed to be or not? If not then that's not going to have anything to do with the servo code. The other part I was busy typing was to ask if you're 100% happy with the IR side of things, disregarding the servo stuff.

I want the servo to move from zero to 1 degree, then this part detect_IR_Signal(); should listen for IR signal then check if the IR code received is 0x18b, if it is, it should break out of the for loop, then store the servo position as current_angle, then double it. And if the IR code received is not 0x18b, the for loop should be repeated, this time at the next servo position of 2 degrees. I want it to continue doing that until the IR code 0x18b is detected and the servo position indicated.

The Serial output is not what I want exactly, I do not have a problem with what it is indicating, I would that at the point the IR sensor faces the IR LED and the IR code is sent Thrice according to the sony protocol, it should decode it and output 18b on the serial monitor. but it isn't even decoding it.

i am not happy with what the IR sensor is reading, I desire it reads 18b when it is directly pointing or facing the IR LED, but rather it is reading whatever it feels like it wants to read...

manor_royal:
Are you 100% happy with the IR side or do we need to sort something there first?

I am not very happy... The IR sensor is making me an unhappy man.... I am really open to any suggestion available.

Ok so you see why this is taking a bit of time to unravel, since your heading included "servomotor" and yes while there was an issue with the < or >, that's not really the problem. The problem is you're not getting the IR working as you expect.

My advice then is to write a brand new sketch, with not a servo in sight, and have it print the codes in the monitor as you already are, but with an if in there so if it finds the 18b, print a line of ***** or something so you know the if worked.

Try to get the IR sorted. When you know that works, put the servo stuff back. One thing at a time :wink:

manor_royal:
PS to the above- I don't see anywhere in the serial output where it's getting an 18b?

yes it is not getting an 18b

manor_royal:
And the 362 for phi1 is presumably when it falls through the for loop with an angle of 181, not having found the code it was hoping for, and you then double that, hence 362.

Yes... thats what it is doing... If the sensor was some donkey, I'll throw some lashes at it...

manor_royal:
So to me, so far, it's working as advertised since you aren't sending an 18b as far as I can see.

The IR code sent is done by a different arduino and the code is this

#include <IRremote.h>

IRsend irsend;

void setup()
{
}

void loop()
{
  for (int i = 0; i < 3; i++)
  {
    irsend.sendSony(0x18b, 20);
    delay(4);
  }
  delay(10); 
}

manor_royal:
You probably don't want the part where it prints phi1 is.... to work if it falls through the for loop, only if it got the right code?

Yes, I only what it to print phi1 is = (whatever value the IR signal was decoded to be 18b)

Yeah bad words my side: you ARE send ing the 18b, it's not getting recognised.

But I really suggest you clear the decks and do a receiver sketch with no servo stuff in there to clutter things.

manor_royal:
Ok so you see why this is taking a bit of time to unravel, since your heading included "servomotor" and yes while there was an issue with the < or >, that's not really the problem. The problem is you're not getting the IR working as you expect.

My advice then is to write a brand new sketch, with not a servo in sight, and have it print the codes in the monitor as you already are, but with an if in there so if it finds the 18b, print a line of ***** or something so you know the if worked.

Try to get the IR sorted. When you know that works, put the servo stuff back. One thing at a time :wink:

The IR sensor and IR LED are both working perfectly well, as i have used these without the servo and the IR sensor is decoding very well, once it points directly at the IR LED, the serial monitor prints

18b
18b
18b
18b

and when it is not pointing directly and the IR signal wasn't received thrice in succession it prints other values like

D1E20CDD
90112230
FFFFFFFF
75C0FF8

Ok well I didn't realise that the 18b was ever being recognised. That's new info....

Is that pause in the servo movement long enough to ensure it's getting 3x 18b then? Is your physical layout such that the receiver on the servo will reliably be blasted with 3x 18b?

(Seeing as it works with no servo in the mix.....)

Crap I just had a thought... faint bell in the back of my mind to do with the servo libarary and the IR library conflicting. Something to do with timers or something.

Ok so it's sorted and this was not a real memory.

This is the code I have now... for the receiver and the servo

#include <IRremote.h>

#include <Servo.h>
Servo IRservomotor;

#define motorspin 5
int angle = 0;
int current_angle;

int RECV_PIN = 3;
IRrecv irrecv(RECV_PIN);
decode_results results;

int phi1, phi2, phi3;


void detect_IR_Signal();

void setup()
{
  Serial.begin(9600);
  Serial.println("Starting");
  irrecv.enableIRIn();
  irrecv.blink13(true);

  IRservomotor.attach(5);
}


void detect_IR_Signal()
{
  if (irrecv.decode(&results))
  {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
  delay(100);
}


void loop()
{
  for(angle = 0; angle <= 180; angle++)
  {
    IRservomotor.write(angle);
    detect_IR_Signal();
    if(results.value == 0x18b){break;}
    delay(100);
  }
  [color=maroon]if(results.value == 0x18b){current_angle = angle;
  phi1 = 2*current_angle;
  delay(20);
  Serial.println("...The value of phi1 is = ");
  Serial.print(phi1);}
  else{Serial.println("No beacon detected");}
  delay(5000);[/color]
}

And this is the code I have for the transmitter

#include <IRremote.h>

IRsend irsend;

void setup()
{
}

void loop()
{
  for (int i = 0; i < 3; i++)
  {
    irsend.sendSony(0x18b, 20);
    [color=red]delay(40);[/color]
  }
  [color=red]delay(100);[/color] 
}

And this is the Output on the Serial Monitor...

Starting
49B0F626
69DBBC3C
9C334DC3
26CC936A
FCABFFBD
498D6522
49B0F626
BCD252C6
10D9CED6
82ABC4C4
9BFD637C
76DF9DBD
69DBBC3E
C40BD816
No beacon detected
49B0F625
4AB0F7B7
44172A6A
BDD59448
C22A6D02
D651C548
E9732B99
9102D69B
97488347
A3A11665
F82C959A
C59A74BC
26A60AF
CC633145
87B9BAF2
1D4DF57C
1529E433
5E3E2FF5
E4BF101C
F147D606
61D15FC2
ECAB744
1AC48276
251B393C
62108126
79565EB4
23681DA9
23681DA9
AD396BBF
F5D79E33
4A3E325C
2F45C97A
41DC74F0
AF8FFE49
18B
...The value of phi1 is =
164

3A4E5A94
4AB0F7B6

This is what happened... I uploaded these two arduino codes to the two Arduino Uno boards, one for the control of the servo and IR sensor, the second for the control of the IR LED transmitter...

I kept the IR LED from the sight of the IR sensor and it completed the for loop and the output on the serial monitor was this

Starting
49B0F626
69DBBC3C
9C334DC3
26CC936A
FCABFFBD
498D6522
49B0F626
BCD252C6
10D9CED6
82ABC4C4
9BFD637C
76DF9DBD
69DBBC3E
C40BD816
No beacon detected

then I lifted the IR LED at a point within the reach of the IR sensor. And this was the output on the serial monitor...

49B0F625
4AB0F7B7
44172A6A
BDD59448
C22A6D02
D651C548
E9732B99
9102D69B
97488347
A3A11665
F82C959A
C59A74BC
26A60AF
CC633145
87B9BAF2
1D4DF57C
1529E433
5E3E2FF5
E4BF101C
F147D606
61D15FC2
ECAB744
1AC48276
251B393C
62108126
79565EB4
23681DA9
23681DA9
AD396BBF
F5D79E33
4A3E325C
2F45C97A
41DC74F0
AF8FFE49
18B
...The value of phi1 is =
164

Then I took away the IR LED transmitter without the reach of the I sensor and it printed this

3A4E5A94
4AB0F7B6

on the serial monitor.

I discovered the error was from my IR LED transmitter and IR Receiver code...

in the IR LED transmitter, the error is in blue

#include <IRremote.h>

IRsend irsend;

void setup()
{
}

void loop()
{
  for (int i = 0; i < 3; i++)
  {
    irsend.sendSony(0x18b, 20);
    [color=blue]delay(4);[/color]
  }
  [color=blue]delay(10);[/color]
}

while the correct code is highlighted in RED above

The error in the receiver code is highlighted in blue

/*
void loop()
{
  for(angle = 0; angle <= 180; angle++)
  {
    IRservomotor.write(angle);
    detect_IR_Signal();
    if(results.value == 0x18b){break;}
    delay(100);
  }
  [color=green]current_angle = angle;
  phi1 = 2*current_angle;
  delay(20);
  Serial.println("...The value of phi1 is = ");
  Serial.print(phi1);
  delay(5000);[/color]
}

while the correction is highlighted in maroon above

thanks A lot for helping me through this...

I am a happy guy now...

The colours don't show inside code... but glad you have it sorted

Ok so what was the actual problem?- the delays meant the receiver and transmitter weren't connecting before the servo moved on?

manor_royal:
Crap I just had a thought... faint bell in the back of my mind to do with the servo libarary and the IR library conflicting. Something to do with timers or something.

Yea, I read about that and I didn't have IRremote Library conflicting with the servo as regards the timers...
But in another section of my project, the IRremote Library had a conflict with my NewPing Library. The writer of the NewPing Library told me to go to the NewPing Library and locate the file .cpp and change the part of the code that says TIMER_ENABLED to false instead of true. This worked, because the method I was using to detect obstacles wasn't the timer method...