// https://forum.arduino.cc/t/i-am-building-an-arduino-rc-car-with-2-ultra-sonic-sensors-hc-sr04/1214989/33

int RenaPin = 13;
int Rin1Pin = 22;
int Rin2Pin = 24;
int Rin3Pin = 26;
int Rin4Pin = 28;
int RenbPin = 12;

int FenaPin = 11;
int Fin1Pin = 30;
int Fin2Pin = 32;
int Fin3Pin = 34;
int Fin4Pin = 36;
int FenbPin = 10;

char command;

//Initializing all variables

//Variables where distances measured are stored.
int distFront;
int distLeft;
int distRight;
int distBack;
//Minimum distance of 20cm from any obstacle.
int distLimit = 20;

//HCSR04 Variables
int trig = 6;
int trig2 = 2;
int echo =  7;
int echo2 = 3;
unsigned long pulsetime = 0;

//Calculate Battery Level1. Arduino
const float maxBattery1 = 8.0;
int perVolt1;                 // Percentage variable
float voltage1 = 0.0;         // Read battery voltage
int level1;
//Calculate Battery Level2. Motor
const float maxBattery2 = 6.0;
int perVolt2;                 // Percentage variable
float voltage2 = 0.0;         // Read battery voltage
int level2;

long previousMillis = -1000 * 10;
long interval = 1000 * 10;
unsigned long currentMillis;

// --------------------------------------------------------------------------- Setup
void setup() {
  Serial.begin(9600);
  pinMode(trig, OUTPUT);
  pinMode(trig2, OUTPUT);
  pinMode(echo, INPUT);
  pinMode(echo2, INPUT);

  // Setup motors

  pinMode(RenaPin, OUTPUT);
  pinMode(Rin1Pin, OUTPUT);
  pinMode(Rin2Pin, OUTPUT);
  pinMode(Rin3Pin, OUTPUT);
  pinMode(Rin4Pin, OUTPUT);
  pinMode(RenbPin, OUTPUT);

  pinMode(FenaPin, OUTPUT);
  pinMode(Fin1Pin, OUTPUT);
  pinMode(Fin2Pin, OUTPUT);
  pinMode(Fin3Pin, OUTPUT);
  pinMode(Fin4Pin, OUTPUT);
  pinMode(FenbPin, OUTPUT);

}

void loop() {
  if (Serial.available() > 0) {
    command = Serial.read();
    motor_stop();   //initialize with motors stopped
    //Change pin mode only if new command is different from previous.
    switch (command) {
      case 'F':
        //Checks for obstacle since forward command is received.
        distFront = readDistanceF();
        if (distFront < distLimit)
        {
          //Override the controller since obstacle is detected.
          override();
          distFront = readDistanceF();
          Serial.print("A");
          Serial.print(";");
          Serial.print(distFront); //send distance to MIT App
          Serial.print(";");
          Serial.print(0, DEC); //2nd value...dummy variable
          Serial.println(";");
        }
        else
        {
          //No obstacle----> move forward.
          drive_forward();
        }
        break;
      case 'B':
        distBack = readDistanceB();
        if (distBack < distLimit)
        {
          motor_stop();
          delay(500);
          drive_forward();
          delay(300);
          motor_stop();
          distBack = readDistanceB();
          Serial.print("R");
          Serial.print(";");
          Serial.print(distBack); //send distance to MIT App
          Serial.print(";");
          Serial.print(0, DEC); //2nd value...dummy variable
          Serial.println(";");
        }
        else
          drive_backward();
        break;
      case 'L':
        turn_left();
        break;
      case 'R':
        turn_right();
        break;
      case 'O' :
        drive_open();
        break;
      case 'C'  :
        drive_close();
        break;

      case 'T':     //reads distance
        {
          distFront = readDistanceF();
          Serial.print("A");
          Serial.print(";");
          Serial.print(distFront); //send distance to MIT App
          Serial.print(";");
          Serial.print(0, DEC); //2nd value...dummy variable
          Serial.println(";");
        }
        break;
    }
    //Read battery voltage every 10sec.
    currentMillis = millis();
    if (currentMillis - (previousMillis) > (interval)) {
      previousMillis = currentMillis;
      voltage1 = (analogRead(A4) * 5.0 / 1024.0) * 2.0;
      perVolt1 = (voltage1 * 100) / maxBattery1;
      if      (perVolt1 <= 75)                {
        level1 = 0;
      }
      else if (perVolt1 > 75 && perVolt1 <= 80) {
        level1 = 1;
      }
      else if (perVolt1 > 80 && perVolt1 <= 85) {
        level1 = 2;
      }
      else if (perVolt1 > 85 && perVolt1 <= 90) {
        level1 = 3;
      }
      else if (perVolt1 > 90 && perVolt1 <= 95) {
        level1 = 4;
      }
      else if (perVolt1 > 95)                 {
        level1 = 5;
      }

      voltage2 = (analogRead(A6) * 5.0 / 1024.0) * 2.0; // 6.0V
      perVolt2 = (voltage2 * 100) / maxBattery2;
      if      (perVolt2 <= 75)                {
        level2 = 0;
      }
      else if (perVolt2 > 75 && perVolt2 <= 80) {
        level2 = 1;
      }
      else if (perVolt2 > 80 && perVolt2 <= 85) {
        level2 = 2;
      }
      else if (perVolt2 > 85 && perVolt2 <= 90) {
        level2 = 3;
      }
      else if (perVolt2 > 90 && perVolt2 <= 95) {
        level2 = 4;
      }
      else if (perVolt2 > 95)                 {
        level2 = 5;
      }

      Serial.print("B");
      Serial.print(";");
      Serial.print(level1);
      Serial.print(";");
      Serial.print(level2);
      Serial.println(";");
    }
  }//serial avail ends here..

  //Checks for obstacle since forward command is received.
  distFront = readDistanceF();
  if (distFront < distLimit)
  {
    //Override the controller since obstacle is detected.
    override();
    distFront = readDistanceF();
    Serial.print("A");
    Serial.print(";");
    Serial.print(distFront); //send distance to MIT App
    Serial.print(";");
    Serial.print(0, DEC); //2nd value...dummy variable
    Serial.println(";");
  }
  //check backwards..
  distBack = readDistanceB();
  if (distBack < distLimit)
  {
    motor_stop();
    delay(500);
    drive_forward();
    delay(300);
    motor_stop();
    distBack = readDistanceB();
    Serial.print("R");
    Serial.print(";");
    Serial.print(distBack); //send distance to MIT App
    Serial.print(";");
    Serial.print(0, DEC); //2nd value...dummy variable
    Serial.println(";");
  }




}

// --------------------------------------------------------------------------- Drive

void motor_stop()
{
  analogWrite(FenaPin, 0);
  analogWrite(FenbPin, 0);
  analogWrite(RenaPin, 0);
  analogWrite(RenbPin, 0);
  digitalWrite(Rin1Pin, LOW);
  digitalWrite(Rin2Pin, LOW);
  digitalWrite(Rin3Pin, LOW);
  digitalWrite(Rin4Pin, LOW);

  digitalWrite(Fin1Pin, LOW);
  digitalWrite(Fin2Pin, LOW);
  digitalWrite(Fin3Pin, LOW);
  digitalWrite(Fin4Pin, LOW);
  delay(25);
}

void drive_forward()
{
  analogWrite(FenaPin, 255);
  analogWrite(FenbPin, 255);
  analogWrite(RenaPin, 255);
  analogWrite(RenbPin, 255);
  digitalWrite(Rin1Pin, HIGH);
  digitalWrite(Rin2Pin, LOW);
  digitalWrite(Rin3Pin, LOW);
  digitalWrite(Rin4Pin, HIGH);

  digitalWrite(Fin1Pin, HIGH);
  digitalWrite(Fin2Pin, LOW);
  digitalWrite(Fin3Pin, LOW);
  digitalWrite(Fin4Pin, HIGH);

}

void drive_backward()
{
  analogWrite(FenaPin, 255);
  analogWrite(FenbPin, 255);
  analogWrite(RenaPin, 255);
  analogWrite(RenbPin, 255);
  digitalWrite(Rin1Pin, LOW);
  digitalWrite(Rin2Pin, HIGH);
  digitalWrite(Rin3Pin, HIGH);
  digitalWrite(Rin4Pin, LOW);

  digitalWrite(Fin1Pin, LOW);
  digitalWrite(Fin2Pin, HIGH);
  digitalWrite(Fin3Pin, HIGH);
  digitalWrite(Fin4Pin, LOW);

}

void turn_left()
{
  analogWrite(FenaPin, 180);
  analogWrite(FenbPin, 180);
  analogWrite(RenaPin, 120);
  analogWrite(RenbPin, 120);
  digitalWrite(Rin1Pin, LOW);
  digitalWrite(Rin2Pin, HIGH);
  digitalWrite(Rin3Pin, LOW);
  digitalWrite(Rin4Pin, HIGH);

  digitalWrite(Fin1Pin, LOW);
  digitalWrite(Fin2Pin, HIGH);
  digitalWrite(Fin3Pin, LOW);
  digitalWrite(Fin4Pin, HIGH);

}

void turn_right()
{
  analogWrite(FenaPin, 180);
  analogWrite(FenbPin, 180);
  analogWrite(RenaPin, 120);
  analogWrite(RenbPin, 120);
  digitalWrite(Rin1Pin, HIGH);
  digitalWrite(Rin2Pin, LOW);
  digitalWrite(Rin3Pin, HIGH);
  digitalWrite(Rin4Pin, LOW);

  digitalWrite(Fin1Pin, HIGH);
  digitalWrite(Fin2Pin, LOW);
  digitalWrite(Fin3Pin, HIGH);
  digitalWrite(Fin4Pin, LOW);
}
void drive_open()
{
  analogWrite(FenaPin, 255);
  analogWrite(FenbPin, 255);
  analogWrite(RenaPin, 255);
  analogWrite(RenbPin, 255);
  digitalWrite(Rin1Pin, LOW);
  digitalWrite(Rin2Pin, HIGH);
  digitalWrite(Rin3Pin, HIGH);
  digitalWrite(Rin4Pin, LOW);

  digitalWrite(Fin1Pin, HIGH);
  digitalWrite(Fin2Pin, LOW);
  digitalWrite(Fin3Pin, LOW);
  digitalWrite(Fin4Pin, HIGH);
}
void drive_close()
{
  analogWrite(FenaPin, 255);
  analogWrite(FenbPin, 255);
  analogWrite(RenaPin, 255);
  analogWrite(RenbPin, 255);
  digitalWrite(Rin1Pin, HIGH);
  digitalWrite(Rin2Pin, LOW);
  digitalWrite(Rin3Pin, LOW);
  digitalWrite(Rin4Pin, HIGH);

  digitalWrite(Fin1Pin, LOW);
  digitalWrite(Fin2Pin, HIGH);
  digitalWrite(Fin3Pin, HIGH);
  digitalWrite(Fin4Pin, LOW);
}


//Returns distance value from ultrasonic sensor
int readDistanceF()
{
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  pulsetime = pulseIn(echo, HIGH);
  return pulsetime / 58.2; //magic
}
int readDistanceB()
{
  digitalWrite(trig2, LOW);
  delayMicroseconds(2);
  digitalWrite(trig2, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig2, LOW);
  pulsetime = pulseIn(echo2, HIGH);
  return pulsetime / 58.2; //magic
}



void override()
{
  /*Note: The time it takes for the rover to turn depends in the
    motors you use...so that will be fixed during debugging.*/

  //Stop receiving data from the user.
  Serial.end();
  delay(10);

  //Obstacle avoidance maneuver and all that jazz..
  motor_stop();
  delay(500);
  drive_backward();
  delay(300);
  motor_stop();
  delay(10);
  scanLeft();
  delay(100);
  scanRight();
  if (distLeft > distRight && distLeft > distLimit)
  {
    turn_left();
    delay(500);
    motor_stop();
  }
  else if (distRight > distLeft && distRight > distLimit)
  {
    turn_right();
    delay(500);
    motor_stop();
  }
  else
  {
    drive_backward();
    delay(300);
    motor_stop();
  }

  //Restart the receiver.
  Serial.begin(9600);
}

void scanLeft()
{
  Serial.println("Scanning Left....");
  delay(10);
  turn_left();  //turns left to scan
  delay(300);
  motor_stop();
  delay(10);
  distLeft = readDistanceF();
  //Serial.print("Left is ");
  //Serial.println(distLeft); //scan
  delay(100);
  turn_right();   //turns to the centre again
  delay(300);
  motor_stop();
}

void scanRight()
{
  Serial.println("Scanning Right....");
  delay(10);
  turn_right();
  delay(300);
  motor_stop();
  delay(10);
  distRight = readDistanceF();
  //Serial.print("Right is ");
  //Serial.println(distRight);
  delay(100);
  turn_left();
  delay(300);
  motor_stop();
}
RenA
Rin1
Rin2
Rin3
Rin4
RenB
FenA
Fin1
Fin2
Fin3
Fin4
FenB
Fdist
Rdist