LedDriver MAX7221
MAX7221: Serially Interfaced, 8-Digit, LED Display Drivers
Este circuito integrado da Maxim pode controlar até 64 led's ou 8 dígitos de displays de 7 segmentos. Controlado por SPI utilizamos apenas 3 fios do Arduino.
Este MAX7221 normalmente é usado em:
Bar Graph Displays
Industrial Controllers
LED Matrix Displays
Panel Meters
A maior parte dos esquemas que se encontram na web utilizam o MAX7221 para controlar uma matriz de 8x8. No entanto existe um esquema que explica as ligações a uma simples Ledbar e encontra-se no site instructables pelo user 'bratan'.
Neste projecto a biblioteca usada é a LedControl 1.0.4
Pinout:
Existem 8 pinos 'Digit' (0-7) e 8 pinos "Segment" (SegA-SegF e SegDP), podemos controlar 64 LEDs vendo os pinos Digit como linhas, que podem ter até 8 LEDs, e os pinos Segment como LEDs individuais, que controlam as linhas de LEDs a acender. 8x8=64 LEDs (matriz 8x8). Desta forma é muito útil para matrizes de Leds (8x8) e Display de 7 segmentos.
Acendendo apenas 10 LEDs, utilizando uma Ledbar, podemos utilizar o seguinte esquema:
A resistência ligada no ISET é calculada tendo em conta as propriedades dos LEDs usados, pois vai limitar a corrente que irá passar por cada um.
A Ledbar usada é a seguinte:
Podemos ligar a cada pino DIG 8 LEDs, como a Ledbar tem 10 LEDs, podemos ligar os Cátodos (-) dos LEDs 1 ao 8 todos juntos ao DIG0 (pino 2). Os restantes 2 Cátodos (2 LEDs finais) vamos ligá-los também entre si e ao DIG1 (pino 11).
Os pinos Ânodo da Ledbar vamos ligá-los aos pinos SEG do Maxim da seguinte forma:
Como também só existem 8 pinos SEG vamos usar o SegDP e o SegA para controlar o LED1\LED9 e LED2\LED10 respetivamente.
Resumo de ligações do MAX7221 e da Ledbar:
Dependendo do DIG ativo (DIG0 e DIG1) e SEG os LEDs vão acender.
NOTA: Podemos colocar um condensador de 10uF e um condensador de cerâmica 0.1uF (code 104) na linha de alimentação e o mais perto possível do MAX7221.
Código de teste:
// V4 2014-01-21 (Improved logic of bit shifting for last 2 LEDs)
// Notes: 33K Rset reisistor must! Also decoupling 10uF polarized and .1uf ceramic capacitors needed on VCC line
// (c) 2014 LensDigital.com
#include "LedControl.h"
#define MAX_LED 10 // Number of LEDs in bar graph array
#define MAX_BRIGHTNESS 15 // 0-15 LED brightness
#define pauseLED 250
#define BLINK_SPEED 250 // Speed of blinking
#define LED_TIMEOUT 20000 // Time out after which LED bar turns off
boolean isOn=true;
boolean isSleeping=false;
boolean okBlink=false; // Triggers blinking
unsigned long lastBlink = 0; // Last time LEDs blinked
unsigned long lastOn = 0; // Last time LED Bar was turned off
byte blinkCount=0; // Counts blinks/flashes
byte Bars=10; // Temp. number of barts to light up
/*
pin 9 is connected to the DataIn
pin 8 is connected to the CLK
pin 7 is connected to LOAD
We have only a single MAX72XX.
*/
LedControl lc=LedControl(9,8,7,1);
void setup() {
Serial.begin(115200);
lc.shutdown(0,false);
/* Set the brightness to a medium values */
lc.setIntensity(0,MAX_BRIGHTNESS);
/* and clear the display */
lc.clearDisplay(0);
LEDBarDisplay (Bars);
okBlink=true;
delay (1000);
Serial.println ("ready");
}
void loop() {
//ADICIONAL PARA TESTE:
//okBlink=true;
//LEDBarBlink(5);
chaseLED();
}
// =============================================================================
// --- Main Function. Light up "mark" number of sequential LEDs in Bar Graph
// =============================================================================
void LEDBarDisplay(int mark) {
if (mark < 0 || mark > MAX_LED) return; // Sanity check, cannot be more than max or less than 0 LEDs
byte LEDBit=B11111111;
if (mark <=8) { // First row (first 8 LEDs)
LEDBit=LEDBit << (8-mark); // Shift bits to the left
lc.setRow(0,0,LEDBit); //Light up LEDs
lc.setRow(0,1,B00000000); // Blank out second row
}
else { // Second row (LED 9-10)
LEDBit=LEDBit << (16-mark); // Shift bits to the left. 16 is 8*row
lc.setRow(0,0,B11111111); //Light first 8 LEDs
lc.setRow(0,1,LEDBit);
}
//Serial.print ("Mark is: "); Serial.print (mark); Serial.print (". In Binary: ");
// Serial.println (LEDBit,BIN);
lastOn=millis();
isSleeping=false;
}
// ===================================================================================================
// --- Blinks LED Bar Graph for specified number of times. Must be permitted with okBlink global var
// ===================================================================================================
void LEDBarBlink (int blinkTimes) {
if (!okBlink) return;
if (millis()-lastBlink > BLINK_SPEED) {
if (isOn) { // Turn LEDs off
isOn=false;
LEDBarDisplay(0);
}
else { // Turn LEDs on
isOn=true;
LEDBarDisplay(Bars);
blinkCount++;
if (blinkCount > blinkTimes-1) {
blinkCount=0;
okBlink=false;
}
}
lastBlink=millis();
}
}
// ====================================================================
// --- Sleep mode. Clears display after timeout period
// ====================================================================
void sleepLEDBar() {
if (isSleeping) return; // Already off
if (millis()-lastOn > LED_TIMEOUT) {
lc.clearDisplay(0);
isSleeping=true;
}
}
// ====================================================================
// --- Back and forth pattern chase
// ====================================================================
void chaseLED() {
for (int i=0;i<10;i++) {
LEDBarDisplay(i);
delay (pauseLED);
}
for (int i=10;i>=0;i--) {
LEDBarDisplay(i);
delay (pauseLED);
}
}
// ====================================================================
// --- Back and forth pattern chase
// ====================================================================
void chaseLED_old() {
for (int i=0;i<10;i++) {
if (i<8) lc.setLed(0,0,i,true);
else lc.setLed(0,1,i-8,true);
delay (pauseLED);
}
for (int i=10;i>=0;i--) {
if (i<8) lc.setLed(0,0,i,false);
else lc.setLed(0,1,i-8,false);
delay (pauseLED);
}
}
Agora vamos fazer o teste com um display de 7 segmentos, para o efeito temos de usar sempre um de Cátodo comum (-), pois podemos ver os pinos do MAX7221 da seguinte forma:
DIGs\Linhas
SEGs\Colunas
NEGATIVOS
POSITIVOS
O display usado é o seguinte:
NOTA: Os segmentos são identificados com as seguintes letras:
As ligações são muito simples, apenas temos de ver a datasheet do display a usar, para saber quais os pinos que correspondem a cada letra\segmento e os pinos comuns.
Neste caso temos a seguinte combinação:
A resistência ISET usada foi também de 30k, de acordo com a tabela vamos limitar em ~20mA.
Para o código basta usar o exemplo de 7 segmentos da biblioteca:
//We always have to include the library
#include "LedControl.h"
/*
Now we need a LedControl to work with.
***** These pin numbers will probably not work with your hardware *****
pin 12 is connected to the DataIn
pin 11 is connected to the CLK
pin 10 is connected to LOAD
We have only a single MAX72XX.
*/
LedControl lc=LedControl(12,11,10,1);
/* we always wait a bit between updates of the display */
unsigned long delaytime=350;
void setup() {
/*
The MAX72XX is in power-saving mode on startup,
we have to do a wakeup call
*/
lc.shutdown(0,false);
/* Set the brightness to a medium values */
lc.setIntensity(0,8);
/* and clear the display */
lc.clearDisplay(0);
}
/*
This method will display the characters for the
word "Arduino" one after the other on digit 0.
*/
void writeArduinoOn7Segment() {
lc.setChar(0,0,'a',false);
delay(delaytime);
lc.setRow(0,0,0x05);
delay(delaytime);
lc.setChar(0,0,'d',false);
delay(delaytime);
lc.setRow(0,0,0x1c);
delay(delaytime);
lc.setRow(0,0,B00010000);
delay(delaytime);
lc.setRow(0,0,0x15);
delay(delaytime);
lc.setRow(0,0,0x1D);
delay(delaytime);
lc.clearDisplay(0);
delay(delaytime);
}
/*
This method will scroll all the hexa-decimal
numbers and letters on the display. You will need at least
four 7-Segment digits. otherwise it won't really look that good.
*/
void scrollDigits() {
for(int i=0;i<13;i++) {
lc.setDigit(0,3,i,false);
lc.setDigit(0,2,i+1,false);
lc.setDigit(0,1,i+2,false);
lc.setDigit(0,0,i+3,false);
delay(delaytime);
}
lc.clearDisplay(0);
delay(delaytime);
}
void loop() {
writeArduinoOn7Segment();
scrollDigits();
for(int i=0;i<10;i++) {
lc.setDigit(0,3,i,false);
lc.setDigit(0,2,i,false);
lc.setDigit(0,1,i,false);
lc.setDigit(0,0,i,false);
delay(2000);
}
lc.clearDisplay(0);
delay(delaytime);
}