19 novembro 2017

Placar eletrônico com Arduino

No post de hoje vamos montar um placar eletrônico com Arduino, usando uma placa Nano e módulos matriz de leds 8x8 Max7219, fazendo o controle por meio de botões tipo push-button.

Placar eletrônico com Arduino e Max7219

Serão dois displays e três botões de controle, e neste tutorial você encontra todo o esquema de ligação dos componentes, assim como os arquivos necessários para montar uma estrutura semelhante à da imagem acima.

O módulo Max7219


O módulo matriz de led 8x8 com Max7219 é um módulo relativamente simples de usar, com 3 pinos de controle e alimentação de 5V.

módulo max7219 matriz de leds 8x8

Uma das vantagens desse módulo é que ele já vem com os pinos de saída para você interligar outros módulos Max7219 (na imagem abaixo, no lado direito). Dessa maneira, você controla vários deles usando as mesmas 4 portas do microcontrolador. É essa ligação que vamos usar para montar o placar eletrônico.

Módulo Max7219 - Detalhe pinagem


Se quiser conhecer outros projetos aqui do Arduino e Cia com o módulo Max7219, confira os posts Painel de led com módulo Max7219 e Módulo Max7219 matriz de leds 8x8.

Circuito do placar eletrônico


O controle do placar eletrônico vai ser feito por um Arduino Nano, que vai se comunicar com os módulos Max7219 através das portas 10 (pino DataIn do módulo), 11 (pino CS) e 12 (pino CLK).

Os botões serão ligados nas portas 6, 7 e 8 do Arduino, e vão utilizar os resistores pull-up internos, dispensando assim o uso desse componente na protoboard.

Circuito Arduino Nano e módulo Max7219


Por fim, os leds serão conectados nas portas 3 e 4, e servem para indicar qual display está ativo, mas vamos explicar isso com mais detalhes logo abaixo.

Detalhe circuito

Programa de controle do placar eletrônico


Para o programa do placar eletrônico, vamos utilizar a biblioteca LedControl, que pode ser instalada através da própria IDE do Arduino, no menu Sketchs -> Incluir Biblioteca -> Gerenciar Bibliotecas e procurar por ledcontrol:

Biblioteca Ledcontrol

Com a biblioteca instalada, carregue o programa abaixo no Arduino Nano:

  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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
//Programa: Placar Eletronico com Arduino e Max7219
//Autor: Arduino e Cia

#include "LedControl.h"

//Conexoes do modulo Max7219
//DataIn = Pino 11
//CLK = Pino 12
//CS = Pino 11

LedControl lc = LedControl(10, 12, 11, 2);

//Armazenam o valor dos botoes
int v_but1, v_but2, v_but3;

//Brilho dos displays
int brilho = 15;

//Numero do display selecionado
int j = 0;

//Array do placar atual
int placar[2] = {0, 0};

//Array do placar anterior
int placar_ant[2] = {0, 0};

unsigned long delaytime = 200;

void setup()
{
  Serial.begin(9600);
  //Inicializa pinos botoes
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  //Inicializa pinos leds
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  digitalWrite(3, HIGH);

  //Inicializa os displays
  lc.shutdown(0, false);
  lc.shutdown(1, false);

  //Ajusta o brilho de cada display
  lc.setIntensity(0, brilho);
  lc.setIntensity(1, brilho);

  //Apaga os displays
  lc.clearDisplay(0);
  lc.clearDisplay(1);

  //Mostra 0 (zero) nos dois displays
  writeOnMatrix(0, 0);
  writeOnMatrix(0, 1);
}

void loop()
{
  //Verifica se o botao de alternar
  //displays foi acionado
  v_but1 = digitalRead(6);
  if (v_but1 == 0)
  {
    j = !j;
    //Acende o led correspondente
    if (j == 0)
    {
      digitalWrite(3, HIGH);
      digitalWrite(4, LOW);
    }
    else
    {
      digitalWrite(3, LOW);
      digitalWrite(4, HIGH);
    }
    while (digitalRead(6) == 0)
    {delay(50);}
  }

  //Verifica se o botao de aumentar
  //contador foi acionado
  v_but2 = digitalRead(7);
  if (v_but2 == 0)
  {
    placar[j] = placar[j] + 1;
    if (placar[j] <= 0 || placar[j] >= 10)
    {
      placar[j] = 0;
    }
    if (placar_ant[j] != placar[j])
    {
      //Chama a rotina que atualiza o display
      writeOnMatrix(placar[j], j);
      v_but3 = digitalRead(8);
      placar_ant[j] = placar [j];
    }
    while (digitalRead(7) == 0)
    {delay(50);}
  }

  //Verifica se o botao de diminuir
  //contador foi acionado
  v_but3 = digitalRead(8);
  if (v_but3 == 0)
  {
    placar[j] = placar[j] - 1;
    if (placar[j] <= 0 || placar[j] >= 10)
    {
      placar[j] = 0;
    }
    if (placar_ant[j] != placar[j])
    {
      //Chama a rotina que atualiza o display
      writeOnMatrix(placar[j], j);
      v_but3 = digitalRead(8);
      placar_ant[j] = placar [j];
    }
    while (digitalRead(8) == 0)
    {delay(50);}
  }
}

void writeOnMatrix(int numero, int tela)
{
  //O array abaixo forma o numero 0
  byte N0[8] = {B00000000, B00000000, B00111110, B01000001,
                B01000001, B00111110, B00000000, B00000000
               };
  //numero 1
  byte N1[8] = {B00000000, B00000000, B00000000, B01000010,
                B01111111, B01000000, B00000000, B00000000
               };
  //numero 2
  byte N2[8] = {B00000000, B00000000, B01100010, B01010001,
                B01001001, B01000110, B00000000, B00000000
               };
  //numero 3
  byte N3[8] = {B00000000, B00000000, B00100010, B01000001,
                B01001001, B00110110, B00000000, B00000000
               };
  //numero 4
  byte N4[8] = {B00000000, B00000000, B00001100, B00001010,
                B00001001, B01111111, B00000000, B00000000
               };
  //numero 5
  byte N5[8] = {B00000000, B00000000, B00100111, B01000101,
                B01000101, B00111001, B00000000, B00000000
               };
  //numero 6
  byte N6[8] = {B00000000, B00000000, B00111110, B01001001,
                B01001001, B00110000, B00000000, B00000000
               };
  //numero 7
  byte N7[8] = {B00000000, B00000000, B01100001, B00010001,
                B00001001, B00000111, B00000000, B00000000
               };
  //numero 8
  byte N8[8] = {B00000000, B00000000, B00110110, B01001001,
                B01001001, B00110110, B00000000, B00000000
               };
  //numero 9
  byte N9[8] = {B00000000, B00000000, B00001110, B01001001,
                B01001001, B00111110, B00000000, B00000000
               };

  //Mostra no display selecionado o numero correspondente
  switch (numero)
  {
    case 0:
      lc.setRow(tela, 1, N0[0]);
      lc.setRow(tela, 1, N0[1]);
      lc.setRow(tela, 2, N0[2]);
      lc.setRow(tela, 3, N0[3]);
      lc.setRow(tela, 4, N0[4]);
      lc.setRow(tela, 5, N0[5]);
      lc.setRow(tela, 6, N0[6]);
      lc.setRow(tela, 7, N0[7]);
      break;
    case 1:
      lc.setRow(tela, 1, N1[0]);
      lc.setRow(tela, 1, N1[1]);
      lc.setRow(tela, 2, N1[2]);
      lc.setRow(tela, 3, N1[3]);
      lc.setRow(tela, 4, N1[4]);
      lc.setRow(tela, 5, N1[5]);
      lc.setRow(tela, 6, N1[6]);
      lc.setRow(tela, 7, N1[7]);
      break;
    case 2:
      lc.setRow(tela, 1, N2[0]);
      lc.setRow(tela, 1, N2[1]);
      lc.setRow(tela, 2, N2[2]);
      lc.setRow(tela, 3, N2[3]);
      lc.setRow(tela, 4, N2[4]);
      lc.setRow(tela, 5, N2[5]);
      lc.setRow(tela, 6, N2[6]);
      lc.setRow(tela, 7, N2[7]);
      break;
    case 3:
      lc.setRow(tela, 1, N3[0]);
      lc.setRow(tela, 1, N3[1]);
      lc.setRow(tela, 2, N3[2]);
      lc.setRow(tela, 3, N3[3]);
      lc.setRow(tela, 4, N3[4]);
      lc.setRow(tela, 5, N3[5]);
      lc.setRow(tela, 6, N3[6]);
      lc.setRow(tela, 7, N3[7]);
      break;
    case 4:
      lc.setRow(tela, 1, N4[0]);
      lc.setRow(tela, 1, N4[1]);
      lc.setRow(tela, 2, N4[2]);
      lc.setRow(tela, 3, N4[3]);
      lc.setRow(tela, 4, N4[4]);
      lc.setRow(tela, 5, N4[5]);
      lc.setRow(tela, 6, N4[6]);
      lc.setRow(tela, 7, N4[7]);
      break;
    case 5:
      lc.setRow(tela, 1, N5[0]);
      lc.setRow(tela, 1, N5[1]);
      lc.setRow(tela, 2, N5[2]);
      lc.setRow(tela, 3, N5[3]);
      lc.setRow(tela, 4, N5[4]);
      lc.setRow(tela, 5, N5[5]);
      lc.setRow(tela, 6, N5[6]);
      lc.setRow(tela, 7, N5[7]);
      break;
    case 6:
      lc.setRow(tela, 1, N6[0]);
      lc.setRow(tela, 1, N6[1]);
      lc.setRow(tela, 2, N6[2]);
      lc.setRow(tela, 3, N6[3]);
      lc.setRow(tela, 4, N6[4]);
      lc.setRow(tela, 5, N6[5]);
      lc.setRow(tela, 6, N6[6]);
      lc.setRow(tela, 7, N6[7]);
      break;
    case 7:
      lc.setRow(tela, 1, N7[0]);
      lc.setRow(tela, 1, N7[1]);
      lc.setRow(tela, 2, N7[2]);
      lc.setRow(tela, 3, N7[3]);
      lc.setRow(tela, 4, N7[4]);
      lc.setRow(tela, 5, N7[5]);
      lc.setRow(tela, 6, N7[6]);
      lc.setRow(tela, 7, N7[7]);
      break;
    case 8:
      lc.setRow(tela, 1, N8[0]);
      lc.setRow(tela, 1, N8[1]);
      lc.setRow(tela, 2, N8[2]);
      lc.setRow(tela, 3, N8[3]);
      lc.setRow(tela, 4, N8[4]);
      lc.setRow(tela, 5, N8[5]);
      lc.setRow(tela, 6, N8[6]);
      lc.setRow(tela, 7, N8[7]);
      break;
    case 9:
      lc.setRow(tela, 1, N9[0]);
      lc.setRow(tela, 1, N9[1]);
      lc.setRow(tela, 2, N9[2]);
      lc.setRow(tela, 3, N9[3]);
      lc.setRow(tela, 4, N9[4]);
      lc.setRow(tela, 5, N9[5]);
      lc.setRow(tela, 6, N9[6]);
      lc.setRow(tela, 7, N9[7]);
      break;
  }
}

O funcionamento é bem simples: utilize o botão da esquerda para selecionar qual dos dois displays será atualizado. O led correspondente ao display selecionado será aceso. Utilize então o botão do meio para aumentar o valor do contador, e o botão da direita para diminuir o valor. Confira no vídeo abaixo o projeto em funcionamento:


Se você quiser uma estrutura como essa para o seu placar eletrônico, disponibilizei os arquivos para impressão 3D no Thingiverse, neste link.

18 comentários:

  1. Primeiramente gostaria de vus parabenizar pelo orojeto.
    Segui todas as instruções porém mesmo tendo carregado o programa no arduino o mesmo não executa as funções .

    ResponderExcluir
    Respostas
    1. Boa noite e obrigado!

      O seu Arduino também é o Nano ou você está usando algum outro modelo? Não aparece nada no display ou apenas os botões não respondem?

      Abraço!

      Adilson

      Excluir
  2. bom dia ja tinha mandado um email para vc de como fazer com sensor de obstaculo teria como vc me ajudar pois estou ja um bom tempo tentando e não consigo

    ResponderExcluir
    Respostas
    1. Oi André,

      Envie novamente, por favor. Utilize o formulário de contato no lado direito da página, ok?

      Abraço!

      Adilson

      Excluir
  3. Boa noite parabéns pelo tutorial... Tem como colocar sensor? .. eu tenho um pebolim e gostaria de colocar nele .. deve ficar show

    ResponderExcluir
  4. boa tarde amigo td bem... entao tem como colocar sensors ao inves de controle por meio de botões tipo push-button?... tenho um pebolim.. acho q ficaria bacana eu colocar sensors no gol ... e quando fazer fizesse gol ia altomaticamente ao invez de eu ter q apertar botao... è passively?? aguardo a resposta otimo dia

    ResponderExcluir
  5. Respostas
    1. Oi Alef,

      Pode até ser um sensor mecânico, dependendo do modelo de pebolim que vc tem. Como geralmente tem uma canaleta para a bola rolar quando entra no gol, vc pode colocar uma chave ali ou algo do tipo. Talvez um sensor infravermelho também funcionasse.

      Abraço!

      Adilson

      Excluir
  6. Tenho interesse em comprar pronto, você venderia? Favor entrar em contato.

    ResponderExcluir
    Respostas
    1. Boa noite,

      Entre em contato utilizando o link "Fale com o administrador" no lado direito do site, por favor.

      Abraço!

      Adilson

      Excluir
  7. Olá, gostaria de saber como eu programaria um display de lcd 16x2 com o módulo 12c, dois sensores óptcos tcrt5000. O projeto seria para fazer um placar para o jogo air hockey onde os sensores serão acoplados nas duas goleiras e seria o seguinte, o display conterá dois placares, por exemplo "TIME A X TIME B" com um tempo. Quando o disco passasse, o time A receberá um gol e assim o mesmo com o time B. Obrigado!

    ResponderExcluir
    Respostas
    1. Oi Brian,

      Legal. Eu tenho aqui no blog um post sobre o TCRT5000. Tente juntar as duas programações:

      https://www.arduinoecia.com.br/2013/10/sensor-optico-reflexivo-tcrt5000.html

      Abraço!

      Adilson

      Excluir
    2. Obrigado Adilson, parabéns pelo blog. Me salvou em várias no curso <3

      Excluir
    3. Valeu Brian!

      Aguardo a sua visita no Arduino e Cia sempre que possível. :)

      Abraço!

      Adilson

      Excluir
  8. Olá, gostaria de saber qual o softwares que voces usam para desenhar o circuito?

    ResponderExcluir
    Respostas
    1. Oi Brian,

      Usamos o Fritzing, que você pode baixar em fritzing.org.

      Abraço!

      Adilson

      Excluir
  9. Ciao
    Bel tutorial
    Come posso modificare il programma per avere 4 display max7219 per poter visualizzare da 0 a 99 e non da 0 a 9
    Attendo una risposta
    Grazie

    ResponderExcluir
    Respostas
    1. Ciao!
      Non ho ancora lo schema di connessione, ma presto lancerò un tutorial aggiungendo questi display.
      Saluti!
      Adilson

      Excluir