14 de mayo de 2012

Arduino: Visor de 8 segmentos controlado por un potenciómetro

Con un visor de 8 segmentos [son 7 "|" y un "·" ;)] quitado de una máquina cualquiera, he probado a ir encendiendo los segmentos de forma que se fueran dibujando los números. Esto no era demasiado divertido, así que decidí controlar el número según lo que girásemos un potenciómetro.

Este es el vídeo con el resultado:



En el visor de 8 segmentos que he utilizado, cada segmento se apaga cuando recibe "0" y se enciende al ponerla a "1". Así que he conectado cada segmento a una salida de la Arduino y el pin común a GND.

En el código ya vemos que lo primero que hago es poner todos los pines a 1, para que todos los segmentos estén apagados.

Respecto al potenciómetro, conecto el cable de datos en una entrada analógica de la Arduino y los otros dos uno a +5v y el otro a GND.

Aquí el código que he utilizado:

/*
   Según los valores indicados con un potenciómetro, muestro números
   del 0 al 9 en un visor de 7 segmentos
 */

// Array donde meto los pines digitales que usaré para el visor de 7 segmentos
int ledPines[] = {0, 1, 2, 3, 4, 5, 6, 7};

// Pin analógico en el que conectaré el cable de datos del potenciómetro
int pinPote = A0;

// Variable en la que guardaré el valor obtenido del potenciómetro
int datoPote;

void setup()
{
  // Ponemos todos los pines como salida digital
  for(int i = 0; i < 8; i++)
    {
      pinMode(ledPines[i], OUTPUT);
    }
  // los apagamos todos poniéndolos a 0
  apagapines();
}

void loop()
{
 apagapines(); // apago leds 
 // miro valor del potenciómetro (varía de 0 a 1023):
 datoPote = analogRead(pinPote); 
 // Lo divido para obtener un valor entre 0 y 9 y decido qué número "pinto" 
 numero(datoPote/113); 
}

//Función que apaga los pines del visor
void apagapines()
{
  for(int i = 0; i < 8; i++)
    {
      digitalWrite(ledPines[i], LOW);
    }  
}

//Función que recibe el número a dibujar y lo dibuja
void numero(int a)
{
  switch(a)
  {
    case 0: for(int i = 0; i < 6; i++)
               {
                digitalWrite(ledPines[i], HIGH);
               }
            break;
    case 1: digitalWrite(ledPines[3], HIGH);
            digitalWrite(ledPines[4], HIGH);
            break;
    case 2: digitalWrite(ledPines[0], HIGH);
            digitalWrite(ledPines[2], HIGH);
            digitalWrite(ledPines[3], HIGH);
            digitalWrite(ledPines[5], HIGH);
            digitalWrite(ledPines[6], HIGH);
            break;
    case 3: for(int i = 2; i < 7; i++)
               {
                digitalWrite(ledPines[i], HIGH);
               }
            break;
    case 4: digitalWrite(ledPines[1], HIGH);
            digitalWrite(ledPines[3], HIGH);
            digitalWrite(ledPines[4], HIGH);
            digitalWrite(ledPines[6], HIGH);
            break;
    case 6: digitalWrite(ledPines[0], HIGH);
    case 5: digitalWrite(ledPines[1], HIGH);
            digitalWrite(ledPines[2], HIGH);
            digitalWrite(ledPines[4], HIGH);
            digitalWrite(ledPines[5], HIGH);
            digitalWrite(ledPines[6], HIGH);
            break;
    case 7: digitalWrite(ledPines[2], HIGH);
            digitalWrite(ledPines[3], HIGH);
            digitalWrite(ledPines[4], HIGH);
            break;
    case 8: for(int i = 0; i < 7; i++)
               {
                digitalWrite(ledPines[i], HIGH);
               }
            break;
    case 9: for(int i = 1; i < 7; i++)
               {
                digitalWrite(ledPines[i], HIGH);
               }
            break;
    // mi visor tiene un puntito. Si hay algún fallo, que encienda el punto: 
    default: digitalWrite(ledPines[7], HIGH); 
  }
} 
 
En los case del switch he aprovechado un poco los break y el orden para no tener que escribir tanto y optimizar un poquito el código. Algo similar he hecho con el case 9 y case 8, haciendo un bucle que va encendiendo los pines correspondientes.