C++

Jogando Super Nintendo no Android com controle original

Posted in Android, Arduino, C++, Electronics, Game on abril 21st, 2011 by Bruno Soares – 70 Comments

Jogando SNES com controle original via bluetooth Logo que comprei meu HTC Desire HD (sistema operacional Android) instalei um emulador de Super Nintendo (SNES), este foi um dos poucos videogames que tive, e era viciado (quando tinha 10 / 11 anos) em Super Mario World, assim que instalei o Mario me veio aquela nostalgia! Mas jogar com o controle touch screen é péssimo, não tem experiência tátil e o seu dedo fica encima do jogo.
Então pensei, é claro que alguém já ligou o controle original no celular, e estava certo,  encontrei este vídeo: “http://www.youtube.com/watch?v=_FZTz2KO9vU“. Mas tem um detalhe muito importante este projeto, é para NES e não o SNES (mais novo), ou seja, sabia que era possível fazer e tinha os materiais para isto, então só esperei sobrar um tempo para fazer (o único componente que não tinha era o controle, mas consegui um paralelo por R$ 8,00 no Mercado Livre).


vimeo.com/bsoares/snes-on-android-with-controller-and-bluesmirf

Como funciona:
O controle do SNES esta ligado a Arduino, é bem fácil obter as teclas pressionadas, mas existe uma biblioteca para tornar esta tarefa ainda mais simples (NESpad/SNESpad). Cada tecla pressionada liga um bit dentro do número que representa o estado das teclas do controle, e este estado (número) é enviado via Bluetooth (uso o BlueSMiRF) para o Android.
No Android, quem recebe este número é o Amarino, mas ele apenas recebe o número, ainda é necessário um App (que foi modificado a partir deste exemplo “SoftKeyboard“) para converter este número em teclas pressionadas (uso Bitwise) como um teclado do Android.
Por fim é só configurar o emulador para entender as teclas pressionadas como os comandos dentro do mesmo (pular, andar, girar, etc…)

Desta forma o controle pode ser usado como o teclado do seu Android, e ainda ser configurado como o controle de outros emuladores.

Sobre o módulo bluetooth BlueSMiRF:
Depois de configurado ele será o seu “cabo USB virtual” pois da mesma forma que usamos o comando Serial.print(“…”) para enviar dados via porta serial, o mesmo dado será enviado via bluetooth.
A App Amarino utiliza 57.600 de baudrate, e os módulos BlueSMiRF normalmente vem com 9.600.
Para configurar o blueSMiRF utilizei alguns tutoriais:
- http://todbot.com/blog/2006/02/23/howto-mac-os-x-bluetooth-serial-port/
- http://www.sparkfun.com/tutorials/67

Sobre o Soft Keyboard (App para Android):
Modifiquei o exemplo de Keyboard App disponível no Android Developers para obter os dados via Amarino e agir como teclado. Me baseei neste projeto criado para NES, porém criei outro código para a Arduino e alterei 95% do código para o Android.

O código fonte do projeto para Androi, Arduino e as versões das bibliotecas que foram utilizadas, podem ser baixadas do meu Github:
https://github.com/BSoares/SNES-on-Android-with-original-controller

Conteúdo Relacionado:
Código fonte
Arduino UNO
BlueSMiRF
Amarino
Android Sample Soft Keyboard
NESpad/SNESpad
Vídeo no Youtube

Enjoy :-)

PianoDuino (Arduino + Processing + SoundCipher)

Posted in Arduino, C++, Electronics, Processing on maio 30th, 2009 by Bruno Soares – 21 Comments

PianoDuino é um experimento simples que integra Arduino, Processing e uma biblioteca para manipular sons, a SoundCipher. A ideia serviu para experimentar o Multiplexador / Demultiplexador 4051.

PianoDuino (Arduino + Processing + SoundCipher) from Bruno Soares on Vimeo.

Arduino:

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
/**
 * PianoDuino
 *
 * @author   Bruno Soares
 * @link     http://www.bsoares.com.br
 * @language Arduino / C++
 */


#define PIN_SELECTOR0 2
#define PIN_SELECTOR1 3
#define PIN_SELECTOR2 4

int value;
int count;

// Selectors
byte s0;
byte s1;
byte s2;

void setup()
{
  Serial.begin(9600);
 
  pinMode(PIN_SELECTOR0, OUTPUT);
  pinMode(PIN_SELECTOR1, OUTPUT);
  pinMode(PIN_SELECTOR2, OUTPUT);
}

void loop()
{
  for (count = 0; count < 8; count++)
  {
    // Extract active bits
    s0 =  count       & 0x1;
    s1 = (count >> 1) & 0x1;
    s2 = (count >> 2) & 0x1;
   
    // Select input
    digitalWrite(2, s0);
    digitalWrite(3, s1);
    digitalWrite(4, s2);
   
    // Read input selected
    value = analogRead(0);
    if (value > 5)
    {
      Serial.print(count);
      while(analogRead(0) > 5);
    }
  }
}

Processing:

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
/**
 * PianoDuino
 *
 * @author   Bruno Soares
 * @link     http://www.bsoares.com.br
 * @language Processing
 */


import arb.soundcipher.*;
import processing.serial.*;

SoundCipher[] sc = new SoundCipher[8];
Serial port;
int portValue = 0;

void setup()
{
  for (int i = 0; i < sc.length; i++)
  {
    sc[i] = new SoundCipher(this);
  }
 
  println(Serial.list());
  port = new Serial(this, Serial.list()[1], 14400);
}

void draw()
{
  while (port.available() > 0) {
    portValue = int(port.readString().substring(0, 1));
    print(portValue);
    sc[portValue].playNote(80 - (portValue * 7), 100, 2.5);
  }
}

Baixe o código fonte completo aqui.

 


 

Conteúdo relacionado:
Fotos no Flickr
Arduino
Processing
SoundCipher
Analog multiplexer / demultiplexer 4051

Operações binárias

Posted in ASP.NET, ActionScript 3.0, Arduino, C++, Electronics, Flash, PHP on maio 25th, 2009 by Bruno Soares – 7 Comments

Ultimamente tenho me deparado com muitos trechos de códigos que utilizam operações binárias, como chaveamento de multiplexador, extração de RGB a partir de um inteiro ou hexadecimal, bitshift para controlar LED Matrix, etc… E finalmente dei aquela estuda, agora vai ai um post sobre o que resultou o estudo.

Obs.: Os trechos de códigos deste post foram escritos em ActionScript, mas pode ser aplicado a C, C++, Java, Processing, PHP, entre outras linguagens.


Introdução
• Bit Shift
   • Operador >> (bitwise right shift)
   • Operador << (bitwise left shift)
• Operações Bitwise
   • Operador & (bitwise AND)
   • Operador | (bitwise OR)
   • Operador ^ (bitwise XOR)
   • Operador ~ (bitwise NOT)
• Exemplos
   • Extraindo o RGB de uma cor
   • Chaveando multiplexador 4051
 


Introdução
Um operador binário, como o nome sugere, é um operador que trabalha com a representação binária do número, e como normalmente não sabemos a representação binária dos números de cabeça, vamos utilizar a tabela abaixo:

 -----------------------
|      BIN |  DEC | HEX |
|-----------------------|
|        1 |    1 |   1 |
|       10 |    2 |   2 |
|       11 |    3 |   3 |
|      100 |    4 |   4 |
|      101 |    5 |   5 |
|      110 |    6 |   6 |
|      111 |    7 |   7 |
|     1000 |    8 |   8 |
|     1001 |    9 |   9 |
|     1010 |   10 |   A |
|     1011 |   11 |   B |
|     1100 |   12 |   C |
|     1101 |   13 |   D |
|     1110 |   14 |   E |
|     1111 |   15 |   F |
|    10000 |   16 |  10 |
|    10001 |   17 |  11 |
|    10010 |   18 |  12 |
|    10011 |   19 |  13 |
|    10100 |   20 |  14 |
|-----------------------|
| 11111111 |  255 |  FF |
 ----------------------- 

A tabela lista os números de 1 à 20 e 255 em três bases diferentes:
Binário (BIN)
• Decimal (DEC)
Hexadecimal (HEX)

Analisando a tabela podemos concluir que 3d = 11b, 19d = 10011b (as letras d e b significam decimal e binário respectivamente). Lembrando que pode ser utilizada uma calculadora que opere em binário (como a do windows) ou uma alternativa de conversão de bases on-line como está: “Conversão de número binário”.

Então vamos deslocar, escorregar, escovar alguns bits para entender melhor.


Operador >>
Deslocamento de bits para a direita (bitwise right shift)

1
2
3
4
trace(8 >> 1); // 4
trace(8 >> 2); // 2
trace(8 >> 3); // 1
trace(8 >> 4); // 0

Olhando os números na base decimal faz pouco sentido, ou talvez nenhum sentido, então passamos os números corretos para a base binária e tudo fica mais claro:
8d = 1000b (8 decimal é igual a 1000 em binário), então:
1000b >> 1 (deslocando uma casa para direita) temos o número:
100b que em decimal é 4(dê uma olhada na tabela).

Agora ficou fácil não? Vamos deslocar o número 13:

1
trace(13 >> 1); // 6

13 em binário é 1101, deslocando uma casa para a direita (ou removendo 1 bit), fica 110, e 110 é igual a 6 em decimal.


Operador <<
Deslocamento de bits para a esquerda (bitwise left shift)

1
2
3
trace(2 << 1); // 4
trace(2 << 2); // 8
trace(2 << 3); // 16

Agora é só seguir o mesmo raciocino já utilizando anteriormente.
Se 2 em base binária é igual a 10 e deslocarmos um bit para esquerda, vamos ganhar mais um zero, ficando com 100 que é igual a 4 em decimal.


Operador &
AND binário (bitwise AND)
O operador & compara bit a bit os números a sua direita e esquerda, por exemplo o resultado de 10 & 11 é 10:

  1010
& 1011
------
  1010

A comparação bit-a-bit somente retorna True (1) quando os bits comparados são iguais a 1, caso contrário retorna False (0). Formando assim um novo número.
Mais alguns exemplos para fortalecer:

|14 &  9|13 & 11|20 &  9|14 & 10|89 &  112|45  &  77|255  &  13|112 &  255|
|       |       |       |       |         |         |          |          |
|  1110 |  1101 |  10100|  1110 |  1011001|   101101|  11111111|   1110000|
|& 1001 |& 1011 |&  1001|& 1010 |& 1110000|& 1001101|&     1101|& 11111111|
|  ---- |  ---- |  -----|  ---- |  -------|  -------|  --------|  --------|
|  1000 |  1001 |      0|  1010 |  1010000|     1101|      1101|   1110000|
|    8d |    9d |     0d|   10d |      80d|      13d|       13d|      112d|


Operador |
OR binário (bitwise OR)
O operador | tem a mesma função do operador OR comum (||) só que atua bit-a-bit, assim como os outros operadores binários. Vejamos um exemplo:

  1010
| 1011
------
  1011

Se um dos bits comparados forem iguais a 1 a expressão retornará 1, caso os dois bits comparados forem iguais a 0, a expressão retorna 0. Agora vamos refazer o exemplo anterior trocando apenas o operador & (and binário) por | (or binário):

|14 |  9|13 | 11|20 |  9|14 | 10|89 |  112|45  |  77|255  |  13|112 |  255|
|       |       |       |       |         |         |          |          |
|  1110 |  1101 |  10100|  1110 |  1011001|   101101|  11111111|   1110000|
|| 1001 || 1011 ||  1001|| 1010 || 1110000|| 1001101||     1101|| 11111111|
|  ---- |  ---- |  -----|  ---- |  -------|  -------|  --------|  --------|
|  1111 |  1111 |  11101|  1110 |  1111001|  1101101|  11111111|  11111111|
|   15d |   15d |    29d|   14d |     121d|     109d|      255d|      255d|


Operador ^
OU exclusivo (bitwise XOR)
A letra X na frente do OR significa Exclusive (Exclusive OR). Isso quer dizer que este operador faz a comparação binária de dois números e resulta os bits que são diferentes. Por exemplos, quais são os bits diferentes entre os números 10 e 11?

  1010
^ 1011
------
     1

Vamos novamente trocar o operador do exemplo anterior para analisar os resultados:

|14 ^  9|13 ^ 11|20 ^  9|14 ^ 10|89 ^  112|45  ^  77|255  ^  13|112 ^  255|
|       |       |       |       |         |         |          |          |
|  1110 |  1101 |  10100|  1110 |  1011001|   101101|  11111111|   1110000|
|^ 1001 |^ 1011 |^  1001|^ 1010 |^ 1110000|^ 1001101|^     1101|^ 11111111|
|  ---- |  ---- |  -----|  ---- |  -------|  -------|  --------|  --------|
|   111 |   110 |  11101|   100 |   101001|  1100000|  11110010|  10001111|
|    7d |    6d |    29d|    4d |      41d|      96d|      242d|      143d|


Operador ~
Negação (bitwise NOT)
O operador NOT inverte o sinal e complementa em um.
Negando o número 168 (~168) teremos -169.

Alguns exemplos:

1
2
3
4
5
6
trace(~7);   // -8
trace(~-7);  // 6
trace(~14);  // -15
trace(~13);  // -14
trace(~255); // -256
trace(~112); // -113

 


Extraindo o RGB de uma cor
Sabendo que uma cor no formato RGB utiliza dois dígitos hexadecimais para definir quanto existe de Vermelho, Verde e Azul (respectivamente), formando cores como: Vermelho (FF0000), Cinza (C0C0C0), Laranja (FF9900), etc. Temos ai a possibilidade de gerar 16.581.375 de cores com este código, é só fazer a conta para conferir: 255 * 255 * 255 ou FF * FF * FF.
Vamos desmembrar um tom de azul (#347BB7) para saber quanto esta cor tem de Vermelho, Verde e Azul (o valor dos canais RGB).

1
2
3
4
5
6
7
8
9
10
// DEC: 3439543
// BIN: 1101000111101110110111
var color:uint = 0x347BB7;

var r:uint = (color >> 16) & 0xFF;
var g:uint = (color >>  8) & 0xFF;
var b:uint =  color        & 0xFF;

trace("Red:", r, "Green:", g, "Blue:", b);
// Red: 52 Green: 123 Blue: 183

Linha 5) Deslocando 16 bits para a direita temos:

  1101000111101110110111 >> 16
=                 110100 (DEC: 52)

Para o caso do vermelho não precisamos continuar a expressão (& 0xFF),
pois deslocando 16 bits para a direita já temos o resultado do vermelho,
mas se a cor estivesse no formato ARGB (Alpha Red Green Blue), seria necessário.

Linha 6) Deslocando 8 bits para conseguir o verde:

  1101000111101110110111 >> 8
=         11010001111011 (DEC: 13435)

Só com o valor do deslocamentos não vamos conseguir a cor verde, então utilizamos o
operador & (AND) com o valor 255 (0xFF) para extrair a parte binária que nos interessa:

  11010001111011 (DEC: 13435)
&       11111111 (DEC: 255, HEX: 0xFF)
  --------------
        01111011 (DEC: 123)

Linha 7) Para extrair o azul não precisamos deslocar bits e sim pegar os últimos 8 bits:

  1101000111101110110111
&               11111111 (DEC: 255, HEX: 0xFF)
  ----------------------
                10110111 (DEC: 183)

Agora voltando para o hexadecimal:

1
2
3
4
5
6
7
var r:uint = 52;
var g:uint = 123;
var b:uint = 183;
var color:uint = (r << 16) | (g << 8) | b;

trace(color.toString(16));
// 347bb7

Linha 4) Deslocando 16 bits para a esquerda do número 52 (Vermelho):

  110100 << 16
= 1101000000000000000000

Deslocando 8 bits para a esquerda do número 123 (Verde):

  1111011 << 8
= 111101100000000

Efetuando o OR (|) com o resultado das duas operações ((r << 16) | (g << 8)):

  1101000000000000000000
|        111101100000000
  ----------------------
  1101000111101100000000

Efetuando a última operação, o OR com o Azul (183)

  1101000111101100000000
| 0000000000000010110111
  ----------------------
  1101000111101110110111

O resultado agora ficou claro. O número 1101000111101110110111 (binário) é igual a 3439543 (decimal) e 347BB7 (hexadecimal).

 


Chaveando multiplexador 4051
A tarefa de chavear um Multiplexador / Demultiplexador (MUX / DEMUX) 4051 é muito parecida com a extração dos canais RGB de uma cor. Você só precisa Ligar ou Desligar três pinos de seleção (select pins) para que o circuito interprete o valor gerado e transmita a voltagem da entrada desejada.
Existe um gif animado do RogerCom muito didático que demonstra o funcionamento do CI 4051, gif animado CI 4051 aqui.
Por exemplo, para ler a entrada 3, precisamos desligar o pino de seleção 0, ligar o 1 e o 2, formando assim o número 011 (binário) que é igual a 3 em decimal. Veja no código (Escrito em Arduino / C++):

1
2
3
4
5
6
7
8
9
10
11
12
// Entrada desejada
int count = 3;

// Extração dos bits ativos
byte s0 =  count       & 0x1;
byte s1 = (count >> 1) & 0x1;
byte s2 = (count >> 2) & 0x1;

// Ligando ou desligando os pinos de seleção
digitalWrite(2, s0);
digitalWrite(3, s1);
digitalWrite(4, s2);

Conteúdo relacionado:
Bitwise operation on Wikipedia
 

Funções do C++ úteis para Arduino

Posted in Arduino, C++, Electronics on maio 16th, 2009 by Bruno Soares – 1 Comment

Para aqueles que sempre gostaram de eletrônica e que agora se envolveram com eletrônica digital, vai uma diga bem interessante.
Nós sabemos que para programar para microcontroladores é necessário entender um pouco de C, C++ ou até mesmo Assembly, e isso pode ser uma barreira para aqueles que tem interesse mas não dominam tais linguagens, então vai ai um site que pode ajudar muito a encontrar as funções necessárias para se manipular string, arrays, converter tipos, alocar memória, efetuar operações matemáticas entre outros:
http://www.cplusplus.com/

Na verdade o que o programa compilador do código Arduino faz é simplesmente converter o código “Arduino” para C++, compilar e gravar no microcontrolador. Por isso que podemos utilizar muitas funções do C++ para o Arduino. Para conferir entre no diretório /applet (sua aplicação/applet) e abra o arquivo com o mesmo nome do seu “.pde” só que com a extensão “.cpp”.

Vou listar aqui algumas funções bem úteis:

Conversão de tipos:
atof
– Converte string para double
atoi – Converte string  para integer
itoa – Converte integer para string
atol – Converte string  para long integer
strtod – Converte string  para double
strtol – Converte string  para long integer
strtoul – Converte string  para unsigned long integer
Obs.: Você pode encontrar mais funões de conversão de tipos no site da Arduino:
char(), byte(), int(), long() e float()

Manipulação dinâmica da memória:
calloc – Aloca espaço na memória para um array
free – Desaloca espaço na memória

Busca e ordenação:
bsearch – Busca binária em arrays
qsort – Ordena elementos de um array

Operações matemáticas (Math):
atan2 – Calcula o arco tangente com dois parâmetros
log – Calcula o logaritmo natural
log10 – Calcula o logaritmo comum
floor – Arredonda um valor para baixo

Manipulação de strings (char*):
strcat – Concatena strings
strncat – Concatena caracteres com base nas suas posições
strchr – Localiza a primeira ocorrência do caracter em uma string
strstr – Localiza a primeira ocorrência de uma string dentro de outra

Vale a pena conferir e dar uma estudada.

Conteúdo relacionado:
Referência
Arduino

Classe C++ para controlar Display de 7 seguimentos

Posted in Arduino, C++, Electronics on maio 5th, 2009 by Bruno Soares – 4 Comments

No meio de um experimento com Display de 7 seguimentos e Arduino, achei melhor criar uma classe para tratar dos números exibidos no Display.
Deixo aqui a Classe e um exemplo de como usá-la.

Configuração de pinos (Digital) utilizada no exemplo:
7 Segments LED Display - Pin Configuration
Obs.: Está configuração pode ser modificada no momento em que é criada a instância da classe “Simple7Segments” (Simple7Segments display(2, 3, 4, 5, 6, 7, 8, 9);).

Simple7Segments.h

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
/**
 * Simple seven segments LED display
 *
 * @author  Bruno Soares
 * @website www.bsoares.com.br
 */


#ifndef Simple7Segments_h
#define Simple7Segments_h

#include <inttypes.h>

class Simple7Segments
{
  private:
    uint8_t *_pins;
    uint8_t _count;
 
  public:
    Simple7Segments(uint8_t, uint8_t, uint8_t, uint8_t,
      uint8_t, uint8_t, uint8_t, uint8_t);
    void showNumber(char);
    void showAll();
    void clearAll();
};

#endif

Simple7Segments.cpp

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
/**
 * Simple seven segments LED display
 *
 * @author  Bruno Soares
 * @website www.bsoares.com.br
 */


#include "Simple7Segments.h"
#include "WProgram.h"

#include <inttypes.h>

#define QUANTITY_PINS 8

Simple7Segments::Simple7Segments(uint8_t a, uint8_t b, uint8_t c, uint8_t d,
  uint8_t e, uint8_t f, uint8_t g, uint8_t pd)
{
  // Alocate memory for Array _pins
  _pins = (uint8_t*)calloc(QUANTITY_PINS, 4);
 
  // Transfer parameters to array pins
  _pins[0] = a;
  _pins[1] = b;
  _pins[2] = c;
  _pins[3] = d;
  _pins[4] = e;
  _pins[5] = f;
  _pins[6] = g;
  _pins[7] = pd;
 
  // Set pin mode to all
  for (_count = 0; _count < QUANTITY_PINS; _count++)
  {
    pinMode(_pins[_count], OUTPUT);
  }
}

void Simple7Segments::showNumber(char letter)
{
  clearAll();
  switch (letter)
  {
    case '0':
      digitalWrite(_pins[0], HIGH);
      digitalWrite(_pins[1], HIGH);
      digitalWrite(_pins[2], HIGH);
      digitalWrite(_pins[3], HIGH);
      digitalWrite(_pins[4], HIGH);
      digitalWrite(_pins[5], HIGH);
    break;
    case '1':
      digitalWrite(_pins[1], HIGH);
      digitalWrite(_pins[2], HIGH);
    break;
    case '2':
      digitalWrite(_pins[0], HIGH);
      digitalWrite(_pins[1], HIGH);
      digitalWrite(_pins[6], HIGH);
      digitalWrite(_pins[4], HIGH);
      digitalWrite(_pins[3], HIGH);
    break;
    case '3':
      digitalWrite(_pins[0], HIGH);
      digitalWrite(_pins[1], HIGH);
      digitalWrite(_pins[6], HIGH);
      digitalWrite(_pins[2], HIGH);
      digitalWrite(_pins[3], HIGH);
    break;
    case '4':
      digitalWrite(_pins[5], HIGH);
      digitalWrite(_pins[6], HIGH);
      digitalWrite(_pins[1], HIGH);
      digitalWrite(_pins[2], HIGH);
    break;
    case '5':
      digitalWrite(_pins[0], HIGH);
      digitalWrite(_pins[5], HIGH);
      digitalWrite(_pins[6], HIGH);
      digitalWrite(_pins[2], HIGH);
      digitalWrite(_pins[3], HIGH);
    break;
    case '6':
      digitalWrite(_pins[0], HIGH);
      digitalWrite(_pins[2], HIGH);
      digitalWrite(_pins[3], HIGH);
      digitalWrite(_pins[4], HIGH);
      digitalWrite(_pins[5], HIGH);
      digitalWrite(_pins[6], HIGH);
    break;
    case '7':
      digitalWrite(_pins[0], HIGH);
      digitalWrite(_pins[1], HIGH);
      digitalWrite(_pins[2], HIGH);
    break;
    case '8':
      digitalWrite(_pins[0], HIGH);
      digitalWrite(_pins[1], HIGH);
      digitalWrite(_pins[2], HIGH);
      digitalWrite(_pins[3], HIGH);
      digitalWrite(_pins[4], HIGH);
      digitalWrite(_pins[5], HIGH);
      digitalWrite(_pins[6], HIGH);
    break;
    case '9':
      digitalWrite(_pins[0], HIGH);
      digitalWrite(_pins[1], HIGH);
      digitalWrite(_pins[2], HIGH);
      digitalWrite(_pins[5], HIGH);
      digitalWrite(_pins[6], HIGH);
    break;
  }
}

void Simple7Segments::clearAll()
{
  for (_count = 0; _count < QUANTITY_PINS; _count++)
  {
    digitalWrite(_pins[_count], LOW);
  }
}

void Simple7Segments::showAll()
{
  for (_count = 0; _count < QUANTITY_PINS; _count++)
  {
    digitalWrite(_pins[_count], HIGH);
  }
}

SevenSegmentsExample.pde

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
/**
 * Simple seven segments LED display
 *
 * @author  Bruno Soares
 * @website www.bsoares.com.br
 */


#include "Simple7Segments.h"

#define LED_FINISH 12
#define DELAY 500

unsigned int count = 0;

// Define variable display.
// The numbers are the pins of the display
Simple7Segments display(2, 3, 4, 5, 6, 7, 8, 9);

void setup()
{
  pinMode(LED_FINISH, OUTPUT);
}

void loop()
{
  char* buffer;
  itoa(count, buffer, 10);
  display.showNumber(buffer[0]);
  delay(DELAY);
  if (++count == 10)
  {
    count = 0;
    finish();
  }
}

void finish()
{
  digitalWrite(LED_FINISH, HIGH);
  delay(50);
  digitalWrite(LED_FINISH, LOW);
  delay(50);
  digitalWrite(LED_FINISH, HIGH);
  delay(50);
  digitalWrite(LED_FINISH, LOW);
}

Linha 17) Cria uma instância da classe Simple7Segments passando no construtor os pinos correspondentes as posições no display.
Linha 27) Converte o valor da variável contadora (count) para char* (“String”).
Linha 28) Chama o método showNumber da instância display passando o número a exibir.
Linha 37) Método chamado quando uma contagem de 0 à 9 chega ao fim (pisca o LED).

Faça o download do código fonte completo aqui.

Conteúdo relacionado:
Arduino: http://www.arduino.cc/
Mais fotos: http://www.flickr.com/photos/bsoares/sets/72157617609513978/
Display de 7 seguimento na Wikipedia: http://en.wikipedia.org/wiki/Seven-segment_display