Archive for maio, 2009

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
 

Vector em AS3 para Flash Player 10

Posted in ActionScript 3.0, Flash on maio 25th, 2009 by Bruno Soares – 2 Comments

Para aqueles que já estão usando Flash Player 10, trocar o Array por Vector é uma boa opção, pois você ganha em performance e organização de código (Vector é um array tipado ou seja, mais organizado).
O que mudou mais é a forma de construir o objeto, a sintaxe funciona como o Generics do C# ou Java. Ressaltando que não existe generics em AS3, somente o Vector que implementa uma sintaxe parecida com a sintaxe de um generics.

Muitos blogueiros já comentaram sobre o Vector logo quando saiu a versão beta do Flash Player 10. Por este motivo não vou falar muito sobre, vou apenas exemplificar e dar links para os outros blog.

Criando um Vector:

1
var vetor:Vector.<T> = new Vector.<T>();

(Substitua o T pelo tipo desejado)

Veja como é parecido com um Array:

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
package
{
    import __AS3__.vec.Vector;
   
    import flash.display.Sprite;
    import flash.utils.getTimer;
   
    [SWF(framerate="30", width="500", height="500")]
    public class Main extends Sprite
    {
        private var _vector:Vector.<String> = new Vector.<String>();
        private var _timer:Number;
       
        public function Main()
        {
            _vector.push("a");
            _vector.push("b");
            trace(_vector.length);
            _vector.push("c");
            trace(_vector.length);
            _vector[_vector.length] = "d";
            trace(_vector.length);
           
            for each (var s:String in _vector)
            {
                trace("FOR: " + s);
            }
           
            trace("Timer Vector:");
            testVector();
           
            trace("Timer Array:");
            testArray();
        }
       
        private function testArray():void
        {
            _timer = getTimer();
            var array:Array = new Array();
            for(var i:uint = 0; i < 1000000; i++)
            {
                array[i] = i;
            }
            trace(getTimer() - _timer);
        }
       
        private function testVector():void
        {
            _timer = getTimer();
            var vector:Vector.<uint> = new Vector.<uint>();
            for(var i:uint = 0; i < 1000000; i++)
            {
                vector[i] = i;
            }
            trace(getTimer() - _timer);
        }
    }
}

(O código acima é a Main Class de um projeto Flex / ActionScript)

Teste de performance entre arrays, vector e outros:
http://businessintelligence.me/projects/performance_tester/performanceTester.html

Veja na imagem abaixo como é “gritante” a diferença de performance entre um Array comum e um Vector:
as3-vector-array-performance-tester

Conteúdo relacionado:
Documentação do Vector
Teste de performance
Post sobre Vector por: Mike Chambers
Post sobre Vector por: DaveOnCode
Post sobre Vector por: The Back Button

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

Controlando a Arduino com PHP via porta serial

Posted in Arduino, Electronics, PHP on maio 1st, 2009 by Bruno Soares – 66 Comments

É isso mesmo, o PHP pode escrever ou ler dados da porta serial, e com isso podemos controlar a Arduino.

Você pode ligar o seu ar-condicionado, cafeteira, luz, etc… via Internet, e de uma forma bem simples.
Serialproxy também é uma ótima forma de se conectar a Arduino via Internet, utilizei no projeto Twitter Hardware, mas este post é sobre PHP, então vamos lá.

Arduino + PHP Diagram

Vou utilizar o exemplo descrito no post “Controlando Led RGB com Arduino e Processing” (trocando o Processing pelo PHP).

A função fopen do PHP da suporte a escrita na porta serial:

1
2
3
$port = fopen('COM2', 'w');
fwrite($port, '1');
fclose($port);

Linha 1) Abre a conexão com a COM2 (porta serial onde a minha Arduino está conectada).
Linha 2) Escreve na porta
Linha 3) Fecha a conexão

Código PHP do exemplo:

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
<?php
/**
 * Arduino + PHP
 *
 * @author  Bruno Soares
 * @website www.bsoares.com.br
 */


$color = $_REQUEST['color'];

if (isset($color) && !empty($color)) {
    $color = hexdec($color);
    $message = '^' . $color . '$';

    // USB Serial Port (COM2)
    $portAddress = 'COM2';
   
    // Open connection on port
    $port = fopen($portAddress, 'w');
   
    // Necessary when the Arduino reset after the connection
    sleep(2);
   
    // Send chars
    fwrite($port, $message);
   
    // Close connection
    fclose($port);
}
?>

Linha 12) Converte a cor de hexadecimal para decimal.
Linha 13) Coloca os caracteres que indicam o inicio e fim da mensagem.
Linha 16) Define a variável com o endereço da porta (no meu caso COM2).
Linha 19) Abre a “conexão” com a porta serial.
Linha 22) Pausa o código por 2 segundo, pois a Arduino costuma reiniciar quando é feita uma conexão a ela.
Linha 25) Escreve a mensagem com a cor na porta serial.
Linha 28) Fecha a “conexão” com a porta serial.

Update 09/07/2009:
Lendo dados:
Tenho recebido diversos e-mails e até alguns comentários de pessoas que precisam ler dados de um sensor, potenciometro, ou qualquer coisa conectada a Arduino, e isso via PHP. Então vamos lá, preparei um código que faz isso de forma fácil.
Acredito que um problema que o pessoal tem tido com esta tarefa é: você deve se dar tempo para a mensagem chegar a Arduino (não que isso seja muito tempo), e também para que a Arduino consiga responder:

Código Arduino:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * Arduino + PHP
 *
 * @author  Bruno Soares
 * @website www.bsoares.com.br
 */


#define ANALOG_PIN 4

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  if (Serial.available() > 0) {
    if (Serial.read() == '1')
      Serial.print(analogRead(ANALOG_PIN), DEC);
  }
}

Código PHP:

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
<?php
/**
 * Arduino + PHP
 *
 * @author  Bruno Soares
 * @website www.bsoares.com.br
 */


// Conecta na porta
$port = fopen('COM2', 'w+');

// Em alguns casos a Arduino pode reiniciar, por isso
// é bom esperar para enviar informação depois de conectar
sleep(2);

// Envia "1" para o programa na Arduino saber que deve responder
fwrite($port, '1');

// Espera para que o dado enviado pelo PHP chegue até a Arduino
sleep(1);

// Agora que a Arduino "Provavelmente já respondeu", pega
// o valor da resposta
echo fgets($port);

// Fecha a conexão com a porta
fclose($port);
?>

O que esse código faz?
A Arduino fica em loop esperando receber pela porta serial o numero 1, assim que recebido ela lê a voltagem do pino analógico 4 e escreve na porta serial.
O PHP abre a porta serial, escreve “1″, e espera para ler novamente, quando lê novamente encontra o valor do pino analógico 4, assim como a Arduino escreveu.
Bom, espero que este exemplo acabe com as dúvidas do pessoal que precise ler dados da Arduino :)

Observações:
Caso você precise fazer um projeto onde muitos usuário vão acessar o script que escreve na porta serial, você deve implementar uma fila, de forma a não ter um usuário escrevendo na porta ao mesmo tempo que outro, isto geraria um erro.
O código fonte escrito para a Arduino é o mesmo do post Controlando Led RGB com Arduino e Processing

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

Conteúdo relacionado:
Arduino: http://www.arduino.cc/
Referência: http://www.arduinoprojects.com/?q=node/10
jQuery ColorPicker: http://www.eyecon.ro/colorpicker/