FAQ | This is a LIVE service | Changelog

Skip to content
Snippets Groups Projects
main.ino 11.2 KiB
Newer Older
#include <Adafruit_MotorShield.h>
Anchit Jain's avatar
Anchit Jain committed
#include <Servo.h>
uint8_t regions[1] = {FORWARD};
uint8_t regions_opposite[1] = {BACKWARD}; 
ayush1301's avatar
ayush1301 committed
int button_val = 0;
int button_port = 0;
bool stuck = false;
ayush1301's avatar
ayush1301 committed
int amber_LED = 4;
int blink_counter = 0;
Anchit Jain's avatar
Anchit Jain committed
unsigned long t = 0;
unsigned long prev_millis = 0;
ayush1301's avatar
ayush1301 committed
int GREEN_LED = 5;
ayush1301's avatar
ayush1301 committed
int RED_LED = 6;

//Motors
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *motors[] = {AFMS.getMotor(3), AFMS.getMotor(4)};
#define left 1 //index value in motor pointer array
#define right 0
ayush1301's avatar
ayush1301 committed
#define white 1
#define black 0
#define IR_floating_avg_num 3
ayush1301's avatar
ayush1301 committed
int IR_threshold[num_IR] = {300, 300, 1024, 1024};
float IR_avgs[num_IR] = {0}; //LRFB
int IR_colours[num_IR] = {0};
int IR_locns[num_IR] = {A0, A3, A1, A2};
float IR_vals[num_IR][IR_floating_avg_num] = {0}; //check
int IR_float_counter[num_IR] = {0};
int cur_status = 0;
long cur_loop_count = 0;
Anchit Jain's avatar
Anchit Jain committed
//US
#define echoPin 2
#define trigPin 3
Anchit Jain's avatar
Anchit Jain committed
#define US_float_avg_num 1
Anchit Jain's avatar
Anchit Jain committed
float duration;
float new_US_distance;
Anchit Jain's avatar
Anchit Jain committed
int US_index = 0;
float US_distance_vals[US_float_avg_num] = {0};
Anchit Jain's avatar
Anchit Jain committed
float US_distance_avg = 0;
Anchit Jain's avatar
Anchit Jain committed

//Metal Detector
ayush1301's avatar
ayush1301 committed
int metal_detector = 12;
ayush1301's avatar
ayush1301 committed
int metal_float_counter = 0;
ayush1301's avatar
ayush1301 committed
#define metal_floating_avg_num 1
ayush1301's avatar
ayush1301 committed
float metal_avg = 0;
float metal_vals[metal_floating_avg_num] = {0};
ayush1301's avatar
ayush1301 committed
bool is_metal = false;
//int is_metal = 0;
//#define metal_lower_bound 30.0
//#define metal_upper_bound 34.0
//#define non_metal_lower_bound 36.0
//#define non_metal_upper_bound 40.0
float metal_threshold = 9.65;
ayush1301's avatar
ayush1301 committed
float min_val = 100;
ayush1301's avatar
ayush1301 committed

Anchit Jain's avatar
Anchit Jain committed
//Servo
#define servo_position 180
Anchit Jain's avatar
Anchit Jain committed
Servo servoright;
Servo servoleft;
Anchit Jain's avatar
Anchit Jain committed

Anchit Jain's avatar
Anchit Jain committed
//Ramp
int ramp_detect_threshold = 500; //Up, Down
int ramp_detect_counter = 0;
bool ramp_on = false;
ayush1301's avatar
ayush1301 committed
int left_right_velocity = 255;
Anchit Jain's avatar
Anchit Jain committed

ayush1301's avatar
ayush1301 committed
//Turning around
ayush1301's avatar
ayush1301 committed
int turn_around_time = 2800;
long turn_around_time_start;
long turn_around_time_end;
ayush1301's avatar
ayush1301 committed

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  if (!AFMS.begin()) {         // create with the default frequency 1.6KHz
  // if (!AFMS.begin(1000)) {  // OR with a different frequency, say 1KHz
    Serial.println("Could not find Motor Shield. Check wiring.");
    while (1);
  }
  for(int j=0; j<2; j++) {
    motors[j]->run(RELEASE);
  }
ayush1301's avatar
ayush1301 committed
  for(int i=0; i< num_IR; i++) {
    pinMode(IR_locns[i], INPUT);
  }
ayush1301's avatar
ayush1301 committed
  pinMode(button_port, INPUT);
Anchit Jain's avatar
Anchit Jain committed
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
ayush1301's avatar
ayush1301 committed
  pinMode(amber_LED, OUTPUT);
ayush1301's avatar
ayush1301 committed
  pinMode(GREEN_LED, OUTPUT);
  digitalWrite(GREEN_LED, LOW);
ayush1301's avatar
ayush1301 committed
  pinMode(RED_LED, OUTPUT);
  digitalWrite(RED_LED, LOW);
ayush1301's avatar
ayush1301 committed
  servoright.attach(10);
  servoleft.attach(9);
ayush1301's avatar
ayush1301 committed
  servoright.write(120);
  servoleft.write(60);
}

void loop() {
  // put your main code here, to run repeatedly:
  for(int i=0; i < 2*IR_floating_avg_num; i++) { //Get some values in before evaluation starts
    update_IR_vals();
  }
  for(int j = 0; j<2; j++) {
    motors[j]->run(regions[0]);
  //servo.write(servo_position);
Anchit Jain's avatar
Anchit Jain committed
  if (region == 0 || region == 2) {
    Serial.print("We are in region ");
    Serial.println(region);
ayush1301's avatar
ayush1301 committed
    prev_millis = millis();
Anchit Jain's avatar
Anchit Jain committed
    while (true) {
      int return_code = basic_region(700, false);
      if (return_code) {
        continue;
      }
Anchit Jain's avatar
Anchit Jain committed
      //Update region 
ayush1301's avatar
ayush1301 committed
      t = millis() - prev_millis;
ayush1301's avatar
ayush1301 committed
      /*
Anchit Jain's avatar
Anchit Jain committed
      if (t > 15000) {
        ramp_on = true;
      }
ayush1301's avatar
ayush1301 committed
      */
Anchit Jain's avatar
Anchit Jain committed
      if (not ramp_on) {
        continue;
      }
      ramp_detect_counter += 1;
ayush1301's avatar
ayush1301 committed
      if (ramp_detect_counter % 4000 == 0) {
Anchit Jain's avatar
Anchit Jain committed
        Serial.println("US");
        float US = update_region(ramp_detect_threshold);
        if (US) {
          break;
        }
      }
Anchit Jain's avatar
Anchit Jain committed
  }
ayush1301's avatar
ayush1301 committed
  else if (region == 1 || region == 3 || region == 4) { //Junction detect region
Anchit Jain's avatar
Anchit Jain committed
    Serial.print("We are in region ");
    Serial.println(region);
    while (true) {
      int return_code = basic_region(700, true);
      if (return_code == 1) {
        Serial.println("THIS SHOULD NOT HAPPEN");
        continue;
      }
      else if (return_code == 2) {
        //region += 1;
        Serial.println("IT WORKED");
        break;
      }
ayush1301's avatar
ayush1301 committed

    if (region == 1) {
      //Move Servo
      bring_down_servos(65);
ayush1301's avatar
ayush1301 committed
      for(int i = 0; i< 1000; i++) {
        update_metal_detector();
ayush1301's avatar
ayush1301 committed
      }
ayush1301's avatar
ayush1301 committed
      long curTime = millis();
      while ((millis() - curTime) < 2500) {
        update_metal_detector();
        if (metal_avg < min_val) {
          min_val = metal_avg;
          Serial.println(min_val);
        }
      }
      if (min_val <= metal_threshold) {
        is_metal = true;
ayush1301's avatar
ayush1301 committed
        digitalWrite(RED_LED, HIGH);
        Serial.println("METAL DETECTED");
      }
      else {
        digitalWrite(GREEN_LED, HIGH);
        Serial.println("NOT DETECTED");
      }

ayush1301's avatar
ayush1301 committed
      turn_around(turn_around_time, 255, right);
ayush1301's avatar
ayush1301 committed
    }
ayush1301's avatar
ayush1301 committed
    else if (region == 3) {
      Serial.println("REGION 3 bois");
ayush1301's avatar
ayush1301 committed
      if (is_metal) {
        turn_around(turn_around_time/2, 255, right);
      }
      else {
        turn_around(turn_around_time/2, 255, left);
      }
      bring_down_servos(110);
      if (is_metal) {
        turn_around(turn_around_time/2, 255, left);
      }
      else {
        turn_around(turn_around_time/2, 255, right);
      }
      region += 1;
ayush1301's avatar
ayush1301 committed
      
      //TO move of the junction
      move_both(motors, 200);
      delay(200);
ayush1301's avatar
ayush1301 committed
      move_both(motors, 0);
ayush1301's avatar
ayush1301 committed
      
ayush1301's avatar
ayush1301 committed
    }
    //region 4
    else {
      move_both(motors, 255);
      delay(800);
ayush1301's avatar
ayush1301 committed
      move_both(motors, 0);
ayush1301's avatar
ayush1301 committed
      while(1);
ayush1301's avatar
ayush1301 committed
    }
Anchit Jain's avatar
Anchit Jain committed
  }
}

bool recovery() {
  if (stuck) {
    Serial.println("RECOVERY CODE");
    move_both(motors, 255);
    ramp_on = true;
ayush1301's avatar
ayush1301 committed
    left_right_velocity = 255;
Anchit Jain's avatar
Anchit Jain committed
    ramp_detect_counter = 0;
    return true;
  }
  return false;
}
Anchit Jain's avatar
Anchit Jain committed
int basic_region(int clock_cycle, bool junction) {
  blink_amber(clock_cycle);
  check_push_button(motors);
  update_IR_vals();
  int IR_check_val = IR_check(IR_colours);
  check_if_in_loop(IR_check_val);
  bool rec = recovery();
  if (rec) {
    return 1;
  }
  bool repeat = check_if_repeat_IR(IR_check_val);
  int line_sense_return_code = line_sensing(motors, IR_check_val, repeat, left_right_velocity, junction);
  if (line_sense_return_code) {
    return 2;
  }
  return 0;
}
Anchit Jain's avatar
Anchit Jain committed
void blink_amber(int clock_cycle) {
  blink_counter += 1;
  if (blink_counter % clock_cycle == 0) {
    blink_counter = 0;
    int curVal = digitalRead(amber_LED);
    digitalWrite(amber_LED, !curVal);
Anchit Jain's avatar
Anchit Jain committed
int update_region(int ramp_detect_threshold) {
  float dist = check_ultrasonic_distance();
  if (dist > ramp_detect_threshold) {
    ramp_detect_counter = 0;
    ramp_on = false;
    region += 1;
    left_right_velocity = 200;
    return 1;
  }
  else {
    return 0;
  }
}

int line_sensing(Adafruit_DCMotor *motors[], int IR_check_val, bool repeat, int velocity, bool junction) {
  if (IR_check_val == 0) {
    move_both(motors, 255);
    Serial.println("FORWARD");
  }
  else if (IR_check_val == 1) {
Anchit Jain's avatar
Anchit Jain committed
    move_one_motor(motors, velocity, left);
    Serial.println("TURN LEFT");
  }
  else if (IR_check_val == 2) {
Anchit Jain's avatar
Anchit Jain committed
    move_one_motor(motors, velocity, right);
    Serial.println("TURN RIGHT");
  }
  else if (IR_check_val == 3) {
    Serial.println("Junction");
Anchit Jain's avatar
Anchit Jain committed
    if (junction) {
      Serial.println("STOP JUNCTIONNNNNNNN");
ayush1301's avatar
ayush1301 committed
      move_both(motors, 0);
ayush1301's avatar
ayush1301 committed
      return 1;
Anchit Jain's avatar
Anchit Jain committed
    }
    else {
      move_both(motors, 150);
    }
  }
  else if (IR_check_val == 4) {
    Serial.println("Ramp off");
  }
  else if (IR_check_val == 5) {
    Serial.println("Ramp on");
  }
  else {
    move_both(motors, 150);
    Serial.println("Else block fml");
Anchit Jain's avatar
Anchit Jain committed
  return 0;
ayush1301's avatar
ayush1301 committed
void move_one_motor(Adafruit_DCMotor *motors[], int velocity, int side) { //May need to account for direction later
  motors[(side+1)%2]->setSpeed(velocity);
  motors[side]->setSpeed(0);
}
void move_both(Adafruit_DCMotor *motors[], int velocity) {
  for(int j=0; j<2; j++) {
    motors[j]->setSpeed(velocity);
  }
}

void rotate(Adafruit_DCMotor *motors[], int velocity, int side) { //May need to account for direction later
  //If you want to turn right, the left motor moves forward but the right motor moves in the other direction
  motors[side]->run(regions_opposite[0]);
  motors[(side+1)%2]->run(regions[0]);
  move_both(motors, velocity);
}

float floating_average(int *index, float vals[], float curAvg, float newVal, int arr_len) {
  curAvg = ((curAvg * float(arr_len)) - vals[*index] + newVal)/float(arr_len);
  vals[*index] = newVal;
  *index = (*index + 1) % arr_len;
  return curAvg;
}

int IR_check(int LRFB[]) {
  if (LRFB[0] == black && LRFB[1] == black && LRFB[2] == white && LRFB[3] == white) {
    return 0;
  }
  else if (LRFB[0] == white && LRFB[1] == black) {
    return 1;
  }
  else if (LRFB[0] == black && LRFB[1] == white) {
    return 2;
  }
  else if (LRFB[0] == white && LRFB[1] == white && LRFB[2] == white && LRFB[3] == white) {
  else if (LRFB[0] == black && LRFB[1] == black && LRFB[2] == white && LRFB[3] == black) {
    return 4;
  }
  else if (LRFB[0] == black && LRFB[1] == black && LRFB[2] == black && LRFB[3] == white) {
    return 5;
  }
  else {
    return 6;
  }
}

void update_IR_vals() {
  for(int i=0; i<num_IR; i++) {
    int new_val = analogRead(IR_locns[i]);
    IR_avgs[i] = floating_average(&IR_float_counter[i], IR_vals[i], IR_avgs[i], new_val, IR_floating_avg_num);
    if (IR_avgs[i] > IR_threshold[i]) {
      IR_colours[i] = black;
    }
    else {
      IR_colours[i] = white;
    }
  }
}
Anchit Jain's avatar
Anchit Jain committed
int update_metal_detector() {
  unsigned long new_val = pulseIn(metal_detector, HIGH);
Anchit Jain's avatar
Anchit Jain committed
  float new_val_Hz = 1000.0/float(new_val);
ayush1301's avatar
ayush1301 committed
  metal_avg = floating_average(&metal_float_counter, metal_vals, metal_avg, new_val_Hz, metal_floating_avg_num);
void check_push_button(Adafruit_DCMotor *motors[]) {
  button_val = digitalRead(button_port);
Anchit Jain's avatar
Anchit Jain committed
  if (button_val == 0) {
    Serial.println("Button pushed. Exiting");
    for(int j = 0; j < 2; j++) {
      motors[j]->run(RELEASE);
    }
    while (1);
  }
}
bool check_if_repeat_IR(int IR_check_val) {
  bool is_repeat_IR = false;
  if (IR_check_val == cur_status) {
    is_repeat_IR = true;
  }
  else {
    cur_status = IR_check_val;
  }
  return is_repeat_IR;
}

void check_if_in_loop(int IR_check_val) {
  if (IR_check_val != 0 && cur_status == IR_check_val) { //Remember to change value after binary
    cur_loop_count += 1;
      stuck = true;
      stuck = false;
    stuck = false;
    cur_loop_count = 0;
  }
Anchit Jain's avatar
Anchit Jain committed

float check_ultrasonic_distance(void){
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);
  new_US_distance = duration * 0.034 / 2;
  US_distance_avg = floating_average(&US_index, US_distance_vals, US_distance_avg, new_US_distance, US_float_avg_num);
Anchit Jain's avatar
Anchit Jain committed
  Serial.println(US_distance_avg);
Anchit Jain's avatar
Anchit Jain committed
  return US_distance_avg;
}
ayush1301's avatar
ayush1301 committed
int turn_around(int turn_around_time, int turn_around_velocity, int side){
ayush1301's avatar
ayush1301 committed
  turn_around_time_start = millis();
ayush1301's avatar
ayush1301 committed
  rotate(motors, turn_around_velocity, side);
ayush1301's avatar
ayush1301 committed
  while(true){
    turn_around_time_end = millis();
    if (turn_around_time_end > turn_around_time_start + turn_around_time){
      move_both(motors, 0);
      motors[0]->run(regions[0]);
      motors[1]->run(regions[0]);
      return 0;
    }
  }
}
Anchit Jain's avatar
Anchit Jain committed

void bring_down_servos(int angle){
  servoright.write(angle);
  servoleft.write(180 - angle);
}

void bring_up_servos(void){
  servoright.write(90);
  servoleft.write(90);
}