/*
Project: Break-beam Timer
Description: Measure the time it takes for an
object to travel from A to B.
"j" triggers Start, "k" triggers the "IR beam"
Creation date: 10/23/23
Author: AnonEngineering
From a question by:
ichiko aoba's cat
Discord Arduino #coding-help 10/23/23 6:13PM
License: https://en.wikipedia.org/wiki/Beerware
*/
#include <Servo.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int SERVO_PIN = 3;
const int BTN_PIN = 5;
const int IR_PIN = 4;
const int CLOSE_ANGLE = 0;
const int OPEN_ANGLE = 180;
const unsigned long RELEASE_DELAY = 10;
Servo gateServo; // create servo object
bool checkButton() {
static bool oldBtnState = true; // INPUT_PULLUP idles high
bool isButtonPressed = false;
int btnState = digitalRead(BTN_PIN);
if (btnState != oldBtnState) { // if the button changed
oldBtnState = btnState; // remember new state
if (btnState == LOW) { // and it's now LOW
isButtonPressed = true;
//Serial.println("Button pressed");
} else {
//Serial.println("Button released");
}
delay(20); // for debounce
}
return isButtonPressed;
}
void checkIR() {
while (digitalRead(IR_PIN)) {
// do nothing until the beam breaks
};
}
void closeGate() {
gateServo.write(CLOSE_ANGLE);
}
void openGate() {
gateServo.write(OPEN_ANGLE);
}
void setup() {
Serial.begin(115200);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // wokwi address 0x3C
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
pinMode(BTN_PIN, INPUT_PULLUP);
pinMode(IR_PIN, INPUT_PULLUP);
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.clearDisplay();
gateServo.attach(SERVO_PIN);
gateServo.write(CLOSE_ANGLE); // initial position
delay(500);
Serial.println("System ready");
display.setCursor(30, 0);
display.print(F("System ready"));
display.display();
}
void loop() {
int btnState = checkButton();
if (btnState) { // the button was pressed
openGate();
delay(RELEASE_DELAY); // mechanical gate delay
unsigned long startTime = millis();
checkIR(); // this function blocks until IR triggers
unsigned long stopTime = millis();
unsigned long duration = stopTime - startTime;
Serial.print("Stop time:\t");
Serial.print(stopTime);
Serial.println(" ms");
Serial.print("Start time:\t");
Serial.print(startTime);
Serial.println(" ms");
Serial.print("Duration:\t");
Serial.print(duration);
Serial.println(" ms");
Serial.println();
closeGate();
delay(500);
Serial.println("System ready");
}
}