Embedded C Program for Obstacle Avoidance Robot
digitalRead() or ADC and controls motors with digitalWrite() to move forward or turn when an obstacle is detected, as shown in if(sensor_detects_obstacle) { stop_motors(); turn_robot(); } else { move_forward(); }.Examples
How to Think About It
Algorithm
Code
#include <avr/io.h> #include <util/delay.h> #define SENSOR_PIN (PIND & (1 << PIND2)) // Example sensor input pin #define MOTOR_PORT PORTB #define MOTOR_DDR DDRB #define MOTOR_FORWARD (1 << PB0) #define MOTOR_TURN (1 << PB1) void move_forward() { MOTOR_PORT |= MOTOR_FORWARD; MOTOR_PORT &= ~MOTOR_TURN; } void turn_right() { MOTOR_PORT &= ~MOTOR_FORWARD; MOTOR_PORT |= MOTOR_TURN; } void stop_motors() { MOTOR_PORT &= ~(MOTOR_FORWARD | MOTOR_TURN); } int main(void) { MOTOR_DDR |= MOTOR_FORWARD | MOTOR_TURN; // Set motor pins as output DDRD &= ~(1 << PIND2); // Set sensor pin as input while(1) { if (SENSOR_PIN == 0) { // Obstacle detected (active low) stop_motors(); _delay_ms(200); turn_right(); _delay_ms(500); } else { move_forward(); } } return 0; }
Dry Run
Let's trace the robot behavior when an obstacle is detected and when no obstacle is present.
Check sensor input
SENSOR_PIN reads 1 (no obstacle) or 0 (obstacle)
Decision making
If SENSOR_PIN == 0, stop motors and turn right; else move forward
Motor control
Set MOTOR_PORT bits to control motor direction
| Sensor Input | Action | Motor_PORT State |
|---|---|---|
| 1 (no obstacle) | Move forward | MOTOR_FORWARD bit set, MOTOR_TURN bit cleared |
| 0 (obstacle) | Stop and turn right | MOTOR_FORWARD bit cleared, MOTOR_TURN bit set after delay |
Why This Works
Step 1: Sensor Reading
The program reads the sensor pin using PIND & (1 << PIND2) to detect obstacles.
Step 2: Motor Control
Motor pins are controlled by setting or clearing bits in PORTB to move forward or turn.
Step 3: Decision Loop
The main loop continuously checks sensors and decides to move forward or turn to avoid obstacles.
Alternative Approaches
#include <avr/io.h> #include <util/delay.h> void ADC_init() { ADMUX = (1 << REFS0); // AVcc reference ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1); } uint16_t ADC_read(uint8_t channel) { ADMUX = (ADMUX & 0xF0) | (channel & 0x0F); ADCSRA |= (1 << ADSC); while (ADCSRA & (1 << ADSC)); return ADC; } int main(void) { ADC_init(); // Motor init code here while(1) { uint16_t distance = ADC_read(0); // Read sensor if (distance < 300) { // Threshold // Stop and turn } else { // Move forward } } return 0; }
#include <avr/io.h> #include <avr/interrupt.h> volatile int obstacle_detected = 0; ISR(INT0_vect) { obstacle_detected = 1; } int main(void) { // Setup interrupt on sensor pin sei(); while(1) { if (obstacle_detected) { // Stop and turn obstacle_detected = 0; } else { // Move forward } } return 0; }
Complexity: O(1) time, O(1) space
Time Complexity
The program runs in a continuous loop with simple conditional checks, so time complexity per iteration is constant O(1).
Space Complexity
Uses fixed memory for variables and hardware registers, so space complexity is O(1).
Which Approach is Fastest?
Direct sensor polling is simple and fast for small robots; interrupt-based methods add responsiveness but more code complexity.
| Approach | Time | Space | Best For |
|---|---|---|---|
| Direct Sensor Polling | O(1) | O(1) | Simple robots, easy to implement |
| ADC Analog Sensor | O(1) | O(1) | Precise distance measurement |
| Interrupt-based Detection | O(1) | O(1) | Fast response to obstacles |