Comandando displays de LEDs com 74HC595 - parte II

Agora, vamos ver como foi feito o software para "domar" os displays. Para isso, criei uma library do Arduino e disponibilizei, free as usual, no Google Code, é só clicar.

É uma biblioteca baseada numa outra que fiz para LEDs RGB, que também está no GC e pode ser visualizada aqui. Para saber como criar uma lib, em português, clique . Já no idioma de sir Mick Jagger, clique .

Não se esqueça de renomear os arquivos da lib, retirando o número da versão do nome. Ou então baixe o arquivo .zip da última versão.

Aqui vai a interface da lib, devidamente comentada:


class LED8SegDisplay595
{

public:

// Constructor

//   int _displayCount: number of 8 segment displays to be managed

//   int _clockPin: number of Arduino port that´s connected the clock pin of the first 595 CI (CI pin 12)

//   int _latchPin: number of Arduino port that´s connected the latch pin of the first 595 CI (CI pin 11)

//   int _dataPin: number of Arduino port that´s connected the data pin of the first 595 CI (CI pin 14)

     LED8SegDisplay595(int _displayCount, int _clockPin, int _latchPin, int _dataPin);

//   set the corresponding display mask (from now on, it will be considered common cathod)

     void setDisplayMask(byte display);

//   clear display mask

     void clearDisplayMask(byte display);    

//   show error message Er.     

     void errorMessage(int millissecs);

//   write a value in the displays

     void write(byte value);

     void write(float value, int decimalPlaces);

     int debug;    //Indicates debug mode 

     byte displayMask[8]; //=  {B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000};       

     char buf[33];

     long errMilissecs;

   private:

     int displayCount;  //Number of LEDs to manage 

     int clockPin;  //Pin connected to Pin 11 of 74HC595 (Clock)

     int latchPin;  //Pin connected to Pin 12 of 74HC595 (Latch)

     int dataPin;   //Pin connected to Pin 14 of 74HC595 (Data)

     void shiftOut(byte dataOut);

};

O uso é muito simples, abaixo um exemplo "b-a-bá":


// Exemplo b-a-bá do display de oito segmentos.



#include <Arduino.h>

// inclui a lib

#include <LED8SegDisplay595.h>



// define o display: 2 é o número de displays, 12 é o pino clock do primeiro 595, que

// está ligado ao Arduino, 8 é o pino latch do mesmo CI e o 11 é o pino dados.

LED8SegDisplay595 ls(2,12,8,11);



void setup() {

}



void loop()

{

// dããããã... 

  ls.write(1);

  delay(1000);

  ls.write(2);

  delay(1000);

  ls.write(3.1,2);

  delay(1000);

}



O método mais importante é o write, em duas versões, uma para números inteiros, e uma para float, onde vc indica o número de casas decimais que o display irá mostrar. Nesse caso, se vc especificar mais casas do que cabe no display, ele vai limitar ao número de casas que couber. Em ambos os métodos, se vc fornecer um número que não caiba no display, ele vai mostrar a mensagem 'Er.' no display. Vamos agora analisar os outros métodos importantes:
// Construtor, já explicado.

LED8SegDisplay595(int _displayCount, int _clockPin, int _latchPin, int _dataPin);

// se vc tiver displays com catodo comum em vez de anodo comum, basta chamar 
// esse método para cada display com essa característica e a lib vai considerar
// isso. Claro que a ligação será diferente, vc terá que ligar o comum desses 
// displays ao positivo do seu circuito. Quanto quiser acionar um segmento,
// o display vai "aterrar" o pino correspondente, fazendo o display funcionar.

     void setDisplayMask(byte display);

// Desliga o indicador de catodo comum
     void clearDisplayMask(byte display);    

// Mostra a mensagem "Er." durante millisecs milissegundos.

     void errorMessage(int millissecs);

// escreve um valor inteiro nos displays

     void write(byte value);

// escreve um valor float nos displays, com decimalPlaces casas decimais.
     

     void write(float value, int decimalPlaces);

Abaixo, um vídeo demostrando as várias features funcionando, para melhor entendimento do potencial do uso da lib.
Se vc montar o circuito com o sensor de temperatura indicado na segunda montagem da parte I desse post, o demo vai funcionar totalmente. Porém, se vc só ligar dois displays, sem sensor nem campainha o circuito vai funcionar da mesma forma, sem a rotina de mostrar a temperatura.

As funcionalidades são as seguintes:


  // escreve alguns números inteiros no display

  writeSomeNumbers();

  // faz uma contagem regressiva de 100 até 0, em décimos de segundo  

  reverseCounter();

  // escreve alguns números como se o display fosse catodo (+) comum. Como o display é anodo comum,

  // os números aparecem "negativos", quer dizer, vc lê o número na parte apagada do display

  reverseNumbers();

  //  escreve alguns números com ponto decimal

  writeFloat();

  // exibe a mensagem de erro.

  errorMessageOverflow();

  //  inicia a rotina de medir temperatura. Fica nela até que o circuito seja resetado ou desligado.

  temperatureAlarm();



É isso, galera. Uma limitação? A lib por enquanto só trabalha com números positivos. Alguém se habilita a "pegar daí"?

Abracadabraço!




Comentários

  1. Qual versão do programa tas usando ? Poderia postar um .zio ou .rar com a biblioteca q tens ai, pois não estou conseguindo. Obrigado

    ResponderExcluir
    Respostas
    1. Lá no http://code.google.com/p/arduino-multiple-8-segment-display-control/downloads/list tem 3 arquivos:

      - EightSegDisplayDemo.ino: arquivo fonte do demo
      - LED8SegDisplay595.0.8.h: é o header (.h) da lib
      - LED8SegDisplay595.0.8.cpp: é a implementação da lib.

      No segundo parágrafo do texto acima tem um link para instruções de como instalar a lib na IDE do Arduino.

      Qual o problema que vc está enfrentando?

      [],

      Mauro

      Excluir
    2. Fiz tudo o que foi explicado, mas quando vou compilar da erro "LED8SegDisplay595 ls(2,12,8,11); ", nessa parte.
      Obrigado.

      Leonardo.

      Excluir
    3. Qdo dá erro nessa linha (embora vc não tenha escrito o tipo de erro) normalmente é porque ele não achou a lib.
      Vc renomeou o arquivo baixado tirando o número da licença? Ex: LEDMatrix595.0.81.cpp para LEDMatrix595.cpp?

      Excluir
    4. Baixei os arquivos criei uma pasara com o mesmo nome "LEDMatriz595", e os arquivos tb e teste no 1.01 e 0.22. O erro é pq ele não acha a biblioteca...por isso que te pedi para colocar um o zip com a biblioteca q tens. Obrigado

      Excluir
  2. Leonardo,

    Coloquei o .zip com os dois arquivos dentro lá no GC: http://code.google.com/p/arduino-multiple-led-rgb-control/downloads/detail?name=LED8SegDisplay595.zip&can=2&q=

    ResponderExcluir
    Respostas
    1. Valeu Mauro, funcionou agora. Tenho uma duvida, pois o que pretendo mesmo fazer é controlar led por led tipo enviar comandos para acender cada led que eu preciso. Tens alguma dica ai para isso ?

      Obrigado

      Excluir
    2. Consegui fazer o que eu precisava. Editei a tua funcao. Obrigado

      Excluir
    3. Olha, eu não fiz uma biblioteca para esse fim. Se vc quiser, pode modificar a minha para funcionar como vc precisa, é um exercício bom de programação.
      Tem uma outra que fiz, mas para LED RGB, que pode ser usada para controlar LEDs "monocromáticos", basta vc imaginar cada cor como um LED. Esse é o post: http://www.automatobr.blogspot.com.br/2012/07/controlando-infinitos-leds-com-arduino_14.html

      Eu tenho a intenção de criar uma lib específica para esse fim. Como já tem a sua demanda, se sobrar um tempo eu faço no finde.

      Excluir
  3. Uai, se quiser, compartilhe então. Me mande e eu coloco no Google Code com os devidos créditos.

    ResponderExcluir
  4. Amigo, desculpe te incomodar, mas se eu quiser usar 3 leds, para marcar 25,8º C, por exemplo, a sua biblioteca comporta? Teria que usar outro CI diretamente nas portas do Arduino, ou consigo continuar usando apenas as 3 portas para escrever nos leds? Obrigado

    ResponderExcluir
    Respostas
    1. PS: depois me conte se deu certo.

      Excluir
    2. Amigo anônimo, no problema, é um prazer ajudar.
      Você pode usar a lib para controlar "n" displays, usando apenas as mesmas três portas do Arduino. Vc precisa de um chip para cada display.
      Nesse caso vc teria que conectar o novo chip da seguinte forma:
      - Conecte os pinos 11 e 12 do novo chip aos dos CIs já conectados.
      - Conecte o pino 9 do penúltimo CI ao pino 14 do último, que é o que vc já adicionou. O penúltimo CI é o que controla o dígito mais significativo que havia antes (é o que vai estar com o pino 9 sem nada conectado).

      Aí, na instrução LED8SegDisplay595 ls(2,12,8,11); vc vai ter que colocar 3 no primeiro parâmero, que é o que indica o número de dígitos.

      Excluir
    3. Amigo Mauro, poxa, nem para eu falar meu nome... Sou o Randal, muito prazer. Você salvou a pátria. Deu certíssimo. Agora entendi melhor a ligação do CI, apesar de ter que estudar mais para entender 100% a lógica deles.. Mas está redondinho... Como sempre, vou abusar mais um pouquinho. Na verdade já rodei a internet e não achei uma solução. De repente você tem uma carta na manga. Estou fazendo um termostato. O meu problema é manter a tensão do LM35 estável. Como ele faz a leitura por tensão, qualquer oscilação interfere na temperatura final. Já estou fazendo por média a fim de diminuir essa oscilação (obtenho 10 leituras, tiro a média e depois escrevo nos leds). Mas quando aciono o relê, daí desanda a leitura, porque diminui a tensão que alimenta o LM35. Você tem alguma dica para me dar. Mas muito obrigado mesmo, porque só do LED já ajudou demais.

      Excluir
    4. Randal,

      Seguinte: vc está ligando a alimentação do LM35 em que porta do Arduino? Vcc? E como vc está alimentando o Arduino? De repente vc pode tentar colocar um resistor de 1k em série com o relé e diminuir a corrente. Ou então vc usar outra fonte para o relé. Se não der certo:
      Tem jeito de vc desenhar o circuito no Fritzing ou outro sw e me mandar? Mande a especificação do relé tb.

      Excluir
    5. Mauro,

      Estou trabalhando com uma fonte de saída 9V. Já tentei pegando a tensão do Vcc e do Vin. Mas em ambos os casos acontece a mesma coisa. O relê é um 125VCA 10 A 5vdc fangke jqc-3f(t73). Se colocar o resistor, não chega os 5 V necessários para acioná-lo. Mesmo um resistor de 0.3 já diminui o suficiente para não acioná-lo. Estou acionando com usando um transistor + diodo, a fim de proteger o rele. Mas tranquilo.. daqui eu sigo em diante e não vou mais ficar te incomodando.. Vou tentar achar uma solução e quando achar posto para você. muito obrigado mais uma vez. Forte abraço

      Excluir
  5. Este comentário foi removido pelo autor.

    ResponderExcluir
  6. Caro Mauro notei que ao colocar um terceiro display ele não mostrou
    como esperado, devo fazer alguma alteração no código para mostrar números maiores que 100 ou no caso do meu projeto de 000 até 9999.
    muito obrigado esta biblioteca ajudou muito.
    Igor Bortolotti

    ResponderExcluir
  7. Olá Mauro, estou iniciando agora na programação e não tenho muita prática, estou usando a sua biblioteca e funciona perfeitamente, o que eu gostaria de saber é se tem como controlar cada segmento dos displays (uso 2) de maneira independente podendo assim criar animações. Obrigado desde já!

    ResponderExcluir
    Respostas
    1. Jeito tem. mas não com essa minha biblioteca. Ela só escreve números. Vc pode olhar os fontes dela e colocar uma função nova para fazer o que vc está querendo. Posso ajudar, se vc quiser.

      Excluir

Postar um comentário

Postagens mais visitadas deste blog

Controle PID de Potência em Corrente Alternada - Arduino e TRIAC - Parte III

Dividindo um programa (sketch) do Arduino em mais de um arquivo

Controle PID de Potência em Corrente Alternada - Arduino e TRIAC - Parte I