Wednesday, March 11, 2015

Fun Turret! (arduino project)


Hi! It's been a while, dear reader, and that is in part due to a very interesting project of bi-directional multi-variable communication between an arduino and a computer program called Processing. My setup will allow the user to customize the color of lighting with knobs that blend Red, Green, and Blue, while the computer shows a related color design; at the same time, the computer mouse will control brightness and blinking on the external lighs. So, ...  ahhhh... ...I'm still working on that.

Anyhow, ... Dashiell Corvin-Brittin and I have just finished a fun and exciting prototype project that we call Fun Turret. Because it shoots fun! Like a gun! Rhyming!

A portion of the Fun Turret project deals with an "H-Bridge" chip, we use it for telling a motor to rotate the turret in both directions. But a notable side-effect of motors is breaking things, so our project also deals with positioning and programming some sensors (in this case, switches) to tell our program when the motor should stop or change directions. Buttons allow the user initiate scanning action in either direction and to stop the scanning movement.

An infrared ("IR") sensor detects when an object is within a measured range. This sensor works between 10-80cm (4-31") – yes, I just listed Metric as the primary units, deal with it, it's the 21st century – and we decided that the turret should only pay attention to things within a couple feet. (feet. okay, so I 'm almost completely switched to Metric). Sensors alone aren't a tape measure, though, they only report a sort of percentage of their range, so we tested to calibrate the system; on a scale of 0-1023, farther to closer, we went with 200. Your mileage will vary.

When Fun Turret detects something in range while scanning, it stops and shines warm white light on the subject while flashing a red beam at it and causing a very small amount of sound [with something we thought might be a speaker]. Once the subject has some fun, chills out, and lays down, Fun Turret stops shooting fun and resumes scanning the area. Fun Turret's IR technology even works in the dark!

Photos:

left to right: arduino Uno R3, "breadboard" for quickly connecting wires and components (without having to solder), Fun Turret (with "limit" switches on either side), and a guy who really needs fun.


Dash and I experienced many emotions throughout this project: wonder, concentration, learning, elation, surprise, burns, traffic, and laying on the shop floor.

The IR sensor is the black box on the front here. Above it are the Fun Light (center) and the warm white spotlights on either side.

Video: http://youtu.be/VTgan53NM6w

Circuit Diagram:


Code:

//============================================================
//=======================VARIABLES============================
//============================================================
// constant variables (addresses)
const int leftButton = 2;
const int rightButton = 3;
const int stopButton = 4;  // this will be interrupt button/sensor
const int stopSwitch1 = 5;
const int stopSwitch2 = 6;
const int leftPin = 7;
const int rightPin = 8;
const int enablePin = 9;
const int operationLight = 10;
const int firingLight = 11;
const int firingSpotlight = 12;
const int firingSound = 13;
const int distanceSensor = A0; // Sharp "2Y0A21 F 92"
// dynamic variables
int leftButtonState = 111;
int rightButtonState = 111;
int stopButtonState = 111;
int stopSwitch1State = 111;
int stopSwitch2State = 111;
int spinDirection = 111;
int spinSpeed = 95;  // percentage speed
int distanceReading = 0;
int firingRange = 200;  // distanceReading to trigger firing
int firingRounds = 10;  // number of times to fire/flash
boolean printCycle = false;  // if things will serial print
int printDelay = 1000;  // amount of delay for serial print
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
int i = 0; //  for counting stuff


//============================================================
//=========================SETUP==============================
//============================================================
void setup() {
  Serial.begin(9600);
  // Input pins:
  pinMode(leftButton, INPUT_PULLUP);
  pinMode(rightButton, INPUT_PULLUP);
  pinMode(stopButton, INPUT_PULLUP);
  pinMode(distanceSensor, INPUT);
  pinMode(stopSwitch1, INPUT_PULLUP);
  pinMode(stopSwitch2, INPUT_PULLUP);
  // H-Bridge (motor) pins:
  pinMode(enablePin, OUTPUT);
  digitalWrite(enablePin, LOW);  // turn off just in case
  pinMode(leftPin, OUTPUT);
  digitalWrite(leftPin, LOW);  // turn off just in case
  pinMode(rightPin, OUTPUT);
  digitalWrite(rightPin, LOW);  // turn off just in case
  // Output pins:
  pinMode(operationLight, OUTPUT);
  pinMode(firingLight, OUTPUT);
  pinMode(firingSound, OUTPUT);
  spinSpeed = map (spinSpeed, 0, 100, 0, 255);
}  // close setup.


//============================================================
//=========================LOOP===============================
//============================================================
void loop() {
  readInputs();  // reads button and sensor inputs and writes to serial.
  safety();  // checks limit switches; if reached, changes direction.
  buttons();  // acts on the button pushes.
  movement();  // tells motor which what to do.
  fire();  // identifies target by distance, stops, and fires.
}  // close loop.


//============================================================
//=======================FUNCTIONS============================
//============================================================
//............................................................
//................readInputs function.........................
//............................................................
void readInputs() {
  printCycle = false;
  leftButtonState = digitalRead(leftButton);
  rightButtonState = digitalRead(rightButton);
  stopButtonState = digitalRead(stopButton);
  stopSwitch1State = digitalRead(stopSwitch1);
  stopSwitch2State = digitalRead(stopSwitch2);
  distanceReading = analogRead(distanceSensor);
  delay(2);  // pause for stability
  currentMillis = millis();
  if (currentMillis > (previousMillis + printDelay)) {
    printCycle = false;
    Serial.println("new cycle: ");
    Serial.print("leftButton = ");
    Serial.print(leftButtonState);
    Serial.print(", rightButton = ");
    Serial.print(rightButtonState);
    Serial.print(", stopButton = ");
    Serial.println(stopButtonState);
    Serial.print("stopSwitch1 = ");
    Serial.print(stopSwitch1State);
    Serial.print(", stopSwitch2 = ");
    Serial.println(stopSwitch2State);
    Serial.print("spinSpeed = ");
    Serial.print(spinSpeed);
    Serial.print(", distanceReading = ");
    Serial.println(distanceReading);
    Serial.println("");
    previousMillis = currentMillis;
  }  // close "if(currentMillis...)"
  else {
    printCycle = false;
  }  // close "else"
}  // close function "readInputs"


//............................................................
//....................safety function.........................
//............................................................
void safety() {
  if (stopSwitch1State == 0) {
    spinDirection = 1;
  }  // close "if(stopSwitch1...)"
  if (stopSwitch2State == 0) {
    spinDirection = 2;
  }  // close "if(stopSwitch2...)"
}  // close function "safety()"


//............................................................
//....................buttons function.......................
//............................................................
void buttons() {
  if ( leftButtonState == 0) {
    spinDirection = 1;
  } // close first "if"
  else {
    if (rightButtonState == 0) {
      spinDirection = 2;
    } // close second "if"
    else {
      if (stopButtonState == 0) {
        spinDirection = 0;
      } // close "if (stopButtonState)..."
    }  //close second "else"
  }  //close first "else"
} // close function "buttons"


//............................................................
//....................Movement function.......................
//............................................................
void movement() {
  if ( spinDirection == 1) {
    if (printCycle = true) {
      Serial.println(", ...going left");
    }  // close "if"
    analogWrite(enablePin, spinSpeed);
    digitalWrite(leftPin, 1);
    digitalWrite(rightPin, 0);
  } // close first "if"
  else {
    if (spinDirection == 2) {
      if (printCycle = true) {
        Serial.println(", ...going right");
      }  // close "if"
      analogWrite(enablePin, spinSpeed);
      digitalWrite(leftPin, 0);
      digitalWrite(rightPin, 1);
    } // close second "if"
    else {
      if (spinDirection == 0) {
        if (printCycle = true) {
          Serial.println(", ...stopping");
        }  // close "if"
        analogWrite(enablePin, 0);
        digitalWrite(leftPin, 0);
        digitalWrite(rightPin, 0);
      } // close "if (stopButtonState)..."
    }  //close second "else"
  }  //close first "else"
} // close function "Movement"


//............................................................
//....................fire function...........................
//............................................................
void fire() {
  if (distanceReading > firingRange) {  // is target in range?
    analogWrite(enablePin, 0);
    digitalWrite(leftPin, 0);
    digitalWrite(rightPin, 0);
//    i = 0;
//    for (int i = 0; i >= firingRounds; i++) {
      digitalWrite(operationLight, LOW);
      digitalWrite(firingLight, HIGH);
      digitalWrite(firingSpotlight, HIGH);
      digitalWrite(firingSound, HIGH);
      delay(20);
      digitalWrite(firingSound, LOW);
      delay(20);
      digitalWrite(firingSound, HIGH);
      delay(20);
      digitalWrite(firingSound, LOW);
      delay(20);
      digitalWrite(firingLight, LOW);
      digitalWrite(firingSound, HIGH);
      delay(20);
      digitalWrite(firingSound, LOW);
      delay(20);
      digitalWrite(firingSound, HIGH);
      delay(20);
      digitalWrite(firingSound, LOW);
      delay(20);
      digitalWrite(firingSpotlight, LOW);
      digitalWrite(operationLight, HIGH);
      Serial.print("FIRING!!!");
      Serial.print(" round ");
      Serial.print(i);
      Serial.print(" of ");
      Serial.println(firingRounds);
      delay(2);
//    }  // close "for..."
  }  // close "if(targetinrange...)"
  else {
    digitalWrite(operationLight, HIGH);
    digitalWrite(firingLight, LOW);
    digitalWrite(firingSpotlight, LOW);
    digitalWrite(firingSound, LOW);
  }  // close else
}  // close function "fire"

No comments:

Post a Comment