Lousa Mágica

De Wiki DAINF
Edição feita às 17h32min de 31 de maio de 2009 por Solanoalves (disc | contribs)

Tabela de conteúdo

O que é

Um exemplo básico de mídia tangível utilizando Arduino e Processing em que cinco botões irão representar esquerda, direita, cima, baixo e reset que de acordo com quais botões estiverem pressionados, uma linha seja desenhada na tela na direção respectiva ao botão e a tecla reset servirá para apagar a tela de modo que se possa fazer um desenho contínuo na tela. A posição dos botões na montagem fica a critério de que montar, entretanto no código deve-se tomar o cuidado de que a sequência escrita pelo arduino na porta serial e lida pelo processing é a seguinte: EDCBR (Esquerda, Direita, Cima, Baixo, Reset).

Problemas

Caso haja mal contato na montagem devido a fios soltos e contatos mal ligados, poderá haver mal funcionamento do programa fazendo com que o ponto ande sozinho ou que a tela apague sem a vontade do usuário. Se estiver tudo montado e não houver resposta na tela ao pressionar os botões, é recomendado que se encerre a execução do programa e desligue da alimentação o arduino e verifique se não há curto-circuito e algum problema associado ao circuito.

Exercício de aprendizagem (Resolver após concluir esse exemplo)

Implemente um botão que ao ser pressionado faça com que a cor alterne entre Branco e Preto, ou seja, ora é branco ora é preto, sendo controlado por um toque, de modo que se possa locomover pela tela com os outros botões sem rabiscá-la. Desse modo é possível escrever letras separadas uma das outras na tela simulando um espaço.

Requisitos

  • 5 Resistores de 100 Ohms
  • 5 Chaves tac (PushButton)
  • Fios para se fazerem as ligações

Cadeia de ferramentas utilizada

As setas vermelhas indicam as ferramentas utilizadas na cadeia de ferramentas para se trabalhar com mídias e hardware.

LousaToolchain.png

Usando os componentes do ABaCo

Com base na cadeia de ferramentas mostrada no diagrama acima, o primeiro passo é construir o Projeto Teórico com a Montagem Virtual do Circuito e utilizando o QUCS. Na aba Componentes no QUCS e Componentes Soltos os items utilizados para montagem são: Porta do subcircuito, Resistor e Switch. E em Fontes foi escolhido Fonte de Tensão CC. E foi usado o Ground(Terra) que está na barra superior do programa. Para mudar o desenho de um componente é necessário clicar com o botão direito sobre o componente e ir em Edit Properties (Editar Propriedades). Os switchs são as chaves tac (PushButton). Os resistores R1,R2,R3,R4 e R5 são iguais e valem 100 Ohms.

O circuito está mostrado abaixo:

LousaCirc.png

Quando todas as chaves estão soltas, então as 5 portas do arduino estão recebendo tensão, que tem a corrente limitada pelos resistores R1,R2,R3,R4 e R5, entretanto quando uma das chaves é pressionada, então toda a corrente vai para o terra e portanto a tensão que o arduino lê naquela porta é zero. Portanto a reta deve ser desenhada quando o nível lógico lido é zero. Nível lógico significa estar entre um nível de tensão ou outro, caso esteja entre 3 e 5 volts então é nível lógico 1 (há tensão) caso esteja entre 0 e 2 volts então o nível lógico é zero (não há tensão, apesar de ter um pouco) e caso esteja entre 2 e 3 volts, então esse intervalo não é definido e projetistas devem evitar cair nesse intervalo.

Agora que o diagrama está montado, pode-se então partir para a Montagem Real do Circuito no Protoboard tomando o devido cuidado para não haver curto-circuitos e eliminação de um componente por estar com seus terminais no mesmo potencial (mesma coluna). será necessário apenas o Arduino e o Protoboard, a fonte de tensão não será necessária, pois o Arduino possui uma alimentação que supre a demanda do circuito.

A imagem abaixo ilustra o circuito montado no protoboard, o circuito não precisa estar montado exatamente da mesma forma, existem N formas de se montar.

LousaReal.jpg


A Alimentação agora se torna necessária e será usada a alimentação do Arduino de 5 Volts e o programa será feito no Ambiente de Programação (IDE) Arduino Programming Language e Processing Interfaceamento.

Código completo:

/*
*  Copyright (C) 2009 Solano Alves
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

int Esq=12;
int Dir=9;
int Cim=11;
int Bai=10;
int Res=8;

int var;

void setup(){
 pinMode(Esq,INPUT);
 pinMode(Dir,INPUT);
 pinMode(Cim,INPUT);
 pinMode(Bai,INPUT);
 pinMode(Res,INPUT);
 Serial.begin(9600);
}

void loop(){
  
  delay(150);
  Serial.print(digitalRead(Esq));
  Serial.print(digitalRead(Dir));
  Serial.print(digitalRead(Cim));
  Serial.print(digitalRead(Bai));
  Serial.print(digitalRead(Res));
  Serial.print("\n");
}

O código do programa para ser embarcado no Arduino está separado em seções:

A seção abaixo declara variáveis que conterão inteiros representando as portas do Arduino as quais receberão as entradas das chaves liga-desliga.

int Esq=12;
int Dir=9;
int Cim=11;
int Bai=10;
int Res=8;
int var;

A seção abaixo diz que essas portas irão exercer a função de Entrada(INPUT), ou seja, as portas vão estar prontas pra dizer se há tensão nelas ou não. E a função Serial.begin(9600) abre uma comunicação serial, para que o processing possa ler depois, a uma velocidade de 9600 bits por segundo. Tudo que está dentro de void setup(){ } só será executado na primeira vez que o programa for iniciado, geralmente funções de configuração.

void setup(){
 pinMode(Esq,INPUT);
 pinMode(Dir,INPUT);
 pinMode(Cim,INPUT);
 pinMode(Bai,INPUT);
 pinMode(Res,INPUT);
 Serial.begin(9600);
}

A seção abaixo diz que a cada loop (iteração ou passagem) é para o programa aguardar 150 milisegundos antes de ler as portas verificando se há tensão ou não. A função Serial.print escreve na saída serial se a porta está com tensão (1) ou está sem tensão (0). A função Serial.print não pula uma linha quando é executada, ao contrário da Serial.println, portanto as 5 leituras serão feitas e na saída serial o padrão será (NNNNN) em que N representa 0 ou 1. O ultimo Serial.print com um "\n" diz que assim que escrever os 5 digitos, pule uma linha, para que o processing possa ler de 5 em 5 digitos.

void loop(){
  delay(150);
  Serial.print(digitalRead(Esq));
  Serial.print(digitalRead(Dir));
  Serial.print(digitalRead(Cim));
  Serial.print(digitalRead(Bai));
  Serial.print(digitalRead(Res));
  Serial.print("\n");
}

Agora basta compilar clicando no botão Play - Verify do Arduino e então File > Upload to I/O Board.

Código completo:


/*
*  Copyright (C) 2009 Solano Alves
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

import processing.serial.*;

Serial porta;
String dados;
int x,y,xant,yant; 

void setup(){
  println(Serial.list());
  porta = new Serial(this, Serial.list()[1], 9600);
  size(500,500);
  stroke(255);
  strokeWeight(1.5);
  strokeCap(SQUARE);
  background(0);
  x= width/2;
  xant = x;
  y= height/2;
  yant = y;
} 

void draw(){
  dados = porta.readString();
  println(dados);
  if( dados != null ){
    if( dados.charAt(0) == '0' ) x-=5;
    if( dados.charAt(1) == '0' ) x+=5;
    if( dados.charAt(2) == '0' ) y-=5;
    if( dados.charAt(3) == '0' ) y+=5;
    if( dados.charAt(4) == '0' ) background(255,0,0);
    stroke(255,255,255);
    line(xant,yant,x,y);
    xant = x;
    yant = y;
  }
    delay(180);
}


O código a ser usado no processing para que esse exemplo de mídia tangível seja finalizado é o que se segue dividido em seções explicadas:

Essa declaração importa as ferramentas necessárias para que se possa ler a porta serial na qual o Arduino está escrevendo.

import processing.serial.*;

Essas declarações criam uma variável porta para que se saiba em qual porta o arduino está escrevendo, uma variável dados que vai conter os 5 digitos que o Arduino enviou através da porta serial e por fim x,y,xant,yant que é a posição atual (x,y) do ponto a ser desenhado e a posição anterior (xant,yant) para que se possa desenhar uma reta entre esses dois pontos.

Serial porta;
String dados;
int x,y,xant,yant;

Novamente tudo que estiver dentro de void setup(){} será executado uma única vez, geralmente funções de configuração, e o que está sendo feito dentro de setup é mostrar com a função println todas as portas disponíveis para comunicação, assim é possível ver se a que você está usando no Arduino está listada pelo processing, feito isso e sabido a porta usada então é criada a comunicação dizendo que quem cria é o próprio programa (this, este mesmo), a porta é a segunda da lista, caso fosse a primeira então deveria ser Serial.list()[0] e com velocidade 9600 bits por segundo. Size diz o tamanho da tela, stroke a cor da linha, strokeWeight a espessura da linha, strokeCap a forma com que a linha terá, background o fundo da tela e x,y,xant,yant as posições iniciais do ponto a ser movido pelas chaves liga-desliga. Para mais detalhes das funções consulte a referência da linguagem processing http://processing.org/reference/.

void setup(){
  println(Serial.list());
  porta = new Serial(this, Serial.list()[1], 9600);
  size(500,500);
  stroke(255);
  strokeWeight(1.5);
  strokeCap(SQUARE);
  background(0);
  x= width/2;
  xant = x;
  y= height/2;
  yant = y;
}

O método( onde funções são executadas ) draw serve para desenhar na tela, ou seja, se há um desenho a ser feito, ele deve ser declarado no método draw. Nele então lê-se serialmente o que o arduino está dizendo em forma de String(texto) e imprime na tela o que foi lido, verifica-se com if se o que foi lido existe (caso não exista é null) e caso exista verifica letra por letra se é 1 ou 0. Caso for 1 então o botão foi pressionado, caso contrário não. Por exemplo se o botão esquerdo for pressionado então dados.charAt(0) será 1 e a variável x será decrementada (subtraída) de 5 unidades fazendo o ponto se deslocar pra esquerda na tela. A função stroke garante que a linha continue branca e então desenha a linha com coordenadas iniciais (xant,yant) e coordenadas finais (x,y). E então pega-se o ponto que foi modificado e diz que ele é anterior de modo que na próxima passagem ele seja usado como ponto inicial para se construir a linha. delay(180) diz para aguardar 180 milisegundos a cada desenho.

void draw(){
  dados = porta.readString();
  println(dados);
  if( dados != null ){
    if( dados.charAt(0) == '0' ) x-=5;
    if( dados.charAt(1) == '0' ) x+=5;
    if( dados.charAt(2) == '0' ) y-=5;
    if( dados.charAt(3) == '0' ) y+=5;
    if( dados.charAt(4) == '0' ) background(255,0,0);
    stroke(255,255,255);
    line(xant,yant,x,y);
    xant = x;
    yant = y;
  }
    delay(180);
}

Agora basta clicar em Play-Run no processing e pressionar os botões para ver o funcionamento na tela.

Ferramentas pessoais