Hey everyone,
I am trying to write a code for four IR obstacle avoidance sensors (two zones with a left and right sensor). Right now, I am primarily focusing on getting one pair to work. Essentially I want the sensors to work as two way toggles for a digital output so assuming you have two sensors (let's call them A1 and A2) and digital output (pin 3):
If A1 is triggered first, the digital output will stay active until A2 is triggered
and
If A2 is triggered first, the digital output will stay active until A1 is triggered.
This is what I have so far:
boolean Active;
int Update;
int Exit;
void setup()
{
Serial.begin(9600);
pinMode(2, INPUT);
pinMode(3, OUTPUT);
pinMode(4, INPUT);
int Update = 0;
int Exit = 0;
}
void loop()
{
int Status;
Active==false;
int A1;
int A2;
if (Update == 0)
{
A1 = digitalRead(2);
A2 = digitalRead(4);
if(A1==0 | A2==0)
{
Active=true;
Status = 1;
Exit = 0;
}
if(A1==1 && A2==1)
{
Active=false;
Status = 0;
}
switch (Status)
{
case 1:
Run();
break;
case 0:
Inactive();
break;
}
}
if (Update == 1)
{
A1 = digitalRead(2);
A2 = digitalRead(4);
digitalWrite(3,HIGH);
if(A1==0 | A2==0)
{
digitalWrite(3,LOW); // Turn Power Off
Exit = 1;
}
if(A1==1 && A2==1)
{
digitalWrite(3,HIGH); // Turn Power On
Exit = 0;
}
switch (Exit)
{
case 1:
Run();
case 0:
Run();
break;
}
}
}
void Run()
{
if (Exit==0)
{
Update = 1;
Serial.println("Running");
delay(500);
}
if (Exit==1)
{
Update = 0;
Serial.println("Exit");
delay(500);
return;
}
}
void Inactive()
{
Serial.println("Inactive");
}
One of the issues I am having here is the sensors occasionally are triggered more than once, as each sensor will be activated for anywhere from 150 ms to 1000 ms. So if sensor A1 is triggered, the code may check for the status of A1 and A2 again, realizing that A1 is still triggered, and shut off the digital output. Does anyone know of a different way to do this? I'm pretty new to the switch/case concept and have seen people use incrementing for similar uses, but I have not been able to produce anything that works better than this at the moment. Give me a shout, any help is appreciated.
Thanks, the state change detection was exactly what I was looking for:
const int I1 = 2;
const int O1 = 3;
const int I2 = 4;
int CounterZ1 = 0;
int I1_State = 0;
int I1_Last = 0;
int I2_State = 0;
int I2_Last = 0;
void setup()
{
Serial.begin(9600);
pinMode(I1, INPUT);
pinMode(O1, OUTPUT);
pinMode(I2, INPUT);
}
void loop() {
I1_State = digitalRead(I1);
I2_State = digitalRead(I2);
if ((I1_State != I1_Last)|(I2_State != I2_Last)) {
if ((I1_State == LOW)|(I2_State == LOW)) {
CounterZ1++;
Serial.println("on");
Serial.print("number of button pushes: ");
Serial.println(CounterZ1);
} else {
Serial.println("off");
}
delay(50);
}
I1_Last = I1_State;
I2_Last = I2_State;
if (CounterZ1 % 2 == 0) {
digitalWrite(O1, LOW);
} else {
digitalWrite(O1, HIGH);
}
}
Also, I know it is a bit counter-intuitive but, with the way I have the circuit wired, the two sensors are ground active, so the default value on digitalRead is 1.
Yeah, you just gotta roll with that, what I meant about not knowing the sense of your sensors.
For some, HIGH means it sensed (whatever). For others, LOW might mean the thing happened or is happening, whatever it is.
It can be convenient to do some basic testing to see how your sensors work, first just by reading and reporting continuous as you try to activate them. See how well they do the job. See if HIGH means what you think and so forth.
In your code it can help to do something like this once at the top of your sketch:
# define ACTIVE HIGH
Later you can just
if (digitalRead(theSensorPin) == ACTIVE) {
// blah blah blah so something because sensor is sensing
}
Use ACTIVE everywhere instead of HIGH or LOW.
Wrong? Just change the definition, viz:
# define ACTIVE LOW
and you are fixed everywhere.
New sensor operates "upside down" to the old one? Change the define to accommodate it.
You can also write
if (digitalRead(theSensorPin) != ACTIVE) {…
if you wanna do something if the sensor is not sensing. Whatever.