martes, 7 de octubre de 2014

Números primos del 0 al 511

Un número primo es aquel número que solo es divisible por si mismo y por la unidad.  Se asume que el número 1 no es primo, aunque hay discusión al respecto.  Así, los veinte primeros números primos son: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 y 71.

Para conocer la historia de los números primos y detalles se recomienda consultar la página  http://es.wikipedia.org/wiki/N%C3%BAmero_primo.


La famosa Criba de Eratóstenes, matemático griego que ideo una forma fácil y sencilla de identificar a los números primos, eliminando los múltiplos de los primeros números primos (como son el 2, 3, 5, 7, 11, 13, 23, etc.) mayores o iguales que el número primo elevado al cuadrado, consultar  en http://amigosdelamatematica.blogspot.es/1202842500/

Veamos como podemos implementar un algoritmo en Arduino que nos permita  dado un número, conocer si este es un número primo o no. Para ello inicialmente elaboramos el código para un contador binario ascendente de 9 bits implementado en Arduino mega 2560:

int outPin[] = {37, 39 ,41, 43, 45,47,49,51,53};
int tiempo = 2000;

void setup()
{
  int i = 0;
  for ( i = 0; i < 9; i++)
  pinMode(outPin[i], OUTPUT);
}

void loop()
{
 int i = 0, j=0;
 for ( i = 0; i <512; i++)
 {
 for ( j = 0; j < 9; j++)
 {
 if ( ( (i >> j) & 1 )  == 1 )
 digitalWrite(outPin[j], HIGH);
 else digitalWrite(outPin[j], LOW);
 }
 delay(tiempo);
 }}

Vamos a analizar con todo detalle el programa hasta aquí, trabajando con una plaqueta Arduino Mega2560:

Lo primero que hacemos es hacer un arreglo o lista de valores, indicando los pines correspondientes a cada led.

La  instrucción   Int outPin[]= {37,39,41,43,45,47,49,51,53}; nos evita tener que declarar por separado para cada led su pin de conexión.

La siguiente instrucción int  tiempo = 2000; determina el tiempo que transcurre para el cambio de un número binario al siguiente, ( 2 segundos)
A continuación  para la   configuración de pines como salidas se tiene la instrucción
 void setup() { int i=0; for (i = 0; i < 9;i++); pinMode(outPin[i],OUTPUT) ;} , donde el primer led  a la derecha, para nuestro caso  correspondiente al bit menos significativo, el LED 0   lo conecta al pin 37, el siguiente, el LED 1 al 39, y así sucesivamente hasta conectar el led correspondiente al bit mas  significativo, LED 8, al extremo izquierdo, en el pin 53.

 Los nueve  leds junto con su valor en paréntesis los vamos a denominar LED 0 (1), LED 1 (2), LED 2(4), LED 3 (8), LED 4 (16), LED 5 (32), LED 6(64), LED 7 (128), LED 8 (256).

Luego pasamos al bucle principal:

void loop() {
int i=0, j=0;
 for (i=0;i<512;i++)
{ for(j=0;j<9;j++)
{ if ( ( ( i >> j ) & 1) ==1)
digitalWrite(outPin[j], HIGH);
else digitalWrite(outPin[j],LOW);}
delay(tiempo);} }

Las instrucciones for anidadas  permiten que el contador avance por todos los 512  números correspondientes a los 9  bits, desde el 0, (000000000)2  hasta el 511, (111111111)2, pero en cada número hace un recorrido del 0 al 8, correspondiente a los 9 bits de cada número en binario manejados por los 9 LEDs.

 La función loop() al  ejecutarse una y otra vez, lo que hace es iterar por los 512 números que podemos mostrar, ya que tenemos 9 Leds, y 2 elevado a 9 es igual a 512.

Fijaremos nuestra mayor atención en la instrucción:

{ if ( ( ( i >> j ) & 1) ==1)
digitalWrite(outPin[j], HIGH);
else digitalWrite(outPin[j],LOW);}

Para que por cada número, se encienda  o apague  cada led correspondiente, la clave está en el bucle que realiza la operación “(i >> j) & 1″.

  La instrucción  ( i >> j ) maneja el  operador de desplazamiento a la derecha >> de los bits de la expresión binaria correspondiente al decimal en referencia.

Por ejemplo al llegar el contador al decimal 100 que ya vimos corresponde al binario 0011001002,  la instrucción (100>>0) establece que el binario permanece sin alteración; 
luego (100>>1) quiere decir que el binario 0011001002 se desplaza hacia la derecha una posición colocando un 0 como bit mas significativo o sea queda  0001100102 que equivale al 50, o sea 100 dividido por 2; luego la instrucción (100>>2) al desplazar al 100 en binario 2 posiciones a la derecha rellenando con cero a la izquierda queda 0000110012 , o sea el 25 decimal, 100 dividido por 4, o lo que es lo mismo 50 dividido por 2. Esto nos lleva a la conclusión que la instrucción ( i >> j ) nos sirve para efectuar las sucesivas divisiones por 2 que hay que realizar con cualquier número en decimal para su conversión en binario.

&1 es un operador AND.  El 1 en 9  bits es 0000000012.  La operación lógica  AND obedece a la siguiente tabla: 0&0=0; 0&1=0; 1&0=0; 1&1=1.  Para que dé un 1 los 2 bits deben ser 1, de lo contrario la AND da 0.

La instrucción (i >> j) & 1 realiza la operación AND bit por bit entre el binario establecido al aplicar el desplazamiento a la derecha del decimal en cuestión con el 1 en binario. Veamos con ejemplos:   (100>>1)&1 = 0  pues la AND bit a bit entre 0001100102 y 0000000012 es igual a 0.  Por otra parte, (100>>2)&1=1, pues la AND bit a bit entre 25 y 1 es igual a 1, pues la AND entre 0000110012 y 0000000012 es igual a 1, por ser ambos 1 los bits menos significativos de las dos expresiones binarias. Vemos entonces que de esta manera se pueden tomar los residuos  al efectuar la divisiones sucesivas  por 2.

Veamos ahora en su conjunto la instrucción completa :

{ if ( ( ( i >> j ) & 1) ==1)
digitalWrite(outPin[j], HIGH);
else digitalWrite(outPin[j],LOW);}

 Cada iteración del bucle divide el número en cuestión por 2 y se queda únicamente con el bit de menor valor. Así  sabemos si tenemos que encender o no el LED.

Por ejemplo, para mostrar el número 341, que en binario es (101010101) deberíamos encender los Leds  0, 2,  4, 6 y 8,  dejando  apagados el resto.  El calculo sería:

LED 0: 341 (101010101 & 1) -> 1, encendido
LED 1: 341 / 2 = 170 (010101010 & 1) -> 0, apagado
LED 2: 170 / 2 = 85 (001010101& 1) -> 1, encendido
LED 3: 85 / 2 =   42 (000101010 & 1) -> 0, apagado
LED 4: 42 / 2 =   21 (000010101 & 1) -> 1, encendido
LED 5: 21 / 2 =   10 (000001010 & 1) -> 1, apagado
LED 6: 10 / 2 =  5    (000000101 & 1) -> 1, encendido
LED 7: 5 / 2 =    2    (000000010 & 1) -> 1, apagado
LED 8: 2 / 2 =    1    (000000001 & 1) -> 1, encendido

Como vemos, el resultado del cálculo es correcto. Básicamente lo que se hace es ir desplazando los bits hacia la derecha y quedándonos con el bit menos significativo.




Lo que vamos a hacer luego  es recorrer todos los números entre el 0 y el número sobre el que queremos saber si es primo o no.

 Dentro de un bucle comprobaremos el principio del número primo. "Divisible por si mismo y por la unidad". Es decir, que si encontramos un número que es divisible por el número evaluado, este dejará de ser primo.

Por ejemplo, el número 10 no es primo. Ya que 10 es divisible por 2 y 5. Esto, expresado en términos matemáticos vendría a decir, que el  residuo  entre los dos números es 0.

Veámoslo:

10/2 = 5, residuo 0
10/5 = 2, residuo 0

La función que nos ayuda a conocer el residuo entre dos números es el módulo. Y en Arduino se representa con el tanto por ciento.

Así:

10%2 = 0
10%5 = 0
10%3 = 1 (Ya que 10/3 = 3 y  el residuo es 1)

Adicional a la identificación de si el número desde el 0 al 511 (9 bits) es primo, en el monitor del puerto serial del Arduino se va  a imprimir el número en sistema decimal, binario, octal, hexadecimal, y su respectivo carácter en código ASCII; así mismo se visualiza en 9 leds el encendido y apagado de los leds en binario, con cambio en el contador cada 5 segundos, y un buzzer electromagnético con un led jumbo se activan durante 150 ms cuando se detecta que el número es primo.

El programa respectivo, completo, es el siguiente:

int outPin[] = {37, 39 ,41, 43, 45,47,49,51,53};//9 leds del contador binario
int tiempo = 5000; //tiempo de reloj del contador
int k = 0;
int residuo = 0;
int nc = 0; //contador de divisiones exactas
int buzzer = 9;
int led = 8;

void setup()
{
  int i = 0;
  for ( i = 0; i < 9; i++)
  pinMode(outPin[i], OUTPUT);
  Serial.begin(9600);
  pinMode(buzzer,OUTPUT);
  pinMode(led,OUTPUT);
}

void loop()
{
 Serial.println("   NUMEROS DEL 0 AL 511 EXPRESADOS EN DECIMAL,BINARIO OCTAL, HEXADECIMAL, CARACTER ASCII,CON IDENTIFICACION SI ES NUMERO PRIMO");
 int i = 0, j=0;
 for ( i = 0; i <512; i++)
 {
 for ( j = 0; j < 9; j++)
 {
 if ( ( (i >> j) & 1 )  == 1 )
 digitalWrite(outPin[j], HIGH);
 else digitalWrite(outPin[j], LOW); 
  }

 for ( k = 1; k <= i; k++)
 {
   residuo = i % k;  //residuo al dividir el número i entre el número k
   if (residuo == 0)
   {
     nc = nc + 1; //contador de divisiones exactas, sin residuo, se incrementa
    }
 }

 if ((nc <= 2)&&( nc > 1))  //contador menor o igual a 2 y a la vez mayor a 1 (número primo)
 {
  Serial.println ("    ");
  Serial.print ("                ");
  Serial.print ("PRIMO.....");
  Serial.print (i,DEC);
  Serial.print ("  Decimal       ");
  Serial.print (i,BIN);
  Serial.print (" Binario        ");
  Serial.print (i,OCT);
  Serial.print ("  Octal      ");
  Serial.print (i,HEX);
  Serial.print(" Hexadecimal      ");
  Serial.print (i,BYTE);
  Serial.print(":Caracter ASCII   ");
  digitalWrite(buzzer,HIGH);
  digitalWrite(led,HIGH);
  delay (150);
  digitalWrite(buzzer,LOW);
  digitalWrite(led,LOW);
  delay(tiempo);
  nc = 0;
   }

  else if (nc != 2)  //contador de divisiones exactas, diferente de 2 (al no ser primo)
 {
  Serial.println ("        " );
  Serial.print ("                          ");
  Serial.print (i,DEC);
  Serial.print ("  Decimal       ");
  Serial.print (i,BIN);
  Serial.print (" Binario        ");
  Serial.print (i,OCT);
  Serial.print ("  Octal      ");
  Serial.print (i,HEX);
  Serial.print(" Hexadecimal      ");
  Serial.print (i,BYTE);
  Serial.print(":Caracter ASCII   ");
  delay(tiempo);
  nc = 0;
   }
 
  }
 }

Importante que el lector entienda el algoritmo para la identificación del número primo, punto crucial del presente proyecto. La instrucción  ((nc <= 2)&&( nc > 1))  establece cuando el número es primo, excluyendo el cero y el uno, permitiendo que estos dos números sean evaluados.

La instrucción (nc != 2)  indica que al ser el contador nc diferente a 2, el número de divisiones exactas, o sea sin residuo, diferente a 2,  ello significa que el número no es primo.
Este proyecto nos invita a estudiar los sistemas numéricos decimal, binario, octal, y hexadecimal, y la conversión de un sistema a otro.

Al ser posicional, el sistema decimal es un sistema de numeración en el cual el valor de cada dígito depende de su posición dentro del número. Al primero corresponde el lugar de la unidades, el dígito se multiplica por 100 (es decir 1); el siguiente las decenas (se multiplica por 10); centenas (se multiplica por 100), etc.


Respecto al sistema binario, en base 2, del cual ya se ha trabajado en proyectos anteriores, sabemos que solo utiliza dos dígitos, llamados bits, el cero y el uno. Se recomienda repasar en el enlace http://es.wikipedia.org/wiki/Sistema_binario.

La matemática binaria fue trabajada por George Boole quien creó un algebra que lleva su nombre. Ver información en  http://es.wikipedia.org/wiki/George_Boole

El sistema numérico en base 8 se llama octal y utiliza los dígitos 0 a 7. Se recomienda consultar http://es.wikipedia.org/wiki/Sistema_octal

Del hexadecimal, base 16,  ya habíamos hablado en proyectos anteriores, sabemos que utiliza 16 caracteres alfanuméricos, los números del 0 al 9, y las letras de la A hasta la F. Consultar la página http://es.wikipedia.org/wiki/Sistema_hexadecimal

Se recomienda al lector ejercitarse en la conversión entre los diferentes sistemas numéricos:http://www.dav.sceu.frba.utn.edu.ar/homovidens/gomezgomez_paz/PROYECTIN/PAGINA/conversionentresistdenumC.htm

Respecto al código ASCII (American Standard Code for Information Interchange) consultar http://es.wikipedia.org/wiki/ASCII

lunes, 22 de septiembre de 2014

Entrada y Salida Analógica en el Arduino

ENTRADA ANÄLOGA:

El  microcontrolador del arduino Uno dispone de un conversor análogo digital de 10 bits, que permite leer valores analógicos desde 0 hasta 5 voltios, como por ejemplo a través de un potenciómetro o un sensor de temperatura o de una fotoresistencia, que se convertirán en valores dentro del rango desde 0 hasta 1023.



Se puede utilizar un potenciómetro para controlar el tiempo de parpadeo de un Led.

Veamos el programa en Arduino:

int potPin = 0;        // pin de entrada análoga para potenciómetro
int ledPin = 10;      //  pin de salida para el Led

void setup ( )
{
     pinMode (ledPin,OUTPUT);  // se declara ledPin como salida
}

void loop ( )
{
     digitalWrite (ledPin, HIGH);  // coloca 5 voltios en el Led encendiendolo
     delay (analogRead (potPin);  // retardo de acuerdo al valor leido en el potenciometro
      digitalWrite (ledPin, LOW);  // coloca 0 voltios en el Led apagándolo
     delay (analogRead (potPin);  // retardo de acuerdo al valor leido en el potenciometro
}

Observe que el pin de entrada análoga no hubo necesidad de declararlo en el void setup ( ). 

De acuerdo al esquema el voltaje análogo leido en el potenciómetro va por el pin 0 de entradas análogas del arduino al conversor análogo digital ADC de 10 bits. La salida binaria 0000000000 corresponde a 0 voltios, y los 10 unos: 1111111111 corresponde a los 5 voltios. La salida binaria del ADC se convierte a decimal, y esos valores desde el 0 hasta el 1023 son los que corresponden al retardo del Led en milisegundos, o sea el máximo retardo corresponde a 1023 milisegundos.

SALIDA ANÁLOGA:

Algunos arduinos poseen  conversores  DAC , entrada digital, salida análoga, de tal manera que la salida análoga  AnalogWrite es verdaderamente análoga, desde 0 hasta 5 voltios.

Pero para el arduino UNO la salida analógica es emulada a través del procedimiento PWM.
En el arduino UNO, el microcontrolador ATmega168 permite habilitar como salidas analógicas tipo PWM los pines 3,5,6,9,10 y 11. 

El valor que se puede enviar a estos pines de salida analógica puede darse en forma de variable o constante pero siempre dentro del arango del 0 al 255.

analogWrite(pin,valor);     // escribe 'valor'  en el 'pin' definido como analógico.

El siguiente ejemplo lee un valor analógico de un pin de entrada analógica, convierte el valor dividiendolo por 4 (debido a que 255 es aproximadamente la cuarta parte de 1023), y envía el nuevo valor convertido a una salida de tipo PWM o salida analógica:

     int led = 10;      // define el pin 10 como 'led'
    int analog = 0;   //  define el apin A0 como 'analog'
    int valor;           //  define la variable 'valor' 

   void setup ( ) {
    pinMode (led,OUTPUT);  }   //se declara el pin 10 como salida, la entrada no es necesaria por ser                                                                analoga

   void   loop  ( ) 
   {
    valor = analogRead (analog);   // lee el pin 0 y lo asocia a la variable 'valor'
    valor /= 4;      // divide 'valor' entre 4 y lo reasigna a 'valor';
    analogWrite (led, valor);  // escribe en el pin 0 valor


    


miércoles, 17 de septiembre de 2014

Display de 7 segmentos en arduino: De la programación a pedal a la del motor.

El objetivo de este documento es mostrar al lector la diferencia entre programar un microcontrolador como el del arduino paso a paso, lo cual es mucho más lento y dispendioso,  y luego  elaborar el mismo programa en una forma más rápida y corta, utilizando arreglos y algunas funciones que permiten agilizar el Proceso.

En mi concepto personal de como maestro de Circuitos Digitales mi parecer es que en un principio es conveniente elaborar el programa paso a paso para comprenderlo mejor, incluyendo si lo vemos necesario el diagrama de flujo correspondiente.

Luego de entender con claridad que es lo que  "ESTAMOS HACIENDO" podemos buscar la forma de hacer la tarea en una forma más corta, eficiente y rápida.

Es como la vida misma:  Primero aprendimos a caminar, a usar la  bicicleta y  luego pasamos a la  moto o al  automóvil. El caminar y la bicicleta nos proporciona el ejercicio físico necesario para la salud, pero cuando requerimos realizar una diligencia rápidamente y a un sitio distante, seguramente lo más práctico es utilizar el Automóvil o un vehículo de transporte público.

Vamos a manejar un display  de 7 segmentos, cátodo Común,  miniatura de Referencia SM420561K,  para  ser Implementado en el protoboard.

El display dispone de 7 leds,  para los segmentos a, b, c, d, e, f, g,  tal como se muestra en la figura anterior.  Además dispone de un octavo led  para el punto. La configuracion de pines  también  se indica en  la figura. Existen dos pines para el cátodo común que dęben conectarse a GND (tierra).

 Pretendemos en este proyecto  visualizar en el display  los numeros del 0 al 9, y las letras A, B, C, D, E, F,
del Sistema Numérico Hexadecimal.
 Nosotros conectamos cada ánodo del led en cada segmento  con cables de colores especificos tal como se muestra en el siguiente esquema, disponiendo de una Resistencia de 220 ohmios, 1/4 watio, en serie con cada led, para limitar la corriente y el voltaje en cada led, y  proteger los puertos del Arduino.  La corriente máxima permitida en cada puerto del arduino es de 40 mA. Una corriente mayor quema el puerto.


El Programa de  pedal del  Arduino es el siguiente:

// Visualizacion en display de  7 segmento de los caracteres del Sistema hexadecimal

// Si el carácter es alfabético se enciende el punto decimal

// Los Leds a, b, c, d, e, f, g, y el punto decimal P se encienden al producirse Nivel lógico alto (HIGH) en el pin 

int i;
int j;
int a = 2;
int b = 3;
int c = 4;
int d = 5;
int e = 6;
int f = 7;
int g = 8;
int P = 9;
int retardo = 2000 ;

void setup ()
{
  pinMode (a, OUTPUT);
  pinMode (b, OUTPUT);
  pinMode (c, OUTPUT);
  pinMode (d, OUTPUT);
  pinMode (e, OUTPUT);
  pinMode (f, OUTPUT);
  pinMode (g , OUTPUT);
  pinMode (P, OUTPUT);

  }

 void loop ()
 {
       
    for (i = 0; i <= 15; i ++) 
   { 
     
     if (i == 0) // 0
    {digitalWrite (a, HIGH); // ENCIENDE EL SEGMENTO a     
     digitalWrite (b, HIGH); // Enciende el SEGMENTO b          
     digitalWrite (c, HIGH); // Enciende el SEGMENTO c         
     digitalWrite (d, HIGH); // Enciende el SEGMENTO d          
     digitalWrite (e, HIGH); // Enciende el SEGMENTO e         
     digitalWrite (f, HIGH); // Enciende el SEGMENTO f         
     digitalWrite (g, LOW); // Apaga el SEGMENTO g     
     digitalWrite (P, LOW); // Apaga el punto P  
     delay (retardo);}
                  
    if (i == 1) // 1
     {digitalWrite (a, LOW); // Apaga el SEGMENTO a  
     digitalWrite (b, HIGH); // Enciende el SEGMENTO b        
     digitalWrite (c, HIGH); // Enciende el SEGMENTO c         
     digitalWrite (d, LOW); // Apaga el SEGMENTO d          
     digitalWrite (e, LOW); // Apaga el SEGMENTO e         
     digitalWrite (f, LOW); // Apaga el SEGMENTO f       
     digitalWrite (g, LOW); // Apaga el SEGMENTO g     
     digitalWrite (P, LOW); // Apaga el punto P
      delay(retardo);}
         
     if (i == 2) // 2
    {digitalWrite (a, HIGH); // ENCIENDE EL SEGMENTO a    
     digitalWrite (b, HIGH); // Enciende el SEGMENTO b         
     digitalWrite (c, LOW); // Apaga el SEGMENTO c         
     digitalWrite (d, HIGH); // Enciende el SEGMENTO d          
     digitalWrite (e, HIGH); // Enciende el SEGMENTO e        
     digitalWrite (f, LOW); // Apaga el SEGMENTO f        
     digitalWrite (g, HIGH); // ENCIENDE EL SEGMENTO g     
     digitalWrite (P, LOW); // Apaga el punto P
      delay (retardo);}
        
     if (i == 3) // 3
    {digitalWrite (a, HIGH); // ENCIENDE EL SEGMENTO a    
     digitalWrite (b, HIGH); // Enciende el SEGMENTO b         
     digitalWrite (c, HIGH); // Enciende el SEGMENTO c        
     digitalWrite (d, HIGH); // Enciende el SEGMENTO d          
     digitalWrite (e, LOW); // Apaga el SEGMENTO e       
     digitalWrite (f, LOW); // Apaga el SEGMENTO f       
     digitalWrite (g, HIGH); // ENCIENDE EL SEGMENTO g     
     digitalWrite (P, LOW); // Apaga el punto P
     delay (retardo);}
          
     if (i == 4) // 4
    {digitalWrite (a, LOW); // Apaga el SEGMENTO a    
     digitalWrite (b, HIGH); // Enciende el SEGMENTO b          
     digitalWrite (c, HIGH); // Enciende el SEGMENTO c         
     digitalWrite (d, LOW); // Apaga el SEGMENTO d         
     digitalWrite (e, LOW); // Apaga el SEGMENTO e         
     digitalWrite (f, HIGH); // Enciende el SEGMENTO f       
     digitalWrite (g, HIGH); // ENCIENDE EL SEGMENTO g     
     digitalWrite (P, LOW); // Apaga el punto P
     delay (retardo);}
      
     if (i == 5) // 5
    {digitalWrite (a, HIGH); // ENCIENDE EL SEGMENTO a  
     digitalWrite (b, LOW); // Apaga el SEGMENTO b          
     digitalWrite (c, HIGH); // Enciende el SEGMENTO c         
     digitalWrite (d, HIGH); // Enciende el SEGMENTO d          
     digitalWrite (e, LOW); // Apaga el SEGMENTO e       
     digitalWrite (f, HIGH); // Enciende el SEGMENTO f         
     digitalWrite (g, HIGH); // ENCIENDE EL SEGMENTO g     
     digitalWrite (P, LOW); // Apaga el punto P 
     delay (retardo);}    
       
     if (i == 6) // 6
    {digitalWrite (a, LOW); // Apaga el SEGMENTO a 
     digitalWrite (b, LOW); // Apaga el SEGMENTO b        
     digitalWrite (c, HIGH); // Enciende el SEGMENTO c         
     digitalWrite (d, HIGH); // Enciende el SEGMENTO d          
     digitalWrite (e, HIGH); // Enciende el SEGMENTO e         
     digitalWrite (f, HIGH); // Enciende el SEGMENTO f         
     digitalWrite (g, HIGH); // ENCIENDE EL SEGMENTO g    
     digitalWrite (P, LOW); // Apaga el punto P
     delay (retardo);}
         
     if (i == 7) // 7
     {digitalWrite (a, HIGH); // ENCIENDE EL SEGMENTO a
     digitalWrite (b, HIGH); // Enciende el SEGMENTO b          
     digitalWrite (c, HIGH); // Enciende el SEGMENTO c         
     digitalWrite (d, LOW); // Apaga el SEGMENTO d         
     digitalWrite (e, LOW); // Apaga el SEGMENTO e         
     digitalWrite (f, LOW); // Apaga el SEGMENTO f       
     digitalWrite (g, LOW); // Apaga el SEGMENTO g     
     digitalWrite (P, LOW); // Apaga el punto P
     delay (retardo);}
   
     if (i == 8) // 8
    {digitalWrite (a, HIGH); // ENCIENDE EL SEGMENTO a 
     digitalWrite (b, HIGH); // Enciende el SEGMENTO b   
     digitalWrite (c, HIGH); // Enciende el SEGMENTO c    
     digitalWrite (d, HIGH); // Enciende el SEGMENTO d   
     digitalWrite (e, HIGH); // Enciende el SEGMENTO e       
     digitalWrite (f, HIGH); // Enciende el SEGMENTO
     digitalWrite (g, HIGH); // ENCIENDE EL SEGMENTO g  
     digitalWrite (P, LOW); // Apaga el punto P 
     delay (retardo);}
    
    if (i == 9) // 9
    {digitalWrite (a, HIGH); // ENCIENDE EL SEGMENTO a  
     digitalWrite (b, HIGH); // Enciende el SEGMENTO b   
     digitalWrite (c, HIGH); // Enciende el SEGMENTO c     
     digitalWrite (d, LOW); // Apaga el SEGMENTO d         
     digitalWrite (e, LOW); // Apaga el SEGMENTO e       
     digitalWrite (f, HIGH); // Enciende el SEGMENTO f         
     digitalWrite (g, HIGH); // ENCIENDE EL SEGMENTO g    
     digitalWrite (P, LOW); // Apaga el punto P
     delay (retardo);}
      
     if (i == 10) // A 
    {digitalWrite (a, HIGH); // ENCIENDE EL SEGMENTO a 
     digitalWrite (b, HIGH); // Enciende el SEGMENTO b   
     digitalWrite (c, HIGH); // Enciende el SEGMENTO c    
     digitalWrite (d, LOW); // Apaga el SEGMENTO d   
     digitalWrite (e, HIGH); // Enciende el SEGMENTO e       
     digitalWrite (f, HIGH); // Enciende el SEGMENTO
     digitalWrite (g, HIGH); // ENCIENDE EL SEGMENTO g  
     digitalWrite (P, HIGH); // Enciende el punto P
        delay (retardo);}

     if (i == 11) // B
    {digitalWrite (a, LOW); // Apaga el SEGMENTO a 
     digitalWrite (b, LOW); // Apaga el SEGMENTO b   
     digitalWrite (c, HIGH); // Enciende el SEGMENTO c    
     digitalWrite (d, HIGH); // Enciende el SEGMENTO d   
     digitalWrite (e, HIGH); // Enciende el SEGMENTO e       
     digitalWrite (f, HIGH); // Enciende el SEGMENTO
     digitalWrite (g, HIGH); // ENCIENDE EL SEGMENTO g  
     digitalWrite (P, HIGH); // Enciende el punto P
        delay (retardo);}


     if (i == 12) // C
    {digitalWrite (a, HIGH); // ENCIENDE EL SEGMENTO a  
     digitalWrite (b, LOW); // Apaga el SEGMENTO b   
     digitalWrite (c, LOW); // Apaga el SEGMENTO c    
     digitalWrite (d, HIGH); // Enciende el SEGMENTO d   
     digitalWrite (e, HIGH); // Enciende el SEGMENTO e       
     digitalWrite (f, HIGH); // Enciende el SEGMENTO
     digitalWrite (g, LOW); // ENCIENDE EL SEGMENTO g  
     digitalWrite (P, HIGH); // Enciende el punto P
    delay (retardo);}
     
   
     if (i == 13) // D
    {digitalWrite (a, LOW); // Apaga el SEGMENTO a  
     digitalWrite (b, HIGH); // Enciende el SEGMENTO b   
     digitalWrite (c, HIGH); // Enciende el SEGMENTO c    
     digitalWrite (d, HIGH); // Enciende el SEGMENTO d   
     digitalWrite (e, HIGH); // Enciende el SEGMENTO e       
     digitalWrite (f, LOW); // Apaga el SEGMENTO f
     digitalWrite (g, HIGH); // ENCIENDE EL SEGMENTO g  
     digitalWrite (P, HIGH); // Enciende el punto P
       delay (retardo);}

    
     if (i == 14) // E
    {digitalWrite (a, HIGH); // ENCIENDE EL SEGMENTO  a 
     digitalWrite (b, LOW); // Apaga el SEGMENTO b   
     digitalWrite (c, LOW); // Apaga el SEGMENTO c    
     digitalWrite (d, HIGH); // Enciende el SEGMENTO d   
     digitalWrite (e, HIGH); // Enciende el SEGMENTO e       
     digitalWrite (f, HIGH); // Enciende el SEGMENTO
     digitalWrite (g, HIGH); // ENCIENDE EL SEGMENTO g  
     digitalWrite (P, HIGH); // Enciende el punto P 
       delay (retardo);}

     
    if (i == 15) // F
    {digitalWrite (a, HIGH); // ENCIENDE EL SEGMENTO a  
     digitalWrite (b, LOW); // Apaga el SEGMENTO b   
     digitalWrite (c, LOW); // Apaga el SEGMENTO c    
     digitalWrite (d, LOW); // Apaga el SEGMENTO d   
     digitalWrite (e, HIGH); // Enciende el SEGMENTO e       
     digitalWrite (f, HIGH); // Enciende el SEGMENTO
     digitalWrite (g, HIGH); // ENCIENDE EL SEGMENTO g  
     digitalWrite (P, HIGH); // Enciende el punto P
       delay (retardo);}
               
     }
     }


Veamos una fotografía del montaje realizado:


La alimentación al Arduino UNO  se establece a través de una pila de 9 Voltios recargable, co conector  de 2,1 mm,positivo al centro.

Ahora veamos la programación de motor del arduino, donde se puede observar que el programa es mucho más corto,  utilizando arreglos y funciones tal como se  muestra a continuacion:

// Display 7 segmentos con caracteres en hexadecimal utilizando arreglos y funciones

void setup (){ 

  for (int X = 2; X <= 9; X++)
  pinMode(X,OUTPUT);
}

void loop (){

  int caracter = 0;
  while (caracter <= 15) {
  display7sg(caracter);
  caracter ++;
  delay (3000);
  }
  }

 void display7sg(int num){
 byte
 valores[]={B00111111,B00000110,B01011011,B01001111,B01100110,B01101101,B01111101,B00000111,B01111111,B01101111,B11110111,B11111100,B10111001,B11011110,B11111001,B11110001};
 for (int X = 0; X <= 7; X++) digitalWrite ( X + 2, bitRead(valores[num],X));
 }
Ahora veamos en detalle algunas cuestiones referentes a este programa conciso:

Para la configuracion de pines como salidas  para los ánodos del display de 7 segmentos  utilizamos una función  for.

Inicializamos la X en   2  como un  pin de salida  del arduino donde vamos a conectar el ánodo a   del display.  Los otros pines 3,4,5,6,7,8 y 9  son salidas para los ánodos b, c, d, e, f, g y  p del display de 7 segmentos, cátodo común.

En el bucle principal  del arduino, o sea en  la función Loop ,  debemos desplegar en el display   los 16 caracteres del hexadecimal, desde  el 0 hasta la letra F. Para ello dentro del bucle  usamos la función While. 

Para generar el  dígito  del 0 al 9, o la letra de la A la  F, del caracter hexadecimal, utilizamos ahora la función   display7sg (caracter).

La segmentación de código en funciones permite al programador crear piezas modulares de código que realizan una tarea definida y luego regresan a la zona de código de la que la función fue "Llamada".  El caso típico para la creación de una función es cuando hay que realizar la misma acción varias veces en el  programa.

La función  display7sg (caracter)  que genera cada  uno de los 16 caracteres  para  desplegar en el display está escrita al final, despues de la Función Loop, utilizando Bytes, o sea  grupos de 8 bits,que en este caso son llamados Enteros num. (Números Enteros) . Se Inicia con el 0 hasta llegar al caracter 15, correspondiente en hexadecimal a la letra F.  El bit 0 corresponde al ánodo a del display, y el bit 7 al ánodo del punto. 
Pará estos  16 caracteres de  8 números binarios cada caracter se define un Arreglo llamado Valores [].
Dentro de la función generadora del caracter hexadecimal se encuentra otra función llamada BItRead, que permite desde el 0 hasta la F ir colocando los niveles lógicos altos y bajos adecuadamente  a los pines del arduino, desde el pin 2 para el ánodo a  hasta el pin 9 para el punto.
La Función BitRead Se Puede consultar en la pagina oficial de arduino:
Se puede observar que los bits se van leyendo desde el bit 0 ( el menos significativo)  hasta el bit 7 ( el mas significativo).
Mediante la función for asociada a la bitRead  con  el renglón de código   for (int X = 0; X <= 7; X++) digitalWrite ( X + 2, bitRead(valores[num],X));  cada bit de cada caracter es leido de derecha a izquierda, o sea del menos al más significativo, y sus niveles bajos o altos se llevan a los pines del arduino para apagar o encender los leds del display y desplegar el caracter respectivo.  Como la función es llamada desde el bucle principal al retornar allí, el código del loop mediante la función while se encarga de pasar al siguiente caracter, y vuelve a la función generadora para repetir el proceso.  Cada 3 segundos se irá entonces desplegando cada caracter de forma indefinida.

Una recomendación para mis estudiantes, o el amable lector de este blog:

Esté seguro de comprender cada función. Estudiela acudiendo a la fuente original, o sea a la página oficial del arduino en inglés:

Debe haber comprendido cada función para poderla aplicar dentro de todo un contexto, y lograr ser competente en la programación. Competencia es saber aplicar cada concepto dentro de un contexto.

Lo invito a que repase las funciones For y While:



Para finalizar una frase para que reflexione sobre ella:  "Para comprender a Dios debemos expresar amor, porque Dios es Amor, y sólamente podemos aplicar lo que logremos comprender"  

Cuando se entiende todo lo que hacemos, disfrutamos del conocimiento adquirido y nos apasionamos y alcanzaremos grandes logros.