Arduino Mega 2560 Obstacle-Avoiding Robot with Sound Detection and Servo Control
View and Edit Project In Cirkit Designer
Circuit Documentation
Summary
This circuit is designed to control multiple servos using an Arduino Mega 2560 and an Adafruit PCA9685 PWM Servo Breakout. It also includes an ultrasonic sensor (HC-SR05) for distance measurement and a sound sensor (KY 038) for detecting claps. The system performs rhythmic movements with the servos based on sound detection and distance measurement.
Component List
Arduino Mega 2560
- Description: A microcontroller board based on the ATmega2560.
- Pins: IOREF, RESET, 3V3, 5V, GND, VIN, A0-A15, D0-D53, AREF, SDA, SCL
HC-SR05
- Description: An ultrasonic sensor used for distance measurement.
- Pins: VCC, TRIG, GND, ECHO, OUT
Micro servo 9G
- Description: A small servo motor used for precise control of angular position.
- Pins: GND, +5V, PWM
KY 038
- Description: A sound sensor module used for detecting sound levels.
- Pins: +, G, A0, D0
Adafruit PCA9685 PWM Servo Breakout
- Description: A 16-channel PWM driver used to control servos.
- Pins: 5.0V, GND, PWRIN, PWM0-PWM15, VCC, SDA, SCL, OE
5V Battery
- Description: A power source providing 5V.
- Pins: +, -
Wiring Details
Arduino Mega 2560
- A0: Connected to KY 038 (A0)
- GND: Connected to KY 038 (G), HC-SR05 (GND), Adafruit PCA9685 PWM Servo Breakout (GND), 5V Battery (-)
- 5V: Connected to KY 038 (+), HC-SR05 (VCC), Adafruit PCA9685 PWM Servo Breakout (VCC)
- D3 PWM: Connected to HC-SR05 (TRIG)
- D2 PWM: Connected to HC-SR05 (ECHO)
- D4 PWM: Connected to HC-SR05 (OUT)
- D21/SCL: Connected to Adafruit PCA9685 PWM Servo Breakout (SCL)
- D20/SDA: Connected to Adafruit PCA9685 PWM Servo Breakout (SDA)
HC-SR05
- VCC: Connected to Arduino Mega 2560 (5V)
- TRIG: Connected to Arduino Mega 2560 (D3 PWM)
- GND: Connected to Arduino Mega 2560 (GND)
- ECHO: Connected to Arduino Mega 2560 (D2 PWM)
- OUT: Connected to Arduino Mega 2560 (D4 PWM)
Micro servo 9G
- GND: Connected to Adafruit PCA9685 PWM Servo Breakout (GND)
- +5V: Connected to Adafruit PCA9685 PWM Servo Breakout (5.0V)
- PWM: Connected to Adafruit PCA9685 PWM Servo Breakout (PWM0, PWM1, PWM2, PWM3)
KY 038
- +: Connected to Arduino Mega 2560 (5V)
- G: Connected to Arduino Mega 2560 (GND)
- A0: Connected to Arduino Mega 2560 (A0)
Adafruit PCA9685 PWM Servo Breakout
- 5.0V: Connected to 5V Battery (+)
- GND: Connected to Arduino Mega 2560 (GND), 5V Battery (-), Micro servo 9G (GND)
- PWRIN: Connected to 5V Battery (-)
- VCC: Connected to Arduino Mega 2560 (5V)
- SDA: Connected to Arduino Mega 2560 (D20/SDA)
- SCL: Connected to Arduino Mega 2560 (D21/SCL)
- PWM0: Connected to Micro servo 9G (PWM)
- PWM1: Connected to Micro servo 9G (PWM)
- PWM2: Connected to Micro servo 9G (PWM)
- PWM3: Connected to Micro servo 9G (PWM)
5V Battery
- +: Connected to Adafruit PCA9685 PWM Servo Breakout (5.0V)
- -: Connected to Arduino Mega 2560 (GND), Adafruit PCA9685 PWM Servo Breakout (GND)
Code Documentation
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
// Create the PCA9685 object
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// PCA9685 configuration constants
#define SERVO_MIN 150 // Minimum pulse length count (adjust as per servo specifications)
#define SERVO_MAX 600 // Maximum pulse length count (adjust as per servo specifications)
// Servo channel assignments
const int servo1XChannel = 0; // PCA9685 channel for Servo 1X
const int servo1YChannel = 1; // PCA9685 channel for Servo 1Y
const int servo2XChannel = 2; // PCA9685 channel for Servo 2X
const int servo2YChannel = 3; // PCA9685 channel for Servo 2Y
// Pin Definitions for Ultrasonic Sensor
const int trigPin = 3; // Trig pin for ultrasonic sensor
const int echoPin = 2; // Echo pin for ultrasonic sensor
// Sound Sensor Pin and Threshold
const int soundSensorPin = A0; // Analog pin for sound sensor
const int clapThreshold = 500; // Threshold for sound detection
// Debounce Variables for Sound Detection
const unsigned long soundDebounceTime = 1000; // Debounce period in ms
unsigned long lastSoundTime = 0; // Timestamp of the last detected sound
// Distance Threshold
const int distanceThreshold = 30; // Distance in cm to detect obstacle
// Rhythm State Variables
bool obstacleDetected = false; // Flag to indicate obstacle detection
bool rhythmActive = false; // Flag to indicate rhythm execution
unsigned long rhythmStartTime = 0; // Start time for rhythm execution
const unsigned long rhythmDuration = 10000; // Duration for rhythm (10 seconds)
int rhythmCounter = 0; // Counter to track which rhythm to perform
void setup() {
// Start I2C communication
Wire.begin();
// Initialize PCA9685
pwm.begin();
pwm.setPWMFreq(60); // Set frequency to 60Hz for servos
// Initialize Ultrasonic Sensor
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.begin(9600); // Start serial communication
}
void loop() {
if (!rhythmActive) {
long distance = measureDistance(trigPin, echoPin); // Measure distance
int soundValue = analogRead(soundSensorPin); // Read sound sensor value
// Check for valid sound detection and debounce
if (soundValue > clapThreshold && millis() - lastSoundTime > soundDebounceTime) {
lastSoundTime = millis(); // Update sound detection time
Serial.println("Sound detected!");
if (distance < distanceThreshold && !obstacleDetected) {
obstacleDetected = true; // Mark obstacle as detected
rhythmActive = true; // Activate rhythm mode
rhythmStartTime = millis(); // Store rhythm start time
rhythmCounter = (rhythmCounter + 1) % 5; // Cycle through rhythms
Serial.print("Obstacle Detected. Starting Rhythm ");
Serial.println(rhythmCounter + 1);
}
}
} else {
performRhythm(rhythmCounter); // Perform the current rhythm
// Deactivate rhythm after its duration
if (millis() - rhythmStartTime > rhythmDuration) {
rhythmActive = false;
obstacleDetected = false;
Serial.println("Rhythm complete. Waiting for next activation...");
}
}
delay(100);
}
// Function to measure distance using the ultrasonic sensor
long measureDistance(int trigPin, int echoPin) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
long distance = duration * 0.034 / 2; // Convert to cm
return distance;
}
// Function to execute rhythmic servo movement
void performRhythm(int rhythm) {
switch (rhythm) {
case 0: // Simple Alternating
setServoPositions(45, 135, 135, 45);
delay(500);
setServoPositions(135, 45, 45, 135);
break;
case 1: // Simultaneous Sweep
for (int angle = 0; angle <= 180; angle += 15) {
setServoPositions(angle, 180 - angle, angle, 180 - angle);