Project 3 – Organisms

In this NMD 200 project, we were placed into teams and given the instructions to create something that emulates an organism. The definition of an organism is something that reacts to the environment in some manner.

In my group of three others, we were going to create a robot that would boldly go forward, until it met either a never ending expanse (drop off) or meets an obstacle. At which point it would back up, and turn. We met with some challenges along the way, but in the end, we created a product that was capable of motion, and reaction.

My contributions for this project included: 3d Modeling, 3D printing, coding, laser cutting, and troubleshooting.

The final product can be seen here as a 3D scan. From the previous link, you can rotate and view the contraption from all sides. Simply click the 3D view below the image to do this. I apologize for the poor quality of the scan. This link will show you a 3D scan of what it looks like below the top

The following stream of images captures portions of the project.

 

The beginning sketches of the design.

Project 3 Proposal (pdf)

I created a holder for our ultrasonic sensor. 3D molded in Rhino3D. Printed on M3D printer. Assembled using assorted nuts/bolts/washers that I keep for just such things. Unfortunately, the dimensions I used from an online spec sheet was for a different manufacture, so the holes were of the wrong size for mounting. The holder did well despite. Below is a video of the testing of the ultrasonic sensor. When the sensor senses something within its range, the Arduino board sets a white light to flash. You can also see the feedback of the sensor, allowing us to see the range it has measured.

The below images show the full assembly coming together.

Circuit Diagram (Autodesk website)

When the unit was finally fully assembled, we could test the drive system’s reaction to sensory input. This time, the code changes the speed and direction of the motors based on the distances detected by the ultrasonic sensor. The closer an object got, the slower the machine became. Once the object was below a certain threshold, the unit will reverse and begin the turning sequence.

 

We met with a larger issue upon testing. The unit was too heavy, and the motors were unable to overcome inertia. We started out by buying larger motors, but found that even they were barely able to propel the vehicle. That was when we started to use gears and developed our own gearing system to amplify the force of the motor. This worked very well, and proved the power of gears.

 

The remainder of this post is a copy of the code that went into the Arduino. The coding is very simple, and I consider it to be open source. If you are not intersted in coding mumbo jumbo, then you can pass on this part.

//NMD 200 Univeristy of Maine
//Group Memembers: Jason Dignan, Jacob Houghman, Andrea Jean, Sam Woodward
//Square Dancin robotic hot rod
//Code Author: Jason Dignan



////////////////////////////////////////////////////////////////////////////////////////// VARIABLES //////////////////////////////
//////////////////////////////PIN DESIGNATIONS
int backLights = 3; //backuplights
int ledArray[] = {0, 1, 2}; //LED outputs for emoting out
int mLeft[] = {4,5}; //Motor Activation. Index 0 is forward, Index 1 is reverse
int mRight[] = {9,8};
int msLeft = 6; //Motor speed. Analog write controls speed of the motor
int msRight = 10;
int sRangeTrig = 13; //Ultrasonic Range Sensor Trigger pin
int sRangeEcho = 12; //Ultrasonic Range Sensor Echo pin
int sLaserPower = 7;
int sLaserOn = 11;
int Speaker = A0;

//////////////////////////////VARIABLES
int currtime = 0; //Stores the current time from millis()
int inches = 0; //Stores distances of things found via sonar
int ledLast =0;
int ledInterval = 200;
int ledCurrent = 0;


//////////////////////////////BOOLEAN STATES

bool Backup = false; //Indicates if the thing is backing up
bool Crazy = false; //Indicates if the thing is going crazy
bool Dance = false; //Indicates if the things is dancing
bool Debug = false; //If true, will activate serial and spit out data


////////////////////////////////////////////////////////////////////////////////////////// SETUP //////////////////////////////
void setup() 
{
 if(Debug)
 Serial.begin(9600); 
 
 for(int i = 0; i < 3; i++) //Set LED pins to output
 {
 pinMode(ledArray[i], OUTPUT);
 if(i<2)
 {
 pinMode(mLeft[i], OUTPUT);
 pinMode(mRight[i], OUTPUT);
 }
 }
 pinMode(msLeft, OUTPUT);
 pinMode(msRight, OUTPUT);
 pinMode(sLaserPower, OUTPUT);
 pinMode(sLaserOn, OUTPUT);
 pinMode(backLights, OUTPUT);
 pinMode(sRangeTrig, OUTPUT);
 pinMode(sRangeEcho, INPUT); //Set the range sensor to input (this is changed later) ((My Range sensor is different then the one used here, will edit final code to reflect this))
 pinMode(Speaker, OUTPUT);
}

////////////////////////////////////////////////////////////////////////////////////////// Loop //////////////////////////////
void loop() 
{
 //lazer(true);
 currtime = currtime + 1; //Finds current Time
 inches = ranger(); //Finds current distance in inches
 motorvator(); //Engages motors.
 if(Backup)
 {
 backupFunc();
 crazyFunc();
 }
 else
 goingForward();

 
 if(Debug)
 {
 Serial.print("In. ");
 Serial.println(inches);
 Serial.print("Ti. ");
 Serial.println(currtime);

 } 
}

////////////////////////////////////////////////////////////////////////////////////////// Motor Control //////////////////////////////
//The motorvator is general purpose transmission. It scales the motor speeds and directions based on distances found
//by the range sensor.
void motorvator()
{
 float motorspeed = map(inches, 2, 50, -100, 255); //Scales the motor's speed with the distance system
 if(Debug) //Debugging output
 {
 Serial.print("MoSp ");
 Serial.println(motorspeed);
 }
 if(motorspeed < 0) //If the motor's speed is less then zero, then it switches which pins are active
 { // Using analog write, we can engage the motors to a certain speed
 Backup= true; //If the unit is backing up, then we set this to true. Will influence other subroutines. 
 analogWrite(msLeft, abs(motorspeed)); //Using abs() as the motor speed can't be negative
 analogWrite(msRight, abs(motorspeed)/2);
 digitalWrite(mLeft[1], HIGH); //This part is what activates and deactivates the enable pins on the motor control chip
 digitalWrite(mRight[1], HIGH);
 digitalWrite(mLeft[0], LOW);
 digitalWrite(mRight[0], LOW);
 }
 else //Similar as to above, but in this case it is if the motor's speed is going forward. 
 {
 Backup= false;
 analogWrite(msLeft, motorspeed);
 analogWrite(msRight, motorspeed);
 digitalWrite(mLeft[0], HIGH);
 digitalWrite(mRight[0], HIGH);
 digitalWrite(mLeft[1], LOW);
 digitalWrite(mRight[1], LOW);
 
 }
}


////////////////////////////////////////////////////////////////////////////////////////// Range Finder Function//////////////////////////////
//The ranger() is used to return, in inches, the distances of objects it detects. 
int ranger()
{
 
 digitalWrite(sRangeTrig, LOW);
 delayMicroseconds(2);
 digitalWrite(sRangeTrig, HIGH);
 delayMicroseconds(10);
 digitalWrite(sRangeTrig, LOW);
 pinMode(sRangeEcho, INPUT);
 return pulseIn(sRangeEcho, HIGH) /74/2; //Converts range finder data to inches
}
 

////////////////////////////////////////////////////////////////////////////////////////// Backup Function //////////////////////////////
void backupFunc()
{
 if(currtime %20 == 0)
 {
 digitalWrite(backLights, HIGH);
 if(currtime %2 == 0)
 tone(Speaker, 700, 4);
 }
 
 
 else
 {
 digitalWrite(backLights, LOW);
 //noTone(Speaker);
 }

}

////////////////////////////////////////////////////////////////////////////////////////// FORWARD Function //////////////////////////////
void goingForward()
{
 if((currtime - ledLast) > ledInterval)
 {
 ledLast = currtime;
 digitalWrite(ledArray[ledCurrent], HIGH);
 for(int i = 0; i < 3; i++)
 {
 if(i != ledCurrent)
 digitalWrite(ledArray[i], LOW);
 }
 if(ledCurrent > 3)
 ledCurrent = 0;
 else
 ledCurrent++;
 }
 
}

////////////////////////////////////////////////////////////////////////////////////////// Crazy Function //////////////////////////////
void crazyFunc()
{

 if(currtime % 1 == 0)
 {
 digitalWrite(ledArray[0], HIGH);
 digitalWrite(ledArray[1], LOW);
 }

 if(currtime % 2 == 0)
 {
 digitalWrite(ledArray[1], HIGH);
 digitalWrite(ledArray[2], LOW);
 }
 if(currtime % 3 == 0)
 {

 digitalWrite(ledArray[0], LOW);
 digitalWrite(ledArray[2], HIGH);
 }
 
}

////////////////////////////////////////////////////////////////////////////////////////// LazerControl //////////////////////////////
void lazer( bool in)
{
 if(in)
 {
 digitalWrite(sLaserOn, HIGH);
 digitalWrite(sLaserPower, HIGH);
 }
 else
 {
 digitalWrite(sLaserOn, LOW);
 digitalWrite(sLaserPower, LOW);
 }
}

Leave a Reply

Your email address will not be published. Required fields are marked *