Taller MBC004 – Ticker
1. Objetivo
Visualizar el conteo desde 0 hasta 99 en dos (2) display 7-Segmentos.
2. Materiales
- Board Núcleo STM32F446RE
- Cable USB Mini A
- Protoboard
- Cables Arduino
- (2) Display 7-Segmentos (Ánodo Común)
- (7) Resistencias 220
3. Hardware
Continuando con el taller del display 7 segmentos, vamos a conectar dos (2) displays para mostrar el conteo desde 0 hasta 99. Para ahorrar pines del microcontrolador dedicados a los displays, vamos a utilizar la técnica del multiplexado.
Multiplexar displays 7 segmentos no es otra cosa que conectar todos los segmentos de los displays unos con otros y controlar el tiempo de encendido de cada uno de los displays. Esto quiere decir que conectamos físicamente el Segmento A del Display 1 con el Segmento A del Display 2, el Segmento B del Display 1 con el Segmento B del Display 2 y así sucesivamente hasta el segmento G. Esto significa que no importa el número de displays a conectar (2 hasta N), en todos los casos todos los segmentos estarán conectados únicamente por 7 líneas. Para la activación de cada displays, se usa bien sea los anodos o los cátodos de los displays conectando cada uno a un pin del microcontrolador.
Nuestro cerebro y la visión del ser humano es capaz de procesar de forma separada entre 10 a 12 imágenes por segundo. Cuando una secuencia de imagenes supera este umbral nuestra visión percibe el movimiento continuo. Este efecto es conocido como persistencia de la visión y se mide en la cantidad de frames por segundo o FPS (Frames per Second). Esta es la razón por la que el cine utiliza 24 FPS y la televisión aproximadamente 30 FPS.
Creditos: https://commons.wikimedia.org/wiki/File:Animhorse.gif
Utilizando el principio de la persistencia de la visión, podemos encender uno a uno los displays de forma secuencial, dejando encencido cada uno de los display un intervalo de tiempo que logre al menos las 30 veces por segundo por display (30 FPS). Para calcular el tiempo en que se debe encender cada display, se obtiene el inverso de la frecuencia de 30 Hz (30 veces por segundo):
Frecuencia (Hz) = 1 / T
T = 1 / Frecuencia (Hz)
T = 1 / 30Hz = 0,0333 = 33,3 ms ≅ 33 ms
T = 33 ms
Entonces se debe configurar esta interrupción para que cada 33 ms, apague el display actual y encienda el otro display. De esta manera nuestra visión percibirá que ambos display estan encendidos todo el tiempo. Si se coloca esta tiempo el ojo humano alcanza a detectar un leve parpadeo entre los display, por esta razon en mi caso siempre eligo la tercera parte de este tiempo, es decir aproximadamente 10 ms.
Una vez comprendido el proceso de multiplexado, veamos cómo se puede programar esto en mbed aprovechando el API disponible.
4. Software
Para este ejemplo usamos los mismos pines para los segmentos de los dos (2) displays:
// Define GPIO Pins 7-Segment Display // PA_10 --> A // PB_3 --> B // PB_5 --> C // PB_4 --> D // PB_10 --> E // PA_8 --> F // PA_9 --> G BusOut display7Seg(PA_9, PA_8, PB_10, PB_4, PB_5, PB_3, PA_10);
Y conectamos los anodos de los dos displays a pines independientes del microcontrolador:
// Anode Display 1 DigitalOut display1(PC_7); // Anode Display 2 DigitalOut display2(PB_6);
Existe una función en mbed que permite generar una interrupción cada cierto tiempo llamada Ticker. Esta función permite definir el tiempo en que la interrupción es generada y la función a la que se llama cuando este tiempo ha transcurrido.
Ticker changeDisplay; // Configure Change Display Selected each 10 ms changeDisplay.attach(&changeDisplaySelected, 0.010);
En este caso la interrupción sera generada cada 33 millisegundos y cada vez que se cumple este tiempo, es llamada la función changeDisplaySelected. En esta función se realiza el cambio del display activo y se exporta al bus el valor a mostrarse en este display. Cuando un display esta encendido, el otro esta apagado.
// Change Display Selected void changeDisplaySelected() { // Check Display Selected if(display1) { // Turn Off Display 1 display1 = 0; // Export data to Bus display7Seg = anodeComun[units]; // Turn On Display 2 display2 = 1; } else { // Turn Off Display 2 display2 = 0; // Export data to Bus display7Seg = anodeComun[tens]; // Turn On Display 1 display1 = 1; } }
De esta manera podemos encender y apagar uno por uno los displays usando las interrupciones del microcontrolador logrando a través de la persistencia de la visión ver ambos displays encendidos al mismo tiempo.
5. Montaje Protoboard
6. Plano
7. Código
Si quieren importar este ejemplo en el workspace de su ambiente Mbed, ingrese a la siguiente URL https://os.mbed.com/teams/Mbed-Colombia-Meetup/code/MBC003-BusOut/ y hagan click en el botón Import to Compiler.
/** * MBC004 - Ticker * This example use the BusOut function with a 7-Segment Display * 12 Jul 2018 - Mbed Colombia - https://mbedcolombia.wordpress.com/ * * Board: ST-Nucleo-F446RE - https://os.mbed.com/platforms/ST-Nucleo-F446RE/ * * Copyright [2018] [Leandro Perez Guatibonza / leandropg AT gmail DOT com] * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "mbed.h"</pre> // Define GPIO Pins 7-Segment Display // PA_10 --> A // PB_3 --> B // PB_5 --> C // PB_4 --> D // PB_10 --> E // PA_8 --> F // PA_9 --> G BusOut display7Seg(PA_9, PA_8, PB_10, PB_4, PB_5, PB_3, PA_10); // Anode Display 1 DigitalOut display1(PC_7); // Anode Display 2 DigitalOut display2(PB_6); // Variables Counter int tens; int units; // Define Logic Anode Comun Display // ABCDEFG int anodeComun[16] = { 0b0000001, // 0 0b1001111, // 1 0b0010010, // 2 0b0000110, // 3 0b1001100, // 4 0b0100100, // 5 0b0100000, // 6 0b0001111, // 7 0b0000000, // 8 0b0001100, // 9 0b0001000, // A 0b1100000, // B 0b1110010, // C 0b1000010, // D 0b0110000, // E 0b0111000 }; // F // Change Display Selected void changeDisplaySelected() { // Check Display Selected if(display1) { // Turn Off Display 1 display1 = 0; // Export data to Bus display7Seg = anodeComun[units]; // Turn On Display 2 display2 = 1; } else { // Turn Off Display 2 display2 = 0; // Export data to Bus display7Seg = anodeComun[tens]; // Turn On Display 1 display1 = 1; } } // Main Loop runs in its own thread in the OS int main() { Ticker changeDisplay; // Configure Change Display Selected each 10 ms changeDisplay.attach(&changeDisplaySelected, 0.010); // Inifite Loop while(1) { // Iterate between 0 and 99 for(int i = 0; i < 100; i++) { // Calculate Tens and Units tens = i / 10; units = i % 10; // Wait 150 millisecond wait_ms(150); } } }
8. Recursos
Aquí dejamos los recursos disponibles para el taller.
- Repositorio Código: https://os.mbed.com/teams/Mbed-Colombia-Meetup/code/MBC004-Ticker/
- Montaje Protoboard: MBC004-Ticker-Protoboard
- Esquemático: MBC004-Ticker-Esquematico
Espero haya sido de utilidad este taller. Cualquier duda o inquietud pueden consultarnos a través de nuestras sociales. Nos vemos en el próximo taller.
Twitter: @leandropg
Facebook: https://www.facebook.com/mbedcolombia
Instagram: leandropg.co