Sunday, February 24, 2013

ProtoCylon: It's ALIVE

ProtoCylon: It’s ALIVE

 

By Bobby Neal Winters
I wasn’t exactly in a laboratory over a cadaver coaxing the lightning to come it; I didn’t exactly have a hunchback named Igor by my side; but I do have some idea of the elation Dr. Frankenstein may have felt in those first few moments.
It he hadn’t been a fictional character, that is.
Along the way in this adventure, I continually referred to the simple-sounding model that organizes my thought so well: Input, Processing, and Output.  The processing consists of writing computer programs and that scares a lot of people, but throughout my adventure--for that is what is has been, an adventure--the Input and Output have been the most difficult. And of those two, Input has been by far the harder.
In Muscles on the Beast, I had put my robot body together and it would roll, but only with a preprogrammed script.  It had null input; it simply had processing and output.  At that time, I was debating whether to have it process input from ultrasonic sensors or to make it into a line following robot.
I decided to do the easiest; big surprise there.  I made into a bat.  It receives input from ultrasonic sensors.  The heuristic for this robot is for it to go straight ahead until it runs into a wall and then to turn until it gets free.  It tries turning one direction three times and if it is still caught it will try the other.  It will continue in this way until it is either free or its batteries run out.
#include
#define FULL_SPEED 256
#define TRAPPED_DIST 10

// motor pins
int speed1=3;
int speed2=11;
int direction1=12;
int direction2=13;

//distance Sensor pins
const int pingPin =4;
int inPin=2;

//variables concerning distance
int myDist;
boolean trapped;

void setup(){
setMotorPins();
setSensorPins();
}

void loop(){

 //How far is the next obstacle?
 myDist=getDistance();
 //If it is too close, I am trapped
 trapped=(myDist
 switch(trapped){
    case true:
     //If I am trapped, begin the struggle
     getFree();
    case false:
     //If I am not trapped, then quarter speed ahead
     goStraight(0.25,0.5);
     break;
 }

}

void setMotorPins(){

 pinMode(speed1,OUTPUT);
 pinMode(speed2,OUTPUT);  
 pinMode(direction1,OUTPUT);  
 pinMode(direction2,OUTPUT);
 return;
}

void setSensorPins(){
  pinMode(pingPin,OUTPUT);
  return;
}

long getDistance(){
 long duration, cm;

 digitalWrite(pingPin,LOW);
 delayMicroseconds(2);
 digitalWrite(pingPin,HIGH);
 delayMicroseconds(5);
 digitalWrite(pingPin,LOW);  
 pinMode(inPin, INPUT);
 //How long does it take for my pings to get back.
 duration=pulseIn(inPin,HIGH);
 //How far is the next obstacle?
 cm=microsecondsToCentimeters(duration);
 return cm;
}  

void goStraight(float prop, float seconds){
 //prop is the proportion of full speed
 int rate=prop*FULL_SPEED;
 //Convert to microseconds
 int duration=1000*seconds;
 //Use both wheels  
 digitalWrite(direction1,HIGH);
 digitalWrite(direction2,HIGH);
 analogWrite(speed1,rate);  
 analogWrite(speed2,rate);  
 //Run awhile before we do anything else.
 delay(duration);
 return;
}

void goTurn(int dir, float seconds){
 //We will only turn at half speed
 float prop=0.5;
 int rate=prop*FULL_SPEED;
 //How long will we turn?
 int duration=1000*seconds;
 //Switch between the various directions.
 switch(dir){
    case 1:
     digitalWrite(direction1,HIGH);
     digitalWrite(direction2,LOW);
     analogWrite(speed1,rate);  
     analogWrite(speed2,0);     
    break;
    case 2:
     digitalWrite(direction1,LOW);
     digitalWrite(direction2,HIGH);
     analogWrite(speed1,0);  
     analogWrite(speed2,rate);
    break;
    default:
    return;
 }  
 delay(duration);  
 return;
}

void stopMotor(int seconds){
 analogWrite(speed1,0);
 analogWrite(speed2,0);  
 delay(1000*seconds);
 return;
}

long microsecondsToCentimeters(long microseconds)
{
return microseconds / 29 / 2;
}

void getFree(){
 //First try one direction
 int sense=0;
 int count=0;
 //Struggle until no longer trapped.
 while(trapped){
    ++count;
    goTurn(sense+1,1);
    if(count>3){
      count=0;
      //Struggle in one direction three times and then try the other.
      ++sense;
      sense=sense % 2;
    }
    myDist=getDistance();
    trapped=(myDist < TRAPPED_DIST);
 }
 return;
  
}

No comments: