---------------------------------------------------------------------------------------
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Pin definitions
#define IR_SENSOR_PIN 4 // GPIO4 for IR sensor output
#define SDA_PIN 21 // GPIO21 for I2C SDA
#define SCL_PIN 22 // GPIO22 for I2C SCL
#define BUZZER_PIN 5 // GPIO5 for passive buzzer
#define LED_PIN 2 // GPIO2 for LED
// LCD configuration
#define LCD_ADDRESS 0x27 // I2C address of LCD (common addresses: 0x27, 0x3F)
#define LCD_COLUMNS 16
#define LCD_ROWS 2
// Create LCD object
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLUMNS, LCD_ROWS);
// Variables for object counting
int objectCount = 0;
bool lastStableSensorState = HIGH; // Last stable state after debouncing
bool currentSensorState = HIGH;
bool lastRawSensorState = HIGH; // For detecting changes
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50; // 50ms debounce delay
// Variables for display update
unsigned long lastDisplayUpdate = 0;
unsigned long displayUpdateInterval = 200; // Update display every 200ms
// Variables for buzzer and LED control
unsigned long buzzerStartTime = 0;
unsigned long ledStartTime = 0;
bool buzzerActive = false;
bool ledActive = false;
unsigned long buzzerDuration = 300; // Buzzer beep duration in milliseconds
unsigned long ledDuration = 500; // LED glow duration in milliseconds
int buzzerFrequency = 2500; // Buzzer frequency in Hz
void setup() {
// Initialize Serial communication
Serial.begin(115200);
Serial.println("IR Object Counter Starting...");
// Initialize I2C communication
Wire.begin(SDA_PIN, SCL_PIN);
// Initialize LCD
lcd.init();
lcd.backlight();
// Clear the LCD
lcd.clear();
// Display initial message
lcd.setCursor(0, 0);
lcd.print("Object Counter");
lcd.setCursor(0, 1);
lcd.print("Count: 0");
// Initialize pins
pinMode(IR_SENSOR_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
// Ensure buzzer and LED are off initially
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_PIN, LOW);
// Initial sensor reading
lastRawSensorState = digitalRead(IR_SENSOR_PIN);
lastStableSensorState = lastRawSensorState;
Serial.println("System initialized successfully!");
Serial.println("Place objects in front of the IR sensor to count them.");
Serial.print("Initial sensor state: ");
Serial.println(lastStableSensorState ? "HIGH (no object)" : "LOW (object detected)");
}
void loop() {
// Read current sensor state
currentSensorState = digitalRead(IR_SENSOR_PIN);
// Check if sensor reading has changed
if (currentSensorState != lastRawSensorState) {
// Reset debounce timer when reading changes
lastDebounceTime = millis();
lastRawSensorState = currentSensorState;
}
// If the sensor reading has been stable for the debounce delay
if ((millis() - lastDebounceTime) > debounceDelay) {
// Check if the stable state is different from our last stable state
if (currentSensorState != lastStableSensorState) {
// Object detected (sensor goes from HIGH to LOW)
if (currentSensorState == LOW && lastStableSensorState == HIGH) {
objectCount++;
Serial.println("Object detected! Count: " + String(objectCount));
// Activate buzzer and LED
activateBuzzerAndLED();
// Immediate display update for responsiveness
updateDisplay();
}
// Object removed (sensor goes from LOW to HIGH)
else if (currentSensorState == HIGH && lastStableSensorState == LOW) {
Serial.println("Object removed.");
}
// Update the stable state
lastStableSensorState = currentSensorState;
}
}
// Handle buzzer timing
handleBuzzer();
// Handle LED timing
handleLED();
// Update display periodically
if (millis() - lastDisplayUpdate > displayUpdateInterval) {
updateDisplay();
lastDisplayUpdate = millis();
}
// Check for reset command from Serial
if (Serial.available() > 0) {
String command = Serial.readString();
command.trim();
if (command.equalsIgnoreCase("reset") || command.equalsIgnoreCase("r")) {
resetCounter();
}
else if (command.equalsIgnoreCase("test") || command.equalsIgnoreCase("t")) {
testSensor();
}
else if (command.equalsIgnoreCase("scan") || command.equalsIgnoreCase("s")) {
scanI2CDevices();
}
else if (command.equalsIgnoreCase("testbuzzer") || command.equalsIgnoreCase("tb")) {
testBuzzer();
}
else if (command.equalsIgnoreCase("testled") || command.equalsIgnoreCase("tl")) {
testLED();
}
}
// Small delay to prevent excessive CPU usage
delay(10);
}
void activateBuzzerAndLED() {
// Start buzzer
buzzerActive = true;
buzzerStartTime = millis();
// Start LED
ledActive = true;
ledStartTime = millis();
digitalWrite(LED_PIN, HIGH);
Serial.println("Buzzer and LED activated");
}
void handleBuzzer() {
if (buzzerActive) {
unsigned long currentTime = millis();
// Generate tone for passive buzzer
if (currentTime - buzzerStartTime < buzzerDuration) {
// Create square wave for the buzzer
static unsigned long lastToggle = 0;
unsigned long toggleInterval = 1000000 / (buzzerFrequency * 2); // in microseconds
if (micros() - lastToggle >= toggleInterval) {
static bool buzzerState = false;
buzzerState = !buzzerState;
digitalWrite(BUZZER_PIN, buzzerState ? HIGH : LOW);
lastToggle = micros();
}
} else {
// Turn off buzzer
digitalWrite(BUZZER_PIN, LOW);
buzzerActive = false;
}
}
}
void handleLED() {
if (ledActive) {
if (millis() - ledStartTime >= ledDuration) {
digitalWrite(LED_PIN, LOW);
ledActive = false;
}
}
}
void updateDisplay() {
// Update the count on LCD
lcd.setCursor(0, 1);
lcd.print("Count: ");
lcd.print(objectCount);
// Clear any extra digits (if count went from 3 digits to 2, etc.)
if (objectCount < 10) {
lcd.print(" ");
} else if (objectCount < 100) {
lcd.print(" ");
}
// Additional information on the display
lcd.setCursor(12, 0);
if (digitalRead(IR_SENSOR_PIN) == LOW) {
lcd.print("OBJ"); // Object detected
} else {
lcd.print(" "); // No object
}
// Show sensor state and activity indicators
lcd.setCursor(12, 1);
lcd.print(digitalRead(IR_SENSOR_PIN) ? "H" : "L");
// Show LED status
lcd.setCursor(14, 1);
lcd.print(ledActive ? "*" : " ");
}
void resetCounter() {
objectCount = 0;
Serial.println("Counter reset to 0");
// Turn off buzzer and LED
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_PIN, LOW);
buzzerActive = false;
ledActive = false;
// Clear and reinitialize display
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Object Counter");
updateDisplay();
// Brief confirmation message
lcd.setCursor(0, 1);
lcd.print("Reset! ");
delay(1000);
updateDisplay();
}
// Function to test sensor readings
void testSensor() {
Serial.println("Testing sensor for 10 seconds...");
Serial.println("Watch the readings (LOW = object detected, HIGH = no object):");
unsigned long testStart = millis();
while (millis() - testStart < 10000) {
int reading = digitalRead(IR_SENSOR_PIN);
Serial.print("Sensor: ");
Serial.print(reading ? "HIGH" : "LOW");
Serial.print(" (Raw: ");
Serial.print(reading);
Serial.println(")");
delay(500);
}
Serial.println("Test complete");
}
// Function to test buzzer
void testBuzzer() {
Serial.println("Testing buzzer...");
activateBuzzerAndLED();
Serial.println("Buzzer test initiated");
}
// Function to test LED
void testLED() {
Serial.println("Testing LED...");
digitalWrite(LED_PIN, HIGH);
delay(1000);
digitalWrite(LED_PIN, LOW);
Serial.println("LED test complete");
}
// Function to scan for I2C devices (useful for debugging)
void scanI2CDevices() {
Serial.println("Scanning for I2C devices...");
byte error, address;
int nDevices = 0;
for(address = 1; address < 127; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16) {
Serial.print("0");
}
Serial.println(address, HEX);
nDevices++;
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found");
} else {
Serial.println("Scan complete");
}
}
// Function to test LCD (call this in setup if needed)
void testLCD() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("LCD Test");
lcd.setCursor(0, 1);
lcd.print("Hello World!");
delay(2000);
}
----------------------------------------------------------------------------------------
Then upload.