Automated Sound-Triggered Alarm with ATmega328P External Interrupts

 I built a circuit that detects sound and sound a buzzer using ATmega328P external interrupt. It can be used in application like automated library noise alert system for school or college. Silence is critical in libraries, and this circuit monitors ambient sound levels in real time. So, when students begin talking too loudly and noise exceed a pre-set threshold then ATmega328P interrupt is triggered instantly which actives a buzzer to provide an immediate reminder to maintain silence. This is only one of many applications that can be built around it. It can be used to monitor baby is crying or detect thief. Other applications include automated clap switch, which turns on/off a light with clap sound, in industrial factories to detect thud or bang sound indicating machinery failure or jamming conveyor belt, voice activated automated system for home, automated photo camera trigger when some sound is produced etc.

The automated sound detector and triggering is enabled using ATmega328P external interrupt feature. I had written about how the external interrupt of ATmega328P works where I showed what external interrupt is and how to use it and how to write external interrupt program with code example. This time a real-world application example is provided with explanation of how the automated sound based triggering system using ATmega328P external interrupt works.

Below is the circuit diagram.

ATmega328P external interrupt automated sound detection and triggering

How the Circuit Works

The circuit operates in three distinct stages:

  • Stage 1: Detection (The Mic & Comparator): The electret microphone converts sound waves into a tiny AC voltage. The LM393 comparator compares this "wiggling" voltage against a reference voltage set by your 10kΩ potentiometer.

  • Stage 2: Logic (The ATmega328P): When the sound voltage crosses the threshold, the LM393 output drops Low. This "Falling Edge" triggers the INT1 (PD3) interrupt on the ATmega328P. The CPU pauses its current task and jumps to the Interrupt Service Routine (ISR).

  • Stage 3: Output (The Transistor & Buzzer): The ISR sets PC5 High. This sends current through the 1kΩ resistor into the base of the 2N3904 transistor. The transistor acts as a high-speed switch, connecting the buzzer to Ground and completing the circuit to make it sound.

The transistor 2N3904 is critical in the circuit, because it decouples the electrical noise from the buzzer to the ground and saves the microcontroller from being damaged. Similarly, the 1k resistor connected between PC5 pin and base of the transistor is important. Without it the ATmega328p will try to push as much as it can through the base to emitter which is forward biased and this can damage the ATmega328P IC internal circuitry. Also, the output of the LM393 op-amp is open collector and therefore a 10k pullup resistor is used. 

Programming and Code

The following is the program code for the automated sound detection and triggering using the ATmega328P external interrupt feature.


#ifndef F_CPU
#define F_CPU 16000000UL // Set to 1000000UL if using internal 1MHz clock
#endif

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define BUZZER PC0
#define MIC_INPUT PD3

void init_system() {
    // Set PC5 as Output for Transistor Base
    DDRC |= (1 << BUZZER);
    
    // Set PD3 as Input (LM393 with physical 10k pull-up)
    DDRD &= ~(1 << MIC_INPUT);
    
    // Configure INT1 for Falling Edge (LM393 output goes Low on sound)
    EICRA |= (1 << ISC11);
    EICRA &= ~(1 << ISC10);

    // Enable INT1
    EIMSK |= (1 << INT1);

    sei(); // Global Interrupts Enabled
}

ISR(INT1_vect) {
    // Sound detected! 
    PORTC |= (1 << BUZZER);  // PC5 High -> Transistor ON -> Buzzer Beeps
    _delay_ms(300);          // Duration of beep
    PORTC &= ~(1 << BUZZER); // PC5 Low -> Transistor OFF -> Buzzer Quiet
}

int main(void) {
    init_system();
    while (1) {
        // Idle
    }
}

This code makes use of external interrupt and is thus a event-driven program. What it means is that instead of the CPU constantly checking the sensor, polling, it "sleeps" until the hardware tells it to act.

Here is what the code does:

1. Configuration & Setup (init_system)

  • F_CPU: Tells the compiler your clock speed (16MHz) so the _delay_ms functions are accurate.

  • DDRC & DDRD: Sets the Data Direction. PC0 (Buzzer) is set as an Output, and PD3 (Mic) is set as an Input.

  • EICRA (External Interrupt Control Register A): This is the "trigger" setting. By setting ISC11, you configure INT1 to trigger on a Falling Edge (when the LM393 output drops from 5V to 0V).

  • EIMSK & sei(): These "turn on the lights." EIMSK enables the specific INT1 interrupt, and sei() enables interrupts globally across the chip.

2. The Interrupt Service Routine (ISR)

ISR function a special function used for external interrupt that causes ATmega328P CPU to execute immediately when sound is detected, pausing whatever else it was doing.

  • PORTC |= (1 << BUZZER): Sends 5V to the transistor base to start the beep.

  • _delay_ms(300): Keeps the buzzer active for a short burst so it is audible to the human ear.

  • PORTC &= ~(1 << BUZZER): Turns the signal off, resetting the circuit for the next sound.

3. The Main Loop (main)

  • while(1): This loop is empty! Because the hardware handles the detection via interrupts, the main CPU doesn't have to do any work. This makes the code extremely power efficient.

Video Demonstration

The following video demonstrates how the above circuit works.



Related


Post a Comment

Previous Post Next Post