Postagem em destaque

Controle PID de Potência em Corrente Alternada - Arduino e TRIAC - Parte I

Este post é o primeiro de uma série de seis que escrevi tratando de controle de potência e PID (controle proporcional, integral e derivativo...

terça-feira, 21 de abril de 2015

Automação no Parque, 18/04/2015

O Automação no Parque está vivendo um bom momento, com alguns projetos desafiadores rolando.

Logo cedo (7:00) chega a Alessandra, que está se inciando com o Arduino. Ela tem que ir embora antes das nove pro trabalho, por isso madruga. Estamos fazendo oficinas básicas de Arduino.


Tem o Rodrigo, com o seu projeto de sensores para a indústria do qual já andei falando e sobre o qual falarei mais na frente.

Tem uma dupla, o Alex e o Carlos (kbca) que estão fazendo coisas muito legais com o LeapMotion, que é nada mais nada menos que um detector de movimentos das mãos que permite o comando de aplicações (jogos etc) no computador usando-se o movimento das mãos.

Os caras estão fazendo um jogo de JoKenPo  (pedra-papel-tesoura), e o PC já tá ganhando todas!

Tem também o Fábio com o seu braço robótico, cortado por ele mesmo em sua máquina de corte à laser:




Quem quiser comprar um ele vende, viu galera? É um "brinquedo" e tanto, e dá cada TCC... ;)

Outro projeto que apareceu por lá é o do Filipe, que quer comandar uma mão robótica (que ele imprimiu numa impressora 3D) através de sinais elétricos captados no braço de uma pessoa. Assim, uma pessoa que não tivesse uma das mãos (ou as duas) poderia manipular objetos usando o device que ele está construindo.


No projeto do Filipe surgiu uma demanda intessante: a mão é comandada por dois servos, um aciona os quatro dedos "compridos" e o outro o dedão. Aí já dá para fazer os movimentos de "pegar" e de "pinça".

Supondo que um determinado movimento implique em acionar num dos motores (chamemos de motor1) de maneira a sair da posição em que se encontra (digamos, 30°, p1) até a posição 100°, np1, enquanto que o motor2 tem que sair de 120° (p2) para 90° (np2).

A saída fácil seria acionar motor1 para se mover da posição p1 até np1 e depois motor2 de p2 até np2.

Ocorre que a gente não move os dedos dessa forma, ou seja, primeiro os quatro e depois o dedão, mas sim todos os cinco simultaneamente.

O desafio, então, é: girar os dois motores simultaneamente de suas posições iniciais até as finais de maneira a que o movimento termine simultaneamente. Ou seja, como motor1 tem que girar 70° e motor2 tem que girar apenas 40° (e na direção contrária), o motor1 tem que se movimentar mais devagar que o motor2.

Após quebrar a cabeça por um tempo, construímos a função posiciona que aparece no programa abaixo:
#include <Servo.h>

// assismauro@hotmail.com
// Ver vídeo em https://youtu.be/5d2tg_7dvi0)

Servo motor1;
Servo motor2;

int val;

// Função posiciona: gira dois motores simultaneamente de modo a
// atingirem suas novas posições simultãneamente
//
// np1: nova posição do motor1
// np2: nova posição do motor2
void posiciona(float np1, float np2)
{
  // Começamos lendo  posição atual de cada motor
  float p1=motor1.read();
  float p2=motor2.read();
  // Em seguida, calculamos a distância, em graus, entre as posições
  // atuais e as novas.
  // Observem que trabalhamos com variáveis float, para diminuir os
  // erros de arredondamento.
  float d1=np1-p1;
  float d2=np2-p2;
  // pc1 e pc2 são as posições correntes, que serão incrementadas 
  // durante o movimento.
  float pc1=p1;
  float pc2=p2;
  // Aqui tá o "pulo" do gato: São calculados s1 (passo do motor1) e
  // s2 (passo do motor2). Eles são o incremento que será dado a cada
  // movimento do motor. s1 será a razão entre d1 e d2, enquanto que
  // s2 será igual à razão entre d2 e d2 (ou seja, 1). Usamos valores
  // absolutos no denominador para preservar o sinal, ou seja, se d1
  // é negativo, s1 também será negativo.
  //
  // Ex:
  //
  // Suponhamos que d1 seja -50 e d2 seja 100. Nesse caso, s1=-0.5 e
  // s2=1. Ou seja, motor1 andará 0.5° para cada 1° que motor2 andar.
  // Ao fim do movimento motor2 terá girado o dobro do que 
  // girou o motor1.
  float s1=d1/abs(d2);
  float s2=d2/abs(d2);
  //
  // imprime os valores calculados, para debug, mostrando na tela
  // os valores calculados
  Serial.print(np1);
  Serial.print(' ');
  Serial.print(np2);
  Serial.print(' ');
  Serial.print(p1);
  Serial.print(' ');
  Serial.print(p2);
  Serial.print(' ');
  Serial.print(d1);
  Serial.print(' ');
  Serial.print(d2);
  Serial.print(' ');
  Serial.print(pc1);
  Serial.print(' ');
  Serial.print(pc2);
  Serial.print(' ');
  Serial.print(s1);
  Serial.print(' ');
  Serial.print(s2);
  Serial.println();
  // Aqui giramos os dois motores, até que ambos tenham assumido
  // a sua posição final, ou seja:
  // enquanto a diferença absoluta entre a posição atual e a nova
  // posição de cada motor for > 1, eu continuo girando.
  while((abs(pc1-np1) > 1) || (abs(pc2-np2) > 1))
  {
    // Somo o incremento à posição corrente de cada motor
    pc1=pc1+s1;
    pc2=pc2+s2;
    // Mostro os valores na tela
    Serial.print(pc1);
    Serial.print(' ');
    Serial.println(pc2);
    // Giro os motores para suas novas posições
    motor1.write(pc1);
    motor2.write(pc2);
    // Dou um tempo de 20 milissegundos para que os motores
    // atinjam a nova posição.
    delay(20);
  }
}

void setup()
{
  // Associo os motores aos pinos que estão conectados.
  motor1.attach(9);
  motor2.attach(10);
  // Inicializo a comunicação com o PC
  Serial.begin(9600);
  // Coloco os dois motores na posição 0
  motor1.write(0);
  motor2.write(0);
}

void loop()
{
  // Para demonstrar a rotina, o programa posiciona os
  // servos em diferentes ângulos.
  posiciona(90,45);
  delay(500);
  posiciona(178,90);
  delay(500);
  posiciona(45,10);
  delay(500);
  posiciona(145,60);
  delay(500);
}

Decidi explicar no código porque achei que talvez ficasse mais fácil.

Aqui o vídeo do programa rodando, acionando os motores:


DESAFIO: observando o código que escrevi e o vídeo vc saberia me dizer quem é o motor2 e quem é o motor1, e porque vc chegou a essa conclusão?

Respostas nos comentários abaixo.

Abracadabraço,

Mauro Assis