Introdução
Desde que fiz o último post sobre músicas para Arduino, algumas pessoas perguntaram como é possível “converter” partituras para tocar na placa. Essa tarefa pode ser um pouco difícil se você não tem nenhuma experiência com música, mas não se preocupe, que eu explico o básico.
Primeiro começamos com uma analogia. Um código para Arduino geralmente diz o que a placa deve fazer em que momento e por quanto tempo. Como exemplo vejamos o famoso código Blink:
// a função setup é executada apenas uma vez ao ligar a placa // Um led deve ser conectado ao pine const int PINO_LED=13; void setup() { // inicializa o pino 13 como saída. pinMode(PINO_LED, OUTPUT); } // a função loop é executada repetidamente enquanto a placa estiver ligada void loop() { digitalWrite(PINO_LED, HIGH); // liga o LED (HIGH é o nível lógico) delay(1000); // espera por um segundo digitalWrite(PINO_LED, LOW); // desliga o LED (LOW é o nível lógico) delay(1000); // espera por um segundo }
Esse código diz que a placa deve repetidamente ligar o LED no pino 13 por um segundo, depois desligar o mesmo por um segundo; A ideia que quero passar é que com o código, dizemos os passos que a placa deve executar por determinado tempo. Da mesma forma, uma partitura diz ao músico como este deve tocar seu instrumento, assim como a duração de cada ação.
Partituras
Em uma partitura, as notas musicais são representadas por símbolos distribuídos em linhas e espaços. Como exemplo vamos usar korobeiniki, uma das músicas no jogo tetris.
Fonte: Flute Tunes
Primeiramente repare que há um conjunto de cinco linhas horizontais, que é chamado pauta ou pentagrama. Este é dividido em medidas temporais iguais, chamadas compassos. As notas são representadas no tempo, indo da esquerda para a direita e representadas dentro dos compassos. A partitura de certa forma funciona como uma algoritmo, dizendo ao músico quando e por quanto tempo tocar determinadas notas.
Nota: Esse post é focado em músicas monofônicas, onde apenas uma nota é tocada por vez. Repare que na partitura acima nunca há duas notas na vertical, porém em muitos instrumentos isso é possível. A função tone() do Arduino pode tocar apenas uma nota de cada vez, sendo necessárias bibliotecas, hardware extra ou outros artifícios para tocar mais de uma nota simultaneamente. As partituras mais fáceis de se adaptar são as de flauta ou outros instrumentos de sopro, por serem capazes naturalmente de tocar apenas uma nota por vez também.
Notas musicais
Afinal, qual o significado físico de uma nota musical? Nós sabemos que o som é apenas a vibração do ar em determinadas frequências. Para cada nota musical equivale um valor bem específico de frequência, que é componente mais presente ou mais “forte” naquele som. A figura abaixo mostra as frequências para cada nota, então para tocar uma nota com o Arduino, basta usar a função tone() em um pino onde esteja conectado um buzzer piezo, usando a respectiva frequência em Hertz na tabela abaixo.
Fonte: Joe Wolfe
Exemplo, para tocar o dó central (C4) por 500 milissegundos:
tone(11, 262); delay(500); noTone(11);
A função tone() recebe um valor inteiro de frequência, por isso 261,63 foi arredondado para 262.
Continuando, as notas musicais são geralmente denominadas Dó, Ré, Mi, Fá, Sol, Lá e Si. Estas também são representadas pelas letras C, D, E, F, G, A e B respectivamente. Quanto mais acima a nota está no pentagrama, mais aguda ela é. Quanto mais abaixo, mais grave. A cada linha e espaço nos compassos corresponde uma nota, como mostrado na figura a seguir.
Fonte : Wikipédia
Veja que para cada pentagrama, as notas musicais mudam de posição. As pautas acimas são representadas pelas claves de Sol (𝄞, repare que esta lembra um G), de Dó (𝄡) e Fá (𝄢, repare que está também lembra um F) . As partituras que procuro para converter músicas para o Arduino possuem geralmente apenas um pentagrama, já que o Arduino só pode tocar uma nota (sem truques). Partituras comuns podem conter dois (piano) ou vários (músicas para conjuntos de músicos);
Embora pareça muito difícil de decorar as notas de cada compasso, há mnemônicos que ajudam. Por exemplo, os espaços no compasso de Sol (G), o primeiro na imagem, formam a palavra FACE. Não há uma forma rápida de se decorar isso, é preciso treino e dedicação, mas se sua intenção é apenas converter a partitura no algorítimo, você pode levar o tempo que quiser e também pode olhar a localização das notas online.
Fonte : Ultra Musician
Acidentes
Em um teclado ou piano, essas notas da figura acima representam apenas as notas brancas. Então para representar as outras notas (sustenido e bemol) são utilizados acidentes (♯ e ♭). Esses dizem que uma nota deve ser abaixada ou elevada um semitom, ou seja, uma nota C (Dó) acompanhada de um ♯ se torna C♯, que é um pouco mais aguda que o dó. Já uma nota D♭ (Ré) se é mais grave que o Ré por um semitom. Isso também quer dizer que esta é equivalente ao C♯. Essas mudanças são válidas para toda o compasso atual, a menos que um bequadro ♮ retorne a nota ao seu tom original.
Esses acidentes podem estar representados no começo do compasso (representado a escala), afetando todas as notas que correspondem aquele espaço ou linha do compasso por toda a partitura. Para mais detalhes visite a página da Wikipédia sobre acidentes.
Duração das notas
Ok, até agora só vimos como descobrir quais as notas, mas não a duração das mesmas. Isso é representado pela formato de cada, como representado na figura a seguir:
Fonte: GCF GLobal
Sim, isso mesmo. As durações são representadas por frações. Essas notas possuem nomes também (como semibreve, mínima etc). A ideia por trás disso é que cada nota na figura tem metade da duração da anterior. No entanto, as notas não tem duração fixa (em segundos, por exemplo) e isso é dado pelo pela marcação de metrônomo para cada música. Repare novamente na partitura de tetris, há na figura um detalhe:
Esse valor é dado em batidas por minuto (BPM). Então em um minuto há 144 notas semínimas (1/4). Dessa forma, para essa partitura uma nota semínima tem duração de 60segundos/144 = 0,41666 segundos ou 416 milissegundos. De forma similar é possível encontrar a duração de todas as outras notas. O que eu faço no Arduíno é calcular a duração na nota semibreve (1) e dividi-la para encontrar as outras.
Ah, muitas vezes as notas vêm acompanhadas de pequenos pontos, esses indicam que as notas devem ser estendidas por mais metade do tempo, ou seja, sua duração é de 150%. Sendo chamadas de notas pontuadas. No exemplo da música de tetris acima é possível ver algumas dessas notas.
Por enquanto é isso sobre a teoria. Esse tutorial foi pensado para ser o mais breve possível e não um curso de música, hehe. Para mais informações sobre o assunto visite a página sobre notação musical moderna na Wikipédia.
Exemplo
Como exemplo vamos utilizar a partitura de tetris acima. Primeiro começamos por listar as frequências de todas as notas. Isso é feito para tornar o código mais legível, em vez de passar a frequência diretamente para a função tone(). Nem todas são utilizadas, mas essa parte geralmente é copiada e colada para poupar tempo.
#define NOTE_B0 31 #define NOTE_C1 33 #define NOTE_CS1 35 #define NOTE_D1 37 #define NOTE_DS1 39 #define NOTE_E1 41 #define NOTE_F1 44 #define NOTE_FS1 46 #define NOTE_G1 49 #define NOTE_GS1 52 #define NOTE_A1 55 #define NOTE_AS1 58 #define NOTE_B1 62 #define NOTE_C2 65 #define NOTE_CS2 69 #define NOTE_D2 73 #define NOTE_DS2 78 #define NOTE_E2 82 #define NOTE_F2 87 #define NOTE_FS2 93 #define NOTE_G2 98 #define NOTE_GS2 104 #define NOTE_A2 110 #define NOTE_AS2 117 #define NOTE_B2 123 #define NOTE_C3 131 #define NOTE_CS3 139 #define NOTE_D3 147 #define NOTE_DS3 156 #define NOTE_E3 165 #define NOTE_F3 175 #define NOTE_FS3 185 #define NOTE_G3 196 #define NOTE_GS3 208 #define NOTE_A3 220 #define NOTE_AS3 233 #define NOTE_B3 247 #define NOTE_C4 262 #define NOTE_CS4 277 #define NOTE_D4 294 #define NOTE_DS4 311 #define NOTE_E4 330 #define NOTE_F4 349 #define NOTE_FS4 370 #define NOTE_G4 392 #define NOTE_GS4 415 #define NOTE_A4 440 #define NOTE_AS4 466 #define NOTE_B4 494 #define NOTE_C5 523 #define NOTE_CS5 554 #define NOTE_D5 587 #define NOTE_DS5 622 #define NOTE_E5 659 #define NOTE_F5 698 #define NOTE_FS5 740 #define NOTE_G5 784 #define NOTE_GS5 831 #define NOTE_A5 880 #define NOTE_AS5 932 #define NOTE_B5 988 #define NOTE_C6 1047 #define NOTE_CS6 1109 #define NOTE_D6 1175 #define NOTE_DS6 1245 #define NOTE_E6 1319 #define NOTE_F6 1397 #define NOTE_FS6 1480 #define NOTE_G6 1568 #define NOTE_GS6 1661 #define NOTE_A6 1760 #define NOTE_AS6 1865 #define NOTE_B6 1976 #define NOTE_C7 2093 #define NOTE_CS7 2217 #define NOTE_D7 2349 #define NOTE_DS7 2489 #define NOTE_E7 2637 #define NOTE_F7 2794 #define NOTE_FS7 2960 #define NOTE_G7 3136 #define NOTE_GS7 3322 #define NOTE_A7 3520 #define NOTE_AS7 3729 #define NOTE_B7 3951 #define NOTE_C8 4186 #define NOTE_CS8 4435 #define NOTE_D8 4699 #define NOTE_DS8 4978 #define REST 0
Repare que apenas os acidentes sustenidos(♯) estão representados. Claro, um bemol ( ♭) equivale a um sustenido ou natural( exemplo G♭ = F♯), não sendo necessário repetir os valores.
Agora calculamos a duração de uma nota semibreve (1).
// "velocidade" da música, em BPM int tempo=144; // isso calcula a duração da nota em ms (60s/tempo)*4semibreves int semibreve = (60000 * 4) / tempo; //duração de uma nota semibreve (1) em milissegundos
Assim, para achar a duração de uma nota semi mínima (1/4) basta dividir esse valor por 4 e assim por diante.
Agora, vamos identificar as notas da música. Começamos pelo primeiro compasso:
Como pode-se ver, há 6 notas no compasso. 2 são semínimas (1/4) e as outras 4 são colcheias (1/8). Você pode pegar o nome das notas pela posição na terceira imagem acima.
Assim:
- a primeira nota é E5, com duração de 1/4;
- a segunda nota é B4, com duração de 1/8;
- a terceira nota é C5, com duração de 1/8;
- a quarta nota é D5, com duração de 1/4;
- a quinta nota é C5, com duração de 1/8;
- a sexta nota é B4, com duração de 1/8;
Essas notas poderiam ser organizadas da seguinte forma:
tone(11, NOTE_E5, semibreve/4); delay(semibreve/4); tone(11, NOTE_B4, semibreve/8); delay(semibreve/8); tone(11, NOTE_C5, semibreve/8); delay(semibreve/8); tone(11, NOTE_D5, semibreve/4); delay(semibreve/4); tone(11, NOTE_C5, semibreve/8); delay(semibreve/8); tone(11, NOTE_B4, semibreve/8); delay(semibreve/8);
Claro que isso ficaria muito longo para a música completa, além de ser mais difícil de ler se for preciso corrigir alguma coisa.
Então a solução que utilizo é colocar as notas em um vetor, acompanhadas das durações. Cada linha representa um compasso:
int melodia[] = { NOTE_E5, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_C5,8, NOTE_B4,8, ... }
Agora, continuando com o compasso seguinte:
int melodia[] = { NOTE_E5, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_C5,8, NOTE_B4,8, NOTE_A4, 4, NOTE_A4,8, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8, ... }
E depois com o terceiro compasso:
Nesse compasso há um caso especial. Uma das notas está acompanhada de um pequeno ponto. Isso indica que essa nota é tocada por mais 50% de sua duração. Então, como essa nota é uma semi mínima (1/4), passa a ter duração (1/4 + 1/8 = 3/8). Não se preocupe com a matemática, o Arduino calula isso pra gente :)
Para representar notas pontuadas, uso um sinal negativo. No código principal, o Arduino toca identifica que os valores negativos são notas pontuadas, tocando-as pelo tempo correto.
int melodia[] = { NOTE_E5, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_C5,8, NOTE_B4,8, NOTE_A4, 4, NOTE_A4,8, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8, NOTE_B4, -4, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4, ... }
Agora você já deve entender o básico para transcrever as notas da partitura para o Arduino. O resultado final é o seguinte:
int melodia[] = { NOTE_E5, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_C5,8, NOTE_B4,8, NOTE_A4, 4, NOTE_A4,8, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8, NOTE_B4, -4, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4, NOTE_C5, 4, NOTE_A4,4, NOTE_A4,8, NOTE_A4,4, NOTE_B4,8, NOTE_C5,8, NOTE_D5, -4, NOTE_F5,8, NOTE_A5,4, NOTE_G5,8, NOTE_F5,8, NOTE_E5, -4, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8, NOTE_B4, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4, NOTE_C5, 4, NOTE_A4,4, NOTE_A4,4, REST, 4, NOTE_E5, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_C5,8, NOTE_B4,8, NOTE_A4, 4, NOTE_A4,8, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8, NOTE_B4, -4, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4, NOTE_C5, 4, NOTE_A4,4, NOTE_A4,8, NOTE_A4,4, NOTE_B4,8, NOTE_C5,8, NOTE_D5, -4, NOTE_F5,8, NOTE_A5,4, NOTE_G5,8, NOTE_F5,8, NOTE_E5, -4, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8, NOTE_B4, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4, NOTE_C5, 4, NOTE_A4,4, NOTE_A4,4, REST, 4, NOTE_E5,2, NOTE_C5,2, NOTE_D5,2, NOTE_B4,2, NOTE_C5,2, NOTE_A4,2, NOTE_GS4,2, NOTE_B4,4, REST,8, NOTE_E5,2, NOTE_C5,2, NOTE_D5,2, NOTE_B4,2, NOTE_C5,4, NOTE_E5,4, NOTE_A5,2, NOTE_GS5,2, };
Mas não acabamos ainda, é preciso uma função que interprete e reproduza o vetor acima. Isso é feito abaixo no setup(), mas o código pode ser copiado para o loop() para se repetir-se. O sketch simplesmente lê cada valor de nota e duração do vetor, usa a função tone() para gerar a onda na frequência adequada e espera pelo tempo de se ler a próxima nota.
int divisor = 0, duracao = 0; void setup() { // itera as notas da melodia. // lembre-se, o vetor é o dobro de notas (notas + durações) for (int nota = 0; nota < totalNotas * 2; nota = nota + 2) { // calcula a duração de cada nota divisor = melodia[nota + 1]; if (divisor > 0) { // nota comum, apenas continua duracao = (semibreve) / divisor; } else if (divisor < 0) { // notas ponteadas são representadas com números negativos!! duracao = (semibreve) / abs(divisor); duracao *= 1.5; // aumenta a duração pela metade para notas pontuadas } // apenas tocamos a nota por 90% da duração, deixando 10% como uma pausa // Isso é feito para "separar" duas notas iguais tocadas em seguida tone(buzzer, melodia[nota], duracao*0.9); // Espera pela duração especificada até a próxima nota. delay(duracao); // para a geração de tom antes de mover pra próxima nota. noTone(buzzer); } } void loop() { // não é preciso repetir a música, mas essa pode ser copiada aqui se desejado. }
Código completo
Assim, o código completo fica:
/* Tetris - (Korobeiniki) Connect a piezo buzzer or speaker to pin 11 or select a new pin. More songs available at https://github.com/robsoncouto/arduino-songs Robson Couto, 2019 */ #define NOTE_B0 31 #define NOTE_C1 33 #define NOTE_CS1 35 #define NOTE_D1 37 #define NOTE_DS1 39 #define NOTE_E1 41 #define NOTE_F1 44 #define NOTE_FS1 46 #define NOTE_G1 49 #define NOTE_GS1 52 #define NOTE_A1 55 #define NOTE_AS1 58 #define NOTE_B1 62 #define NOTE_C2 65 #define NOTE_CS2 69 #define NOTE_D2 73 #define NOTE_DS2 78 #define NOTE_E2 82 #define NOTE_F2 87 #define NOTE_FS2 93 #define NOTE_G2 98 #define NOTE_GS2 104 #define NOTE_A2 110 #define NOTE_AS2 117 #define NOTE_B2 123 #define NOTE_C3 131 #define NOTE_CS3 139 #define NOTE_D3 147 #define NOTE_DS3 156 #define NOTE_E3 165 #define NOTE_F3 175 #define NOTE_FS3 185 #define NOTE_G3 196 #define NOTE_GS3 208 #define NOTE_A3 220 #define NOTE_AS3 233 #define NOTE_B3 247 #define NOTE_C4 262 #define NOTE_CS4 277 #define NOTE_D4 294 #define NOTE_DS4 311 #define NOTE_E4 330 #define NOTE_F4 349 #define NOTE_FS4 370 #define NOTE_G4 392 #define NOTE_GS4 415 #define NOTE_A4 440 #define NOTE_AS4 466 #define NOTE_B4 494 #define NOTE_C5 523 #define NOTE_CS5 554 #define NOTE_D5 587 #define NOTE_DS5 622 #define NOTE_E5 659 #define NOTE_F5 698 #define NOTE_FS5 740 #define NOTE_G5 784 #define NOTE_GS5 831 #define NOTE_A5 880 #define NOTE_AS5 932 #define NOTE_B5 988 #define NOTE_C6 1047 #define NOTE_CS6 1109 #define NOTE_D6 1175 #define NOTE_DS6 1245 #define NOTE_E6 1319 #define NOTE_F6 1397 #define NOTE_FS6 1480 #define NOTE_G6 1568 #define NOTE_GS6 1661 #define NOTE_A6 1760 #define NOTE_AS6 1865 #define NOTE_B6 1976 #define NOTE_C7 2093 #define NOTE_CS7 2217 #define NOTE_D7 2349 #define NOTE_DS7 2489 #define NOTE_E7 2637 #define NOTE_F7 2794 #define NOTE_FS7 2960 #define NOTE_G7 3136 #define NOTE_GS7 3322 #define NOTE_A7 3520 #define NOTE_AS7 3729 #define NOTE_B7 3951 #define NOTE_C8 4186 #define NOTE_CS8 4435 #define NOTE_D8 4699 #define NOTE_DS8 4978 #define REST 0 // pino onde o buzzer está conectado int buzzer =11; // "velocidade" da música, em BPM int tempo=144; // notas da melodia seguidas da duração. // um 4 significa uma semínima, um 8 uma colcheia , 16 semicolcheia, etc // !!números negativos são usados para representar notas pontuadas, // então -4 significa uma semínima pontuada, isto é, uma semínima mais uma colcheia!! int melodia[] = { NOTE_E5, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_C5,8, NOTE_B4,8, NOTE_A4, 4, NOTE_A4,8, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8, NOTE_B4, -4, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4, NOTE_C5, 4, NOTE_A4,4, NOTE_A4,8, NOTE_A4,4, NOTE_B4,8, NOTE_C5,8, NOTE_D5, -4, NOTE_F5,8, NOTE_A5,4, NOTE_G5,8, NOTE_F5,8, NOTE_E5, -4, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8, NOTE_B4, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4, NOTE_C5, 4, NOTE_A4,4, NOTE_A4,4, REST, 4, NOTE_E5, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_C5,8, NOTE_B4,8, NOTE_A4, 4, NOTE_A4,8, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8, NOTE_B4, -4, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4, NOTE_C5, 4, NOTE_A4,4, NOTE_A4,8, NOTE_A4,4, NOTE_B4,8, NOTE_C5,8, NOTE_D5, -4, NOTE_F5,8, NOTE_A5,4, NOTE_G5,8, NOTE_F5,8, NOTE_E5, -4, NOTE_C5,8, NOTE_E5,4, NOTE_D5,8, NOTE_C5,8, NOTE_B4, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_E5,4, NOTE_C5, 4, NOTE_A4,4, NOTE_A4,4, REST, 4, NOTE_E5,2, NOTE_C5,2, NOTE_D5,2, NOTE_B4,2, NOTE_C5,2, NOTE_A4,2, NOTE_GS4,2, NOTE_B4,4, REST,8, NOTE_E5,2, NOTE_C5,2, NOTE_D5,2, NOTE_B4,2, NOTE_C5,4, NOTE_E5,4, NOTE_A5,2, NOTE_GS5,2, }; // retorna o numero de notas no vetor int totalNotas=sizeof(melodia)/sizeof(melodia[0])/2; // isso calcula a duração da nota em ms (60s/tempo)*4semibreves int semibreve = (60000 * 4) / tempo; //duração de uma nota semibreve (1) em milissegundos int divisor = 0, duracao = 0; void setup() { // itera as notas da melodia. // lembre-se, o vetor é o dobro de notas (notas + durações) for (int nota = 0; nota < totalNotas * 2; nota = nota + 2) { // calcula a duração de cada nota divisor = melodia[nota + 1]; if (divisor > 0) { // nota comum, apenas continua duracao = (semibreve) / divisor; } else if (divisor < 0) { // notas ponteadas são representadas com números negativos!! duracao = (semibreve) / abs(divisor); duracao *= 1.5; // aumenta a duração pela metade para notas pontuadas } // apenas tocamos a nota por 90% da duração, deixando 10% como uma pausa // Isso é feito para "separar" duas notas iguais tocadas em seguida tone(buzzer, melodia[nota], duracao*0.9); // Espera pela duração especificada até a próxima nota. delay(duracao); // para a geração de tom antes de mover pra próxima nota. noTone(buzzer); } } void loop() { // não é preciso repetir a música, mas essa pode ser copiada aqui se desejado. }
Veja o resultado do código no vídeo abaixo:
Acha o código difícil? Para adaptar suas músicas você só precisa substituir as notas e durações do vetor e mudar a variável tempo para o valor adequado.
Mais músicas para Arduino podem ser encontardas no meu github. Lá eu também deixo os links das partituras utilizadas em cada código.
Por enquanto é isso. Obrigado pela leitura e até um próximo post o/
Parabéns Robson. Ficou show a didática e o código.
Muito obrigado, Augusto!
Comecei agora com Arduino e tava brincando com essa parte de músicas pelo buzzer e estou tentando já tem 2 dias mas não consigo imaginar como fazer um led piscar junto das notas.
Você tem uma dica, fera?
VLW! Ótimo trabalho!
trabalho com conserto e montagen orgao analogico com ci cmos gostei muito do seu trabalho
um dia pretendo mudar para digital