Arquivos de Categoria: arduino

Novo site

Este post pretende ser o último por aqui, todo o material daqui vai para o novo site no domínio http://jetersilveira.com.br. Saudações!

Anúncios

[SOLUÇÃO] LCD Nokia 5110 – Erro ‘class Adafruit_PCD8544’ has no member named ‘print

Compilando o programa de exemplo da biblioteca Adafruit PCD8544 para o display LCD do Nokia 5110 recebi várias vezes o erro acima, variando, conforme algumas alterações no código e no diretório (pasta) de bibliotecas (libraries), para o erro: int8_t RobotControl::keyboardRead()

A solução que encontrei foi a seguinte: criei uma pasta com o nome `tmp`na raiz do diretório arduino (que contém o diretório libraries), e movi o diretório Robot_Control de libraries para tmp, excluindo, portanto, essa biblioteca do diretório. Depois disso, o erro que dava era que não conseguia encontrar o arquivo “SPI.h“, que as bibliotecas da Adafruit tentavam incluir. Assim, copiei os dois arquivos SPI.cpp e SPI.h do diretório SPI (contido em libraries, também) para o interior da pasta PCD8544 (onde estão as bibliotecas Adafruit PCD8544 e Adafruit GDX).

Feito isso, fucionou perfeitamente. Segundo informações de desenvolvedores do arduino, no fórum, esse é um erro de incompatibilidade entre algumas bibliotecas que têm sido criadas para arduino, e que devem ser evitados pelos desenvolvedores das mesmas. Esperemos que, em breve, não necessitemos do workaround. 🙂

Saudações!

Installing Pronterface on Ubuntu and the error: Not a directory: ‘/usr/share/printrun/pronterface.py’

Hello, people! Installing PRONTERFACE on my machine, when I tried to run it, I got the error Not a directory: ‘/usr/share/printrun/pronterface.py’. So I’ve created my workaround 😀 I decided to write a small step-by-step to explain how to install this software through the available repository and also solve this error. Let’s go. Open a terminal, and get it done:

sudo apt-get install python python-serial python-wxgtk2.8 python-tk
sudo apt-add-repository ppa:richi-paraeasy/ppa
sudo apt-get update
sudo apt-get install pronterface skeinforge

After running these commands, you’re going to have Pronterface installed. Open the terminal again e try to execute the command “$ pronterface” (whithout the $). You’ll probably get the following error:

OSError: [Errno 20] Not a directory: ‘/usr/share/printrun/pronterface.py’

Ok. Once this happened, let’s go to the next steps. You will edit the files pronterface.py and pronsole.py. You’ll find them at the directory /usr/share/printrun/.

Open each file, as a superuser, with your favorite text editor (like Vim).

If you use gedit, as a text editor, you can execute:

sudo gedit /usr/share/printrun/pronterface.py

Inside the file, look for this line (it should be next to 24):

os.chdir(os.path.realpath(__file__))

And replace for this one:

os.chdir(os.path.realpath(‘./’))

Save and close the file. Next, open the second file:

sudo gedit /usr/share/printrun/pronsole.py

And make the same change in the same line (it should be next to 30, on this file). Then, save and close the file. You have to make this change in both pronterface.py e pronsole.py. Actually, all you are going to do is replace  __file__  for ‘./’  on these lines.

Once you’ve done that, you can run pronterface:

pronterface

If necessary, as superuser:

sudo pronterface

And happy printing!  😀

pronter

 

[RESOLVIDO] Instalando o Pronterface no Ubuntu para a RepRap e o erro Not a directory: ‘/usr/share/printrun/pronterface.py’

Salve, pessoal! Instalando o programa PRONTERFACE aqui na minha máquina, deparei com o erro Not a directory: ‘/usr/share/printrun/pronterface.py’. Criei o meu workaround 😀 Resolvi fazer um tutorialzinho para explicar como instalar esse programa através do repositório disponível e já resolver esse erro. Vamos lá. Abra um terminal e mande brasa:

sudo apt-get install python python-serial python-wxgtk2.8 python-tk
sudo apt-add-repository ppa:richi-paraeasy/ppa
sudo apt-get update
sudo apt-get install pronterface skeinforge

Depois de executar esses comandos, você vai ter o pronterface instalado. Abra um terminal e tente executar o comando “$ pronterface”. Você provavelmente vai receber o seguinte erro como resposta:

OSError: [Errno 20] Not a directory: ‘/usr/share/printrun/pronterface.py’

Certo. Verificado que está acontecendo este erro, faça o seguinte. Você vai precisar editar os arquivos pronterface.py e pronsole.py. Você irá encontrá-los no diretório /usr/share/printrun/

Abra um arquivo de cada vez, com permissões de superusuário, em seu editor de textos favorito (eu uso o Vim).

Se você usar gedit, como editor de texto, pode executar:

sudo gedit /usr/share/printrun/pronterface.py

Dentro do arquivo, procure a seguinte linha (deve estar próxima à linha 24):

os.chdir(os.path.realpath(__file__))

E substitua por essa outra:

os.chdir(os.path.realpath(‘./’))

Salve e feche o arquivo. Na sequência, abra o próximo:

sudo gedit /usr/share/printrun/pronsole.py

E faça a mesma modificação (deve estar próxima à linha 30). Depois, salve e feche o arquivo. Faça as mundanças na linha referida em cada um dos arquivos pronterface.py e pronsole.py. Na realidade você só vai precisar substituir  __file__  por ‘./’ nessas linhas.

Feito isto, execute o pronterface no terminal:

pronterface

Se for necessário, como superusuário:

sudo pronterface

E boas impressões! 😀

pronter

Biblioteca no Arduino para o Sensor de Cor TCS320 e TCS3200

color-sensor-TCS230-Color-Recognition-Sensor-Detector-Module-DC-3-5V-Input-Color-090541

Sensor de Cor TCS230/TCS3200 em uma breakout board

O sensor de reconhecimento de cor TCS230/3200 da AMS (antiga TAOS) possui um conjunto de 64 fotodiodos para detecção de cores: 16 com filtro para a frequencia de cor vermelha (Red), 16 com filtro para a frequencia de cor verde (Green), 16 com filtro para a frequencia de cor azul (Blue), e ainda 16 fotodiodos sem filtro de cores. Esse conjunto de fotodiodos permite ao circuito integrado fazer o que chama de transformação de luz-para-frequência (light-to-frequency). O que acontece é o seguinte: a saída do sensor é um pulso de 50% de duty cycle (isso significa que é um pulso quadrado “perfeito”, ou seja, metade do tempo em nível lógico alto e metade em nível lógico baixo), que varia a frequência conforme a intensidade da luz.

O TCS230/3200 possui quatro entradas: S0, S1, S2, e S3. As duas primeiras servem para selecionar uma escala de frequência (2%, 20% ou 100%), ou simplesmente desligar o sensor. As duas últimas servem para selecionar o conjunto de fotodiodos que você quer o resultado: como são dois bits, teremos exatamente quatro possiblidades, que são correspondentes aos quatro conjuntos de fotodiodos. Assim o sensor dará um resultado com a intensidade de cada cor que ele consegue medir, e a intensidade total, permitindo o desenvolvimento de uma aplicação que calcule o valor RGB para a cor detectada. Veja abaixo a tabela, extraída do datasheet:

tcs230Finalmente temos uma biblioteca para lidar com esse sensor no Arduino!!! A bilioteca MD_TCS230 está disponível para download no GitHub e no CodePlex. Vamos a um passo-a-passo para testar seu primeiro programinha com o sensor de cores no Arduino!!

1º passo –  Instalando a biblioteca MD_TCS230

Faça o download da biblioteca nesse link (aconselho utilizar este link direto para a página de download no CodePlex, pois a MD_TCS230 possui uma dependencia que está incluída neste pacote zip). Depois de completar o download, abra o pacote zip com o descompactador e extraia as pastas FreqCount e MD_TCS230 no dentro do diretório ~/sketchbook/libraries (ou /home/[SEU_USUARIO/sketchbook/libraries ou, se usar Windows – sério que vc faz isso??? :O – você irá encontrar a pasta libraries dentro da pasta sketchbook provavelmente no sua pasta de usuário – c:\Users\[SEU_USUARIO]\sketchbook\libraries – não mudou nada, né? rs). Feche todas as janelas da Arduino IDE (isso é importante! – em alguns casos só funciona se fizer isso – wtf?) e depois abra o Arduino IDE novamente. Pronto! As bibliotecas MD_TCS230 e FreqCount estão instaladas (a FreqCount é uma dependência da MD_TCS230).

2º passo – Carregando o programa de exemplo da biblioteca

Vamos utilizar aqui o mais simples programa de exemplo disponível na biblioteca, que simplesmente irá retornar no Serial Monitor as leituras realizadas em um código RGB. Se tudo deu certo no passo anterior, você poderá acessar o programa de exemplo da MD_TCS230 através do menu: File -> Sketchbook -> libraries -> MD_TCS230 -> Simple_NB_TCS230. Quando você clicar aí, carregará o seguinte código:

// TCS230 sensor reading example
//
// This is just to show basic functionality without calibration.
// Utilises the non-blocking version of the reading function.
// Output uses the Serial console.
//
#include <MD_TCS230.h>
#include <FreqCount.h>

// Pin definitions
#define  S2_OUT  12
#define  S3_OUT  13
#define  OE_OUT   8    // LOW = ENABLED 

MD_TCS230  CS(S2_OUT, S3_OUT, OE_OUT);

void setup()
{
  Serial.begin(57600);
  Serial.println("[TCS230 Simple NON_BLOCKING Example]");
  Serial.println("\nMove the sensor to different color to see the RGB value");
  Serial.println("Note: These values are being read in without sensor calibration");
  Serial.println("and are likely to be far from reality");

  CS.begin();
}

void readSensor()
{
  static  bool  waiting;
 
  if (!waiting)
  {
    CS.read();
    waiting = true;
  }
  else
  {
    if (CS.available())
    {
      colorData  rgb;
      
      CS.getRGB(&rgb);
      Serial.print("RGB [");
      Serial.print(rgb.value[TCS230_RGB_R]);
      Serial.print(",");
      Serial.print(rgb.value[TCS230_RGB_G]);
      Serial.print(",");
      Serial.print(rgb.value[TCS230_RGB_B]);
      Serial.println("]");
      
      waiting = false;
    }
  }
}

void loop()
{
  readSensor();
}

 

 

Pronto! Esse programa aí você carregará para a memória do Arduino em breve (é aconselhável montar todo o hardware antes de carregar o programa pro Arduino, o que faremos no próximo passo).

3º passo – Montando o hardware: ligações com o Arduino

120_1_H

Arduino UNO

Nesse primeiro programa de exemplo, que é bastante simples, você precisará fazer apenas quatro conexões além do VCC e GND, que são a alimentação do sensor: S2, S3, OE, e OUT. Até mesmo OE (Output Enable), se quiser, você pode simplesmente ligar o pino OE do sensor ao GND, sem conectar no Arduino, mas é aconselhável seguir o projeto do programa, já que estamos aprendendo e poderá ser importante, no futuro, desabilitar temporariamente a saída do sensor.

É fácil descobrir as conexões para S2, S3, e OE simplesmente verificando as linhas de código dentro do programa:

// Pin definitions
#define  S2_OUT  12
#define  S3_OUT  13
#define  OE_OUT   8    // LOW = ENABLED

Mas… e onde vou conectar OUT no Arduino?? Como é que eu sei onde vou conectar a saída do meu sensor de cores RGB no Arduino? Então, tive um trabalho aqui, mas foi apenas falta de ler a documentação da bilioteca. Se  você observar na descrição da biblioteca aqui, perceberá uma NOTA IMPORTANTE onde o autor da biblioteca avisa sobre uma limitação da dependencia FreqCount, que permite a utilização apenas de determinados pinos para a contagem da frequencia e limita o uso de outros pinos, conforme a tabela abaixo:

Board         Input Pin   Pins Unusable with analogWrite()
-----------   ---------   --------------------------------
Arduino Uno   5           3, 9, 10, 11
Arduino 2009  5           3, 9, 10, 11
Arduino Mega  47          9, 10, 44, 45, 46
Sanguino      1           12, 13, 14, 15

Logo, sabemos que o pino para a conexão da saída do sensor (pino OUT), é o pino 5 do Arduino. Ficam então as conexões:

SENSOR     ARDUINO UNO
------     -----------
 VCC           5V
 GND           GND
 S2            12
 S3            13
 OE            2
 OUT           5

Uma vez terminadas as conexões, carregue o programa para dentro do Arduino e teste seu programa! Assim que carregar o programa (você verá ver a mensagem “Done uploading.” na barra de status da Arduino IDE), pressione Ctrl+Shift+M ou vá em Tools -> Serial Monitor. Quando abrir o Serial Monitor, selecione a taxa de transferência de 57600 baud no canto inferior direito, senão você apenas enxergará caracteres malucos em sua tela… rs. Aproxime uma folha branca de papel do sensor para ver como ele marca perfeitamente: [255,255,255] no Serial Monitor. Outras cores ficarão aproximadas, o preto é bastante difícil de detectar. Cores mais “claras” são mais fáceis por terem uma SATURAÇÃO  maior e também maior INTENSIDADE de luz, permitindo assim que o software tenha mais informações com que trabalhar. Deixe seu comentário e até a próxima!!

Debouncing via software com Arduino sem usar delay – millis()

Nesse post quero compartilhar minha tradução (com algumas alterações) do código de debounce da documentação do Arduino. Primeiro, para quem desconhece o que significa debounce em eletrônica digital, aconselho a leitura desse excelente artigo do site Embarcados, autoria do Rodrigo Almeida, que trata desde o conceito de bouncing (com excelentes ilustrações), até as formas de debouncing através de hardware e software (o exemplo do artigo é para o PIC). Lembrando que o ideal é utilizar uma combinação das duas formas, para que o tempo de resposta seja o maior possível; pois, como veremos adiante, o tratamento do bouncing por software implica um delay (atraso) na resposta ao comando.

Em um outro post que fiz aqui, utilizei como método de debouncing por software a própria função delay() – nessa postagem também não testo se o estado da chave foi modificado, de forma que se o usuário mantiver pressionado o botão por tempo superior ao delay() o comando será executado repetidas vezes.  Mas utilizar a função delay() não é a forma correta. Por quê? Simplesmente porque ela congela a execução do programa pelo microcontrolador (Arduino), atrasando todos as demais tarefas que sua rotina deve fazer, por exemplo, atualizar uma amostragem de algum dado num display LCD. A forma de contornar isso é utilizando instruções condicionais if que testam se já passou um determinado tempo (cria um delay apenas para essa tarefa, digamos assim, de verificar a alteração de estado da chave), a partir de comparação com o tempo total e absoluto de execução do programa no Arduino, que é obtido em milissegundos através da função millis().

        OBS.: Em um código que encontrei na internet, o programador usou uma instrução while para testar se o tempo havia passado, e isso resolve… NADA! Por quê? Simplesmente porque a execução do programa ficará nesse while [tempo_não_passa] até que o tempo realmente tenha passado, o que equivale a usar a função delay()! Se for para fazer isso, melhor usar delay(), em vez de ficar declarando e configurando novas variáveis apenas para a estrutura do while [tempo_nao_passa] nao_faz_nada funcionar…

        OBS. 2: A principal alteração que fiz no código da documentação está na retirada do resistor de PULL DOWN (previsto no circuito da documentação). Como ficou então nosso circuito? Optei por utilizar o resistor de PULL UP interno do próprio Arduino, tendo para que funcionasse assim apenas de inverter a lógica da detecção de alteração de estado da chave ou do botão de entrada. Atenção: Importante lembrar que a maneira mais simples e enxuta de habilitar o resistor de PULL UP interno do Arduino é declarando explicitamente em “pinMode(pinodeentrada, INPUT_PULLUP)“, dessa forma. É possível também declarar “pinMode(pinodeeentrada, INPUT)” e na outra linha “digitalWrite(pinodeentrada, HIGH)“. Isso também irá habilitar o resistor interno de PULL UP do Arduino, mas o ideal é enxugar o código e usar apenas as instruções necessárias, ocupando menos espaço em ambas as memórias e por isso mesmo otimizando a execução do programa.

Mais informações nos próprios comentários do código. Segue abaixo também o desenho da montagem do circuito, feito no Fritzing.

/*
Debounce – Estabilizacao

Cada vez que o pino de entrada vai de HIGH para LOW (e.g. devido ao pressionamento
do botao), o pino de saida eh alternado de LOW para HIGH ou de HIGH para LOW. Existe
um pequeno atraso entre essas alternancias para estabilizar o circuito (i.e. para
ignorar o ruido).

O circuito:
* LED do pino 13 ao GND (terra ou negativo)
* botao pulsante (pushbutton) do pino 2 ao GND (terra ou negativo)

* Nota: Na maioria das placas Arduino, jah existe um LED na placa conectado
ao pino 13, assim vc nao precisa adicionar nenhum componente neste circuito.
Ateh mesmo o botao pulsante pode ser substituido por um mero ‘jumper’ (um ‘fiozinho’)
com o qual vc podera simular o pressionamento do botao fazendo contato entre
o pino 2 e qualquer GND do Arduino.

criado em 21 Nov 2006
por David A. Mellis
modificado em 30 Ago 2011
por Limor Fried
modificado em 28 Dez 2012
por Mike Walters
modificado e traduzido em 31 Ago 2014
por Jeter Silveira

Esse codigo foi copiado e alterado para disponibilizacao gratuita na internet em:
http://www.jetersilveira.com.br

O original tambem eh dominio publico e pode ser encontrado na pagina oficial de
documentacao do Arduino no endereco abaixo:

http://www.arduino.cc/en/Tutorial/Debounce

*/

// as constantes nao mudam. Elas sao usadas aqui
// para ‘setar’ os numeros dos pinos
const int buttonPin = 2; // o numero do pino do botao pulsante (“pushbutton”)
const int ledPin = 13; // o numero do pino do LED

// Variaveis sofrerao mudancaso
int ledState = HIGH; // o atual estado do pino de saida (LED)
int buttonState; // a leitura atual do pino de entrada
int lastButtonState = HIGH; // a leitura anterior do pino de entrada

// as variaveis seguintes sao to tipo ‘long’ porque o tempo, medido em milissegundos
// rapidamente se tornara um numero maior do que o que cabe em uma ‘int’.
long lastDebounceTime = 0; // a ultima vez que o pino de saida foi modificado (toggled)
long debounceDelay = 50; // o tempo de estabilizacao (debounce);
// aumente se houver oscilacao na saida.

void setup() {
pinMode(buttonPin, INPUT_PULLUP); // habilita o resistor de PULL UP interno do Arduino
pinMode(ledPin, OUTPUT);

// ‘seta’ estado inicial do LED
digitalWrite(ledPin, ledState);
}

void loop() {
// le o estado do botao em uma variavel local
int reading = digitalRead(buttonPin);

// testa para ver se voce recem acaba de apertar o botao
// (i.e. a entrada foi de LOW para HIGH, e vc esperou tempo suficiente
// desde o ultimo pressionamento para ignorar qualquer ruido).

// Se o estado do botao mudou, seja por pressionamento ou por ruido
if (reading != lastButtonState) {
// ‘reseta’ o temporizador de debounce
lastDebounceTime = millis();
}

if ((millis() – lastDebounceTime) > debounceDelay) {
// seja qual for o valor da leitura, ele esta lah a mais tempo que
// o tempo de debounce (debounceDelay), entao podemos utilizar o valor:

// verifica se o botao mudou
if (reading != buttonState) {
buttonState = reading;

// apenas muda o estado (toggle) do LED se buttonState for LOW
if (buttonState == LOW) {
ledState = !ledState;
}
}
}

// ‘seta’ o LED
digitalWrite(ledPin, ledState);

// salva a leitura. Na proxima vez que passar no loop
// essa leitura sera o ultimo estado do botao (lastButtonState).
lastButtonState = reading;
}

 

Diagrama de montagem do circuito. O LED que deverá ser observado é incluido na placa. Observe que é há LED SMD próximo dos LEDS indicadores de TX e RX e do pino 13, indicado pela letra L. Esse LED tem em praticamente todas as placas Arduino e está ligado ao pino 13, para indicar seu status. Daí porquê esse circuito tem apenas o botão, com o objetivo de agilizar e facilitar seu aprendizado da técnica de debouncing por software. Lembre que no início do artigo falamos sobre a importância do debouncing via hardware também. No entanto, para a grande maioria das aplicações a técnica de software que aqui demonstramos é suficiente.

debounce_pullup

 

 

Método de Entrada ASCII com um Potenciômetro – Arduino

Esse é um projeto de método de entrada de caracteres ASCII para o Arduino utilizando um potenciômetro para escolher o caractere. Esse projeto pode ser ainda mais simples, utilizando apenas um botão e um potenciômetro para inserir qualquer caractere da tabela ASCII. Nesse aqui, no entanto, eu adicionei um botão para automaticamente inserir o caractere ESPAÇO, dividi a tabela ASCII em categorias (tipos) de caracteres e adicionei um botão para alternar entre essas/esses categorias/tipos, e ainda um terceiro botão que serve para apagar um caractere ou, se pressionado por mais de meio segundo, toda a linha.  Esse método de entrada pode ser usado em substituição a um teclado para inserir pequenos grupos de caracteres, como para colocar senhas, por exemplo, em algum sistema de controle de acesso.

Seguem o código, o diagrama e um vídeo do projeto montado e funcionando.

#include <LiquidCrystal.h>

// configura os pinos do LCD

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

int inserir = 3;
int apagar = 5;
int espaco = 4;
int sel_tipo = 2;
int tipo = 0;
char palavra[16];
int i = 0;

void setup() {
lcd.begin(16,2);
pinMode(inserir, INPUT_PULLUP);
pinMode(apagar, INPUT_PULLUP);
pinMode(sel_tipo, INPUT_PULLUP);
pinMode(espaco, INPUT_PULLUP);
}

void loop() {

lcd.setCursor(0,0); // seta a posicao do cursor para o inicio

if(digitalRead(sel_tipo) == LOW){ // quando o botao ‘sel_tipo’ eh pressionado
delay(500); // o delay de meio segundo eh para evitar dupla execucao da funcao
if(tipo < 6){
tipo++;
} else {
tipo = 0;
}
}

int primeiro = 65; // valor que inicia o mapeamento da entrada analogica
int ultimo = 90; // valor que termina o mapeamento da entrada analogica

switch(tipo){ // esse switch vai definir as faixas de mapeamento pela tabela ASCII
case 0:
primeiro = 65;
ultimo = 90;
lcd.print(“ABC”);
break;

case 1:
primeiro = 97;
ultimo = 122;
lcd.print(“abc”);
break;

case 2:
primeiro = 48;
ultimo = 57;
lcd.print(“123”);
break;

case 3:
primeiro = 33;
ultimo = 47;
lcd.print(“!*.”);
break;

case 4:
primeiro = 58;
ultimo = 64;
lcd.print(“>?@”);
break;

case 5:
primeiro = 91;
ultimo = 96;
lcd.print(“[\\]”);
break;

case 6:
primeiro = 123;
ultimo = 126;
lcd.print(“{|}”);
break;
}

/* Esse bloco eh o responsavel pela selecao do caractere.
A funcao ‘map’ ira mapear o valor analogica lida em ‘A0’, que na transformacao
analogico-digital interna do ATMEGA varia de 0 a 1023, para a faixa escolhida pelo
‘switch’ logo acima, que eh escolhida pressionando o botao ‘sel_tipo’. Por exemplo,
se ‘tipo’ for igual a 0, o valor de ‘analogRead(A0)’ sera transportado da faixa de
0 a 1023 para a faixa de 65 a 90, ou seja, de A a Z.
*/
char caractere = map(analogRead(A0), 0, 1023, primeiro, ultimo);
lcd.setCursor(14,0);
lcd.print(caractere);

if(digitalRead(inserir) == LOW){ // quando o botao ‘inserir’ eh pressionado
delay(500);
if(i == 15){ // se o cursor esta no final, nao insere caractere e avisa!
lcd.clear();
lcd.setCursor(0,0);
lcd.print(” CHEGA! Delete “);
lcd.setCursor(0,1);
lcd.print(” alguma coisa! “);
delay(700);
lcd.clear();
} else {
palavra[i] = caractere; // insere caractere na string ‘palavra’
i++;
}
}

if(digitalRead(espaco) == LOW){ // adiciona o caractere ESPACO quando
delay(500); // o botao ‘espaco’ eh pressionado
if(i == 15){ // se o cursor esta no final do display, nao insere caractere e avisa!
lcd.clear();
lcd.setCursor(0,0);
lcd.print(” CHEGA! Delete “);
lcd.setCursor(0,1);
lcd.print(” alguma coisa! “);
delay(700);
lcd.clear();
} else {
palavra[i] = 32; // insere caractere ESPACO -> ASCII 32
i++;
}
}

if(digitalRead(apagar) == LOW){ // quando o botao ‘apagar’ eh pressionado
if(i > 0){ // testa se existe algo para apagar
i–;
}
palavra[i] = false; // ‘unseta’ o caractere da posicao ‘i’ no vetor/string ‘palavra’
delay(500);
if(digitalRead(apagar) == LOW){ // se o botao ‘apagar’ ficar
for(int j=0;j<16;j++){ // pressionado mais de meio-segundo
palavra[j] = false; // ‘unseta’ todos os caracteres do vetor/string ‘palavra’
i = 0; // e retorna o indice ‘i’ para o inicio do vetor
}
}
lcd.clear(); // eh importante para nao deixar o cursor perdido
}

// muda para a segunda linha do LCD, mostra a palavra (se existir) e o cursor
lcd.setCursor(0,1);
lcd.print(palavra);
lcd.print(“_”);
}

Esse é o diagrama que gerei com o Fritzing. Os botões do tipo “pushbutton” estão na ordem: ‘sel_tipo’, ‘inserir’, ‘espaco’, ‘apagar’ (ver comentários do código). O display LCD está com um brilho fixo através do resistor de 1k no terceiro pino, caso queira colocar um potenciômetro para ajuste, sem problemas: consulte a página do arduino sobre isso se tiver dúvida.

ASCII_input_pot_bb

Aqui está o vídeo de demonstração do projeto. No vídeo, aparecem alguns componentes (resistor e LM7805 – tinha mais um LED mas tirei pra fazer o vídeo) que adicionei para fazer o projeto funcionar fora da porta USB – que está servindo para alimentar o circuito com 5V -, alimentando com uma bateria de 7.4 V sucateada de um tablet… rs. Enjoy! =)

Hino Nacional no LCD

No SmartKit do Garagino Rev 1, do Laboratório de Garagem, vinha um programa de exemplo que tocava o Hino Nacional… Com meus recém adquiridos conhecimentos sobre a biblioteca LCD do Arduino e os desde sempre escassos sobre teoria musical, implementei isso aí que dá pra ver: as notinhas aparecendo conforme toca huehue até os pontos de aumento 😀

O código ficou uma bagunça, porque fui colocando tudo fora de ordem kkk (atentar para as ligações do LCD, que mudei pq estava trabalhando em outro projeto ao msm tempo, usando um módulo receptor de RF…):

#include “pitches.h”
#include <LiquidCrystal.h> //Inclui a biblioteca do LCD
#define NO_SOUND 0

LiquidCrystal lcd(12, 10, 5, 4, 3, 7); //Configura os pinos do Arduino para se comunicar com o LCD

byte semicolcheia[8] = {
B00010,
B00011,
B00010,
B00011,
B01110,
B11110,
B01100,
};

byte colcheia[8] = {
B00010,
B00011,
B00010,
B00010,
B01110,
B11110,
B01100,
};

byte seminima[8] = {
B00010,
B00010,
B00010,
B00010,
B01110,
B11110,
B01100,
};

byte minima[8] = {
B00010,
B00010,
B00010,
B00010,
B01110,
B10010,
B01100,
};

// Notas que devem ser tocadas ordenadamente;
int melodia[] = {
NOTE_C4,
NOTE_F4,NOTE_E4,NOTE_F4,NOTE_G4,NOTE_A4,NOTE_G4,NOTE_A4,NOTE_AS4,
NOTE_B4,NOTE_C5,NOTE_F4,NOTE_C4,
NOTE_F4,NOTE_E4,NOTE_G4,NOTE_F4,NOTE_A4,NOTE_G4,NOTE_AS4,NOTE_A4,
NOTE_FS4,NOTE_G4,NO_SOUND,NO_SOUND,NOTE_C4,
NOTE_G4,NOTE_FS4,NOTE_G4,NOTE_A4,NOTE_AS4,NOTE_A4,NOTE_AS4,NOTE_B4,

NOTE_CS5,NOTE_D5,NOTE_G4,NOTE_C4,
NOTE_G4,NOTE_F4,NOTE_A4,NOTE_G4,NOTE_AS4,NOTE_A4,NOTE_B4,NOTE_AS4,
NOTE_GS4,NOTE_A4,NO_SOUND,NOTE_A4,NOTE_A4,
NOTE_AS4,NOTE_A4,NO_SOUND,NOTE_A4,NOTE_AS4,NOTE_A4,
NOTE_A4,NOTE_D5,NOTE_C5,NOTE_AS4,
NOTE_AS4,NOTE_A4,NOTE_A4,NOTE_G4,NOTE_G4,NOTE_F4,NOTE_F4,NOTE_E4,

NOTE_E4,NOTE_D4,NO_SOUND,NOTE_G4,NOTE_G4,
NOTE_A4,NOTE_G4,NO_SOUND,NOTE_G4,NOTE_A4,NOTE_G4,
NOTE_G4,NOTE_C5,NOTE_B4,NOTE_A4,
NOTE_A4,NOTE_G4,NOTE_G4,NOTE_F4,NOTE_F4,NOTE_E4,NOTE_E4,NOTE_D4,
NOTE_D4,NOTE_C4,NO_SOUND,NOTE_C4,NOTE_E4,NOTE_G4,
NOTE_AS4,NOTE_C4,NOTE_E4,NOTE_G4,NOTE_AS4,NOTE_C4,NOTE_E4,NOTE_G4,

NOTE_AS4,NOTE_AS4,NOTE_C4,
NOTE_F4,NOTE_E4,NOTE_F4,NOTE_G4,NOTE_A4,NOTE_G4,NOTE_A4,NOTE_AS4,
NOTE_B4,NOTE_C5,NOTE_F4,NOTE_C4,
NOTE_F4,NOTE_E4,NOTE_G4,NOTE_F4,NOTE_A4,NOTE_G4,NOTE_AS4,NOTE_A4,
NOTE_FS4,NOTE_G4,NO_SOUND,NOTE_C4,
NOTE_G4,NOTE_FS4,NOTE_G4,NOTE_A4,NOTE_AS4,NOTE_A4,NOTE_AS4,NOTE_B4,

NOTE_CS5,NOTE_D5,NOTE_G4,NOTE_C4,
NOTE_G4,NOTE_FS4,NOTE_A4,NOTE_G4,NOTE_AS4,NOTE_A4,NOTE_C5,NOTE_AS4,
NOTE_GS4,NOTE_A4,NO_SOUND,NO_SOUND,NOTE_F4,
NOTE_G4,NOTE_F4,NOTE_E4,NOTE_F4,NOTE_E4,NOTE_F4,NOTE_G4,NOTE_F4,
NOTE_F4,NOTE_AS4,NOTE_AS4,NO_SOUND,NOTE_G4,
NOTE_A4,NOTE_G4,NOTE_FS4,NOTE_G4,NOTE_FS4,NOTE_G4,NOTE_A4,NOTE_G4,//2ºFS4

NOTE_G4,NOTE_C5,NOTE_C5,NO_SOUND,NOTE_A4,
NOTE_AS4,NOTE_A4,NOTE_GS4,NOTE_A4,NOTE_GS4,NOTE_A4,NOTE_AS4,NOTE_A4,//2ºGS4
NOTE_A4,NOTE_D5,NOTE_C5,NOTE_AS4,NOTE_G4,
NOTE_G4,NOTE_F4,NO_SOUND,NOTE_E4,NOTE_F4,NOTE_G4,
NOTE_AS4,NOTE_A4,NOTE_E4,NOTE_F4,NOTE_CS4,NOTE_D4,NOTE_AS4,NOTE_G4,
NOTE_G4,NOTE_F4,NO_SOUND,NOTE_G4,NOTE_A4,NOTE_AS4,

NOTE_B4,NOTE_C5,NOTE_A4,NOTE_F4,NOTE_D4,NOTE_AS4,
NOTE_A4,NOTE_F4,NOTE_D4,NOTE_C4,NOTE_D4,NOTE_E4,
NOTE_F4

};

// Duração das Notas: Colcheia:8; Semínima: 4; Mínima:2; Semibreve:1
int tempoNotas[] = {
4,
6,16,6,16,6,16,6,16,
3,8,4,4,
6,16,6,16,6,16,6,16,
4,4,4,16,8,
6,16,6,16,6,16,6,16,

3,8,4,4,
6,16,6,16,6,16,6,16,
4,4,4,6,16,
4,4,8,8,6,16,
4,2,8,8,
8,8,8,8,8,8,8,8,

4,4,4,6,16,
4,4,8,8,6,16,
4,2,8,8,
8,8,8,8,8,8,8,8,
4,4,8,8,8,8,
8,8,8,8,8,8,8,8,

2,4,4,
6,16,6,16,6,16,6,16,
3,8,4,4,
6,16,6,16,6,16,6,16,
4,4,4,4,
6,16,6,16,6,16,6,16,

3,8,4,4,
6,16,6,16,6,16,6,16,
4,4,4,8,16,
6,16,6,16,6,16,6,16,
3,8,4,8,8,
6,16,6,16,6,16,6,16,

3,8,4,8,8,
6,16,6,16,6,16,6,16,
4,3,8,8,8,
4,4,8,8,8,8,
8,8,8,8,8,8,8,8,
4,4,8,8,8,8,

8,8,8,8,4,4,
4,6,16,4,6,16,
2
};

const int compasso = 2000; // Altera o compasso da música

void setup() {
lcd.begin(16, 2); //Inicia o LCD com dimensões 16×2(Colunas x Linhas)
lcd.createChar(0, colcheia);
lcd.createChar(1, seminima);
lcd.createChar(2, minima);
lcd.createChar(3, semicolcheia);
pinMode(13, OUTPUT);
digitalWrite(13, 1);
for (int Nota = 0; Nota < 230; Nota++) {//o número 80 indica quantas notas tem a nossa matriz.
int tempo = compasso/tempoNotas[Nota]; //Tempo = compasso dividido pela indicação da matriz tempoNotas.
tone(8, melodia[Nota],tempo); //Toca a nota indicada pela matriz melodia durante o tempo.
// Para distinguir as notas adicionamos um tempo entre elas (tempo da nota + 20%).
lcd.clear();
lcd.setCursor(0,1);
if(melodia[Nota] == 262){
lcd.print(“C  (do)”);
} else if(melodia[Nota] == 440){
lcd.print(“A  (la)”);
} else if(melodia[Nota] == 349){
lcd.print(“F  (fa)”);
} else if(melodia[Nota] == 294){
lcd.print(“D  (re)”);
} else if(melodia[Nota] == 330){
lcd.print(“E  (mi)”);
} else if(melodia[Nota] == 392){
lcd.print(“G  (sol)”);
} else if(melodia[Nota] == 494){
lcd.print(“B  (si)”);
} else if(melodia[Nota] == 523){
lcd.print(“C  (do)”);
} else if(melodia[Nota] == 466){
lcd.print(“Bb (si bemol)”);
} else if(melodia[Nota] == 370){
lcd.print(“F# (fa susten.)”);
} else if(melodia[Nota] == 415){
lcd.print(“G# (sol susten.)”);
} else if(melodia[Nota] == 554){
lcd.print(“C# (do susten.)”);
} else if(melodia[Nota] == 587){
lcd.print(“D  (re)”);
} else if(melodia[Nota] == 277){
lcd.print(“C# (do susten.)”);
} else if(melodia[Nota] == 0){
lcd.print(“-  (pausa)”);
} else {
lcd.print(melodia[Nota]);
}
lcd.setCursor(0,0);
lcd.print(“Tempo: “);
if(tempoNotas[Nota] == 8 || tempoNotas[Nota] == 6){
lcd.write(byte(0));
if(tempoNotas[Nota] == 6){
lcd.print(“.”);
}
} else if(tempoNotas[Nota] == 4 || tempoNotas[Nota] == 3){
lcd.write(byte(1));
if(tempoNotas[Nota] == 3){
lcd.print(“.”);
}
} else if(tempoNotas[Nota] == 16){
lcd.write(byte(3));
} else if(tempoNotas[Nota] == 2){
lcd.write(byte(2));
}
delay(tempo*1.2);
}
}
void loop(){
//Não é necessária a repetição pois a mesma será feita pelo botão Reset.
}
//Fim de Programa