Programação para AGV

Olá pessoal, preciso de uma ajuda dos experts, já aviso que sou novo em programação mas quero muito aprender e melhorar cada vez mais. Estamos fazendo um AGV com alguns colegas de turma, estamos usando um arduino mega, ponte H para dois motores e um modulo shield com 4 sensores infra para ler faixa no piso, primeiro fiz a programação para o funcionamento dos motores e leitura da faixa, funcionou perfeitamente, para frente quando desviava a rota lia a faixa e corrigia e quando encontra faixa na transversal ele para. O problema foi quando começamos a colocar outros dispositivos daí o código começou a falhar, colocamos 4 botões, start para iniciar o programa, stop para parada manual, reset e 1 botão de emergencia. Não estou conseguindo amarrar no codigo o botão start com as partes dos codigos, frente, direita e esquerda, quando aperto o start ele só vai reto e não interpreta mais a faixa, pois o codigo ficou preso na primeira parte, já tentei fazer varias mudanças, escalonar os ifs, trocar para while e for mas não tenho muito experiencia, acho preciso amarrar com variáveis mas não estou conseguindo fazer, se alguem puder dar um auxilio eu agradeço. (o codigo está bem extenso e básico com muitos ifs, pretendo melhorar, também tem alguns implementações que ainda estou fazendo, como colocar o stop, reset e emergencia)

Léo

// Módulo seguidor de linha;
// Código AGV seguidor de linha.
 
int UT1 = 28;
int UT2 = 26;
int UT3 = 24;
int UT4 = 22;
int Bot2 = 49;
int Bot1 = 47;
int Green = 39;
int Red = 41;
int Emergency = 51;
int Reset = 53;
int Buzzer = 43;
 
int Sensor1 = 0;//estado inicial dos sensores
int Sensor2 = 0;
int Sensor3 = 0;
int Sensor4 = 0;
int Start;
int Stop;


void read() {
 Sensor1 = digitalRead(UT1);
 Sensor2 = digitalRead(UT2);
 Sensor3 = digitalRead(UT3);
 Sensor4 = digitalRead(UT4);
 Start = digitalRead(Bot1);
 Stop = digitalRead(Bot2);

 return;
}
 
void setup() {

pinMode(UT1, INPUT);//definindo sensores como entrada de sinal
pinMode(UT2, INPUT);
pinMode(UT3, INPUT);
pinMode(UT4, INPUT);
pinMode(Stop, INPUT_PULLUP);//define o pino de entrada do botão,PULLUP para evitar flutuação(ligar o botão ao GND)
pinMode(Start, INPUT_PULLUP);//define o pino de entrada do botão,PULLUP para evitar flutuação(ligar o botão ao GND)
pinMode(Emergency, INPUT);
pinMode(Reset, INPUT);
pinMode(Green, OUTPUT);
pinMode (Red, OUTPUT);


digitalWrite(4,0);//definindo inicio de motores como parados
digitalWrite(7,0);
digitalWrite(8,0);
digitalWrite(9,0);

}

void loop() {

 
 //motores em frente
    if((Start == LOW) and (Sensor1==0) and (Sensor2==0) and (Sensor3==0) and (Sensor4==0)) {
    digitalWrite(7,1);
    digitalWrite(8,0);

    digitalWrite(4,1);
    digitalWrite(9,0);
    digitalWrite(Green, LOW);//acende o verde e apaga o amarelo no Andon
    digitalWrite(Red, HIGH);//apaga o vermelho no Andon
    digitalWrite(Buzzer, HIGH);//liga a campainha do Andon
    
    analogWrite(5,250);//velocidade motores
    analogWrite(6,250);
    delay(200); 
  

  }


    //motores parados
    if((Sensor1==1) and (Sensor2==1) and (Sensor3==1) and (Sensor4==1)) {
    digitalWrite(7,0);
    digitalWrite(8,0);

    digitalWrite(4,0);
    digitalWrite(9,0);

    analogWrite(5,0);
    analogWrite(6,0);

    delay(200);
  }
    
  
    //virar a direita
    if((Start == LOW) and (Sensor1==1) and (Sensor2==0) and (Sensor3==0) and (Sensor4==0)) {
    digitalWrite(7,1);
    digitalWrite(8,0);

    digitalWrite(4,0);
    digitalWrite(9,0);
    analogWrite(5,200);
    analogWrite(6,200);
    delay(200); 
  }

    //virar a direita
    if((Start == LOW) and (Sensor1==0) and (Sensor2==1) and (Sensor3==0) and (Sensor4==0)) {
    digitalWrite(7,1);
    digitalWrite(8,0);

    digitalWrite(4,0);
    digitalWrite(9,0);

    analogWrite(5,200);
    analogWrite(6,200);
    delay(200); 
  }

    //virar à esquerda
    if((Start == LOW) and (Sensor1==0) and (Sensor2==0) and (Sensor3==1) and (Sensor4==0)) {
    digitalWrite(7,0);
    digitalWrite(8,0);

    digitalWrite(4,1);
    digitalWrite(9,0);

    analogWrite(5,200);
    analogWrite(6,200);
    delay(200); 
  }

    //virar à esquerda

    if((Start == LOW) and (Sensor1==0) and (Sensor2==0) and (Sensor3==0) and (Sensor4==1)) {
    digitalWrite(7,0);
    digitalWrite(8,0);

    digitalWrite(4,1);
    digitalWrite(9,0);

    analogWrite(5,200);
    analogWrite(6,200);
    delay(200); 
  }

  if(digitalRead(Stop) == LOW){
    digitalWrite(7,0);
    digitalWrite(8,0);

    digitalWrite(4,0);
    digitalWrite(9,0);

    analogWrite(5,0);
    analogWrite(6,0);
    digitalWrite(Green, HIGH );//apaga o verde e acende o amarelo no Andon
    digitalWrite(Red, LOW);//apaga o vermelho no Andon
  
  }
  }

Olá,

A função read() actualiza as variáveis de controlo dos sensores e botões lendo as entradas digitais às quais estão ligadas os sensores e botões, mas parece que esta função nunca é chamada. Para actualizar estas variáveis é necessário chamar esta função na função loop(). Por exemplo, no inicio da função loop():

void loop() {

  // Actualizar as variaveis de controlo de acordo com o estado dos
  // sensores e botões.
  read();
  
  // Actuar os motores de acordo com as variáveis de controlo.
  // ...

}  

1 Like

Obrigado pela resposta. Inseri o 'Read' mas mesmo assim ele nem parte, acho já tinha tentado inserir antes olhando outros codigos, estou na duvida quando declaro
int Start ;
e
int Stop ; //se está correto assim, tentei também declarar:
int Start = 1;
int stop = 1; já que os dois são PULL_UP mas não sei se é correto, ambos não funciona.
O códiog abaixo é diferente e foi o melhor que consegui, os botões funcionam mas o AGV sempre vai para a esquerda e ignora os sensores de faixa.

// Módulo seguidor de linha;
// Código AGV seguidor de linha.
 
int UT1 = 28;
int UT2 = 26;
int UT3 = 24;
int UT4 = 22;
int Stop = 49;
int Start = 47;
int Green = 39;
int Red = 41;
int Emergency = 51;
int Reset = 53;
int Buzzer = 43;
 
int Sensor1 = 0;//estado inicial dos sensores
int Sensor2 = 0;
int Sensor3 = 0;
int Sensor4 = 0;



void read() {
 Sensor1 = digitalRead(UT1);
 Sensor2 = digitalRead(UT2);
 Sensor3 = digitalRead(UT3);
 Sensor4 = digitalRead(UT4);


 return;
}
 
void setup() {

pinMode(UT1, INPUT);//definindo sensores como entrada de sinal
pinMode(UT2, INPUT);
pinMode(UT3, INPUT);
pinMode(UT4, INPUT);
pinMode(Stop, INPUT_PULLUP);//define o pino de entrada do botão,PULLUP para evitar flutuação(ligar o botão ao GND)
pinMode(Start, INPUT_PULLUP);//define o pino de entrada do botão,PULLUP para evitar flutuação(ligar o botão ao GND)
pinMode(Emergency, INPUT);
pinMode(Reset, INPUT);
pinMode(Green, OUTPUT);
pinMode (Red, OUTPUT);


digitalWrite(4,0);//definindo inicio de motores como parados
digitalWrite(7,0);
digitalWrite(8,0);
digitalWrite(9,0);

}

void loop() {
    
  if(digitalRead(Start) == LOW){ 
 //motores em frente
    if((Sensor1==0) and (Sensor2==0) and (Sensor3==0) and (Sensor4==0)) {
    digitalWrite(7,1);
    digitalWrite(8,0);

    digitalWrite(4,1);
    digitalWrite(9,0);
    digitalWrite(Green, LOW);//acende o verde e apaga o amarelo no Andon
    digitalWrite(Red, HIGH);//apaga o vermelho no Andon
    digitalWrite(Buzzer, HIGH);//liga a campainha do Andon
    
    analogWrite(5,250);//velocidade motores
    analogWrite(6,250);
    delay(200); 
  

  }


    //motores parados
    if((Sensor1==1) and (Sensor2==1) and (Sensor3==1) and (Sensor4==1)) {
    digitalWrite(7,0);
    digitalWrite(8,0);

    digitalWrite(4,0);
    digitalWrite(9,0);

    analogWrite(5,0);
    analogWrite(6,0);

    delay(200);
  }
    
  
    //virar a direita
    if((Sensor1==1) and (Sensor2==0) and (Sensor3==0) and (Sensor4==0)) {
    digitalWrite(7,1);
    digitalWrite(8,0);

    digitalWrite(4,0);
    digitalWrite(9,0);
    analogWrite(5,200);
    analogWrite(6,200);
    delay(200); 
  }

    //virar a direita
    if((Sensor1==0) and (Sensor2==1) and (Sensor3==0) and (Sensor4==0)) {
    digitalWrite(7,1);
    digitalWrite(8,0);

    digitalWrite(4,0);
    digitalWrite(9,0);

    analogWrite(5,200);
    analogWrite(6,200);
    delay(200); 
  }

    //virar à esquerda
    if((Sensor1==0) and (Sensor2==0) and (Sensor3==1) and (Sensor4==0)) {
    digitalWrite(7,0);
    digitalWrite(8,0);

    digitalWrite(4,1);
    digitalWrite(9,0);

    analogWrite(5,200);
    analogWrite(6,200);
    delay(200); 
  }

    //virar à esquerda

    if((Sensor1==0) and (Sensor2==0) and (Sensor3==0) and (Sensor4==1)) {
    digitalWrite(7,0);
    digitalWrite(8,0);

    digitalWrite(4,1);
    digitalWrite(9,0);

    analogWrite(5,200);
    analogWrite(6,200);
    delay(200); 
  }
  }

  if(digitalRead(Stop) == LOW){
    digitalWrite(7,0);
    digitalWrite(8,0);

    digitalWrite(4,0);
    digitalWrite(9,0);

    analogWrite(5,0);
    analogWrite(6,0);
    digitalWrite(Green, HIGH );//apaga o verde e acende o amarelo no Andon
    digitalWrite(Red, LOW);//apaga o vermelho no Andon
  
  }
  }

As variáveis no código actual e o anterior são ligeiramente diferentes o que pode baralhar aqui um pouco a situação.

Agora o Start e Stop representam as entradas (input) dos botões e não variáveis de controlo que guardam o estado das entradas (no código anterior eram o Bot1 e Bot2). Então têm de ser inicializadas com o valor correspondente ao terminal/pino de entrada e não lhe pode ser atribuído outro valor.

Então as variáveis:

int Stop = 49;      // Botão que liga o pino 49 do Arduino Mega ao GND
int Start = 47;     // Botão que liga o pino 47 do Arduino Mega ao GND

podem ser utilizadas com a função digitalRead() para obter o estado lógico da entrada digital correspondente ao botão, mas não podem ser inicializadas ou lhe serem atribuídas outro valor directamente.

Eu sugeria fazer um pequeno programa à parte apenas com os botões, os sensores e os LEDs, para verificar e compreender o funcionamento destes elementos.

Exemplo usando as variáveis do código anterior, para colocar os botoes start e stop apenas a acender/apagar os LEDs verde e vermelho, respectivamente:

// Definicao de terminais/pinos de entrada/saída digital no Arduino Mega.
int UT1 = 28;   // Entrada digital para o sensor 1.
int UT2 = 26;   // Entrada digital para o sensor 2.
int UT3 = 24;   // Entrada digital para o sensor 3.
int UT4 = 22;   // Entrada digital para o sensor 4.
int Bot1 = 49;  // Entrada digital para o botao start.
int Bot2 = 47;  // Entrada digital para o botao stop.
int Green = 39; // Saída digital para o LED verde.
int Red = 41;   // Saída digital para o LED vermelho.
int Emergency = 51;  // Entrada digital para o botao de emergencia.
int Reset = 53;      // Entrada digital para o botao de reset.
int Buzzer = 43;     // Saída digital para o Buzzer.

// Declaracao e inicializalcao de variaveis de controlo.
// Nota: a inicializacao nao e' necessaria porque estas variaveis
// deverao ser actualizadas no inicio de cada ciclo do sistema
// na funcao loop().
int Sensor1 = 0;    // Estado inicial dos sensores.
int Sensor2 = 0;
int Sensor3 = 0;
int Sensor4 = 0;
int Start = 1;      // Estado inicial dos botoes.
int Stop = 1;

// Funcao para actualizar as variaveis de controlo com
// o estado logico das entradas.
void read() {
  Sensor1 = digitalRead(UT1);
  Sensor2 = digitalRead(UT2);
  Sensor3 = digitalRead(UT3);
  Sensor4 = digitalRead(UT4);
  // No caso dos botoes o ideal sera realizar o debounce!
  // (Ver um tutorial de debounce para botoes no Arduino)
  Start = digitalRead(Bot1);
  Stop = digitalRead(Bot2);
}


void setup() {

  pinMode(UT1, INPUT);//definindo sensores como entrada de sinal
  pinMode(UT2, INPUT);
  pinMode(UT3, INPUT);
  pinMode(UT4, INPUT);
  pinMode(Bot1, INPUT_PULLUP);//define o pino de entrada do botão,PULLUP para evitar flutuação(ligar o botão ao GND)
  pinMode(Bot2, INPUT_PULLUP);//define o pino de entrada do botão,PULLUP para evitar flutuação(ligar o botão ao GND)
  pinMode(Emergency, INPUT_PULLUP);
  pinMode(Reset, INPUT_PULLUP);
  pinMode(Green, OUTPUT);
  pinMode (Red, OUTPUT);

  //digitalWrite(4,0);//definindo inicio de motores como parados
  //digitalWrite(7,0);
  //digitalWrite(8,0);
  //digitalWrite(9,0);
}

void loop() {

  // Actualizar as variaveis de controlo de acordo com o estado dos
  // sensores e botoes.
  read();

  // Actuar os motores de acordo com as variaveis de controlo.
  // ...

  // Neste caso testar apenas com os LEDs.


  if (Start == LOW) {
    digitalWrite(Green, HIGH);
  } else {
    digitalWrite(Green, LOW);
  }

  if (Stop == LOW) {
    digitalWrite(Red, HIGH);
  } else {
    digitalWrite(Red, LOW);
  }

}
1 Like

Eu tinha feito um pequeno codigo para implementar os botões, e neste segundo codigo que coloquei o Start e Stop estão funcionando, o reset e o emergencia ainda não implementei. Quando aciono o start o AGV arranca mas tende a ir para a esquerda então aciono o stop e ele para, ou seja, deixou de reconhecer os sensores infra neste codigo porque ficou travado em algum bloco do mesmo, ainda não consegui corrigir. Acho terei de modificar o codigo, será usando switch case consigo implementar? Tenho mais dificuldades para fazer assim.
TEm como colocar video curto aqui no forum? Dai coloco o que está acontecendo.
Obrigado!

Não sei se dá para colocar vídeo aqui :roll_eyes: ...

A utilização de uma variável para indicar o estado do sistema (AGV parado, em frente, direita, etc.) e de um "switch...case" poderia ajudar a organizar o código. Mas deverá ser perfeitamente possível colocar o sistema a funcionar usando apenas condições do tipo "if...else".

Sugiro a utilização de uma única variável de controlo para iniciar/parar o AGV. Por exemplo, "agv_run" em vez de duas variáveis ("start" e "stop"). Quando o botão Start é pressionado fica agv_run=1, quando o Stop é pressionado fica agv_run=0.

Nesse caso o programa poderia ficar assim:

// Módulo seguidor de linha;
// Código AGV seguidor de linha.

int UT1 = 28;
int UT2 = 26;
int UT3 = 24;
int UT4 = 22;
int Bot2 = 49;
int Bot1 = 47;
int Green = 39;
int Red = 41;
int Emergency = 51;
int Reset = 53;
int Buzzer = 43;

int Sensor1 = 0; //estado inicial dos sensores
int Sensor2 = 0;
int Sensor3 = 0;
int Sensor4 = 0;

// Variavel para guardar o estado de paragem/arranque
// do sistema com os botoes Start/Stop.
int agv_run = 0;

void read_inputs() {
 Sensor1 = digitalRead(UT1);
 Sensor2 = digitalRead(UT2);
 Sensor3 = digitalRead(UT3);
 Sensor4 = digitalRead(UT4);

 // Verificar o botao Start e Stop para actualizar a variavel agv_run
 if (digitalRead(Bot1)== LOW) {
   agv_run = 1; // Botao start pressionado, activa o AGV.
 } else if (digitalRead(Bot2) == LOW) {
   agv_run = 0; // Botao stop pressionado, desactiva o AGV.
 }
}

void setup() {

 pinMode(UT1, INPUT); //definindo sensores como entrada de sinal
 pinMode(UT2, INPUT);
 pinMode(UT3, INPUT);
 pinMode(UT4, INPUT);
 pinMode(Bot1, INPUT_PULLUP); //define o pino de entrada do botão,PULLUP para evitar flutuação(ligar o botão ao GND)
 pinMode(Bot2, INPUT_PULLUP); //define o pino de entrada do botão,PULLUP para evitar flutuação(ligar o botão ao GND)
 pinMode(Emergency, INPUT);
 pinMode(Reset, INPUT);
 pinMode(Green, OUTPUT);
 pinMode(Red, OUTPUT);

 digitalWrite(4, 0); //definindo inicio de motores como parados
 digitalWrite(7, 0);
 digitalWrite(8, 0);
 digitalWrite(9, 0);

}

void loop() {

 // Actualiza as variaveis com o estado dos sensores e AGV On/Off.
 read_inputs();

 if (agv_run) {  // AGV esta activo/ligado?

   //motores em frente
   if ((Sensor1 == 0) && (Sensor2 == 0) && (Sensor3 == 0) && (Sensor4 == 0)) {
     digitalWrite(7, 1);
     digitalWrite(8, 0);

     digitalWrite(4, 1);
     digitalWrite(9, 0);
     digitalWrite(Green, LOW); //acende o verde e apaga o amarelo no Andon
     digitalWrite(Red, HIGH); //apaga o vermelho no Andon
     digitalWrite(Buzzer, HIGH); //liga a campainha do Andon

     analogWrite(5, 250); //velocidade motores
     analogWrite(6, 250);
     delay(200);

   }

   //motores parados
   if ((Sensor1 == 1) && (Sensor2 == 1) && (Sensor3 == 1) && (Sensor4 == 1)) {
     digitalWrite(7, 0);
     digitalWrite(8, 0);

     digitalWrite(4, 0);
     digitalWrite(9, 0);

     analogWrite(5, 0);
     analogWrite(6, 0);

     delay(200);
   }

   //virar a direita
   if ( ((Sensor1 == 1) && (Sensor2 == 0) && (Sensor3 == 0) && (Sensor4 == 0)) ||\
        ((Sensor1 == 0) && (Sensor2 == 1) && (Sensor3 == 0) && (Sensor4 == 0))) {
     digitalWrite(7, 1);
     digitalWrite(8, 0);

     digitalWrite(4, 0);
     digitalWrite(9, 0);
     analogWrite(5, 200);
     analogWrite(6, 200);
     delay(200);
   }

   //virar à esquerda
   if ( ((Sensor1 == 0) && (Sensor2 == 0) && (Sensor3 == 1) && (Sensor4 == 0)) ||\
        ((Sensor1 == 0) && (Sensor2 == 0) && (Sensor3 == 0) && (Sensor4 == 1))) {
     digitalWrite(7, 0);
     digitalWrite(8, 0);

     digitalWrite(4, 1);
     digitalWrite(9, 0);

     analogWrite(5, 200);
     analogWrite(6, 200);
     delay(200);
   }

 } else {  // agv_run == 0, AGV esta parado...
   digitalWrite(7, 0);
   digitalWrite(8, 0);

   digitalWrite(4, 0);
   digitalWrite(9, 0);

   analogWrite(5, 0);
   analogWrite(6, 0);
   digitalWrite(Green, HIGH); //apaga o verde e acende o amarelo no Andon
   digitalWrite(Red, LOW); //apaga o vermelho no Andon
 }

}
1 Like

Bom dia!
Fiquei bem feliz pois funcionou da maneira como você fez e novamente agradeço pelos ensinamentos. Esqueci de mencionar, quando ele chega na faixa transversal ele para como deveria, mas daí quando aciono o start ele não arranca porque está ainda em cima da faixa, como faço pra ele ignorar a faixa transversal por uns instantes? Coloquei um delay antes da rotina de parada mas ele ainda para em cima da faixa.
O código ja ficou mais limpo também, tinha visto que o & comercial é usado como "And" mas não tinha tentado ainda, só queria entender o que fez nesse bloco, as duas barras na vertical interpretam uma "OR"? Eu tinha tentado da mesma maneira mas usando OR e não tinha funcionado.

Você pode me explicar como deve funcionar o reset também? Pra mim é a mesma função do Stop pois vai parar e basta dar o Start pra reiniciar, daí apenas ligo em paralelo, o emergência coloquei pra cortar os motores daí pensei em colocar também em paralelo um sinal para o stop, mas nesse caso eu vou colocar apensas o LED vermelho pra acender. Não tinha comentado mas os LEDs verde e amarelo eu coloquei juntos em um rele NA/NF, assim quando um acende o outro apaga. Agora irei ligar dois sensores ultrassônicos na frente para detectar objetos e parar.

Parece-me que essa situação ocorre quando todos os sensores têm o nível lógico 1.
Primeiro é preciso determinar o que o AGV deve fazer nessa situação. Qual a acção a tomar?

Ele tem de sair da situação em que todos os sensores estão a 1. Deverá recuar, virar ou andar em frente até que saia dessa situação? Deve parar e aguardar que um operador pressione o start para prosseguir em frente até que saia da situação de todos os sensores a 1? O objectivo terá de ser previamente especificado para desenvolver o código de acordo :wink: .

Se for esse o objectivo, parar e aguardar que um operador pressione o start para prosseguir em frente, então uma das muitas soluções poderá ser criar uma variável para sinalizar a detecção de faixa transversal e adicionar um novo estado à variável agv_run:

agv_run == 1 -> botao start accionado e faixa transversal não detectada.
agv_run == 2 -> botao start accionado e faixa transversal detectada.
agv_run == 0 -> botao stop accionado.

Exemplo no código:

// Módulo seguidor de linha;
// Código AGV seguidor de linha.

int UT1 = 28;
int UT2 = 26;
int UT3 = 24;
int UT4 = 22;
int Bot2 = 49;
int Bot1 = 47;
int Green = 39;
int Red = 41;
int Emergency = 51;
int Reset = 53;
int Buzzer = 43;

int Sensor1 = 0; //estado inicial dos sensores
int Sensor2 = 0;
int Sensor3 = 0;
int Sensor4 = 0;

// Variavel para guardar o estado de paragem/arranque
// do sistema com os botoes Start/Stop.
int agv_run = 0;

// Variavel para guardar o estado de deteccao da
// faixa transversal, ou seja, quando os
// sensores (Sensor1 a Sensor4) teem o nível
// logico 1.
int det_faixa_transversal = 0;

void read_inputs() {
  Sensor1 = digitalRead(UT1);
  Sensor2 = digitalRead(UT2);
  Sensor3 = digitalRead(UT3);
  Sensor4 = digitalRead(UT4);

  if (digitalRead(Bot1)== LOW) {    // Botao start accionado?
    if (det_faixa_transversal) {    // Faixa transversal previamente detectada?
      agv_run = 2;
    } else {                        // Faixa transversal nao detectada?
      agv_run = 1;
    }
  } else if (digitalRead(Bot2) == LOW) {
    agv_run = 0;
  }
}

void setup() {

  pinMode(UT1, INPUT); //definindo sensores como entrada de sinal
  pinMode(UT2, INPUT);
  pinMode(UT3, INPUT);
  pinMode(UT4, INPUT);
  pinMode(Bot1, INPUT_PULLUP); //define o pino de entrada do botão,PULLUP para evitar flutuação(ligar o botão ao GND)
  pinMode(Bot2, INPUT_PULLUP); //define o pino de entrada do botão,PULLUP para evitar flutuação(ligar o botão ao GND)
  pinMode(Emergency, INPUT);
  pinMode(Reset, INPUT);
  pinMode(Green, OUTPUT);
  pinMode(Red, OUTPUT);

  digitalWrite(4, 0); //definindo inicio de motores como parados
  digitalWrite(7, 0);
  digitalWrite(8, 0);
  digitalWrite(9, 0);

}

void loop() {

  // Actualiza as variaveis com o estado dos sensores e AGV On/Off.
  read_inputs();

  if (agv_run == 1) {  // AGV esta ligado e faixa transversal nao detectada?
    //motores em frente
    if ((Sensor1 == 0) && (Sensor2 == 0) && (Sensor3 == 0) && (Sensor4 == 0)) {
      digitalWrite(7, 1);
      digitalWrite(8, 0);

      digitalWrite(4, 1);
      digitalWrite(9, 0);
      digitalWrite(Green, LOW); //acende o verde e apaga o amarelo no Andon
      digitalWrite(Red, HIGH); //apaga o vermelho no Andon
      digitalWrite(Buzzer, HIGH); //liga a campainha do Andon

      analogWrite(5, 250); //velocidade motores
      analogWrite(6, 250);
      delay(200);

    }

    //motores parados
    if ((Sensor1 == 1) && (Sensor2 == 1) && (Sensor3 == 1) && (Sensor4 == 1)) {
      // Sinaliza que a faixa transversal foi detectada.
      det_faixa_transversal = 1;
      // Muda para o estado parado.
      agv_run = 0;

      digitalWrite(7, 0);
      digitalWrite(8, 0);

      digitalWrite(4, 0);
      digitalWrite(9, 0);

      analogWrite(5, 0);
      analogWrite(6, 0);

      delay(200);
    }

    //virar a direita
    if ( ((Sensor1 == 1) && (Sensor2 == 0) && (Sensor3 == 0) && (Sensor4 == 0)) ||\
         ((Sensor1 == 0) && (Sensor2 == 1) && (Sensor3 == 0) && (Sensor4 == 0))) {
      digitalWrite(7, 1);
      digitalWrite(8, 0);

      digitalWrite(4, 0);
      digitalWrite(9, 0);
      analogWrite(5, 200);
      analogWrite(6, 200);
      delay(200);
    }

    //virar à esquerda
    if ( ((Sensor1 == 0) && (Sensor2 == 0) && (Sensor3 == 1) && (Sensor4 == 0)) ||\
         ((Sensor1 == 0) && (Sensor2 == 0) && (Sensor3 == 0) && (Sensor4 == 1))) {
      digitalWrite(7, 0);
      digitalWrite(8, 0);

      digitalWrite(4, 1);
      digitalWrite(9, 0);

      analogWrite(5, 200);
      analogWrite(6, 200);
      delay(200);
    }

    // **Edit: adicionei a chaveta que faltava antes do else if:**
  } else if (agv_run == 2) {  // AGV esta ligado e faixa transversal detectada?
    //motores em frente
    digitalWrite(7, 1);
    digitalWrite(8, 0);

    digitalWrite(4, 1);
    digitalWrite(9, 0);
    digitalWrite(Green, LOW); //acende o verde e apaga o amarelo no Andon
    digitalWrite(Red, HIGH); //apaga o vermelho no Andon
    digitalWrite(Buzzer, HIGH); //liga a campainha do Andon

    analogWrite(5, 250); //velocidade motores
    analogWrite(6, 250);
    delay(200);

    // Verifica se a faixa transversal ja nao esta a ser detectada.
    if (!((Sensor1 == 1) && (Sensor2 == 1) && (Sensor3 == 1) && (Sensor4 == 1)) ) {
        det_faixa_transversal = 0;
        // **Edit:** mudanca de estado no caso de fim de deteccao de faixa transversal.
        agv_run = 1;
    }

  } else {  // agv_run == 0, AGV esta desligado...
    digitalWrite(7, 0);
    digitalWrite(8, 0);

    digitalWrite(4, 0);
    digitalWrite(9, 0);

    analogWrite(5, 0);
    analogWrite(6, 0);
    digitalWrite(Green, HIGH); //apaga o verde e acende o amarelo no Andon
    digitalWrite(Red, LOW); //apaga o vermelho no Andon
  }

}

Em relação ao "and" e "or", há duas situações. Na liguagem C/C++ geralmente usa-se && e || para operações lógicas "and" e "or". Os símbolos & e | (isolados) são usados para operações "and" e "or" bit a bit.

&& -> "and" para operações lógicas. O resultado dá 1 quando o valor total de cada variável é diferente de zero, caso contrário o resultado dá zero.
Exemplos:

  a = 1, b = 2, (a && b) = 1
  a = 1, b = 0, (a && b) = 0.

|| -> "or" para operações lógicas. O resultado dá zero quando o valor total de cada variável é zero, caso contrário dá 1.
Exemplos:

  a = 0, b = 0, (a || b) = 0
  a = 1, b = 0, (a || b) = 1.

& -> "and" para operações bit a bit. O resultado depende dos bits de cada variável.
Exemplos, considerando variáveis de 8 bits (ou seja, um byte ou char):

  a       = 1 (00000001b)
  b       = 2 (00000010b)
  (a & b) = 0 (00000000b)

  a       = 1 (00000001b)
  b       = 3 (00000011b)
  (a & b) = 1 (00000001b)

| -> "or" para operações bit a bit. O resultado depende dos bits de cada variável.
Exemplos, considerando variáveis de 8 bits (ou seja, um byte ou char):

  a       = 1 (00000001b)
  b       = 2 (00000010b)
  (a | b) = 3 (00000011b)

  a       = 1 (00000001b)
  b       = 3 (00000011b)
  (a | b) = 3 (00000011b)

O reset depende do que se pretenda. Geralmente usa-se o reset para o utilizador reiniciar o microcontrolador caso ele fique bloqueado ou entre numa situação falha para a qual não foi programado.

Os microcontroladores têm um terminal/pino de reset, no caso do Arduino Mega 2560 esse pino está disponível perto dos terminais de alimentação, podes ligar aí o teu botão de reset, quando accionado deve ligar o pino de reset ao GND. Ou então basta usar o botão de reset que a placa já traz.

No caso deste reset não é preciso desenvolver qualquer código, basta ligar a linha de reset momentâneamente ao GND que o microcontrolador reinicia automaticamente.

Esta informação é bastante básica, sugiro que faças uns tutoriais com o Arduino :slight_smile: aprende-se muito seguindo alguns tutoriais simples :wink:

Geralmente um botão de emergência tem os contactos normalmente fechados e está na linha de alimentação do dispositivo/bloco que se pretenda parar numa emergência. Se alguém premir o botão os contactos abrem e deixa de existir alimentação. Nesse caso não é necessário código.

Geralmente não é boa ideia fazer depender uma paragem de emergência de um sistema de uma variável de controlo no microcontrolador desse sistema. Se o microcontrolador estiver bloqueado ou em outra falha o botão de emergência poderá não ser processado. É mais seguro colocá-lo na linha de alimentação, aí o sistema pára de certeza :wink:

Deu uma aula agora, depois vou ler novamente sua explicação sobre as And e OR e vou tentar implementar algo mais simples pra entender bem.
Quanto ao Reset realmente não sabia que tinha um pino específico, fica bem mais fácil então, infelizmente no meu curso não conseguimos ir tão a fundo em praticar bem o arduino, um pouco por causa da pandemia pois ficamos estudando online e o outro motivo é a falta de suporte que tivemos e poucas aulas práticas, mas quem quer aprender corre atrás e é o que quero fazer.
Eu preciso que ele após detectar a faixa transversal pare, que será o momento em que uma pessoa retirará peças do carrinho e então movimente novamente ao acionar start, testei o novo exemplo que mandou e quando ele aciona algum sensor da direita ou esquerda ele está parando, estou olhando novamente a rotina do programa para ver se consigo corrigir.
Quanto ao botão emergência, já coloquei para parar os motores diretamente e está funcionando bem, mas pensei em além disso o arduino receber um sinal para parar a rotina também, pois caso contrario se a pessoa voltar o botão de emergencia sem acionar stop ou reset ele voltará a movimentar imediatamente.
Postei um video no youtube com o penultimo codigo e coloquei o link aqui pra mostrar o andamento, vai ficar um bom tutorial esse tópico.:slight_smile:

Faltava uma chaveta antes do else if ... :

else if (agv_run == 2) {  // AGV esta ligado e faixa transversal detectada?

Já editei o código anterior para:

} else if (agv_run == 2) {  // AGV esta ligado e faixa transversal detectada?

Não sei se será isto que está a causar a paragem quando vira para um dos lados.
Se não for isto não sei bem o que possa ser. O código para virar (direita/esquerda) é igual ao anterior que estava a funcionar.

Observando o código, o AGV só deveria parar no caso accionamento do botao stop ou deteccao de faixa transversal...

Ah, OK, então se o botão de emergência tem um contacto auxiliar pode ser ligado a um dos terminais do Arduino e efectuar a respectiva leitura dentro da função read_inputs().

Por exemplo:

void read_inputs() {
  Sensor1 = digitalRead(UT1);
  Sensor2 = digitalRead(UT2);
  Sensor3 = digitalRead(UT3);
  Sensor4 = digitalRead(UT4);
  
  if (digitalRead(Bot1)== LOW) {
    agv_run = 1;
  } else if (digitalRead(Bot2) == LOW) {
    agv_run = 0;
  }

  // Se o botao de emergencia esta' normalmente fechado entao
  // esta' normalmente a LOW. Quando e' accionado fica aberto
  // ficando o respectivo pino a HIGH.
  // Entao se a emergencia for detectada podemos parar os motores
  // colocando a variavel de controlo agv_run no estado 0.
  // O utilizador, depois de desactivar a emergencia tera de accionar
  // o start para prosseguir.
  if (digitalRead(Emergency) == HIGH) {
    agv_run = 0;
  }
}

Tal como para os outros botões, na função setup() será boa ideia activar o pullup no microcontrolador do botão de emergência (se não existir uma resistência pullup como nos outros dois botões):

pinMode(Emergency, INPUT_PULLUP);

Edit: Ah, e no bloco de código:

    // Verifica se a faixa transversal ja nao esta a ser detectada.
    if (!((Sensor1 == 1) && (Sensor2 == 1) && (Sensor3 == 1) && (Sensor4 == 1)) ) {
        det_faixa_transversal = 0;
    }

Falta mudar do estado 2 no agv_run para o estado 1 assim que a faixa transversal deixar de ser detectada:

    // Verifica se a faixa transversal ja nao esta a ser detectada.
    if (!((Sensor1 == 1) && (Sensor2 == 1) && (Sensor3 == 1) && (Sensor4 == 1)) ) {
        det_faixa_transversal = 0;
        agv_run = 1;
    }

(Já editei no código anterior também.)

Projecto bem interessante :+1: :slight_smile:

Coloquei agora com a sua edição e depois que ele para ele aceita o start e inicia novamente :slight_smile: verifiquei que a paragem que ele dá as vezes parece ser um problema dos sensores infra que as vezes algum perde a referência do piso e como já tem outro que pegou faixa (dois sensores interpretando faixa) ele para, o bom sería se ele parasse apenas quando todos os sensores interpretasse faixa, mas parece não é o que acontece.

Talvez o ajuste da distancia dos sensores ao piso ajude a melhorar a situação? Ou testar noutro piso.

Parece que no fim da tarde para a noite as falhas aumentam deve ser por falta de luz, vou testar novamente amanhã de dia. O local onde pretendo colocar o AGV tem o piso bem regular e totalmente branco daí acredito vai ser mais fácil controlar.

Olá meu amigo, percebeu no video que ao corrigir o trajeto o AGV da pequenos trancos? É porque no programa ele está setado para quando começar a sair da faixa ele pare o motor de um lado totalmente e apenas continue do outro até corrigir a trajetória, pensei de ao invés de ele parar totalmente ele apenas diminuir a velocidade de um motor. Não sei se é fácil de implementar isso no código pois pelo que entendi, por exemplo neste trecho ele seta se ligado ou desligado os motores.

   digitalWrite(7, 0);
  digitalWrite(8, 0);
  digitalWrite(4, 0);
  digitalWrite(9, 0);

E aqui ele seta as velocidades.

      analogWrite(5, 200);
      analogWrite(6, 200);

Consigo implementar o que descrevi sem mudar tudo?

(Acabei de montar os sensores ultrassonicos e vou testar o programa anti colisão também)

Olá.

Tendo como referência o AGV, penso que como está ele pára o motor da direita e mantém o da esquerda a rodar para virar à direita. E faz o inverso para virar à esquerda.

Então nesse caso, em vez desligar o motor ao virar é mantê-lo ligado e diminuir a respectiva velocidade. Exemplo da situação de viragem à direita, supondo que o pino 5 controla a velocidade do motor da direita:

    //virar a direita
    if ( ((Sensor1 == 1) && (Sensor2 == 0) && (Sensor3 == 0) && (Sensor4 == 0)) ||\
         ((Sensor1 == 0) && (Sensor2 == 1) && (Sensor3 == 0) && (Sensor4 == 0))) {
      digitalWrite(7, 1);   // Motor da esquerda? ON para virar a' direita.
      digitalWrite(8, 0);

      //digitalWrite(4, 0);  // Motor da direita? OFF para virar a' direita.
      digitalWrite(4, 1);    // Motor da direita? ON, mas lento para virar a' direita.
      digitalWrite(9, 0);
      //analogWrite(5, 200);
      analogWrite(5, 80);   // Velocidade do motor da direita? Diminuir velocidade.
      analogWrite(6, 200);  // Velocidade do motor da esquerda?
      delay(200);
    }
1 Like

Realmente foi como pensamos, ao invés de parar o motor eu diminuí a velocidade e ele faz as correções sem tantos trancos, ficou bem melhor.
Implementei e montei dois sensores ultrassonicos na frente anti colisão, testei e no primeiro obstaculo funcionou mas quando retirei ele voltou a rodar e saiu da faixa, tentando corrigir essa parte. Outro problema que deveria ser uma coisa simples é que coloquei uma luz na frente e outra atras pra acender quando ele estiver em movimento, mas quando liga a chave liga/desliga eles ja acendem, apesar de não ser um problema tao grave irá consumir muita bateria.
Segue o codigo até agora:

// Módulo seguidor de linha;
// Código AGV seguidor de linha.

int UT1 = 28;   //configura os pinos UT para sinais dos sensores infravermelhos
int UT2 = 26;
int UT3 = 24;
int UT4 = 22;
int Bot2 = 49;     //configura o pino 49 para botao 2 stop
int Bot1 = 47;     //configura o pino 47 para botao 1 start
int Green = 39;     //configura o pino 39 para acender o led verde e amarelo do andon (rele na/nf)
int Red = 41;      //configura o pino 41 para o led vermelho do andon
int Emergency = 51;   //configura o pino 51 para o botao emergencia
int Reset = 53;
int Buzzer = 43;    //configura o pino 43 para acionamento do buzzer do andon
int Luz = 45;     //configura o pino 45 para luz de posição dianteira e traseira
int trig1 = 14;    //configura o pino 14 da Arduino para conexão do Trig do sonar
int echo1 = 15;    //configura o pino 15 da Arduino para conexão do Echo do sonar
int trig2 = 14;    //configura o pino 14 da Arduino para conexão do Trig do sonar
int echo2 = 15;    //configura o pino 15 da Arduino para conexão do Echo do sonar

int Sensor1 = 0; //estado inicial dos sensores
int Sensor2 = 0;
int Sensor3 = 0;
int Sensor4 = 0;

// Variavel para guardar o estado de paragem/arranque
// do sistema com os botoes Start/Stop.
int agv_run = 0;

void read_inputs() {
 Sensor1 = digitalRead(UT1);
 Sensor2 = digitalRead(UT2);
 Sensor3 = digitalRead(UT3);
 Sensor4 = digitalRead(UT4);

 // Verificar o botao Start e Stop para actualizar a variavel agv_run 
 if (digitalRead(Bot1)== LOW) {
   agv_run = 1; // Botao start pressionado, activa o AGV.
 } else if (digitalRead(Bot2) == LOW) {
   agv_run = 0; // Botao stop pressionado, desactiva o AGV.
 }
}

void setup() {

 pinMode(UT1, INPUT); //definindo sensores como entrada de sinal
 pinMode(UT2, INPUT);
 pinMode(UT3, INPUT);
 pinMode(UT4, INPUT);
 pinMode(Bot1, INPUT_PULLUP); //define o pino de entrada do botão,PULLUP para evitar flutuação(ligar o botão ao GND)
 pinMode(Bot2, INPUT_PULLUP); //define o pino de entrada do botão,PULLUP para evitar flutuação(ligar o botão ao GND)
 pinMode(Emergency, INPUT);
 pinMode(Reset, INPUT);
 pinMode(Green, OUTPUT);
 pinMode(Red, OUTPUT);
 pinMode(Buzzer, OUTPUT);
 pinMode(Luz, OUTPUT);
 pinMode(trig1, OUTPUT);   //define o pino 14 como um output (envia sinal do sensor)
 pinMode(echo1, INPUT);    //define o pino 15 como um input (recebe sinal do sensor)
 pinMode(trig2, OUTPUT);   //define o pino 16 como um output (envia sinal do sensor)
 pinMode(echo2, INPUT);    //define o pino 17 como um input (recebe sinal do sensor)
    
    
 digitalWrite(4, 0); //definindo inicio de motores como parados
 digitalWrite(7, 0);
 digitalWrite(8, 0);
 digitalWrite(9, 0);

}

void loop() {

 // Actualiza as variaveis com o estado dos sensores e AGV On/Off.
 read_inputs();

 if (agv_run) {  // AGV esta activo/ligado?
  
   //motores em frente
   if ((Sensor1 == 0) && (Sensor2 == 0) && (Sensor3 == 0) && (Sensor4 == 0)) {
     digitalWrite(7, 1);
     digitalWrite(8, 0);

     digitalWrite(4, 1);
     digitalWrite(9, 0);
     digitalWrite(Green, LOW); //acende o verde e apaga o amarelo no Andon
     digitalWrite(Red, HIGH); //apaga o vermelho no Andon
     digitalWrite(Buzzer, LOW); //liga a campainha do Andon
     digitalWrite(Luz, LOW); //liga as luzes dianteira e traseira

     analogWrite(5, 250); //velocidade motores
     analogWrite(6, 250);
     delay(200);

   }

   //motores parados
   if ((Sensor1 == 1) && (Sensor2 == 1) && (Sensor3 == 1) && (Sensor4 == 1)) {
     digitalWrite(7, 0);
     digitalWrite(8, 0);

     digitalWrite(4, 0);
     digitalWrite(9, 0);

     analogWrite(5, 0);
     analogWrite(6, 0);

     delay(200);
   }

   //virar a direita
   if ( ((Sensor1 == 1) && (Sensor2 == 0) && (Sensor3 == 0) && (Sensor4 == 0)) ||\
        ((Sensor1 == 0) && (Sensor2 == 1) && (Sensor3 == 0) && (Sensor4 == 0))) {
     digitalWrite(7, 1);
     digitalWrite(8, 0);

     digitalWrite(4, 1);
     digitalWrite(9, 0);
     
     
     analogWrite(5, 150);
     analogWrite(6, 50);
     delay(200);
   }

   //virar à esquerda
   if ( ((Sensor1 == 0) && (Sensor2 == 0) && (Sensor3 == 1) && (Sensor4 == 0)) ||\
        ((Sensor1 == 0) && (Sensor2 == 0) && (Sensor3 == 0) && (Sensor4 == 1))) {
     digitalWrite(7, 1);
     digitalWrite(8, 0);

     digitalWrite(4, 1);
     digitalWrite(9, 0);

     analogWrite(5, 50);
     analogWrite(6, 150);
     delay(200);
   }

 } else {  // agv_run == 0, AGV esta parado...
   delay(200);
   digitalWrite(7, 0);
   digitalWrite(8, 0);

   digitalWrite(4, 0);
   digitalWrite(9, 0);

   analogWrite(5, 0);
   analogWrite(6, 0);
   digitalWrite(Green, HIGH); //apaga o verde e acende o amarelo no Andon
   digitalWrite(Red, LOW); //apaga o vermelho no Andon
 }
  float tempo1, tempo2, cm1, cm2;
    //comandos para enviar um pulso do sonar e armazenar o tempo de resposta
    digitalWrite(trig1, LOW);
    digitalWrite(trig2, LOW);
    delayMicroseconds(2);
    digitalWrite(trig1, HIGH); //ativa o sonar por 10 microssegundos
    digitalWrite(trig2, HIGH); //ativa o sonar por 10 microssegundos
    delayMicroseconds(10);
    digitalWrite(trig1, LOW);
    digitalWrite(trig2, LOW);
    delayMicroseconds(2);
    tempo1 = pulseIn(echo1, HIGH);  // tempo, recebe o tempo de ida e volta do sinal
    tempo2 = pulseIn(echo2, HIGH);  // tempo, recebe o tempo de ida e volta do sinal
    cm1 =  tempo1/29/2; //converte duration em centímetros
    cm2 =  tempo2/29/2; //converte duration em centímetro
    Serial.println(cm1);
    Serial.println(cm2);
    // Se cm1 menor ou igual a 60, desliga
    if (cm1 <= 60)
    {

   delay(200);
   digitalWrite(7, 0);
   digitalWrite(8, 0);

   digitalWrite(4, 0);
   digitalWrite(9, 0);

   analogWrite(5, 0);
   analogWrite(6, 0);
   digitalWrite(Green, HIGH); //apaga o verde e acende o amarelo no Andon
   digitalWrite(Red, LOW); //apaga o vermelho no Andon
 
    }
    // Se cm2 menor ou igual a 60, desliga motores
    if (cm2 <= 60)
    {

   delay(200);
   digitalWrite(7, 0);
   digitalWrite(8, 0);

   digitalWrite(4, 0);
   digitalWrite(9, 0);

   analogWrite(5, 0);
   analogWrite(6, 0);
   digitalWrite(Green, HIGH); //apaga o verde e acende o amarelo no Andon
   digitalWrite(Red, LOW); //apaga o vermelho no Andon
 
    }
    }

Do modo como o código está feito a detecção de obstáculo não parece impedir totalmente o prosseguimento do AGV. No fim da função loop(), ao detectar o obstáculo o AGV pára os motores, no entanto, quando o loop seguinte é iniciado o AGV pode iniciar novamente os motores (dependendo dos sensores de detecção de faixa) durante 200 ms por cada loop, seguindo-se outros 200ms de paragem. Ou seja, quando detecta obstáculo deve mover-se por impulsos. Não sei se será isso que origina o problema de sair da faixa.

Uma possibilidade, para evitar que o AGV se mova opós detecção de obstáculo, seria a existência de outra variável global de controlo para sinalizar essa detecção, por exemplo:

int det_obstaculo = 0;

Depois no inicio do loop é verificar o estado dessa variável junto com a do agv_run. Se AGV está a movimentar-se e não detecta obstáculo, prossegue, caso contrário, pára:

void loop() {

 // Actualiza as variaveis com o estado dos sensores e AGV On/Off.
 read_inputs();

 if (agv_run && !det_obstaculo) {  // AGV esta activo/ligado e não detecta obstaculo?
...

A variável det_obstaculo pode ser asserida no bloco de código quando é detectado o obstáculo (que pode ser substituído por um único if.. em vez de dois):

  if (cm1 <= 60 || cm2 <= 60) {
    det_obstaculo = 1;  // Obstaculo detectado.
    delay(200);
    digitalWrite(7, 0);
    digitalWrite(8, 0);

    digitalWrite(4, 0);
    digitalWrite(9, 0);

    analogWrite(5, 0);
    analogWrite(6, 0);
    digitalWrite(Green, HIGH); //apaga o verde e acende o amarelo no Andon
    digitalWrite(Red, LOW); //apaga o vermelho no Andon

  } else {
    det_obstaculo = 0;  // Obstaculo nao detectado.
  }

O único ponto onde a luz é actuada é no momento em que o AGV anda em frente. Então será necessário desligar a luz quando ele pára. Uma possibilidade será ligar e desligar a luz apenas no momento de detecção dos botões start e stop:

void read_inputs() {
  Sensor1 = digitalRead(UT1);
  Sensor2 = digitalRead(UT2);
  Sensor3 = digitalRead(UT3);
  Sensor4 = digitalRead(UT4);

  // Verificar o botao Start e Stop para actualizar a variavel agv_run 
  if (digitalRead(Bot1) == LOW) {
    agv_run = 1; // Botao start pressionado, activa o AGV.
    digitalWrite(Luz, LOW); //liga as luzes dianteira e traseira
  } else if (digitalRead(Bot2) == LOW) {
    agv_run = 0; // Botao stop pressionado, desactiva o AGV.
    digitalWrite(Luz, HIGH); //desliga as luzes dianteira e traseira
  }
}