Seguindo com as publicações de meus protótipos com o Arduino, hoje mostro o Luminolaser. Será nos mesmos moldes da última publicação, resumido e direto (ou seja, conhecimento prévio se fará necessário).

O objetivo do Luminolaser foi, principalmente, estudar o uso de Servo Motores e o controle sob eles. Sempre tentando criar algo um pouco além do simples exemplo, procurei fazer uma espécie de scanner de ambiente que identifica o ponto mais luminoso (eu só tinha um sensor de luminosidade – LDR – a disposição) e marca esse ponto com um laser pointer.

Posteriormente incrementei um pouco mais de modo que fosse possível controlar o laser através de um controle analógico.

Bem, vamos aos materiais usados:

  • Arduino “Brasileirino” (Duemilanove) ATMega328 [Arduino Uno];
  • Bateria recarregável de 9V [Deal Extreme];
  • Bateria de 4V de alta descarga para alimentar o módulo laser;
  • Bateria de 7,4V de alta descarga para os servos;
  • 2 Mini Servos Motores [Deal Extreme];
  • Módulo de laser vermelhor 5mW [Deal Extreme];
  • Botão de lanterna para mudar a função do protótipo [Deal Extreme];
  • Muitos fios conectores para protoboard [Deal Extreme];
  • Analógico do PSP [Deal Extreme];
  • LDR (sensor de luminosidade) [Wiki].
  • Transistor NPN Tip122 [Wiki];

Como pode-se notar, existem muitos componentes from China. Realmente acredito que valha a pena, principalmente quando não existe pressa para receber os produtos.

À esquemática:

lumino_laser

Observem que, por não ter uma imagem do controle analógico para o Fritzing, acabei substituindo por 2 potenciômetros rotatórios… Até porque são equivalentes. Assim como o Led vermelho da imagem simboliza o módulo do laser.

E para simplificar a visualização, incluí apenas 1 servo motor na esquemática e separei os componente. Na versão final o laser e o LDR ficam juntos na ponta do segundo servo.

O botão incluí para alterar o modo de controle dos servos entre automático (busca o ponto mais luminoso do ambiente) e manual (permitindo o direcionamento do laser através do controle analógico).

Now it’s time to code!

#include <Servo.h> 
 
Servo servo_base;
Servo servo_upper;
 
//Posição dos servos inferior e superior
int servo_base_pos = 0;
int servo_upper_pos = 0;
 
//Posição para onde os servos devem se mover
//para apontar onde está a mais forte fonte de luz
int final_base_pos = 0;
int final_upper_pos = 0;
 
//Pinos dos servos, sensor ldr e sinal do laser
int servo_base_pin = 5;
int servo_upper_pin = 3;
int ldr_pin = 5;
int laser_pin = 13;
 
//Pinos do analógico e do botão
int dpad_x = 0;
int dpad_y = 1;
int button_pin = 8;
 
void setup() 
{ 
  servo_base.attach(servo_base_pin);
  servo_upper.attach(servo_upper_pin);
  pinMode(laser_pin, OUTPUT);
  pinMode(button_pin, INPUT);
} 
 
void loop() 
{ 
  if(verificaClick()) {
    //Função de direcionamento manual do laser
    ligarLaser();
    readAnalogPad();
    direcionaLaser();
  } else {
    //Busca automática pela maior luminosidade
    desligaLaser();
    buscaMaiorLuminosidade_1();
    direcionaLaser();
    ligarLaser();
    delay(10000);
  }
}
 
//Percorre todo o alcance dos servos buscando a maior luminosidade
//detectada pelo LDR e salva essa posição para mover depois
void buscaMaiorLuminosidade_1() {
  int maior_luminosidade = 0;
 
  for(servo_base_pos = 0; servo_base_pos < 180; servo_base_pos += 20) 
  {
    servo_base.write(servo_base_pos);
    delay(500);
    for(servo_upper_pos = 0; servo_upper_pos < 180; servo_upper_pos += 5) 
    {
      servo_upper.write(servo_upper_pos);
      delay(100);
      if(verificaClick()) {
        //Se o botão foi clicado, encerra a busca
        return;
      }
 
      int ldr = obtemLuminosidade();
      if(ldr > maior_luminosidade) {
        maior_luminosidade = ldr;
        final_base_pos = servo_base_pos;
        final_upper_pos = servo_upper_pos;
      }
    }
 
    servo_upper.write(0);
  }
 
  servo_base.write(0);
}
 
int obtemLuminosidade() {
  return analogRead(ldr_pin);
}
 
void direcionaLaser() {
  servo_upper.write(final_upper_pos);
  servo_base.write(final_base_pos);
}
 
void ligarLaser() {
  digitalWrite(laser_pin, HIGH);
}
 
void desligaLaser() {
  digitalWrite(laser_pin, LOW);
}
 
boolean verificaClick() {
  return digitalRead(button_pin) == HIGH;
}
 
//Obtem a leitura do controle analógico.
//Devido à baixa qualidade do mesmo, não foi possível fazer 
//simplesmente um mapeamento do sinal de entrada para a posição final.
void readAnalogPad() {
  int analog_x = analogRead(dpad_x);
  int analog_y = analogRead(dpad_y);
 
  int y = 0;
  int x = 0;
 
  if(analog_y > 620) {
    y = analog_y > 680 ? 5 : 1;
  } else if(analog_y < 540) {
    y = analog_y < 480 ? -5  : -1;
  } else {
    y = 0;
  }
 
  if(analog_x > 330) {
    x = analog_x > 380 ? 5 : 1;
  } else if(analog_x < 280) {
    x = analog_x < 190 ? -5 : -1;
  } else {
    x = 0;
  }
 
  final_upper_pos = final_upper_pos + y;
  final_base_pos = final_base_pos - x;
 
  final_upper_pos = final_upper_pos > 180 ? 180 : final_upper_pos;
  final_upper_pos = final_upper_pos < 0 ? 0 : final_upper_pos;
 
  final_base_pos = final_base_pos > 180 ? 180 : final_base_pos;
  final_base_pos = final_base_pos < 0 ? 0 : final_base_pos;
 
  delay(100);
}

Existem algumas melhorias para serem feitas no código, mas uma funcionalidade adicional que quero implementar é a capacidade de seguir. Imagino que seja possível fazer isso através de micro ajustes (ou micro buscas em uma área menor). Assim, teoricamente, seria possível seguir a fonte de luz mesmo se houver deslocamento da mesma. Além disso, pretendo trocar o sensor de luminosidade por um sensor de infra vermelho e, se funcionar como eu espero, poder detectar e seguir fontes de calor, como o corpo humano.

Bem, por fim vamos ao resultado final atual:

Por hora é só… Quando eu tiver tempo de dar um upgrade nesse protótipo, edito esse post para incluir as alterações.

Share