quinta-feira, novembro 01, 2012

Motores de Passo: Aperfeiçoando o controle com Arduino e L293D

Vamos agora aperfeiçoar o que vimos no post anterior e operar em "full step" e acrescentar sensores de fim de curso. O driver utilizado continua sendo o L293D.



Full Step

Na operação Full Step, com um motor bipolar, acionamos sempre as duas bobinas do motor, de forma que uma esteja empurrando e a outra puxando. Isto resulta em maior torque e uma operação mais suave. A figura abaixo mostra a tensão aplicada nas bobinas.


Para implementar isto, utilizei um variável (que chamei de fase) que varia ciclicamente de 0 a 3. Para dar um passo basta posicionar as entradas das pontes H conforme o valor atual de fase:
void Passo ()
{
  switch (fase)
  {
    case 0:  // + -
      digitalWrite (L293_INP1, HIGH);
      digitalWrite (L293_INP2, LOW);
      digitalWrite (L293_INP3, LOW);
      digitalWrite (L293_INP4, HIGH);
      break;
    case 1:  // + +
      digitalWrite (L293_INP1, HIGH);
      digitalWrite (L293_INP2, LOW);
      digitalWrite (L293_INP3, HIGH);
      digitalWrite (L293_INP4, LOW);
      break;
    case 2:  // - +
      digitalWrite (L293_INP1, LOW);
      digitalWrite (L293_INP2, HIGH);
      digitalWrite (L293_INP3, HIGH);
      digitalWrite (L293_INP4, LOW);
      break;
    case 3:  // - -
      digitalWrite (L293_INP1, LOW);
      digitalWrite (L293_INP2, HIGH);
      digitalWrite (L293_INP3, LOW);
      digitalWrite (L293_INP4, HIGH);
      break;
  }
    delay (DELAY);
}
Para andar para frente ou para trás basta incrementar ou decrementar fase, em módulo 4. Para não precisar de divisão, pode ser usando um AND. O incremento fica

fase = (fase + 1) & 3;

O decremento poderia ser feito de outras formas, mas preferi aproveitar algumas propriedades da aritmética modular e usar

fase = (fase + 3) & 3;

Se quiser, experimente a fórmula com fase variando de 0 a 3 e confirme que o resultado varia, respectivamente,  de 3 a 0.

Sensor de Fim de Curso

Minha tentativa inicial foi usar botões simples para detectar quando o carro chega nos extremos. Entretanto, o motor não teve força suficiente para acioná-los. Passei então a usar reed relays acionados por um imã:


Um lado dos sensores é ligado direto a terra e o outro a uma entrada digital. Acionando os resistores de "pullup" internos ao ATmega, o sinal será alto quando o sensor nâo estiver acionado (chave aberta). Quando o sensor é acionado o sinal passa a ser lido em nível baixo.

Calibração

Resolvi não deixar fixo no software qual sensor indica qual extremo e quantos passos existem entre eles. A rotina de calibração obtêm automaticamente estas informações.
void Calibra ()
{
  digitalWrite (L293_ENA1, HIGH);
  digitalWrite (L293_ENA2, HIGH);
  
  // Afasta dos sensores
  fase = 0;
  if (digitalRead(FC1) == LOW)
  {
    for (int i = 0; i < 20; i++)
    {
      fase = (fase+1) & 3;
      Passo ();
    }
    if (digitalRead(FC1) == LOW)
    {
      for (int i = 0; i < 20; i++)
      {
        fase = (fase+3) & 3;
        Passo ();
      }
    }
  }
  if (digitalRead(FC2) == LOW)
  {
    for (int i = 0; i < 20; i++)
    {
      fase = (fase+1) & 3;
      Passo ();
    }
    if (digitalRead(FC2) == LOW)
    {
      for (int i = 0; i < 20; i++)
      {
        fase = (fase+3) & 3;
        Passo ();
      }
    }
  }

  // Procura o mínimo
  for (int limite = 10000; limite > 0; limite--)
  {
    fase = (fase+3) & 3;
    Passo();
    if (digitalRead(FC1) == LOW)
    {
      fcMin = FC1;
      fcMax = FC2;
      break;
    }
    if (digitalRead(FC2) == LOW)
    {
      fcMin = FC2;
      fcMax = FC1;
      break;
    }
  }
  
  // Procura o maximo
  posMax = 0;
  for (int limite = 10000; limite > 0; limite--)
  {
    posMax++;
    fase = (fase+1) & 3;
    Passo();
    if (digitalRead(fcMax) == LOW)
      break;
  }
  posAtual = posMax;
  
  digitalWrite (L293_ENA1, LOW);
  digitalWrite (L293_ENA2, LOW);
}
O código completo pode ser baixado dos arquivos do blog (está no arquivo L293D_Passo3.zip). O vídeo abaixo mostra o teste em funcionamento:








Nenhum comentário: