Social Icons

Controle um círculo de LEDs com um joystick

Circuito completo

Detalhe do cabeamento dos LEDs

Detalhe do cabeamento ao Arduino

Como funciona?

O joystick fornece coordenadas (x,y) ao Arduino de acordo com a sua posição. Como pode se ver, o espaço no qual o joystick se move é um círculo. Esse círculo será o que chamaremos de agora em diante de 'Torta' (veja a parte inferior direita da primeira imagem).
A única coisa que precisamos entender é que a Torta está dividida em 8 fatias. A cada fatia há um LED correspondente. (Veja a figura abaixo). Dessa forma, quando o joystick fornece-nos uma coordenada, ela necessariamente pertencerá a uma dessas fatias. O programa então acende o LED correspondente à fatia.

Código

 /* Controle_CírculodeLED_com_joystick
  * ------------
  * Este esboço controla um círculo com 8 LEDs
  * via joystick
  *
  * Primeiro lê-se os dois pinos analógicos conectados
  * ao joystick feito com dois potenciômetros
  *
  * Essa entrada é interpretada como coordenadas (x,y)
  *
  * Em seguida, calcula-se qual das 8 zonas possíveis 
  * faz parte das coordenadas (x,y)
  * 
  * Finalmente acende-se o LED que está na zona detectada
  *
  * @authors: Cristina Hoffmann and Gustavo Jose Valera
  * @hardware: Cristina Hofmann and Gustavo Jose Valera
  * @context: Arduino Workshop at medialamadrid
  */

  // Declaração de variáveis

  int ledPins [] = { 2,3,4,5,6,7,8,9 };
 // Matriz com 8 LEDs organizados em círculo
  int ledVerde = 13;
  int espera = 40;     // Tempo necessário para ligar o LED
  int joyPin1 = 0;   // variável deslizante conectada ao pino analógico 0
  int joyPin2 = 1;   // variável deslizante conectada ao pino analógico 1
  int coordX = 0;  // variável para ler o valor no pino analógico 0
  int coordY = 0;    // variável para ler o valor no pino analógico 1
  int centerX = 500;  // valor para a posição central do joystick
  int centerY = 500;
  int actualZone = 0;
  int previousZone = 0;

  // delegação dos pinos
  void setup()
  {
    int i;
    beginSerial(9600);
    pinMode (ledVerde, OUTPUT);
    for (i=0; i< 8; i++)
    {
      pinMode(ledPins[i], OUTPUT);
    } 
  }

  // função que calcula a inclinação da linha que passa pelos pontos
  // x1, y1 e x2, y2
  int calculateSlope(int x1, int y1, int x2, int y2)
  {
    return ((y1-y2) / (x1-x2));
  }

  // função que calcula em qual das 8 zonas possíveis
  // estão as coordenadas x, y dado o centro cx, cy
  int calculateZone (int x, int y, int cx, int cy)
  {
    int alpha = calculateSlope(x,y, cx,cy); 
// inclinação do segmento entre o ponto e o centro

    if (x > cx)
    {
      if (y > cy) // 1o quadrante
      {
        if (alpha > 1) // Inclinação > 1, portanto parte mais alta do 1o quadrante
          return 0;
        else
          return 1;    // Caso contrário, parte mais baixa do 1o quadrante
      }
      else // 2o quadrante
      {
        if (alpha > -1)
          return 2;
        else
          return 3;
      }
    }

    else
    {
      if (y < cy) // 3o quadrante
      {
        if (alpha > 1)
          return 4;
        else
          return 5;
      }
      else // 4o quadrante
      {
        if (alpha > -1)
          return 6;
        else
          return 7;
      }
    }
  } 

   void loop() {
    digitalWrite(ledVerde, HIGH); 
// flag para sabermos que se entrou em loop(), é opcional

    // leia o valor dos potenciômetros
    coordX = analogRead(joyPin1);   
    coordY = analogRead(joyPin2);   

    // calcule em qual x
    actualZone = calculateZone(coordX, coordY, centerX, centerY); 

    digitalWrite (ledPins[actualZone], HIGH);     

    if (actualZone != previousZone)
      digitalWrite (ledPins[previousZone], LOW);

   // imprima no terminal o valor cartesiano da coordenada
   // e a zona ao qual faz parte
   //não é necessário caso o Arduino rode em modo autônomo
    serialWrite('C');
    serialWrite(32); // imprima espaço
    printInteger(coordX);
    serialWrite(32); // imprima espaço
    printInteger(coordY);
    serialWrite(10);
    serialWrite(13);

    serialWrite('Z');
    serialWrite(32); // imprima espaço
    printInteger(actualZone);
    serialWrite(10);
    serialWrite(13);

  // Não apague a linha abaixo, ela é necessária!
    previousZone = actualZone;
   // delay (500);

 }

Nenhum comentário:

Postar um comentário