Saturday 2 January 2016

Back to Arduino Robots

I have been looking to make a very low cost robot car, you know the type that wanders about, but avoids walls and objects in its way.

As a basis I chose an Arduino Uno from dx.com. This kit can be used for experiments with its breadboard, but this won't be used for the robot. Then I added a mounting board from Amazon.

Next I added these parts:

- Small Motor Drive shield
- Two Motors and wheels

- A caster bearing for the front

- A set of IR detectors (3 of the 5 used)

- Double side sticky pads

Lastly I bought a battery holder for 5 AA cells - to give a supply of 7.5V. This powers the motors shield and the Arduino Uno via the Vin connection.

Altogether this is what is needed to make an obstacle detecting robot, the cost is about £30 + p&p. The Arduino Uno is fixed onto the mounting Platform. The motors and detectors are fixed to the bottom and top of the platform using the sticky pads. The detectors face forwards and left and right at the front of the platform.

The Motor drive shield is plugged in to the Arduino Uno and connected to the motors, the IR detectors are wired to 5V and GND and the inputs to pins 11, 12, 13 of the Arduino.

The code for the robot is below, it will need tuning for your robot, to get the speed right and the delays to getit to turn at the right angle. You can also change the wander direction change setting.:

// OliverRobot. Wanders about, reacts if detects obstacle
// IR detectors at L, F & R. Two motors M1 (L) & M2 (R)

// =====================================================
// IR detector inputs
#define LDET 11
#define FDET 12
#define RDET 13

// DRV8835 Dual Motor Driver shield
#define M1DIR 7
#define M1PWM 9
#define M2DIR 8
#define M2PWM 10

// directions
#define FWD 1
#define REV 2
#define LEFT 3
#define RIGHT 4


// time to next wander direction change
#define WTIME 1000

// wander times
unsigned long wt, prevwt;

// =====================================================
void setup() {
  pinMode(LDET, INPUT); // IR detectors
  pinMode(FDET, INPUT);
  pinMode(RDET, INPUT);
  pinMode(M1DIR, OUTPUT); // motor direction
  pinMode(M2DIR, OUTPUT);
}

// =====================================================
// d = dir, s = speed, t = time
void loop() {
  switch(event()) {
    
    case 1: // right a bit
      action(RIGHT, 50); // right (d, s)
      delay(200); // (t)
      break;
      
    case 2:  // left a bit
      action(LEFT, 50); // left (d, s)
      delay(200); // (t)
      break;
      
    case 3:  // forward slow
      action(FWD, 30); // fwd (d, s)
      break;
      
    case 4:  // stop, back a bit, random L or R
      action(FWD, 0); // stop (d, s)
      delay(500);
      action(REV, 20); // rev (d, s)
      delay(500);
      if(random(0,2)) {
        action(LEFT, 50); // left a bit (d, s)
        delay(200); // (t)
      }
      else {
        action(RIGHT, 50); // right a bit (d, s)
        delay(200); // (t)
      }
      break;
      
    case 5:  // right 90deg
        action(RIGHT, 50); // right (d, s)
        delay(400); // (t)
      break;
      
    case 6:  // left 90 deg (s, t)
        action(LEFT, 50); // left (d, s)
        delay(400); // (t)
      break;
      
    case 7:  // stuck, 180deg spin R on the spot
      action(RIGHT, 30); // right (d, s)
      delay(800); // (t)
      break;
      
    default: // wander forewards
      wander(50); // (s)
      break;
  }
  delay(50); // loop stablise ?needed?
}

// =====================================================
// Event map
// L   F   R
//     4
//  5  7  6
// 1   3   2

// get event, none = 0
byte event(){
  byte event;
  
  event = 0;
  if(digitalRead(LDET)) event += 1;
  if(digitalRead(FDET)) event += 4;
  if(digitalRead(RDET)) event += 2;

  return event;
}

// action dir d, speed s
void action(byte d, byte s) {
  switch(d) {
    
    case 1: // FWD
      digitalWrite(M1DIR, HIGH);
      digitalWrite(M2DIR, HIGH);
      break;
      
    case 2: // REV
      digitalWrite(M1DIR, LOW);
      digitalWrite(M2DIR, LOW);
      break;
      
    case 3: // LEFT
      digitalWrite(M1DIR, HIGH);
      digitalWrite(M2DIR, LOW);
      break;
      
    case 4: // RIGHT
      digitalWrite(M1DIR, LOW);
      digitalWrite(M2DIR, HIGH);
      break;
  }
  // speed
  analogWrite(M1DIR, s);
  analogWrite(M2DIR, s);
}

void wander(byte s) {
  action(FWD, 50);
  wt = millis();
  if(wt > prevwt + WTIME) {
    if(random(0, 2)) {
      action(LEFT, 50); // left (d, s)
      delay(200); // (t)
    }
    else {
      action(RIGHT, 50);
      delay(200);
    }
  }
  prevwt = wt;
}

No comments: