TURL-X FINAL COMMAND

Let’s get TURL-X to move around on it’s own, looking for obstacles and avoiding them when detected.

The HC-SR04 Ultrasonic Sensor sends out a cone of sound that covers only about 15 degrees from it’s centre. It is not enough to avoid all obstacles so we will get the head to scan, moving left to right, thereby increasing the scan area.

MISSION:

TURL-X will move forward, moving its head left and right.
When an obstacle is detected 30cm or less it turns until nothing closer than 40cm is detected, while flashing it’s LED warning.
  1. Once again remember to copy the code to your IDE
  2. Upload the code to TURL-X
  3. Unplug USB and place it on the floor
  4. Turn on it’s power and watch it go!
➕➕
filename.cpp
// Obstacle Avoiding TURL-X with Scanning Sensor
// Servo on pin 3 sweeps the HC-SR04 left and right
// HC-SR04: Trig = 13, Echo = 12
// LED on pin 2 flashes when it sees something close

#include <Servo.h>          // This library lets us control the servo easily

Servo ultraServo;           // Give the servo a name

// Pin names (easy to change later)
#define MOTOR1_IN1  9       // Right motor pin 1
#define MOTOR1_IN2 10       // Right motor pin 2
#define MOTOR2_IN1  5       // Left motor pin 1
#define MOTOR2_IN2  6       // Left motor pin 2

#define TRIG_PIN   13
#define ECHO_PIN   12
#define SERVO_PIN   3
#define LED_PIN     2

void setup() {
  // Tell Arduino these pins send signals out
  pinMode(MOTOR1_IN1, OUTPUT);
  pinMode(MOTOR1_IN2, OUTPUT);
  pinMode(MOTOR2_IN1, OUTPUT);
  pinMode(MOTOR2_IN2, OUTPUT);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);

  ultraServo.attach(SERVO_PIN);   // Plug the servo into pin 3
  ultraServo.write(90);           // Start looking straight ahead

  // Make sure motors are stopped at the beginning
  digitalWrite(MOTOR1_IN1, LOW);
  digitalWrite(MOTOR1_IN2, LOW);
  digitalWrite(MOTOR2_IN1, LOW);
  digitalWrite(MOTOR2_IN2, LOW);

  delay(1000);   // Wait 1 second so you can see it’s ready
}

void loop() {
  // === 1. Go forward ===
  digitalWrite(MOTOR1_IN1, HIGH);   // Right motor forward
  digitalWrite(MOTOR1_IN2, LOW);
  digitalWrite(MOTOR2_IN1, HIGH);   // Left motor forward
  digitalWrite(MOTOR2_IN2, LOW);

  // === 2. Sweep the sensor slowly left to right ===
  for(int angle = 60; angle <= 120; angle += 4) {
    ultraServo.write(angle);        // Move servo a little bit
    delay(20);                      // Wait so the move looks slow and smooth

    // Measure distance right now
    digitalWrite(TRIG_PIN, LOW);
    delayMicroseconds(5);
    digitalWrite(TRIG_PIN, HIGH);
    delayMicroseconds(10);
    digitalWrite(TRIG_PIN, LOW);
    long duration = pulseIn(ECHO_PIN, HIGH);
    int distance = duration / 58;

    // If something is closer than 30 cm → obstacle!
    if(distance > 0 && distance <= 30) {
      avoidObstacle();
    }
  }

  // === 3. Sweep the sensor slowly right to left ===
  for(int angle = 120; angle >= 60; angle -= 4) {
    ultraServo.write(angle);
    delay(20);

    // Measure distance again
    digitalWrite(TRIG_PIN, LOW);
    delayMicroseconds(5);
    digitalWrite(TRIG_PIN, HIGH);
    delayMicroseconds(10);
    digitalWrite(TRIG_PIN, LOW);
    long duration = pulseIn(ECHO_PIN, HIGH);
    int distance = duration / 58;

    if(distance > 0 && distance <= 30) {
      avoidObstacle();
    }
  }
}

// ─────────────────────────────────────────────
// This is a helper block called a “function”
// You call it by writing avoidObstacle();
// It does everything needed when the robot sees something close
// ─────────────────────────────────────────────
void avoidObstacle() {
  // Stop moving forward
  digitalWrite(MOTOR1_IN1, LOW);
  digitalWrite(MOTOR1_IN2, LOW);
  digitalWrite(MOTOR2_IN1, LOW);
  digitalWrite(MOTOR2_IN2, LOW);

  // Keep turning right until the path ahead is clear (>40 cm)
  bool pathIsClear = false;
  while(!pathIsClear) {
    
    // Spin right (turn in place)
    digitalWrite(MOTOR1_IN1, LOW);    // Right motor backward
    digitalWrite(MOTOR1_IN2, HIGH);
    digitalWrite(MOTOR2_IN1, HIGH);   // Left motor forward
    digitalWrite(MOTOR2_IN2, LOW);

    // Look straight ahead while turning
    ultraServo.write(90);
    delay(30);

    // Measure distance straight ahead
    digitalWrite(TRIG_PIN, LOW);
    delayMicroseconds(5);
    digitalWrite(TRIG_PIN, HIGH);
    delayMicroseconds(10);
    digitalWrite(TRIG_PIN, LOW);
    long duration = pulseIn(ECHO_PIN, HIGH);
    int distance = duration / 58;

    // If nothing is closer than 40 cm → path is clear!
    if(distance > 40 || distance == 0) {
      pathIsClear = true;
    }

    // Flash the LED (200 ms on, 200 ms off)
    digitalWrite(LED_PIN, HIGH);
    delay(200);
    digitalWrite(LED_PIN, LOW);
    delay(200);
  }

  // Stop turning when path is clear
  digitalWrite(MOTOR1_IN1, LOW);
  digitalWrite(MOTOR1_IN2, LOW);
  digitalWrite(MOTOR2_IN1, LOW);
  digitalWrite(MOTOR2_IN2, LOW);

  delay(300);   // Small pause before going forward again
}
You should recognise most of what we have in the code.
I did however make use of Functions, Variables (we only learnt about int) like Bool and if statements. Don’t panic! It’s good to be exposed to it now.
We will cover all of this in our next project.

I know you have learnt a lot but more importantly I hope you had fun!

Go back to the lessons and concepts you may have struggled with; often you have to do things many times before you fully understand something.

UNTIL THE NEXT ROBOT