segunda-feira, 3 de novembro de 2014

Carrinho estilo tanque controlado por smartphone android



Introdução

Olá! Neste artigo vou mostrar como fazer um carrinho estilo tanque controlado por um smartphone android.
Antes de eu começar, já vou avisando que eu não sou expert em eletrônica. Sou Bacharel em Sistemas de Informação e sei quase nada de eletrônica. Então, se você que está lendo for um fera na eletrônica não critique meu humilde trabalho. Dê sugestões para que eu possa deixar meu carrinho ainda melhor.
Este carrinho é um trabalho que fiz para apresentar no meu primeiro semestre da minha pós em Sistemas Embarcados. Esta pós é da Engenharia Eletrônica. Estou fazendo esta pós porque sou fascinado por eletrônica, robótica, automação e coisas do tipo. Bom, é isto! Chega de falatório e vamos à ação!


Lista de materiais

Quantidade
Descrição
1
1
CI L293D (ponte H dupla);
1
CI LM7805 (Regulador de tensão - 5v);
2
Capacitores eletrolíticos (470µF; tensão 16V);
2
Capacitores cerâmicos (0,1µF; tensão 6,3V);
1
Interruptor simples;
2
Baterias 18650 de 3,7v de 5800mAh com suporte;
1
1
1
1

Obviamente você irá precisar também de outros materiais para soldar, fazer a placa e conectar, mas estes listados acima são os essenciais para o projeto. Se houver alguma dúvida com relação aos outros materiais entre em contato.


Mecânica

Não tem muito o que ser dito sobre a parte mecânica, as imagens falam por si:


Motores e caixas de redução
Esteira
Suporte dos motores e esteira
Suporte com os motores, caixas de redução e esteira

Microcontrolador

Caixa aberta do microcontrolador 
Microcontrolador em detalhe

Todas as peças e a placa eletrônica já confeccionada

Esteira, suporte e caixa de redução com os motores

Detalhe na caixa de redução

Placa eletrônica já completa
(Tem mais componentes do que mostra o esquemático.
Os componentes extras são para que ela funcione com RF)

Detalhe do módulo bluetooth HC-06

Placa vista de frente

Placa vista de cima

Estas são baterias 18650 de 3,7v e 5800mAh.
São usadas por policiais em lanternas táticas.
Não confunda com pilhas AA.

Detalhe da Launchpad, com o microcontrolador no centro

Projetei minha placa para encaixar e usar os pinos da Launchpad.

Quase tudo pronto

Sanduíche

Tudo junto e funcionando

Tela do aplicativo android antes de conectar ao carrinho

Tela do aplicativo depois de conectar ao carrinho.
Deslize as barrinhas azuis sobre as cinzas para controlar os motores.





Eletrônica

Como você poderá observar abaixo, a parte eletrônica do projeto é muitíssimo simples, justamente pelo fato de eu não possuir muitos conhecimentos na área e também por ser esta a minha intenção: um projeto simples e funcional.

Este esquemático foi feito no Fritzing. Baixe-o aqui.
Observações importantes:

  1. O módulo de bluetooth usado não é o que está no esquemático. Ele está lá apenas para ilustrar as conexões. Use o bluetooth do link na lista de materiais ou similar;
  2. Quando você for parear o android com o carrinho ele irá pedir uma senha, que normalmente é 1234 ou 0000. Esta senha já vem definida no módulo bluetooth;
  3. O microcontrolador não deverá ser usado sozinho, mas sim com a sua Launchpad. O VCC deverá ser ligado no TP1 e o GND deverá ser ligado no TP3 (procure estes 'buraquinhos' próximo à porta USB da Launchpad).


Softwares

Este carrinho precisa de dois programas para funcionar: um no smartphone android e outro no microcontrolador.

Basicamente o android conecta com o carrinho e envia 8 bits por vez para que o programa dentro do microcontrolador do carrinho possa decodificar estes 8 bits e executar.


1 - Aplicativo Android

Você poderá fazer o download do aplicativo do carrinho aqui. Só instalar e se divertir!
Porém, se você quiser baixar o código-fonte do aplicativo, para estudar, modificar e compilar na sua máquina, clique aqui.
Pretendo futuramente publicar a minha versão do código-fonte do aplicativo android no github. Ela está mais estável do que esta versão do link acima.


2 - Programa para o carrinho

O programa do microcontrolador MSP430 foi escrito em C usando um software chamado Energia. Se você já brincou com arduino vai gostar muito do Energia, pois ele é uma cópia do software usado para criar os programas que rodam no arduino, porém adaptado para os microcontroladores da Texas Instruments.
Simplesmente abra este código (ou copie abaixo) no Energia, compile e faça o upload para o microcontrolador:


//Pino de alimentação do microcontrolador
#define ANALOG_HALFVCC_INPUT 11

volatile unsigned int dc1 = 0;  //Rotacao do Motor1 (esquerdo)
volatile unsigned int dc2 = 0;  //Rotacao do Motor2 (direito)

static const unsigned int periodo = 3472;
static const unsigned int dc_incr = 112;  // periodo/resolucao (3472 / 31)

//Pinos de saida para a ponte H (L293D) para controlar os Motores
const unsigned int motEsqFrente =   6; //(P1.4) Motor esquerdo para frente
const unsigned int motEsqTras   =   7; //(P1.5) Motor esquerdo para tras
const unsigned int motDirFrente =  15; //(P1.7) Motor direito para frente
const unsigned int motDirTras   =  14; //(P1.6) Motor direito para tras

//Pinos de saida para a ponte H (L293D) para fazer o PWM
const unsigned int motEsqPWM    =   9; //(P2.1) Saida para o pino Enable 1 do L293D
const unsigned int motDirPWM    =  12; //(P2.4) Saida para o pino Enable 2 do L293D

void setup()
{
  if(tensaoCorreta())
  {
    DCOCTL = CALDCO_8MHZ;

    //Mantendo o LED indicador de baixa tensao desligado
    pinMode(RED_LED, OUTPUT);
    digitalWrite(RED_LED, LOW);
 
    //"Inicializando" a ponte H:
    pinMode(motEsqFrente, OUTPUT);
    pinMode(motEsqTras, OUTPUT);
    pinMode(motDirFrente, OUTPUT);
    pinMode(motDirTras, OUTPUT);
    pinMode(motEsqPWM, OUTPUT);
    pinMode(motDirPWM, OUTPUT);
    pararTodos();

    Serial.begin(9600);
  }
  else
  {
    //Acende o LED vermelho da MSP para informar baixa tensao no microcontrolador.
    pinMode(RED_LED, OUTPUT);
    digitalWrite(RED_LED, HIGH);
  }
}

void loop()
{
  if (Serial.available() > 0)
  {
    char c = Serial.read();

    if (c & 0x80)
    {
      pararTodos();
    }
    else
    {
      char frente = (c & 0x20);
      char acelerador = (c & 0x1F);

      if (c & 0x40)
      {
        //Este e o motor 1 (esquerdo)
        if (frente)
        {
          dc1 = (~acelerador & 0x1F) * dc_incr;
       
          if(dc1 != periodo)
          {
            //Velocidade do motor
            int vel = periodo - dc1;
            int velMap = map(vel, 0, periodo, 0, 255);
            //Adicionando 10% ao motor (inercia)
            int velAdd = (velMap + 25) > 255 ? 255 : velMap + 25;
         
            analogWrite(motEsqPWM, velAdd);
            digitalWrite(motEsqTras, LOW);
            digitalWrite(motEsqFrente, HIGH);
          }
          else
          {
            digitalWrite(motEsqPWM, LOW);
            digitalWrite(motEsqTras, LOW);
            digitalWrite(motEsqFrente, LOW);
          }
        }
        else
        {
          dc1 = acelerador * dc_incr;
          //Velocidade do motor
          int velMap = map(dc1, 0, periodo, 0, 255);
          //Adicionando 10% ao motor (inercia)
          int velAdd = (velMap + 25) > 255 ? 255 : velMap + 25;
       
          analogWrite(motEsqPWM, velAdd);
          digitalWrite(motEsqFrente, LOW);
          digitalWrite(motEsqTras, HIGH);
        }
      }
      else
      {
        //Este e o motor 2 (direito)
        if (frente)
        {
          dc2 = (~acelerador & 0x1F) * dc_incr;

          if(dc2 != periodo)
          {
            //Velocidade do motor
            int vel = periodo - dc2;
            int velMap = map(vel, 0, periodo, 0, 255);
            //Adicionando 10% ao motor (inercia)
            int velAdd = (velMap + 25) > 255 ? 255 : velMap + 25;
         
            analogWrite(motDirPWM, velAdd);
            digitalWrite(motDirTras, LOW);
            digitalWrite(motDirFrente, HIGH);
          }
          else
          {
            digitalWrite(motDirPWM, LOW);
            digitalWrite(motDirTras, LOW);
            digitalWrite(motDirFrente, LOW);
          }
        }
        else
        {
          dc2 = acelerador * dc_incr;
          //Velocidade do motor
          int velMap = map(dc2, 0, periodo, 0, 255);
          //Adicionando 10% ao motor (inercia)
          int velAdd = (velMap + 25) > 255 ? 255 : velMap + 25;
       
          analogWrite(motDirPWM, velAdd);
          digitalWrite(motDirFrente, LOW);
          digitalWrite(motDirTras, HIGH);
        }
      }
    }
  }
}

//Informa se a tensao e suficiente para o microcontrolador
boolean tensaoCorreta()
{
  //Retorno da validacao
  boolean retorno = true;

  //Inicia com a referência interna de 1,5 volt
  analogReference(INTERNAL1V5);
  int data = analogRead(ANALOG_HALFVCC_INPUT);

  if (data < 0x3ff)
  {
    retorno = false;
  }

  //Retonando para a referencia analogica padrao
  analogReference(DEFAULT);

  return retorno;
}

void pararTodos()
{
    digitalWrite(motEsqFrente, LOW);
    digitalWrite(motEsqTras, LOW);
    digitalWrite(motDirFrente, LOW);
    digitalWrite(motDirTras, LOW);
    digitalWrite(motEsqPWM, LOW);
    digitalWrite(motDirPWM, LOW);
}


Resultado final





Nenhum comentário: