// Projeto: Controle de Robô com ESC, DRV8833 e Bluetooth
// Plataforma: Arduino Nano
// Autor: ChatGPT (OpenAI) + Usuário
//#include <SoftwareSerial.h>
//#include <ServoTimer2.h>
#include <Servo.h>
#include "neotimer.h"
#include <TimerFreeTone.h>
// Pinos de comunicação Bluetooth
#define Rx 2
#define Tx 3
// Controle de motores (DRV8833)
#define In1 5
#define In2 6
#define In3 9
#define In4 10
// Buzina e ESC
#define Buzina 11
#define ESC A0
// Sensor de vibração
#define WSensor A1
// Bluetooth e ESC
//SoftwareSerial Bt(Rx, Tx);
//ServoTimer2 Esc;
Servo Esc;
// Temporizadores
Neotimer Delay0 = Neotimer(100);    // Ciclos de aumento da serra
Neotimer Delay1 = Neotimer(3000);   // Tempo mínimo desligado após sensor
Neotimer Delay2 = Neotimer(300);    // Debounce de comandos
// Variáveis de controle
String Text = "";       //cria textos a partir dos caracteres recebidos por Crct
char Crct = "";         //guarda os caracteres
int Nivel[] = {95, 95}; //X e Y
int Pw = 1000;          //valor de
int Max_Pw = 2000;      //valor maximo que define a velocidade
int Pw_Gain = 10;       //valor de ganho de velocidade
bool Ats = false;       //inicializador da Serra
bool DY = false;
bool DX = false;
bool cmm = false;
// Setup inicial
void setup() {
  //inicia a comunicação dentre dispositivos
  Serial.begin(115200);
 // Bt.begin(115200);
  //definição de portas
  pinMode(Buzina, OUTPUT);
  pinMode(WSensor, INPUT);
  pinMode(In1, OUTPUT);
  pinMode(In2, OUTPUT);
  pinMode(In3, OUTPUT);
  pinMode(In4, OUTPUT);
  Esc.attach(ESC);
  armarESC();
  //Serial.println("Sistema iniciado");
}
// Loop principal
void loop() {
  Bluetooth();
  Mc();
  Serra(); //menu iniciar serra de corte
  if (Ats == true) { //verifica estado da serra
    if (DX == true){
    ligarSerra();
    }
  } else {
    //if (DY == true){
    desligarSerra(); //desligar serra de corte
    //}
  }
}
// Armar ESC no início
void armarESC() {
  Esc.writeMicroseconds(2000); //valor maximo para calibrar o Esc
  delay(2500);
  Esc.writeMicroseconds(1000); //valor minimo para concluir a calibração e manter o motor armado
  delay(2000);
}
// Liga a serra
void ligarSerra() {
  Pw = 1000;
  DY = true; //valida a função DY para iniciar o aumento de rotações do motor
  DX = false;
  Ats = true;
//  Serial.println("Serra ligada.");
}
// Desliga a serra
void desligarSerra() {
  Pw = 1000;
  DY = false;
  DX = true;
  Ats = false;
  Esc.writeMicroseconds(Pw);
//  Serial.println("Serra Desligada.");
}
// Controle da serra com sensor de segurança
void Serra() {
  if (Delay1.repeat(1)) { //valida a função DY para iniciar o aumento de rotações do motor
    DY = true;
  }
  if (Pw <= Max_Pw && DY == true) { //aumenta as rotações do motor da serra
    if (Delay0.repeat()) {
      Pw += Pw_Gain;
      if (Pw >= Max_Pw) {
        Pw = Max_Pw;
        DY = false; //invalida DY para a parar o aumento de rotações do motor
      }
    }
  }
  Esc.writeMicroseconds(Pw); //envia todos os valores para o esc
//  if (digitalRead(WSensor) == HIGH && Pw >= 1500) {
//    Serial.println("Sensor de vibração ativo! Desligando serra...");
  //  Delay1.repeatReset();
  //  DY = false;
  //  Pw = 1000;
  //  Esc.writeMicroseconds(Pw);
  }
//}
// Comunicação Bluetooth
void Bluetooth() {
  if (Serial.available()) {
    Crct = Serial.read();
    if (Crct >= 32 && Crct <= 126) {
      Text += Crct;
      if (Text == "A") {
        if (cmm == true) {
          Ats = !Ats;
          cmm = false;
          Delay2.repeatReset();
        }
        Text = "";
      } else if (Text == "W") {
        if (cmm == true) {
       // Serial.println("Buzina acionada");
        // NewTone(Buzina, 391);
        TimerFreeTone(Buzina, 1567, 500);
        //motor direito
        digitalWrite(In2, LOW);
        digitalWrite(In1, LOW);
        //motor esquerdo
        digitalWrite(In4, LOW);
        digitalWrite(In3, LOW);
        Text = "";
        cmm = false;
        Delay2.repeatReset();
      }
      } else {
       if(Delay2.repeat(1)){
        cmm = true;
        }
      }
      if (Text.endsWith("X") || Text.endsWith("Y")) {
        char eixo = Text.charAt(Text.length() - 1);
        int val = Text.substring(0, Text.length() - 1).toInt();
        if (val >= 0 && val <= 180) {
          if (eixo == 'X') {
            Nivel[0] = val;
        //    Serial.print("X: "); Serial.println(val);
          } else {
            Nivel[1] = val;
         //   Serial.print("Y: "); Serial.println(val);
          }
        }
        Text = "";
      }
      if (Text.length() > 6) Text = "";
    }
  }
}
// Controle de direção com sinais digitais (sem PWM)
void Mc() {
  /* Função de movimento dos motores
     contorle por potenciometro de 0 a 180
     Nivel[] recebe os valores e guarda em (X, Y).
     X define a direção e o quanto o robô conseguirar virar para tal direção
     Y Define a velocidade e se o robô deverá seguir para frente ou para Tras
     110 - 180X define a Esquerda
        80 - 0X define a Direita
     110 - 180Y faz ir para Frente
        80 - 0Y faz ir para Tras
     90 - 100X/Y centro - nada acontece
  */
  if (Nivel[1] >= 150 && Nivel[0] >= 150) { //frente + esquerda
    //motor direito
    digitalWrite(In1, LOW); //define o quanto a velocidade aumenta para ir para frente
    digitalWrite(In2, LOW);
    //motor esquerdo
    digitalWrite(In3, HIGH);
    digitalWrite(In4, LOW);
  } else if (Nivel[1] >= 150 && Nivel[0] <= 60) { //frente + direita
    //motor direito
    digitalWrite(In1, HIGH);
    digitalWrite(In2, LOW);
    //motor esquerdo
    digitalWrite(In3, LOW); //define o quanto a velocidade aumenta para ir para frente
    digitalWrite(In4, LOW);
  } else if (Nivel[1] <= 60 && Nivel[0] >= 150) { //ré + esquerda
    //motor direito
    digitalWrite(In2, LOW); 
    digitalWrite(In1, HIGH);
    //motor esquerdo
    digitalWrite(In4, LOW);
    digitalWrite(In3, LOW); //define o quanto a velocidade aumenta para ir para tras
  } else if (Nivel[1] <= 60 && Nivel[0] <= 60) { //ré + direita arrumar
    //motor direito
    digitalWrite(In2, LOW);
    digitalWrite(In1, HIGH); //define o quanto a velocidade aumenta para ir para tras
    //motor esquerdo
    digitalWrite(In4, LOW);
    digitalWrite(In3, LOW);
  } else if (Nivel[1] >= 150) { //ré
    //motor direito
    digitalWrite(In1, HIGH);
    digitalWrite(In2, LOW);
    //motor esquerdo
    digitalWrite(In3, HIGH);
    digitalWrite(In4, LOW);
  } else if (Nivel[1] <= 60) { //frente
    //motor direito
    digitalWrite(In1, LOW);
    digitalWrite(In2, HIGH);
    //motor esquerdo
    digitalWrite(In3, LOW);
    digitalWrite(In4, HIGH);
  } else if (Nivel[0] >= 150) { //esquerda
    //motor direito
    digitalWrite(In1, LOW);
    digitalWrite(In2, HIGH);
    //motor esquerdo
    digitalWrite(In3, HIGH);
    digitalWrite(In4, LOW);
  } else if (Nivel[0] <= 60) { //direita
    //motor direito
    digitalWrite(In1, HIGH);
    digitalWrite(In2, LOW);
    //motor esquerdo
    digitalWrite(In3, LOW);
    digitalWrite(In4, HIGH);
  } else {
    //motor direito
    digitalWrite(In2, LOW);
    digitalWrite(In1, LOW);
    //motor esquerdo
    digitalWrite(In4, LOW);
    digitalWrite(In3, LOW);
  }
}