quarta-feira, 15 de junho de 2011

Código do robô

Iremos dividir o código abaixo em funções para que fique melhor organizado. O código abaixo foi testado e funciona perfeitamente:

/*
Atenção para que o robô possa funcionar corretamente as seguintes regras devem valer:

 1. Se fótoscópio norte é o 1 (ligado na serial 0) servo do norte é o 2 (ligado na digital pwm 5);
 2. Se fótoscópio sul é o 2 (ligado na serial 1) servo do sul é o 1 (ligado na digital pwm 3);
 3. Se fótoscópio leste é o 3 (ligado na serial 3) servo do leste é o 4 (ligado na digital pwm 9);
 4. Se fótoscópio oeste é o 4 (ligado na serial 4) servo do oeste é o 3 (ligado na digital pwm 6);
*/

#include <Servo.h>                 //Esta biblioteca contem as operações para manuseio e reconhecimento dos servos
Servo servo[4];                    //Cria um vetor do tipo servo para os 4 servos (o tipo servo é tipo importado da biblioteca servo.h)

//cria constantes inteiras relativas as portas de entrada analógicas
const int pinLDRtower1 = 0;       //pino do fótoscópio 1 na porta 0, etc...
const int pinLDRtower2 = 1;
const int pinLDRtower3 = 2;
const int pinLDRtower4 = 3;

//criação das variáveis
int LDRtower[5];                   //variável do tipo número inteiro que irá receber a tensão do circuito do fotoscópio
int sensibilidade = 390;           //variável do tipo número inteiro indicando a quantidade mínima de bits recebidos pela porta analógica quando ha presença e luz
int contador;                      //variável do tipo número inteiro que servirá de contador. Será usado para comparar qual fótoscópio recebeu sinal maior
int daVez;                         //variável que irá definir qual fótoscópio o robô tem que seguir (qual é o da vez)
int fonteLuzDetectada;             //variável do tipo número inteiro que servirá de semáforo para dar inicio aos movimentos do robô caso haja uma fonte emisora de fótons

void setup(){
  //mostrar para o CI onde estão ligados os Servos
  servo[0].attach(3); //servo 0 corresponde ao primeiro servo ligado na porta 3, assim por diante...
  servo[1].attach(5);
  servo[2].attach(6);
  servo[3].attach(9);

  //inicializo cada valor do vetor que recebe os valores do fótoscópio com 0
  for(contador = 1; contador < 5; contador++){
    LDRtower[contador] = 0;
  }

  //inicializo o funcionamento da porta serial com leitura 9600bps (bps = bites por segundo)
  Serial.begin(9600);
}

void zerarVarDeControle(int daVez, int fonteLuzDetectada){
  //zerar as variáveis que iram definir qual lado o robô deve seguir
  daVez = 0;
  fonteLuzDetectada = 0;
}

void receberLeiturasAssociandoFotoscopioaPino(int LDRtower[4], int pinLDRtower1, int pinLDRtower2, int pinLDRtower3, int pinLDRtower4){
  //faz com que cada valor do vetor de fótoscopios receba as medidas de suas respectivas portas
  LDRtower[1] = analogRead(pinLDRtower1); //A torre do LDR 1 recebe os valores da porta analógica 0 (pinLDRtower1), e assim por diante...
  LDRtower[2] = analogRead(pinLDRtower2);
  LDRtower[3] = analogRead(pinLDRtower3);
  LDRtower[4] = analogRead(pinLDRtower4);
}

void funcaoDeixarRobodePe(Servo servo[4]){
  //deixa o robô em pé colocando todos os servos num angulo de 90º
  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(90);
}

int verificaRecepcaoLuminosa(int contador, int LDRtower[4], int sensibilidade, int fonteLuzDetectada){
  //verifica se algum fotoscopio recebeu sinal luminoso
  for (contador = 1; contador < 5; contador++){
    if (LDRtower[contador] > sensibilidade) fonteLuzDetectada = 1;
  }
  return(fonteLuzDetectada);
}

int achaMaior(int daVez, int contador, int LDRtower[4]){
  //verifica qual fotoscopio recebeu sinal maior e taxa-o como daVez
  daVez = 1;
  for (contador = 2; contador < 5; contador++) if (LDRtower[daVez] < LDRtower[contador]) daVez = contador;
  return(daVez);
}

void irEmDirecaoAoFotoscopio1(Servo servo[4]){
  //movimento de sincrono que inicia a movimentação do robô em direção ao fotoscopio 1:
 
  //deita uma perna
  servo[0].write(45);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(90);
  delay(500);

  servo[0].write(0);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(90);
  delay(500);

  //deita a outra
  servo[0].write(0);
  servo[1].write(135);
  servo[2].write(135);
  servo[3].write(135);
  delay(500);

  servo[0].write(0);
  servo[1].write(180);
  servo[2].write(180);
  servo[3].write(180);
  delay(100);

  //pula!
  servo[0].write(180);
  servo[1].write(0);
  servo[2].write(180);
  servo[3].write(180);
  delay(500);

  //levanta uma perna
  servo[0].write(135);
  servo[1].write(0);
  servo[2].write(135);
  servo[3].write(135);
  delay(500);

  servo[0].write(90);
  servo[1].write(0);
  servo[2].write(90);
  servo[3].write(90);
  delay(500);

  //levanta a outra
  servo[0].write(90);
  servo[1].write(45);
  servo[2].write(90);
  servo[3].write(90);
  delay(500);

  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(90);
  delay(500);
}

void irEmDirecaoAoFotoscopio2(Servo servo[4]){
  //movimento de sincrono que inicia a movimentação do robô em direção ao fotoscopio 2:
 
  //deita uma perna
  servo[0].write(90);
  servo[1].write(45);
  servo[2].write(90);
  servo[3].write(90);
  delay(500);

  servo[0].write(90);
  servo[1].write(0);
  servo[2].write(90);
  servo[3].write(90);
  delay(500);

  //deita a outra
  servo[0].write(135);
  servo[1].write(0);
  servo[2].write(135);
  servo[3].write(135);
  delay(500);

  servo[0].write(180);
  servo[1].write(0);
  servo[2].write(180);
  servo[3].write(180);
  delay(100);

  //pula!
  servo[0].write(0);
  servo[1].write(180);
  servo[2].write(180);
  servo[3].write(180);
  delay(500);

  //levanta uma perna
  servo[0].write(0);
  servo[1].write(135);
  servo[2].write(135);
  servo[3].write(135);
  delay(500);

  servo[0].write(0);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(90);
  delay(500);

  //levanta a outra
  servo[0].write(45);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(90);
  delay(500);

  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(90);
  delay(500);
}

void irEmDirecaoAoFotoscopio3(Servo servo[4]){
  //movimento de sincrono que inicia a movimentação do robô em direção ao fotoscopio 3:
 
  //deita uma perna
  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(45);
  servo[3].write(90);
  delay(500);

  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(0);
  servo[3].write(90);
  delay(500);

  //deita a outra
  servo[0].write(135);
  servo[1].write(135);
  servo[2].write(0);
  servo[3].write(135);
  delay(500);

  servo[0].write(180);
  servo[1].write(180);
  servo[2].write(0);
  servo[3].write(180);
  delay(100);

  //pula!
  servo[0].write(180);
  servo[1].write(180);
  servo[2].write(180);
  servo[3].write(0);
  delay(500);

  //levanta uma perna
  servo[0].write(135);
  servo[1].write(135);
  servo[2].write(135);
  servo[3].write(0);
  delay(500);

  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(0);
  delay(500);

  //levanta a outra
  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(45);
  delay(500);

  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(90);
  delay(500);
}

void irEmDirecaoAoFotoscopio4(Servo servo[4]){
  //movimento de sincrono que inicia a movimentação do robô em direção ao fotoscopio 4:
 
  //deita uma perna
  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(45);
  delay(500);

  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(0);
  delay(500);

  //deita a outra
  servo[0].write(135);
  servo[1].write(135);
  servo[2].write(135);
  servo[3].write(0);
  delay(500);

  servo[0].write(180);
  servo[1].write(180);
  servo[2].write(180);
  servo[3].write(0);
  delay(100);

  //pula!
  servo[0].write(180);
  servo[1].write(180);
  servo[2].write(0);
  servo[3].write(180);
  delay(500);

  //levanta uma perna
  servo[0].write(135);
  servo[1].write(135);
  servo[2].write(0);
  servo[3].write(135);
  delay(500);

  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(0);
  servo[3].write(90);
  delay(500);

  //levanta a outra
  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(45);
  servo[3].write(90);
  delay(500);

  servo[0].write(90);
  servo[1].write(90);
  servo[2].write(90);
  servo[3].write(90);
  delay(500);
}

//função padrão do Arduino, pode ser interpretada como principal, e fica em constante loop
void loop(){
  //zerar as variáveis que iram definir qual lado o robô deve seguir
  zerarVarDeControle(daVez, fonteLuzDetectada);

  //faz com que cada valor do vetor de fótoscopios receba as medidas de suas respectivas portas
  receberLeiturasAssociandoFotoscopioaPino(LDRtower, pinLDRtower1, pinLDRtower2, pinLDRtower3, pinLDRtower4);

  //deixa o robô em pé colocando todos os servos num angulo de 90º
  funcaoDeixarRobodePe(servo);

  //verifica se algum fótoscópio recebeu o sinal luminoso
  fonteLuzDetectada = verificaRecepcaoLuminosa(contador, LDRtower, sensibilidade, fonteLuzDetectada);

  //se recebeu quem recebeu o sinal maior
  if (fonteLuzDetectada == 1){
    daVez = achaMaior(daVez, contador, LDRtower);
    //uma vez que se sabe qual é o maior sinal luminoso de acordo com a variável daVez, executa-se seu respectivo movimento de acordo com o valor de daVez.
    switch (daVez) {
      case 1:    //verifica se o fotoscópio da vez é o 3
        while(daVez == 1){    //executa as funções abaixo até que o daVez não seja mais o 1
          //faz o robô andar em direção da luz recebida pelo fótoscópio 1 até que ela suma ou outro fótoscópio receba luminosidade maior
          irEmDirecaoAoFotoscopio1(servo);
 
          //zerar as variáveis que iram definir qual lado o robô deve seguir
          zerarVarDeControle(daVez, fonteLuzDetectada);

          //faz com que cada valor do vetor de fótoscopios receba as medidas de suas respectivas portas
          receberLeiturasAssociandoFotoscopioaPino(LDRtower, pinLDRtower1, pinLDRtower2, pinLDRtower3, pinLDRtower4);

          //verifica se algum fótoscópio recebeu o sinal luminoso
          fonteLuzDetectada = verificaRecepcaoLuminosa(contador, LDRtower, sensibilidade, fonteLuzDetectada);
         
          //verifica qual fotoscopio recebeu sinal maior no case de deteccao de luz
          if (fonteLuzDetectada == 1){
            daVez = achaMaior(daVez, contador, LDRtower);
          }
        }
        break;
      case 2:    //verifica se o fotoscópio da vez é o 2
        while(daVez == 2){    //executa as funções abaixo até que o daVez não seja mais o 2
          //faz o robô andar em direção da luz recebida pelo fótoscópio 2 até que ela suma ou outro fótoscópio receba luz maior
          irEmDirecaoAoFotoscopio2(servo);
 
          //zerar as variáveis que iram definir qual lado o robô deve seguir
          zerarVarDeControle(daVez, fonteLuzDetectada);
 
          //faz com que cada valor do vetor de fótoscopios receba as medidas de suas respectivas portas
          receberLeiturasAssociandoFotoscopioaPino(LDRtower, pinLDRtower1, pinLDRtower2, pinLDRtower3, pinLDRtower4);
 
          //verifica se algum fótoscópio recebeu o sinal luminoso
          fonteLuzDetectada = verificaRecepcaoLuminosa(contador, LDRtower, sensibilidade, fonteLuzDetectada);
   
          //verifica qual fotoscopio recebeu sinal maior no case de deteccao de luz
          if (fonteLuzDetectada == 1){
            daVez = achaMaior(daVez, contador, LDRtower);
          }
        }
        break;
      case 3: //verifica se o fotoscópio da vez é o 3
        while(daVez == 3){    //executa as funções abaixo até que o daVez não seja mais o 3
          //faz o robô andar em direção da luz recebida pelo fótoscópio 3 até que ela suma ou outro fótoscópio receba luminosidade maior
          irEmDirecaoAoFotoscopio3(servo);

          //zerar as variáveis que iram definir qual lado o robô deve seguir
          zerarVarDeControle(daVez, fonteLuzDetectada);
 
          //faz com que cada valor do vetor de fótoscopios receba as medidas de suas respectivas portas
          receberLeiturasAssociandoFotoscopioaPino(LDRtower, pinLDRtower1, pinLDRtower2, pinLDRtower3, pinLDRtower4);
 
          //verifica se algum fótoscópio recebeu o sinal luminoso
          fonteLuzDetectada = verificaRecepcaoLuminosa(contador, LDRtower, sensibilidade, fonteLuzDetectada);
   
          //verifica qual fotoscopio recebeu sinal maior no case de deteccao de luz
          if (fonteLuzDetectada == 1){
            daVez = achaMaior(daVez, contador, LDRtower);
          }
        }
        break;
      case 4: //verifica se o fotoscópio da vez é o 4
        while(daVez == 4){ //executa as funções abaixo até que o daVez não seja mais o 4
          //faz o robô andar em direção da luz recebida pelo fótoscópio 4 até que ela suma ou outro fótoscópio receba luz maior
          irEmDirecaoAoFotoscopio1(servo);
 
          //zerar as variáveis que iram definir qual lado o robô deve seguir
          zerarVarDeControle(daVez, fonteLuzDetectada);
   
          //faz com que cada valor do vetor de fótoscopios receba as medidas de suas respectivas portas
          receberLeiturasAssociandoFotoscopioaPino(LDRtower, pinLDRtower1, pinLDRtower2, pinLDRtower3, pinLDRtower4);
   
          //verifica se algum fótoscópio recebeu o sinal luminoso
          fonteLuzDetectada = verificaRecepcaoLuminosa(contador, LDRtower, sensibilidade, fonteLuzDetectada);
         
          //verifica qual fotoscopio recebeu sinal maior no case de deteccao de luz
          if (fonteLuzDetectada == 1){
            daVez = achaMaior(daVez, contador, LDRtower);
          }
        }
      break;
    default:
      //se nada acontecer deixa o robô de pé escrevendo um angulo de 90º em todos os servos
      funcaoDeixarRobodePe(servo);
      break;
    }
    delay(180); //tempo em microssegundos que a aplicação é repedida
  }
}

Ultima apresentação

Esses são os slides da nossa ultima apresentação. Já que na ultima apresentação nós ficamos durante 30 minutos falando sobre os princípios físicos e o funcionamento de cada componente do robô e as dificuldades que encontramos durante o desenvolvimento do mesmo não havia muito o que se falar nesta ultima apresentação:


Breve estaremos aperfeiçoando o poster e postando novamente.

segunda-feira, 6 de junho de 2011

LDR

O Light Dependent Resistor (LDR), como o nome já da uma dica, é um resistor que varia sua resistividade de acordo com a incidência luminosa.
Um LDR quando não está em contato com a luz costuma ter uma resistividade de 1000000Ω, esta resistividade diminui com incidência da luz obedecendo a formula R = LCA, onde L é a luminosidade em Lux, A é o valor da corrente que passa por ele e C é a constante que depende do material que foi usado para construir o LDR. A resistência mínima do LDR sobre incidência de luz é de 100Ω.






O LDR que também é conhecido como fotoresistência ou célula fotocondutiva é constituído de um material fotossensível conectado a dois eletrodos metálicos, esse material pode ser sulfeto ou seleneto de Cádmio ou sulfeto de Chumbo (Obs: material também usado nos filmes das antigas maquinas fotográficas).


Mas como funciona?

O LDR é um semicondutor, quando existe a incidência de luz, os fótons levam os elétrons da camada de valência para a camada de condução que é mais longe da zona proibida. O aumento do número de elétrons na camada de condução é o que diminui a resistividade (não entendeu? Veja + sobre semicondutores).

Quem usa o LDR?

Um bom exemplo do uso de LDR são os postes de iluminação, a luzes das praças, sensores de luminosidade e o incrível instrumento a laser dos nossos amigos do projeto Projeto de Física para Computação.


O que isso ajuda para nós?

(Já agradecendo ao Enio Benatti da comunidade Laboratório de Garagem e a nossa querida professora Mariza Cavalcante por ter nos avisado de antemão)
Os eletroscópios por nós criados nesse projeto, apresentam uma inconveniência na funcionalidade de nosso robô.

Pois o mesmo possui muita variação e interferência, mesmo utilizando um algoritmo para filtragem dos valores recebidos pelo Arduino (breve postaremos os códigos) ainda assim o FET de vez em quando muda o valor da sua resistividade. Exemplo: Se o circuito deverá ascender uma lâmpada na presença de um campo, as vezes a lâmpada ascende e as vezes apaga.
Sendo assim nosso robô não poderia caçar fantasmas :P.

A solução foi mudar o componente FET para uma fotocélula.
Então modificamos o circuito da seguinte maneira:

Desta maneira não há muita influência na programação do nosso robô (pois a tensão aplicada é a mesma) e tendo em vista que alguns “espectros” produzem fótons o nome do robô será o mesmo.

(OBS: Não acreditamos em fantasmas, o nome do robô foi dado devido a forma que ele se comporta, brincadeiras aparte ;)

Links de pesquisa:

Toni Eletrônica
Feira de Ciencias
Mundo Educacao
Technology Student
LDR - Light Dependent Resistor

sexta-feira, 27 de maio de 2011

Robô ghost hunter prototype

No dia 10/05 foi apresentado um prototipo do nosso robô. Ele foi montado da seguinte maneira:

 Os servos são as caixinhas azuis na imagem acima, e os pontos cinza são as pernas dos servos (pernas unidirecionais, neste caso posicionadas em 90º). Se verificarmos a posição dos servos, observamos que as paletas (pernas) estão em linha reta em direção a paleta oposta.
Esta montagem possibilita que o robô salte de maneira instavel pra qualquer direção, apartir do campo detectado. Para ficar mais claro é só olhar o modelo de movimento do robô.






Como trata-se de uma montagem para apresentar nossos resultados, montamos o robô em uma caixa de papelão e "socamos" uma protoboard dentro para usar apenas um trilho para alimentação de todos os componentes (exagero, mas a idéia é usar um protoshield ou um trilho feito a mão mesmo)

quinta-feira, 26 de maio de 2011

Servo motores (pernas do nosso robô)

Nas postagens anteriores ouvimos falar muito sobre os Servo motores, e neste post estaremos explicando um pouco sobre seu funcionamento.



O servo motor é constituído de um CI de controle, que tem a função de receber o sinal do controlador, monitorar a posição na qual ele se encontra, e trabalhar com o potenciômetro para mover o motor.
O servo motor é, um potenciômetro, um motor elétrico, engrenagens que reduzem a rotação do motor e transferem mais força para o eixo, tudo isso numa caixinha de plástico (buniteenha).



Para alimentar o servo é preciso no mínimo, 4.8 volts. Nosso controlador, o Arduino, pode mandar para o servo uma tensão de 0 até 5 volts em um intervalo de 1 milissegundo até 2 milissegundos
A velocidade do sinal que o Arduino manda para o servo é o que determina a posição pra qual o servo vai se mover, é ai que entra o CI de controle do servo e o potênciometro ;)

Um sinal de 1ms corresponde a uma posição do braço do servo todo a esquerda ou 0º
Um sinal de 1,5ms é o que chamamos de posição central do servo ou 90º
Um sinal de 2ms corresponde a uma posição do braço do servo todo a direita ou 180º


 Detalhe! O Servo motor não roda mais que 180º, existem racks que fazer eles girarem continuamente, mas isso lobotomiza o servo e você não terá mais controle sobre ele, muito menos sobre o sentido de sua rotação.


Potenciômetro

Potenciômetros são resistores com uma variação central e a resistência entre seus dois extremos é fixa em seu valor nominal. Já o valor de resistência entre uma das extremidades depende do posicionamento do cursor.
Cria-se, então, uma estrutura que pode ser compreendida como dois resistores em série:

As informações sobre Servo motores foram retiradas do site Asas Elétricas
E as informações sobre Potenciômetro do site Saber Eletrônica Online

Esquema técnico do Ardumoto

Qualé eu não podia ficar devendo essa imagem:


A imagem acima foi retirada do link: Ardumoto v12 (PDF)