Embedded C Program for Bluetooth Controlled LED
'1' to turn ON and '0' to turn OFF the LED.Examples
How to Think About It
Algorithm
Code
#include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define LED_PIN PB0 void UART_init(unsigned int ubrr) { UBRR0H = (unsigned char)(ubrr>>8); UBRR0L = (unsigned char)ubrr; UCSR0B = (1<<RXEN0) | (1<<RXCIE0); // Enable RX and RX interrupt UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); // 8-bit data sei(); // Enable global interrupts } void LED_init() { DDRB |= (1 << LED_PIN); // Set LED pin as output } ISR(USART_RX_vect) { char data = UDR0; // Read received data if (data == '1') { PORTB |= (1 << LED_PIN); // Turn LED ON } else if (data == '0') { PORTB &= ~(1 << LED_PIN); // Turn LED OFF } } int main(void) { LED_init(); UART_init(103); // 9600 baud rate for 16MHz clock while(1) { // Main loop does nothing, LED controlled in ISR } return 0; }
Dry Run
Let's trace receiving '1' and '0' commands through the code.
Initialize UART and LED pin
UART set for 9600 baud, LED pin PB0 set as output.
Receive '1' via UART
ISR triggered, data = '1', LED pin PB0 set HIGH, LED turns ON.
Receive '0' via UART
ISR triggered, data = '0', LED pin PB0 cleared LOW, LED turns OFF.
| Step | Received Data | LED Pin State | LED State |
|---|---|---|---|
| 2 | '1' | HIGH | ON |
| 3 | '0' | LOW | OFF |
Why This Works
Step 1: UART Initialization
The UART is set up to receive data from the Bluetooth module at 9600 baud, enabling RX and RX interrupt to handle incoming data asynchronously.
Step 2: LED Pin Setup
The GPIO pin connected to the LED is configured as an output so it can be turned ON or OFF by setting the pin HIGH or LOW.
Step 3: Interrupt Service Routine
When data arrives via UART, the ISR reads it and checks if it is '1' or '0' to turn the LED ON or OFF immediately without blocking the main program.
Alternative Approaches
#include <avr/io.h> #define LED_PIN PB0 void UART_init(unsigned int ubrr) { UBRR0H = (unsigned char)(ubrr>>8); UBRR0L = (unsigned char)ubrr; UCSR0B = (1<<RXEN0); // Enable RX UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); // 8-bit data } char UART_receive() { while (!(UCSR0A & (1<<RXC0))) {} return UDR0; } void LED_init() { DDRB |= (1 << LED_PIN); } int main(void) { LED_init(); UART_init(103); while(1) { char data = UART_receive(); if (data == '1') PORTB |= (1 << LED_PIN); else if (data == '0') PORTB &= ~(1 << LED_PIN); } return 0; }
// This approach sends AT commands to configure Bluetooth module and then controls LED similarly. // Code depends on module and is more complex, involves command mode and data mode switching.
Complexity: O(1) time, O(1) space
Time Complexity
The program reacts instantly to UART data via interrupts, so no loops dominate runtime; response is constant time.
Space Complexity
Uses fixed memory for UART registers and one GPIO pin; no dynamic memory allocation.
Which Approach is Fastest?
Interrupt-driven UART is faster and more efficient than polling, as it frees CPU for other tasks.
| Approach | Time | Space | Best For |
|---|---|---|---|
| Interrupt-driven UART | O(1) | O(1) | Efficient real-time control |
| Polling UART | O(1) | O(1) | Simple but CPU-blocking |
| AT Command Bluetooth | O(1) | O(1) | Advanced Bluetooth features |