Source Code

"To control servos with the tiny microcontroller on the Trinket, we'll need a Servo library. The default Arduino Servo library is really only good for Uno/Leonardo/Due and similar beefy processors that can drive servos 'standalone'. Sadly, the Attiny85 can't quite do that as it does not have 16bit timers."

If you haven't installed the Adafruit Software Servo Library yet, read through this guide and install the library.

Good to go?

The following sketch uses the Parallax Ping))) Distance Sensor and is a starting point; ultra-bare bones. And this, is where all the fun begins!

#include <Adafruit_SoftServo.h>

#define SERVO1PIN 0   // Servo control line (orange) on Trinket Pin #0
#define SERVO2PIN 1   // Servo control line (orange) on Trinket Pin #1

Adafruit_SoftServo servo_left, servo_rght;

// Connect the sonar signal pin to this pin on the Trinket.
const int sonar = 2;

// Moderate speed forward for both servos. Given the orientation of the servos
// one will be going forward, and the other backward. You may need to adjust 
// these slightly to get the rover to move straight forward.
const int left_speed = 75;
const int rght_speed = 90;

// Number in cm when the rover will reverse and try to navigate around.
const int obstacle = 8;

// Multiplier used to determine how far the rover will back-up.
const int back_track = 100;

// Duration of a ping, distance in inches, distance converted to cm.
long duration, inches, cm;

void setup() 
  // Attach servos... and off we go!

void loop() 
  // Setting servos in forward motion.
  servo_left.write(left_speed - cm);
  servo_rght.write(rght_speed + cm);

  // establish variables for duration of the ping, and the distance 
  // result in inches and centimeters.
  duration = 0;
  inches = 0;
  cm = 0;

  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(sonar, OUTPUT);
  digitalWrite(sonar, LOW);
  digitalWrite(sonar, HIGH);
  digitalWrite(sonar, LOW);

  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(sonar, INPUT);
  duration = pulseIn(sonar, HIGH);

  // convert the time into a distance.
  inches = microsecondsToInches(duration);
  cm = microsecondsToCentimeters(duration);  

  // Long distances will cause the servos to misbehave... cap at 50 cm.
  if ( cm > 50 ) {
    cm = 50;

  if ( cm < obstacle ) {
    // back_track * delay(15) = distance the rover will back-up during 
    // obstacle avoidance.
    for (int i = 0; i < back_track; i++) {
      // Magic numbers... will always backup the same direction. Can you 
      // think of a better way to navigate obstacles?

long microsecondsToInches(long microseconds)
  // According to Parallax's datasheet for the PING))), there are
  // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
  // second).  This gives the distance travelled by the ping, outbound
  // and return, so we divide by 2 to get the distance of the obstacle.
  // See:
  return microseconds / 74 / 2;

long microsecondsToCentimeters(long microseconds)
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the
  // object we take half of the distance travelled.
  return microseconds / 29 / 2;
Last updated on 2015-05-04 at 04.26.49 PM Published on 2014-01-02 at 01.32.18 PM