miércoles, 9 de marzo de 2016

Encender cada segmento del módulo TM1637

Cómo encender cada segmento del módulo TM1637

https://fabricadigital.org/leccion/como-encender-cada-segmento-del-modulo-tm1637/

Conexión

Este display 7 segmentos tiene dos hilos para alimentación, GND y VCC (que puede ser 5V o 3.3V), y dos pines de datos (CLK y DIO) que podemos conectar a los pines digitales de Arduino que queramos. En los ejemplos siguientes vamos a conectar CLK al pin digital 2 de Arduino, y DIO al pin digital 3.
TM1637 esquema-conexion

Instalación de librería

Para utilizar el chip TM1637 tenemos que instalar una librería en Arduino IDE. Descarga la librería (enlace directo), abre Arduino IDE y ve a Programa > Include Library > Add .ZIP Library, busca el archivo descargado y selecciónalo.

Encendiendo segmentos

Esto se pone interesante. Vamos a ver cómo se encienden los segmentos del display TM1637.
1.En Arduino IDE > Programa > Include Library > TM1637-master
2. Definimos las variables CLK y DIO:
const int CLK = 2;
const int DIO = 3;
3. Instanciamos el TM1637. Para ello creamos un objeto indicando en su constructor los pines a los que CLK y DIO están conectados.
TM1637Display display(CLK, DIO);
4. Creamos una variable byte de tipo array para encender cada uno de los segmentos de los dígitos. Un dígito de un display 7 segmentos tiene etiquetados cada uno de sus segmentos como muestra la imagen siguiente:
Dígito de display 7 segmentos con etiquetas
¿Cómo funcionan estas variables? Existen varias formas de crear variables de tipo array, la que vamos a usar contiene el tamaño y su valor. Es decir, vamos a crear una variable de tamaño 8 bytes y cada byte tendrá un valor. ¿Qué valores serán?
Segmento A 00000001
Segmento B 00000010
Segmento C 00000100
Segmento D 00001000
Segmento E 00010000
Segmento F 00100000
Segmento G 01000000
Además, algunas pantallas 7 segmentos incluyen un octavo representando separadores (como puntos o dos puntos) u otros símbolos que se iluminan con el bit 10000000.
¿Probamos iluminar nuestro display 7 segmentos TM1637? Vamos a representar la palabra “HOLA”
Para hacer la letra H necesitamos iluminar los segmentos B, C, E, F, G. Para hacer la letra O necesitamos los segmentos A, B, C, D, E, F, y así con el resto de las letras. De forma que nuestra variable byte HOLA queda así:
byte HOLA[] = {
0b01110110, // H
0b00111111, // O
0b00111000, // L
0b01110111  // A
};
Para mayor comodidad, la librería que estamos usando incluye las siguientes macros que facilitan el trabajo con los segmentos:
 #define SEG_A 0b00000001
#define SEG_B 0b00000010
#define SEG_C 0b00000100
#define SEG_D 0b00001000
#define SEG_E 0b00010000
#define SEG_F 0b00100000
#define SEG_G 0b01000000
De esta forma, si queremos representar un HOLA, podemos hacer una OR de cada uno de los segmentos y almacenar el resultado en el byte de datos:
byte HOLA[] = {
SEG_B | SEG_C | SEG_E | SEG_F | SEG_ G,            // H
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F,             // O
SEG_D | SEG_E | SEG_F,                             // L
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_ G     // A
};
¡Puedes usar cualquiera de las dos formas, la que te resulte más cómoda!
Ya solo nos queda mostrar los datos en la pantalla. Para ello vamos a usar las siguientes funciones:
display.setBrightness(); podemos definir la intensidad de brillo del display, desde un valor hexadecimal 0x00 (0 en decimal), hasta un brillo máximo 0x0f (15 en decimal). En el paréntesis podremos el valor del brillo, por ejemplo, 0x0f
display.setSegments(); recibe el array de dígitos a encender en “formato segmento”, y los muestra por pantalla. En el paréntesis pondremos qué queremos mostrar, en nuestro caso, la variable array HOLA.
El código completo nos quedaría así:
/**
* Ejemplo de mensaje en display TM1637 con Arduino iluminando cada segmento de cada dígito
* Copyright 2016 - Fábrica Digital (fabricadigital.org)
*
* Publicado bajo licencia CC-BY-SA 4.0
* Creative Commons: Reconocimiento - Compartir Igual 4.0 Internacional
* http://creativecommons.org/licenses/by-sa/4.0/deed.es_ES
*
* Modificado el 15 de enero de 2016
* por Eloísa Romero para Fábrica Digital
*/
#include <TM1637Display.h> // librería TM1637
const int CLK = 2; // el pin CLK está conectado al pin digital 3
const int DIO = 3; // el pin DIO está conectado al pin digital 2
TM1637Display display(CLK, DIO); //instanciamos el TM1637, creando un objeto
byte HOLA[] = {
0b01110110, // H
0b00111111, // 0
0b00111000, // L
0b01110111 // A
};
void setup() {
display.setBrightness(0x0f); // brillo
}
void loop() {
display.setSegments(HOLA); // muestra la variable byte HOLA
}
view rawHOLA_TM1637.ino hosted with ❤ by GitHub
Y si hemos usado las variables SEG_ definidas en la librería, el código sería:
/**
* Ejemplo de mensaje en display TM1637 con Arduino usando las variables SEG_ para iluminiar los segmentos
* Copyright 2016 - Fábrica Digital (fabricadigital.org)
*
* Publicado bajo licencia CC-BY-SA 4.0
* Creative Commons: Reconocimiento - Compartir Igual 4.0 Internacional
* http://creativecommons.org/licenses/by-sa/4.0/deed.es_ES
*
* Modificado el 15 de enero de 2016
* por Eloísa Romero para Fábrica Digital
*/
#include <TM1637Display.h> // librería TM1637
const int CLK = 2; // el pin CLK está conectado al pin digital 3
const int DIO = 3; // el pin DIO está conectado al pin digital 2
TM1637Display display(CLK, DIO); //instanciamos el TM1637, creando un objeto
byte HOLA[] = {
SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // H
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F, // O
SEG_D | SEG_E | SEG_F, // L
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G // A
};
void setup() {
display.setBrightness(0x0f); // brillo
}
void loop() {
display.setSegments(HOLA); // muestra la variable byte HOLA
}

TM1637 Display 7 Seg. Arduino


Resultado de imagen de TM1637Resultado de imagen de TM1637
/*
 * TM1637TestArduino
 * Proves de la llibreria TM1637
 */
#include <TM1637Display.h>
#include <Arduino.h>
// Module connection pins (Digital Pins)
#define CLK 2
#define DIO 3

// The amount of time (in milliseconds) between tests
#define TEST_DELAY1   500
#define TEST_DELAY2   100

const uint8_t SEG_DONE[] = {
    SEG_B | SEG_C | SEG_D | SEG_E | SEG_G,           // d
    SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,   // O
    SEG_C | SEG_E | SEG_G,                           // n
    SEG_A | SEG_D | SEG_E | SEG_F | SEG_G            // E
    };

TM1637Display display(CLK, DIO);
//Define global variables
bool lz = false;

void setup()
{
}

void loop()
{
  int k;
  //Guarda el valor 8 en cada digit i el mosta
  uint8_t data[] = { 0xff, 0xff, 0xff, 0xff };
  display.setBrightness(0x0f);
 
  // All segments on
  display.setSegments(data);
  delay(TEST_DELAY1);
  /**/
 
  // Selectively set different digits
  // Mostra lineas horitzontals
  data[0] = 0b01001001;
  data[1] = display.encodeDigit(1);
  data[2] = display.encodeDigit(2);
  data[3] = display.encodeDigit(3);
 
  for(k = 3; k >= 0; k--) {
    display.setSegments(data, 1, k);
    delay(TEST_DELAY1);
    }
   
  display.setSegments(data+2, 2, 2);
  delay(TEST_DELAY1);
 
  display.setSegments(data+2, 2, 1);
  delay(TEST_DELAY1);
 
  display.setSegments(data+1, 3, 1);
  delay(TEST_DELAY1);

  // Show decimal numbers with/without leading zeros
  lz=false;
  for (uint8_t z = 0; z < 2; z++) {
    for(k = 0; k < 10000; k += k*4 + 7) {
        display.showNumberDec(k, lz);
        delay(TEST_DELAY1);
    }
      lz = true;
  }

  // Contar 0 a 9999 amb o sense zeros a l'esquerra
  lz=false; // sense zeros a la dreta
  for (uint8_t z = 0; z < 2; z++) {
    for(k = 0; k < 10000; k+=10) {
      display.showNumberDec(k, lz);
      delay(TEST_DELAY2);
    }
      lz = true; //Zeros a la dreta
  }
/**/
  // Show decimal number whose length is smaller than 4
  for(k = 0; k < 4; k++)
    data[k] = 0;
  display.setSegments(data);
 
  display.showNumberDec(153, false, 3, 1);
  delay(TEST_DELAY1);
  display.showNumberDec(22, false, 2, 2);
  delay(TEST_DELAY1);
  display.showNumberDec(0, true, 1, 3);
  delay(TEST_DELAY1);
  display.showNumberDec(0, true, 1, 2);
  delay(TEST_DELAY1);
  display.showNumberDec(0, true, 1, 1);
  delay(TEST_DELAY1);
  display.showNumberDec(0, true, 1, 0);
  delay(TEST_DELAY1);

  // Brightness Test
  for(k = 0; k < 4; k++)
    data[k] = 0xff;
  for(k = 0; k < 16; k++) {
    display.setBrightness(k);
    display.setSegments(data);
    delay(TEST_DELAY1);
  }
   
  // Done!
  display.setSegments(SEG_DONE);
 
  while(1);
}
...
Llibreria "TM1637Display.h"
//  Author: avishorp@gmail.com
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef __TM1637DISPLAY__
#define __TM1637DISPLAY__

#include <inttypes.h>

#define SEG_A   0b00000001
#define SEG_B   0b00000010
#define SEG_C   0b00000100
#define SEG_D   0b00001000
#define SEG_E   0b00010000
#define SEG_F   0b00100000
#define SEG_G   0b01000000

class TM1637Display {

public:
  //! Initialize a TM1637Display object, setting the clock and
  //! data pins.
  //!
  //! @param pinClk - The number of the digital pin connected to the clock pin of the module
  //! @param pinDIO - The number of the digital pin connected to the DIO pin of the module
  TM1637Display(uint8_t pinClk, uint8_t pinDIO);
 
  //! Sets the brightness of the display.
  //!
  //! The setting takes effect when a command is given to change the data being
  //! displayed.
  //!
  //! @param brightness A number from 0 (lowes brightness) to 7 (highest brightness)
  void setBrightness(uint8_t brightness);
 
  //! Display arbitrary data on the module
  //!
  //! This function receives raw segment values as input and displays them. The segment data
  //! is given as a byte array, each byte corresponding to a single digit. Within each byte,
  //! bit 0 is segment A, bit 1 is segment B etc.
  //! The function may either set the entire display or any desirable part on its own. The first
  //! digit is given by the @ref pos argument with 0 being the leftmost digit. The @ref length
  //! argument is the number of digits to be set. Other digits are not affected.
  //!
  //! @param segments An array of size @ref length containing the raw segment values
  //! @param length The number of digits to be modified
  //! @param pos The position from which to start the modification (0 - leftmost, 3 - rightmost)
  void setSegments(const uint8_t segments[], uint8_t length = 4, uint8_t pos = 0);
 
  //! Displayes a decimal number
  //!
  //! Dispalyes the given argument as a decimal number
  //!
  //! @param num The number to be shown
  //! @param leading_zero When true, leading zeros are displayed. Otherwise unnecessary digits are
  //!        blank
  //! @param length The number of digits to set. The user must ensure that the number to be shown
  //!        fits to the number of digits requested (for example, if two digits are to be displayed,
  //!        the number must be between 0 to 99)
  //! @param pos The position least significant digit (0 - leftmost, 3 - rightmost)
  void showNumberDec(int num, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);
 
  //! Translate a single digit into 7 segment code
  //!
  //! The method accepts a number between 0 - 15 and converts it to the
  //! code required to display the number on a 7 segment display.
  //! Numbers between 10-15 are converted to hexadecimal digits (A-F)
  //!
  //! @param digit A number between 0 to 15
  //! @return A code representing the 7 segment image of the digit (LSB - segment A;
  //!         bit 6 - segment G; bit 7 - always zero)
  uint8_t encodeDigit(uint8_t digit);

protected:
   void bitDelay();
  
   void start();
  
   void stop();
  
   bool writeByte(uint8_t b);
  
private:
    uint8_t m_pinClk;
    uint8_t m_pinDIO;
    uint8_t m_brightness;
};

#endif // __TM1637DISPLAY__

...
TM1637Display.cpp

//  Author: avishorp@gmail.com
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

extern "C" {
  #include <stdlib.h>
  #include <string.h>
  #include <inttypes.h>
}

#include <TM1637Display.h>
#include <Arduino.h>

#define TM1637_I2C_COMM1    0x40
#define TM1637_I2C_COMM2    0xC0
#define TM1637_I2C_COMM3    0x80

//
//      A
//     ---
//  F |   | B
//     -G-
//  E |   | C
//     ---
//      D
const uint8_t digitToSegment[] = {
 // XGFEDCBA
  0b00111111,    // 0
  0b00000110,    // 1
  0b01011011,    // 2
  0b01001111,    // 3
  0b01100110,    // 4
  0b01101101,    // 5
  0b01111101,    // 6
  0b00000111,    // 7
  0b01111111,    // 8
  0b01101111,    // 9
  0b01110111,    // A
  0b01111100,    // b
  0b00111001,    // C
  0b01011110,    // d
  0b01111001,    // E
  0b01110001     // F
  };


TM1637Display::TM1637Display(uint8_t pinClk, uint8_t pinDIO)
{
    // Copy the pin numbers
    m_pinClk = pinClk;
    m_pinDIO = pinDIO;
   
    // Set the pin direction and default value.
    // Both pins are set as inputs, allowing the pull-up resistors to pull them up
    pinMode(m_pinClk, INPUT);
    pinMode(m_pinDIO,INPUT);
    digitalWrite(m_pinClk, LOW);
    digitalWrite(m_pinDIO, LOW);
}

void TM1637Display::setBrightness(uint8_t brightness)
{
    m_brightness = brightness;
}

void TM1637Display::setSegments(const uint8_t segments[], uint8_t length, uint8_t pos)
{
    // Write COMM1
    start();
    writeByte(TM1637_I2C_COMM1);
    stop();
   
    // Write COMM2 + first digit address
    start();
    writeByte(TM1637_I2C_COMM2 + (pos & 0x03));
   
    // Write the data bytes
    for (uint8_t k=0; k < length; k++)
      writeByte(segments[k]);
     
    stop();

    // Write COMM3 + brightness
    start();
    writeByte(TM1637_I2C_COMM3 + (m_brightness & 0x0f));
    stop();
}

void TM1637Display::showNumberDec(int num, bool leading_zero, uint8_t length, uint8_t pos)
{
    uint8_t digits[4];
    const static int divisors[] = { 1, 10, 100, 1000 };
    bool leading = true;
   
    for(int8_t k = 0; k < 4; k++) {
        int divisor = divisors[4 - 1 - k];
        int d = num / divisor;
       
        if (d == 0) {
          if (leading_zero || !leading || (k == 3))
            digits[k] = encodeDigit(d);
          else
            digits[k] = 0;
        }
        else {
            digits[k] = encodeDigit(d);
            num -= d * divisor;
            leading = false;
        }
    }
   
    setSegments(digits + (4 - length), length, pos);
}

void TM1637Display::bitDelay()
{
    delayMicroseconds(50);
}
  
void TM1637Display::start()
{
  pinMode(m_pinDIO, OUTPUT);
  bitDelay();
}
  
void TM1637Display::stop()
{
    pinMode(m_pinDIO, OUTPUT);
    bitDelay();
    pinMode(m_pinClk, INPUT);
    bitDelay();
    pinMode(m_pinDIO, INPUT);
    bitDelay();
}
 
bool TM1637Display::writeByte(uint8_t b)
{
  uint8_t data = b;

  // 8 Data Bits
  for(uint8_t i = 0; i < 8; i++) {
    // CLK low
    pinMode(m_pinClk, OUTPUT);
    bitDelay();
   
    // Set data bit
    if (data & 0x01)
      pinMode(m_pinDIO, INPUT);
    else
      pinMode(m_pinDIO, OUTPUT);
   
    bitDelay();
   
    // CLK high
    pinMode(m_pinClk, INPUT);
    bitDelay();
    data = data >> 1;
  }
 
  // Wait for acknowledge
  // CLK to zero
  pinMode(m_pinClk, OUTPUT);
  pinMode(m_pinDIO, INPUT);
  bitDelay();
 
  // CLK to high
  pinMode(m_pinClk, INPUT);
  bitDelay();
  uint8_t ack = digitalRead(m_pinDIO);
  if (ack == 0)
    pinMode(m_pinDIO, OUTPUT);
   
   
  bitDelay();
  pinMode(m_pinClk, OUTPUT);
  bitDelay();
 
  return ack;
}

uint8_t TM1637Display::encodeDigit(uint8_t digit)
{
    return digitToSegment[digit & 0x0f];
}