Hi everyone.
I should probably begin by saying this is my first ever electronics project, sketch and forum post.
I'm hoping to receive an answer to two questions, and other ideas to improve my code.
Project
I am making a counter to verify whether someone is in a room. If so, it lights up a LED.
Hardware
Two IR LEDs, connected to an astable 555 timer, as the transmitter.
Two TSOP1236 IR receivers, that are active-low and go high when the beam is broken, are both connected to a different LM311 which are both - in turn - connected to two Arduino digital input pins. The Arduino is also connected to a LED for output.
Software
When both beams are broken, detected via attachInterrupt(), the direction is established and the counter goes up or down, finally telling me whether > 0 people are in the room. The internal pull-up is used to filter noise and the loop() function filters out false hits meaning consecutive beam breaks.
I commented the source code.
Picture of the Serial Monitor feedback.
Question #1. Sometimes the 'beam is broken' when the beam is effectively broken, sometimes only when the beam is restored after being broken. This causes issues. The receivers are three centimeters apart but a person is wider. If a person breaks beam one and then beam two, but beam two triggers immediately whilst beam one isn't yet restored, the system thinks someone is exiting due to comparison of the respective times. Any ideas how to prevent this?
Question #2. I'd like to get rid of the big Arduino and put the sketch on a small AVR microcontroller, using the Arduino ISP. I am thinking the ATTIny85; I only need three I/O pins and its performance is apparently great for its small size. However, it seems you can't simply 'burn' this sketch on that thing but need to seriously rework the code. In short; how can I achieve this the simpliest way?
#define LED_Occupied 13
#define BEAM_One 2 //first beam when entering the room, second beam when exiting
#define BEAM_Two 3 //first beam when exiting the room, second beam when entering
int people_in_room = 0;
int both_interrupted = 0;
bool beam_one_broken = false, beam_two_broken = false;
volatile unsigned long time_interruption_beam_one = 0, time_interruption_beam_two = 0;
void setup() {
pinMode(LED_Occupied, OUTPUT);
pinMode(BEAM_One, INPUT); //Connected to pin 7 of LM311 in turn connected to TSOP1236; goes high if IR beam break
pinMode(BEAM_Two, INPUT); //Connected to pin 7 of another LM311 in turn connected to TSOP1236; goes high if IR beam break
digitalWrite(BEAM_One, HIGH); //Pull-ups for noise
digitalWrite(BEAM_Two, HIGH);
attachInterrupt(digitalPinToInterrupt(2), timestamp_one, RISING);
attachInterrupt(digitalPinToInterrupt(3), timestamp_two, RISING);
Serial.begin(9600);
}
void loop() {
if ((beam_one_broken == true) && (beam_two_broken == true) && (time_interruption_beam_one == time_interruption_beam_two)) { //Filter false readings during start-up
Serial.println("Debugging: POWERING ON ... DEVICE READY.");
beam_one_broken = false; //Reset flag
beam_two_broken = false;
}
else if ((beam_one_broken == true) && ((millis() - time_interruption_beam_one) >= 250)) { //Debounce
Serial.println("Debugging: COUNTED ONE TIME.");
both_interrupted++;
beam_one_broken = false;
check();
}
else if ((beam_two_broken == true) && ((millis() - time_interruption_beam_two) >= 250)) {
Serial.println("Debugging: COUNTED ONE TIME.");
both_interrupted++;
beam_two_broken = false;
check();
}
}
void timestamp_one() {
Serial.println("Debugging: BEAM ONE BROKEN.");
beam_one_broken = true;
time_interruption_beam_one = millis(); //Register when it was broken
}
void timestamp_two() {
Serial.println("Debugging: BEAM TWO BROKEN.");
beam_two_broken = true;
time_interruption_beam_two = millis();
}
void check() {
if (both_interrupted % 2 == 0) { //A person broke two beams, so actually entered or exited
Serial.println("Debugging: BOTH BEAMS BROKEN; OK!");
if (time_interruption_beam_one < time_interruption_beam_two) { //Compare for direction; the person entered the room
people_in_room++;
Serial.println("Debugging: PEOPLE ENTERING ROOM.");
}
else if (time_interruption_beam_one > time_interruption_beam_two) { //Compare for direction; the person exited the room
people_in_room--;
Serial.println("Debugging: PEOPLE EXITING ROOM.");
}
letmeknow();
}
}
void letmeknow(){
if (people_in_room > 0) {
digitalWrite(LED_Occupied, HIGH); //Turn on occupancy red LED
}
else {
digitalWrite(LED_Occupied, LOW); //Turn off occupancy red LED
}
Serial.print("Debugging: ");
Serial.print(people_in_room);
Serial.println(" PERSON(S) IN THE ROOM.");
Serial.println();
}