FAQ | This is a LIVE service | Changelog

Skip to content
Snippets Groups Projects
main.ino 7.17 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}; 
int region = 0;
ayush1301's avatar
ayush1301 committed
int button_val = 0;
int button_port = 0;
bool stuck = false;

//Motors
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *motors[] = {AFMS.getMotor(3), AFMS.getMotor(4)};
ayush1301's avatar
ayush1301 committed
#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
int IR_threshold[num_IR] = {400, 300, 500, 300};
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
#define US_float_avg_num 5
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};
float US_distance_avg;

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

Anchit Jain's avatar
Anchit Jain 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);
  //servo.attach(9);
}

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
  
    check_push_button(motors);

    update_IR_vals();
    int IR_check_val = IR_check(IR_colours);
    
    //New code for stuck in a loop
    check_if_in_loop(IR_check_val);
    if (stuck) {
      Serial.println("RECOVERY CODE");
      move_both(motors, 255);
      continue;
    }
    bool repeat = check_if_repeat_IR(IR_check_val);

    line_sensing(motors, IR_check_val, repeat);
int line_sensing(Adafruit_DCMotor *motors[], int IR_check_val, bool repeat) {
  if (repeat) {
    return 0;
  }
  
  if (IR_check_val == 0) {
    move_both(motors, 255);
    Serial.println("FORWARD");
  }
  else if (IR_check_val == 1) {
    move_one_motor(motors, 200, left);
    Serial.println("TURN LEFT");
  }
  else if (IR_check_val == 2) {
    move_one_motor(motors, 200, right);
    Serial.println("TURN RIGHT");
  }
  else if (IR_check_val == 3) {
    Serial.println("Junction");
  }
  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");
    /*
    for(int j = 0; j < 2; j++) {
      motors[j]->setSpeed(0);
    */
    /*
    for(int j = 0; j < num_IR; j++) {
      Serial.print(IR_avgs[j]);
      Serial.print(" -> ");
    */
    //Serial.println();
    //while (1);
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;
    }
  }
}

void check_push_button(Adafruit_DCMotor *motors[]) {
  button_val = digitalRead(button_port);
  if (button_val == 1) {
    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);
  return US_distance_avg;
}

int turn_around(int velocity, int side){
  // will be called when block collection junction is detected
  // velocity and side variables control speed and sense of rotation
  // returns 0 if it successfully turns around (i.e. detects junction again.
  // Else returns 0 if it continues turning too long without detecting junction
  int turn_around_count = 0; //measures time spent turning
  rotate(motors, velocity, side); // starts turning both motors to facilitate turning around
  delay(10); //small delay to avoid detecting the junction again in the start
  while(true){
    turn_around_count += 1;
ayush1301's avatar
ayush1301 committed
    update_IR_vals();
    int junction_status = IR_check(IR_colours);
ayush1301's avatar
ayush1301 committed
    if (junction_status == 3){
      Serial.println("Junction detected, turn around completed successfully");
      move_both(motors, 0);
ayush1301's avatar
ayush1301 committed
      for(int j=0; j<2; j++) {
        motors[j]->run(regions[0]);
      }
      return 0;   
    }
    if (turn_around_count > 5000){
      Serial.println("Loop Completed, Junction Not Detected");
      return 1;
    }
  }
}