I'm fairly new to Arduino and am currently using an Uno with the standard Arduino IDE. My aim:
Is to activate a servo when an IR Beam is broken. I think I've managed to get close by borrowing code from others. I'm not sure if the problem I face is code related or the GPIOs I have things plugged into. The issue is:
The code seems to work, in that when the IR beam is broken my LED activates for a few seconds, which is perfect. However when I connect the PWM lead from the Servo in the LED seems to stop working (almost like they're conflicting) When reviewing the serial output it appears that the receiver still detects a broken beam.
Setup: (using breadboard, with common +ve & -ve on the board)
Pin2 = IR Receiver Signal (XC4427)
Pin3 = IR Transmitter (using 220Ohm Resistor) - (XC4426)
Pin4 = Servo PWM
Pin 7 = Status LED (using 220Ohm Resistor)
# define IRPIN 3
# define SENSORPIN 2
# define LED_PIN 7
//# define SENSORPOWER 5
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int pos = 0;
int sensorState = 0, lastState=0; // variable for reading the pushbutton status
void setup() {
// put your setup code here, to run once:
//IRPIN 20
pinMode(IRPIN,OUTPUT);
//SENSORPIN 4
pinMode(SENSORPIN,INPUT);
//pin for solenoid
pinMode(LED_PIN, OUTPUT);
digitalWrite(SENSORPIN,HIGH);
//igitalWrite(SENSORPOWER,HIGH);
//digitalWrite(IRPIN, HIGH);
tone (3, 38000);
Serial.begin(115200);
myservo.attach(5); //attach the servo to digital pin 5.
}
void loop() {
// put your main code here, to run repeatedly:
sensorState = digitalRead(SENSORPIN);
// check if the sensor beam is broken
// if it is, the sensorState is LOW:
if (sensorState == HIGH) {
//
Serial.println("unbroken");
// Serial.println("relay ON"); // if IR is broken write broken and relay on which means water delivered
digitalWrite(LED_PIN, LOW); //turn to low the solenoid which opens it
myservo.write(0); // tell servo to go to position in variable 'pos'
delay(1000);
}
else {
// turn LED off:
Serial.println("broken"); //if its unbroken write unbroken
// digitalWrite(LED_PIN, LOW);
delay (20);
digitalWrite(LED_PIN, HIGH);
myservo.write(180); // tell servo to go to position in variable 'pos'
delay(10000);
}
lastState = sensorState;
}
I apologize if I have posted in the wrong area etc. I've tried to adhere to the guidelines etc.
What model Arduino are you using?
Can you post a copy of your circuit diagram please?
Can you post link to spec/data of your servo?
How are you powering your project.
A delay of 10,000ms is 10seconds, not sure why you need that.
In your code, you have the servo attach to pin 5, but in your description you say pin 4.
Not sure what the tone function is for.
Its a good start, we just need to see how you connect and power your project.
Can I suggest you put this line in your setup after serial.begin
Serial.println("SETUP COMPLETE");
This should only appear once, but if your code is resetting due to power problems it will keep repeating.
Can you try to find a data sheet for the IR Receiver ( VS18388 ) on that breakout board XC4427.
Only a limited number of IR Receiver types are suitable for use with a continuous beam. Usually those which can also be used with a remote control device are NOT suitable. Those designed specifically for beam break applications may be suitable.
What that means for you in practice is that not only do you have to modulate the beam at 38kHz, but you must also break it up into bursts of say 20 carrier pulses with a pause in between each burst. Exactly how may depend on the requirements in the data sheet
Thanks for your reply. I'll see what I can find in terms of the data sheet.
To work around the continuous beam not being recognized, (If I understand correctly) I found that people are using tone() to generate the required pulses.
I'm cleaning up the code and working on a diagram now.
Thanks for the replies so far. I've tried to clean up the code and add comments to make it clearer where my mind is at with each step.
I've done a diagram (my first one and it's messy ) - seems it's quite an art form making neat diagrams.
I did note that if I power the servo from the 5v pin and everything else from 3.3v it seems to be more stable, than running everything from 3.3V - perhaps I was having voltage issues?
The code below seems to work, but every once in a while it seems to trigger the servo twice (eg it will activate the LED, spin the servo and return the servo to 0 degrees after 10 seconds.. then do it a second time) - not sure why.
#include <IRremote.h> //import Remote Libraries
#include <Servo.h> //import Servo Motor Libraries
Servo myservo; // create servo object to control a servo
#define SENSORPIN 2 //IR Reciever connected to pin 2
#define IRPIN 3 //IR Transmitter connected to pin 3
#define PIN_STATUS 13 //Notification LED (using onboard LED which is pin13 on Uno)
#define LED_PIN 7 //LED Pin, External to Arduino Uno, lights up when servo activated
int sensorState = 0, lastState=0; // variable for reading the pushbutton status
void setup()
{
pinMode(IRPIN,OUTPUT); //Set the transmitter Pin(#3) as output (send IR Signal)
pinMode(SENSORPIN,INPUT); //Set the Receiver Pin(#2) as an Input (eg recieve signal)
pinMode(LED_PIN, OUTPUT); //Set External LED as output so it can light up
//You cannot just light up an IR LED and have it detected as the
//recievers expect a special pattern and frequency 38Khz I believe
//Tone will send a frequency of 38Khz to Pin3 (our IR Transmitter)
tone (3, 38000);
Serial.begin(115200); //Start Serial at Baudrate 115200 for output to console
myservo.attach(5); //attach the servo to digital pin 5.
Serial.println(“SETUP COMPLETE”); //To show that setup phase has finished
}
void loop()
{
sensorState = digitalRead(SENSORPIN); //get value of IR Receiver LOW or HIGH?
// check if the sensor beam is broken
// if it is, the sensorState is LOW:
if (sensorState == HIGH)
{
Serial.println("unbroken");
digitalWrite(LED_PIN, LOW); //turn to low the solenoid which opens it
myservo.write(0); // tell servo to go 0 degrees
}
else
{
Serial.println("broken"); //if its unbroken write unbroken
delay (20);
digitalWrite(LED_PIN, HIGH);
myservo.write(170); // tell servo to go to 170 Degrees
delay(10000); //Delay for 10 seconds (gives me time to see system working)
}
lastState = sensorState;
}
The code below kinda works as a prototype, but sometimes acts strange - any suggestions?
Did you have the serial monitor open at the time to see if you got the setup message when the glitch occurred?
What is your power supply.
What is your servo?
You may need some bypass and filtering on the 5V supply.
Try adding a 0.1uF capacitor across the power rails on the protoboard.
Also add a 10uf capacitor across the power rails on the protoboard.
That is not exactly what I meant. The carrier (38kHz), which is generated by the tone() function, is continuous. For some IR receivers such as the TSOP4838, it has to be broken up with pauses:
Here, the 600us is just over 20 bursts of a 38kHz carrier.
This is necessary because the IR receiver has an interference suppression to eliminate constant features of background noise (fluorescent lights etc.). It is not clear to me if that applies also to your specific IR receiver.