Cubo de Leds 3x3x3 com Arduino | Modulo Eletrônica

Cubo de Leds 3x3x3 com Arduino

Publicado: 15/08/2019

Construir um cubo de Leds é um desafio que está incluso na lista de desejos da grande maioria de usuários do Arduino e isso pode ser confirmado verificando a enorme quantidade de artigos e vídeos sobre o tema em várias línguas que estão disponíveis na Internet. Portanto, esse é um tema que não poderia faltar no blog da Módulo Eletrônica.

Nesse artigo vamos apresentar o projeto de um cubo de Leds de 3x3x3 operando com o Arduino Uno. Entretanto, o mesmo resultado será obtido se o Uno for substituído pelo Pro Mini ou pelo Arduino Nano.

Serão apresentadas as linhas gerais de montagem do cubo de Led 3x3x3. É importante ressaltar que, como dissemos, há farto material disponível na Internet com detalhes sobre como montar esses dispositivos. Além disso, não deixaremos de explorar o funcionamento da biblioteca <LedCube.h> adotada em nosso projeto.

Lista de componentes: 1 Arduino Uno, 27 Leds difuso, 5 mm, na cor azul (evidentemente, outras cores podem ser usadas), 3 transistores 2N2222, 3 resistores de 10K Ohms, ¼ W, 5%, 9 resistores de 270 Ohms, ¼ W, 5%, 1 placa padrão de circuito impresso cortada no tamanho de 7 x 10 cm, 1 fonte de alimentação de 12 V / 1 A, 1 barra de 40 pinos de 180 graus, tipo header fêmea pcb e 13 cabos jumpers.

Os componentes foram montados na placa de circuito impresso padrão conforme o esquema apresentado na figura 1. Como foi utilizada uma placa padrão, as conexões indicadas no circuito do esquema da figura 1 foram completadas utilizando-se fios.

Figura 1: Esquema de Montagem da Placa

O cubo de Leds foi fisicamente construído conforme está ilustrado na figura 2, com a identificação da posição de cada Led do esquema no cubo.

Figura 2: Numeração de cada Led indicando sua posição no cubo

Como regra geral de construção do cubo, deve-se perceber que os Leds foram agrupados em andares ou níveis horizontais, ligando-se todos os catodos (ou terminais negativos) a um ponto comum. Assim sendo, formando o nível 1 temos os Leds L1, L4, L7, L10, L13, L16, L19, L22 e L25. O ponto comum dos terminais negativos desse nível horizontal foi conectado ao coletor do transistor Q1 (2N2222).

Formando o nível horizontal 2 temos os Leds L2, L5, L8, L11, L14, L17, L20, L23 e L26. O ponto comum dos terminais negativos desse nível horizontal foi conectado ao coletor do transistor Q2 (2N2222). E, por sua vez, formando o nível 3 temos os Leds L3, L6, L9, L12, L15, L18, L21, L24 e L27. O ponto comum dos terminais negativos desse nível horizontal foi conectado ao coletor do transistor Q3 (2N2222).

Além disso, os terminais positivos de uma coluna vertical de Leds como, por exemplo, L1, L2 e L3, são interligados a um ponto comum e este é conectado a um dos terminais de um resistor de 270 Ohms, indo o outro terminal desse resistor para o pino 2 do Arduino. Do mesmo modo, os terminais positivos da coluna vertical de Leds formada por L4, L5 e L6 são interligados a um ponto comum e este é conectado a um dos terminais de um resistor de 270 Ohms, indo o outro terminal desse resistor para o pino 3 do Arduino. Como pode ser verificado no esquema da figura 1, cada uma das nove colunas verticais de três Leds é ligada como descrito acima e conectada a um dos terminais de um resistor de 270 Ohms, indo a outra extremidade do resistor para um pino digital do Arduino.

Como um Led acende?

Para acender o Led 1, por exemplo, será necessário ligar nível lógico HIGH (ou 5 Volts) no pino 2 do Arduino e ligar nível lógico HIGH (ou 5 Volts) no pino 11 do Arduino. Com isso, o transistor Q1 irá conduzir, fechando o circuito de L1 para a terra (GND). Seguindo o mesmo princípio, para acender o Led 23, por exemplo, será necessário ligar nível lógico HIGH (ou 5 Volts) no pino 9 do Arduino e ligar nível lógico HIGH (ou 5 Volts) no pino 12 do Arduino. Com isso, o transistor Q2 irá conduzir, fechando o circuito de L23 para a terra (GND). Dessa forma, cada Led do cubo poderá ser ligado ou desligado individualmente.

Montar os resistores, transistores e a barra de pinos na placa de circuito impresso não é algo complexo, muito pelo contrário. Entretanto, a montagem dos Leds exige um certo cuidado. Recomenda-se usar um gabarito e ser paciente quando for executar a soldagem dos terminais dos Leds para formar o cubo. No gabarito, que pode ser de madeira MDF ou até mesmo de papelão grosso, a distância entre os furos dos Leds é de dois centímetros tipicamente.

Figura 3: Gabarito de Montagem para Cubo de Leds

Os testes após a montagem são fortemente recomendados para garantir que não há erros nas conexões, evitando dessa forma danificar o Arduino e os outros componentes usados no projeto.

Para executar o teste não é necessário ligar o Arduino, bastando usar uma fonte de + 5 Volts, um protoboard e cabos jumpers (ou fios). Nos testes, para facilitar o manuseio, as ligações deverão ser feitas através de um protoboard.

Tenha 3 fios (cabos jumpers) para manusear: 1 terra (GND), 1 fio com +5 V (uma simples derivação da fonte de 5 Volts) para ligar os níveis horizontais e um segundo fio com +5 V (uma outra derivação da mesma fonte de 5 Volts) para ligar as colunas verticais.

Em primeiro lugar, ligue o terra da fonte ao terminal GND da placa. O próximo passo é ligar o fio de +5 V ao terminal da placa que será ligado ao pino 11 do Arduino (ver esquema na figura 1). Então, ligue o segundo fio de +5 V aos Leds do primeiro nível horizontal (L1, L4, L7, L10, L13, L16, L19, L22 e L25), um de cada vez. Veja cada Led acender individualmente.

Ligue o fio de +5 V ao terminal da placa que será ligado ao pino 12 do Arduino (figura 1). Ligue o segundo fio de +5 V aos Leds do segundo nível horizontal (L2, L5, L8, L11, L14, L17, L20, L23 e L26), um de cada vez. Veja cada Led acender individualmente.

Ligue o fio de +5 V ao terminal da placa que será ligado ao pino 13 do Arduino. Ligue o segundo fio de +5 V aos Leds do segundo nível horizontal (L3, L6, L9, L12, L15, L18, L21, L24 e L27), um de cada vez. Veja cada Led acender individualmente.


Vídeo 1 testes —

Após garantir que tudo está corretamente montado, ligue o Arduino usando os cabos jumpers e carregue o sketch abaixo.

*** *** *** *** *** ***

Video 2 cubo funcionando —

Observações sobre o sketch

O sketch tem como base a biblioteca <LedCube.h> e aproveita os vários recursos da mesma, com destaque para as seguintes funções:

Tabela 1: Funções da biblioteca <LedCube.h> ADd


As funções acima citadas da biblioteca <LedCube.h> serão combinadas com a função for() para criar diferentes efeitos de iluminação nos Leds do cubo. Em outras palavras, cada função dessa biblioteca será a instrução principal de um determinado efeito luminoso e funcionará em conjunto com funções for().

No sketch a palavra “nome” foi substituída pelo nome atribuído ao cubo de Leds. O autor do sketch escolheu para o cubo o nome “cube”.

A parte inicial do programa contempla a inclusão da biblioteca <LedCube.h> e as instruções de estruturação do cubo.

Tabela 2: Parte inicial do sketch

Não há instruções no setup() como, por exemplo, estabelecer que os pinos digitais serão saídas e outros detalhes, pois todas as definições já estão embutidas na biblioteca <LedCube.h> e feitas na parte inicial do sketch.

O loop() começa com uma espera de 10 milisegundos – delay(10) – e o primeiro efeito de iluminação, chamado de “acender uma luz em um sinal de tempo, uma luz de cada vez”, é iniciado. Esse efeito de iluminação dos Leds utiliza a seguinte rotina:

Em primeiro lugar, precisamos entender que cube.getLevels() retorna o número de níveis horizontais, que são 3. Assim sendo, no primeiro for() o índice level (declarado do tipo byte) irá variar de 0 até 2, sendo incrementado de 1 em 1, formando assim um loop. Dentro desse loop – nesse primeiro for() – o programa roda uma segunda função for() cujo índice é a variável col (declarada do tipo byte). A função cube.getCols() retorna o numero de colunas verticais, que são 9. Assim sendo, no segundo for() o índice col irá variar de 0 até 8, sendo incrementado de 1 em 1, formando assim um outro loop. Isso significa que o sketch está varrendo os Leds de cada coluna vertical em cada nível horizontal. Para cada rodada do loop é executada a instrução cube.lightPulse(level, col, 100). Essa instrução acende o Led definido pelo nível horizontal e pela coluna vertical pelo tempo de 100 milisegundos.

O sketch continua com o efeito chamado “um nível de luz (acende um nível de Leds) de cada vez, o aumento da velocidade”. Essa parte do programa também usa funções for() combinadas com funções da biblioteca <LedCube.h>. Na instrução for(byte d=25; d>2; d-=2) o índice d (do tipo byte) inicia com 25 e é decrementado de 2 em 2. A variável d será o tempo de espera (ou delay). Na instrução seguinte temos uma nova função for() – for(byte l=1; l <= cube.getLevels(); l++) – que varre os 3 níveis horizontais do cubo. Note que a variável l (do tipo byte) é o índice usado para definir cada nível horizontal do cubo. Finalmente, a instrução principal é a cube.lightLevel(l, d) que acende os Leds do nível horizontal definido pela variável l pelo tempo de d milissegundos, que é o tempo de espera definido na função for() do primeiro loop dessa parte do skecth.

O próximo efeito foi chamado de “acender cada linha em cada nível” e tem cube.lightRow(row, level) como sua instrução principal, que acende os Leds da linha definida pela variável row no nível horizontal definido pela variável level. Como nos efeitos anteriores, a varredura das linhas e dos níveis do cubo são executadas por funções for() e estão colocadas nessa parte do skecth antes da instrução principal.

O próximo efeito foi chamado de “acender cada plano” e tem como instrução principal cube.lightPlane(row, 10*i), que acende os Leds no plano definido pela variável row e espera o tempo (significa que o Led permanece aceso por esse tempo de espera) de i multiplicado por 10, em milisegundos.

O próximo efeito de iluminação foi chamado de “luz aleatória simples de cada vez” e tem como instrução principal cube.randomLight(random(25,100),100), que acende um Led escolhido (de forma pseudoaleatória) dentro de um intervalo numérico (entre 25 e 100) e faz o Led permanecer aceso durante um tempo de espera de 100 milisegundos.

No sketch que estamos comentando o próximo efeito foi chamado de “coluna aleatória” e tem como instrução principal: cube.lightDrop(random(0,cube.getCols()), random(50,150))

Essa instrução acende os Leds em uma coluna definida de forma pseudoaleatória por random(0,cube.getCols()), permanecendo acesos por um determinado tempo definido de forma pseudoaleatória por random(50,150).

O próximo efeito de iluminação foi chamado de “círculo em torno de cubo em um nível aleatório” e tem como instrução principal a seguinte:

cube.lightPerimeter(random(0,cube.getLevels()), random(1,5), random(25,100))

A instrução acende Leds no entorno (perímetro) definido por 3 parâmetros: random(0, cube.getLevels()) define o byte de nível horizontal, random(1,5) define o byte de rotação e random(25,100) define o tempo de espera.

O efeito seguinte foi chamado de “acender cada rosto” e isso significa selecionar e acender os Leds nos diferentes planos do cubo. A instrução principal desse efeito é cube.lightPlane(planes[p], 5*i), que acende os Leds definidos pelos parâmetros da array planes[p], contendo o byte do plano selecionado, permanecendo esses Leds acesos pelo tempo i multiplicado por 5, em milissegundos.

Na sequência do sketch temos ainda os efeitos “desligar uma luz de cada vez”, “colunas aleatórias”, “desativar uma única coluna aleatoriamente”, “dentro e fora”, “diamante e caixa”, “efeito helicóptero” e “desligar uma luz de cada vez”, todos muito interessantes. Mesmo considerando que já há elementos suficientes no texto que permitem a compreensão de todos os efeitos de luz no cubo, nos colocamos a disposição para fornecer esclarecimentos sobre o código apresentado. Sendo assim, se você tem dúvidas em qualquer parte desse artigo envie suas perguntas e faça seus comentários. Adquira os componentes para criar o seu próprio cubo de Leds na loja virtual da Módulo Eletrônica. Teremos prazer em te ajudar a vencer esse desafio. Bem, é isso aí, até a próxima.


***** ***** *****

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
*/
#include <LedCube.h>
#define SIZE 3
#define COLS (SIZE*SIZE)
 
byte levelPins[SIZE] = {11,12,13};
byte colPins[COLS] = {2,3,4,5,6,7,8,9,10};
LedCube cube(SIZE, levelPins, colPins);
 
void setup ()
{}
void loop ()
{
    delay(10);
     
    // acender uma luz em um sinal de tempo, uma luz de cada vez
    for(byte level=0; level<cube.getLevels(); level++)
    {
        for(byte col=0; col<cube.getCols(); col++)
        {
            cube.lightPulse(level, col, 100);
        }
    }
     
    // um nível de luz de cada vez, o aumento da velocidade
    for(byte d=25; d>2; d-=2)
    {
        for(byte l=1; l <= cube.getLevels(); l++)
        {
            cube.lightLevel(l, d);
        }
    }
     
    // acender cada linha em cada nível
    for(byte level=1; level<=cube.getLevels(); level++)
    {
        for(byte row=1; row<=cube.getLevels()*2; row++)
        {
            cube.lightRow(row, level);
        }
    }
     
    // acender cada plano
    for(byte i=3; i; i--)
    {
        for(byte row=1; row<=cube.getLevels()*2; row++)
        {
            cube.lightPlane(row, 10*i);
        }
    }
     
    // luz aleatória simples de cada vez
    cube.randomLight(random(25,100),100);
     
    // coluna aleatória
    for(byte x=0; x<=15; x++)
    {
        cube.lightDrop(random(0,cube.getCols()), random(50,150));
    }
     
    // círculo em torno de cubo em um nível aleatório
    for(byte x=0; x<=5; x++)
    {
        cube.lightPerimeter(random(0,cube.getLevels()), random(1,5), random(25,100));
    }
     
    // acender cada rosto
    byte planes[] = {cube.getLevels()+1,cube.getLevels(),cube.getLevels()*2,1};
    for(byte i=5; i; i--)
    {
        for(byte p=0; p<sizeof(planes); p++)
        {
            cube.lightPlane(planes[p], 5*i);
        }
    }
     
    // colunas aleatórias
    cube.randomColumn(25);
     
    // desativar uma única coluna aleatoriamente
    cube.enableBuffer();
    for(byte c=0; c<30; c++)
    {
        cube.fillBuffer();
        cube.invertBuffer();
        cube.randomColumn();
        cube.drawBuffer(7);
    }
    cube.enableBuffer(false);
     
    // dentro e fora
    for(byte c=1, d=0; c<=10; c++)
    {
        if(c%2 == 0)
        {
            for(d=0; d<20; d++)
            {
                cube.lightColumn(2,1);
                cube.lightColumn(4,1);
                cube.lightColumn(6,1);
                cube.lightColumn(8,1);
            }
        }
        else if(c%4 == 1)
        {
            for(d=0; d<30; d++)
            {
                cube.lightColumn(1,1);
                cube.lightColumn(3,1);
                cube.lightColumn(7,1);
                cube.lightColumn(9,1);
            }
        }
        else
        {
            for(d=0; d<70; d++)
            {
                cube.lightColumn(5,1);
            }
        }
    }
     
    // diamante e caixa
    byte diamond[] = {0,4,  1,1, 1,3, 1,4, 1,5, 1,7,   2,4};
    byte box[] = {
        2,0, 2,1, 2,2, 2,3, 2,5, 2,6, 2,7, 2,8,
        1,0, 1,2, 1,6, 1,8,
        0,0, 0,1, 0,2, 0,3, 0,5, 0,6, 0,7, 0,8
    };
    cube.lightSequence(box, sizeof(box), 200);
    cube.lightSequence(diamond, sizeof(diamond), 400);
     
    // efeito helicóptero
    byte topSeq[8] = {0,3,6,7,8,5,2,1};
    byte botSeq[8] = {8,5,2,1,0,3,6,7};
    for(byte loops = 0, delay = 50; loops<=8; loops++)
    {
        for(byte s=0; s<8; s++)
        {
            byte seq[] = {2,topSeq[s], 1,4, 0,botSeq[s]};
            cube.lightSequence(seq, sizeof(seq), delay);
        }
        if(loops < 5) delay-=10;  else delay += 10;
    }
     
    // desligar uma luz de cada vez
    cube.enableBuffer();
    cube.fillBuffer();
    cube.drawBuffer(25);
    for(byte w=0, l, c, max = cube.getNumLights(); w<max; )
    {
        // limite inferior é, inclusive, superior é exclusivo
        l = random(0, cube.getLevels());
        c = random(0, cube.getCols());
         
        if(cube.getBufferAt(l,c) == HIGH)
        {
            cube.lightOff(l,c);
            cube.drawBuffer(5);
            w++;
        }
    }
    cube.enableBuffer(false);
}
Voltar
Clique Aqui
(19) 99363-2833