terça-feira, 10 de junho de 2014

Código-fonte

Código-fonte: functions.h

#ifndef FUNCTIONS_H
#define FUNCTIONS_H

TMRpcm player;

/*
 * AVISO: Código duplicado à vista!
 */

void playNote(MUX mux)
{
  int z_val = mux.readZ() >= 1015;
  int mux_y = mux.getY();
  
  static int active_mux = 0;
  static int active_y = -1;
  
  if (z_val && !player.isPlaying())
  {
    active_y = mux_y;
    active_mux = mux.id();
    
    if (active_mux == 1)
    {
      switch (mux_y)
      {
        case 0:
          player.play("CF3/CF3_C4.wav");
          break;
        case 1:
          player.play("CF3/CF3_Cs4.wav");
          break;
        case 2:
          player.play("CF3/CF3_D4.wav");
          break;
        case 3:
          player.play("CF3/CF3_Ds4.wav");
          break;
        case 4:
          player.play("CF3/CF3_E4.wav");
          break;
        case 5:
          player.play("CF3/CF3_F4.wav");
          break;
        case 6:
          player.play("CF3/CF3_Fs4.wav");
          break;
        case 7:
          player.play("CF3/CF3_G4.wav");
          break;
      }
    }
    else if (active_mux == 2)
    {
      switch (mux_y)
      {
        case 0:
          player.play("CF3/CF3_Gs4.wav");
          break;
        case 1:
          player.play("CF3/CF3_A4.wav");
          break;
        case 2:
          player.play("CF3/CF3_As4.wav");
          break;
        case 3:
          player.play("CF3/CF3_B4.wav");
          break;
        case 4:
          player.play("CF3/CF3_C5.wav");
          break;
        case 5:
          player.play("CF3/CF3_Cs5.wav");
          break;
        case 6:
          player.play("CF3/CF3_D5.wav");
          break;
        case 7:
          player.play("CF3/CF3_Ds5.wav");
          break;
      }
    }
    else if (active_mux == 3)
    {
      switch (mux_y)
      {
        case 0:
          player.play("CF3/CF3_E5.wav");
          break;
        case 1:
          player.play("CF3/CF3_F5.wav");
          break;
        case 2:
          player.play("CF3/CF3_Fs5.wav");
          break;
        case 3:
          player.play("CF3/CF3_G5.wav");
          break;
        case 4:
          player.play("CF3/CF3_Gs5.wav");
          break;
        case 5:
          player.play("CF3/CF3_A5.wav");
          break;
        case 6:
          player.play("CF3/CF3_As5.wav");
          break;
        case 7:
          player.play("CF3/CF3_B5.wav");
          break;
      }
    }
  }
  else if (z_val == 0 && mux_y == active_y && active_mux == mux.id())
  {
    player.stopPlayback();
    active_y = -1;
    active_mux = 0;
  }
}

void toneNote(MUX mux)
{
  int z_val = mux.readZ() >= 1015;
  int mux_y = mux.getY();
  
  static int active_mux = 0;
  static int active_y = -1;
  
  if (z_val)
  {
    active_y = mux_y;
    active_mux = mux.id();
    
    if (active_mux == 1)
    {
      switch (mux_y)
      {
        case 0:
          tone(46, NOTE_C4);
          break;
        case 1:
          tone(46, NOTE_CS4);
          break;
        case 2:
          tone(46, NOTE_D4);
          break;
        case 3:
          tone(46, NOTE_DS4);
          break;
        case 4:
          tone(46, NOTE_E4);
          break;
        case 5:
          tone(46, NOTE_F4);
          break;
        case 6:
          tone(46, NOTE_FS4);
          break;
        case 7:
          tone(46, NOTE_G4);
          break;
      }
    }
    else if (active_mux == 2)
    {
      switch (mux_y)
      {
        case 0:
          tone(46, NOTE_GS4);
          break;
        case 1:
          tone(46, NOTE_A4);
          break;
        case 2:
          tone(46, NOTE_AS4);
          break;
        case 3:
          tone(46, NOTE_B4);
          break;
        case 4:
          tone(46, NOTE_C5);
          break;
        case 5:
          tone(46, NOTE_CS5);
          break;
        case 6:
          tone(46, NOTE_D5);
          break;
        case 7:
          tone(46, NOTE_DS5);
          break;
      }
    }
    else if (active_mux == 3)
    {
      switch (mux_y)
      {
        case 0:
          tone(46, NOTE_E5);
          break;
        case 1:
          tone(46, NOTE_F5);
          break;
        case 2:
          tone(46, NOTE_FS5);
          break;
        case 3:
          tone(46, NOTE_G5);
          break;
        case 4:
          tone(46, NOTE_GS5);
          break;
        case 5:
          tone(46, NOTE_A5);
          break;
        case 6:
          tone(46, NOTE_AS5);
          break;
        case 7:
          tone(46, NOTE_B5);
          break;
      }
    }
  }
  else if (z_val == 0 && mux_y == active_y && active_mux == mux.id())
  {
    noTone(46);
    active_y = -1;
    active_mux = 0;
  }
}

void checkEaster(MUX mux1, MUX mux2)
{
  int z1, z2, y1, y2;
  y1 = mux1.getY();
  z1 = mux1.readZ() >= 1015;
  
  y2 = mux2.getY();
  z2 = mux2.readZ() >= 1015;
  
  if (z1 && z2 && y1 ==0 && y2 == 0)
  {
    noTone(46);
    if (player.isPlaying()) player.stopPlayback();
    digitalWrite(13, !digitalRead(13));
    delay(1000);
  }
}


#endif

Código-fonte: mux.h

#ifndef MUX_H
#define MUX_H

#include <Arduino.h>

class MUX
{
private:
  unsigned A0, A1, A2;
  unsigned Z;
  unsigned Y;
  void initPins();
  static unsigned toBin(const unsigned);
  static unsigned id_counter;
  unsigned _id;
public:  
  MUX(unsigned, unsigned, unsigned, unsigned);
  unsigned readZ();
  unsigned getY();
  void shiftPorts();
  unsigned id();
};

unsigned MUX::id_counter = 0;

MUX::MUX(unsigned A0, unsigned A1, unsigned A2, unsigned Z)
{
  this->A0 = A0;
  this->A1 = A1;
  this->A2 = A2;
  this->Z  = Z;
  Y = 0;
  _id = ++id_counter;
  initPins();
}

unsigned MUX::id()
{
  return _id;
}

void MUX::initPins()
{
  pinMode(this->A0, OUTPUT);
  pinMode(this->A1, OUTPUT);
  pinMode(this->A2, OUTPUT);
  pinMode(this->Z, INPUT);
}

unsigned MUX::toBin(const unsigned number)
{
  int a = number, m = 1, res = 0;
  while (a > 0)
  {
    res += a % 2 * m;
    a /= 2;
    m *= 10;
  }
  return res;
}

unsigned MUX::readZ()
{
  return analogRead(Z);
}

unsigned MUX::getY()
{
  return Y;
}

void MUX::shiftPorts()
{
  Y = (Y + 1) % 8;
  int bin = toBin(Y);
  
  digitalWrite(this->A0, bin % 10);
  digitalWrite(this->A1, bin / 10 % 10);
  digitalWrite(this->A2, bin / 100);
}

#endif

Código-fonte: Piano.ino

#include "notes.h"
#include "mux.h"
#include <SD.h>
#include <SPI.h>
#include <TMRpcm.h>
#include "functions.h"

#define speaker 46
#define SDPin 53

MUX mux1(9, 10, 11, A0);
MUX mux2(22, 24, 26, A1);
MUX mux3(28, 30, 32, A2);

void setup()
{
  Serial.begin(9600);
  pinMode(SDPin, OUTPUT);
  pinMode(speaker, OUTPUT);
  pinMode(13, OUTPUT);
  
  if (!SD.begin(SDPin))
  {
    while (true)
    {
      digitalWrite(13, !digitalRead(13));
      delay(1000);
    }
  }

  digitalWrite(13, HIGH);
  player.speakerPin = speaker;
  player.setVolume(4);
  player.quality(1);
}

void loop()
{
  checkEaster(mux1, mux2);
  
  mux1.shiftPorts();
  if (digitalRead(13))
    playNote(mux1);
  else
    toneNote(mux1);
  
  mux2.shiftPorts();
  if (digitalRead(13))
    playNote(mux2);
  else
    toneNote(mux2);
  
  mux3.shiftPorts();
  if (digitalRead(13))
    playNote(mux3);
  else
    toneNote(mux3);
    
  delayMicroseconds(100);
}

domingo, 8 de junho de 2014

Samples


O que são samples?

Samples ("amostras", em inglês) são trechos de sons gravados de um instrumento para serem usados noutro equipamento ou programa.
Samples geralmente são gravadas de acordo com um padrão para atingir maior realismo na replicação de um efeito e/ou instrumento a ser implementado.

Ok, mas o que isso tem a ver com o projeto?

Estamos desenvolvendo um piano usando o Arduino, certo? Nada mais justo do que usar uma biblioteca de samples para reproduzir sons mais realistas do que aqueles encontrados em teclados mais baratos.

Nós preparamos uma biblioteca especial para o projeto, gravada de um piano de cauda para concertos, um Yamaha CF III.

Como vamos usar essas samples?

Para este projeto, estaremos utilizando uma biblioteca chamada TMRpcm.h, ela torna possível a reprodução de sons. Essas samples no entanto tem que atender alguns requisitos:

- Formato PCM sem compressão, com extensão .wav;
- Taxa de amostragem de 32000 Hz;
- Deve possuir apenas uma faixa (mono).

O Arduino não possui alto falantes, como eu vou ouvir o som?

Vamos usar um Audio Jack, que é um conector P2 fêmea, possibilitando o uso de qualquer caixa de som.

_________________________________________________________________

Mais informações sobre a biblioteca usada pode ser encontrada aqui: https://github.com/TMRh20/TMRpcm/wiki

As samples podem ser encontradas aqui:
https://www.dropbox.com/sh/x97ye327u215fsb/AABNn2TjAxmn1HcY8v_IPLEVa

Multiplexadores




Multiplexador ou MUX é um circuito que codifica múltiplas entradas numa única saída. Multiplexadores são usados quando se necessita um maior número de entradas do que há disponível ou quando o custo para a implementação de mais entradas é maior do que o custo necessário para a utilização de multiplexação.


Neste projeto nós usamos o MUX modelo 4051, que é um multiplexador 8-para-1, confira abaixo o esquema de pinagem do CI:






Os pinos "Y0" a "Y7" representam as entradas; "A0", "A1" e "A2" são pinos correspondentes as chaves de seleção; "E" é o pino que determina se está ativo; "Vss" é o pino que deve ser ligado ao Terra; "Vdd" e "Vee" são pinos que recebem tensões positivas e negativas, respectivamente.


Para o uso como MUX no Arduino, tanto 'E', 'Vee' e 'Vss' devem ser conectados ao Terra(GND). O motivo é simples: para multiplexação nós queremos que o MUX esteja sempre ativo, logo não há necessidade de atribuir uma porta para o pino 'E', podemos deixá-lo no GND. Como possuímos uma fonte de energia não-balanceada no Arduino, o pino 'Vee' fica inutilizado. Por último, o 'Vss' corresponde ao próprio Terra.


As chaves de seleção funcionam de acordo com um modelo binário, mostrado na tabela a seguir:






quarta-feira, 21 de maio de 2014

Fotos do Projeto em Andamento

Desmontando o teclado
As teclas que usaremos


Placa perfurada

Tinta condutiva

Solda + MUX

Partes do teclado

MUX pós solda

Acendendo um LED com 3 pilhas (4,5V)

Projeto de piano feito com Arduino


Introdução:

A ideia surgiu entre colegas, ao ter visto alguns vídeos sobre o Arduino e diversos projetos no YouTube; o piano foi o que realmente chamou a atenção, parecendo simples o suficiente para fazer uma versão própria.



Vimos que para o projeto seria melhor que fizéssemos primeiro apenas o piano e depois fossemos adicionando outras funcionalidades, como a possibilidade de trocar os sons de piano pelo de outros instrumentos.




Como funciona:

O piano é composto por:

- Arduino (Uno ou Duemilanove, no nosso usamos o Duemilanove);

- Jumpers (para ligar os componentes);
- Resistores (para impedir a passagem de correntes que possam danificar o circuito);
- Multiplexador (ou simplesmente MUX, usamos o 4051);
- Tinta e botões de borracha condutiva;
- Teclas;
- Auto-falante (para reprodução dos sons).

O Arduino é a placa que serve de intermédio para as interações Computador-Circuito. Como o Arduino, nesse caso o Duemilanove é limitado a apenas 14 portas digitais e 6 portas analógicas, é impossível criar um piano com pelo menos uma oitava completa. Para isso, usamos o multiplexador (daqui em diante vamos chamá-lo de MUX), que é um circuito integrado que é capaz de "ler" mais portas analógicas e traduzir a informação para um menor número de entradas disponíveis no Arduino, expandindo sua capacidade.


O MUX só pode "ler" uma única porta analógica por vez, mas ele pode trocar de porta em altíssimas velocidades e é esse recurso que nós vamos aproveitar.




Metodologia:

Primeiramente, conferimos todos os componentes necessários, montando uma lista inicial do que seria necessário para construir um protótipo. Nesse estágio optamos pelo MUX HCF4051 por ser o mais conhecido, barato e trabalhar na faixa de tensão desejada. O Duemilanove foi escolhido por ser um modelo que já tínhamos disponível desde o inicio do projeto, com o microcontrolador ATMega328, que é capaz de armazenar cerca de 30 KB de código, suficiente para o projeto. O resto dos componentes são baratos e simples de usar.

Foi realizada a divisão do grupo em 3 partes: Design, Elétrica e Programação.


- Design: Felipe e Thiago;

- Elétrica: Paulo e Victor;
- Programação: Fabrício e Lucas.

Como o projeto ainda se encontra em estado inicial(protótipo), não nos preocupamos com o design e colocamos apenas o necessário afim de realizar análises e obter feedback.




Pelo Arduino, nós configuramos para trocar as portas

sucessivamente, dessa forma podemos "ler" mais de uma nota "simultaneamente". Conseguindo assim colocar mais notas sendo lidas "simultaneamente" no piano.

Para cada nota é preciso criar uma corrente que passa pelo MUX e é direcionada ao Arduino. A corrente precisa ser baixa para gerar valores menores a serem lidos pelo Arduino, que os identifica como a nota não sendo tocada. Um botão localizado na parte inferior de cada tecla habilita uma trilha de alta corrente quando pressionado, gerando valores de leitura maiores para o Arduino, caracterizando uma nota pressionada.


No quesito de design, que foi convencionado ser executado após os testes de funcionamento do MUX, será feita uma estrutura básica para apenas suportar as teclas e uma chave para ligar o circuito.


Por último, o projeto ainda está em andamento, sendo assim, não temos o case para o piano, nem sua funcionalidade completa.

sexta-feira, 14 de março de 2014

Conabajur - apresentação

Nosso conabajur em ação!

Segue link para o código:

[EM BREVE]

"Perfurando a madeira"


"Parte de dentro da cúpula do abajur"


"Tiroteio de cola dos huezeiros"


"Protoboard com o arduíno e o relé conectados"


"Corpo do conajur, fazendo as medições"


"Cúpula com o sensor LDR já acoplado"


"Mãos à obra!"


"Dando os últimos reparos no conajur"


"Acoplando o relé ao cone"


"Vitinho manufaturando no cone"



"Vídeo pequeno de nós perfurando a placa de madeira" 



"Encaixando o soquete"



"Fazendo os últimos reparos no conajur"

terça-feira, 25 de fevereiro de 2014

Teste: postagem de código-fonte

Código-fonte (versão 1):

const int led_verde = 12;

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

void loop()
{
    static int contador = 0, estado = 0;
    if (++contador % 10 == 0)
    {
        digitalWrite(led_verde, ++estado % 2);
    }
}

Código-fonte (versão 2):


const int led_verde = 12; void setup() { pinMode(led_verde, OUTPUT); } void loop() { static int contador = 0, estado = 0; if (++contador % 10 == 0) { digitalWrite(led_verde, ++estado % 2); } }

Primeiro Poste

Sejam bem-vindos ao blog dos PUC Saints!
Usaremos este blog para postar e comentar sobre o nosso progresso referente ao(s) trabalho(s) e projeto(s) envolvendo Arduino tratados na nossa aula de Física Experimental 2 da faculdade.

INTEGRANTES

Em ordem alfabética:

Fabrício da Silva Werneck
Felipe Prado Garrossino
Lucas Veronesi Gouveia de Mattos
Paulo Vitor Geraldes Ribas
Thiago Viana
Victor Abranches