0
0
Power-electronicsProgramBeginner · 2 min read

Embedded C Program for Bluetooth Controlled LED

Use an Embedded C program that initializes UART for Bluetooth communication and toggles an LED connected to a GPIO pin based on received Bluetooth commands like '1' to turn ON and '0' to turn OFF the LED.
📋

Examples

InputBluetooth sends '1'
OutputLED turns ON
InputBluetooth sends '0'
OutputLED turns OFF
InputBluetooth sends 'x'
OutputLED state unchanged
🧠

How to Think About It

To control an LED via Bluetooth, first set up UART communication to receive data from the Bluetooth module. Then, read the incoming data continuously. If the data is '1', turn the LED ON by setting the GPIO pin high; if '0', turn it OFF by setting the pin low. Ignore other inputs.
📐

Algorithm

1
Initialize UART for Bluetooth communication.
2
Configure the GPIO pin connected to the LED as output.
3
Continuously read data from UART.
4
If received data is '1', set LED pin HIGH to turn ON LED.
5
If received data is '0', set LED pin LOW to turn OFF LED.
6
Ignore any other data.
💻

Code

embedded_c
#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;
}
Output
LED turns ON when '1' received and OFF when '0' received via Bluetooth UART
🔍

Dry Run

Let's trace receiving '1' and '0' commands through the code.

1

Initialize UART and LED pin

UART set for 9600 baud, LED pin PB0 set as output.

2

Receive '1' via UART

ISR triggered, data = '1', LED pin PB0 set HIGH, LED turns ON.

3

Receive '0' via UART

ISR triggered, data = '0', LED pin PB0 cleared LOW, LED turns OFF.

StepReceived DataLED Pin StateLED State
2'1'HIGHON
3'0'LOWOFF
💡

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

Polling UART instead of Interrupt
embedded_c
#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;
}
Polling is simpler but wastes CPU time waiting for data, unlike interrupts which are more efficient.
Using a Bluetooth module with AT commands
embedded_c
// 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.
More complex but allows advanced Bluetooth features like pairing and device naming.

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.

ApproachTimeSpaceBest For
Interrupt-driven UARTO(1)O(1)Efficient real-time control
Polling UARTO(1)O(1)Simple but CPU-blocking
AT Command BluetoothO(1)O(1)Advanced Bluetooth features
💡
Use UART interrupts to handle Bluetooth data efficiently without blocking your main program.
⚠️
Beginners often forget to configure the GPIO pin as output or enable UART RX interrupt, causing the LED not to respond.