Académique Documents
Professionnel Documents
Culture Documents
porta analgica do Arduino, ele fica restrito capacidade dela, normalmente restrita a
tenses positivas entre 0 e 5V (voc pode aumentar essa faixa usando circuitos externos
tais como divisores de tenso, se desejar).
Ele tambm no tem suporte a alguns recursos comuns em osciloscpios atuais, como
seleo dinmica da frequncia/perodo, acompanhamento simultneo de mais de uma
entrada, entre outros e alguns desses talvez entrem em uma futura verso do
programa, se eu tiver a demanda. Em especial, ele no tenta fazer uma relao entre o
valor lido na porta e a tenso externa correspondente a ele.
Meu (quase-)osciloscpio um (no-)osciloscpio que plota os valores lidos de uma
porta analgica, com controle dinmico de centro e amplitude do grfico.
O que ele faz, atendendo plenamente minha demanda atual, exibir um grfico do
valor lido da porta (atualizado ~10 vezes por segundo), oferecendo duas maneiras de
selecionar dinamicamente os parmetros do grfico. Uma delas manual, girando um
par de potencimetros que definem qual valor corresponde ao centro do eixo Y do
grfico (default: 512) e qual a amplitude exibida na tela (default: 1024).
A outra automtica: pressionando um boto que define a partir das 80 leituras mais
recentes o melhor centro e amplitude para visualizar os dados atualmente em exibio.
Alm do grfico contnuo, que preenche a tela a cada ~8 segundos, so exibidos
permanentemente no alto da tela os valores mnimo, central e mximo da faixa exibida
no eixo Y, e na parte de baixo da tela um acompanhamento do valor mais recente lido e
plotado.
Para os potencimetros que eu usei, o pino esquerdo (use como referncia a imagem
acima) conectado ao GND, e o pino direito conectado ao pino AREF (ou 3V3). O
pino central de cada um deles conectado a um pino analgico do Arduino na minha
montagem, o pino central do potencimetro da esquerda foi conectado ao pino A2 do
Arduino, e o pino central do potencimetro da direita foi conectado ao pino A4 do
Arduino.
Para ter dados significativos para plotar, basta conectar um sensor a uma porta analgica
(a A0, no meu caso). Meu escolhido foi um LDR, um resistor cuja resistncia varia
conforme a incidncia de luz, servindo portanto para detectar a luminosidade. Usei nele
uma configurao com pull-up, ilustrada no diagrama acima: um de seus terminais vai
conectado ao GND do Arduino, o outro vai conectado tanto ao pino A0 do Arduino
quanto a um resistor de 10K ligado ao pino AREF ou 3V3 do Arduino.
Para completar, s falta descrever a conexo do mdulo display LCD 84x48, que um
dia j foi parte de um celular Nokia 5110. J expliquei detalhadamente sobre ele no
artigo anterior, portanto agora vou apenas listar as conexes de pinos que usei:
// nokia-monitor-grafico
// exibicao.
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
// configuracoes de hardware
void setup()
display.begin();
display.clearDisplay();
display.setContrast(50);
display.display();
pinMode(pinoBotao,INPUT_PULLUP);
int X=0;
int Y=0;
int cMin;
int cMax;
int oldX=-1;
int oldY=-1;
int cY;
int cCentro;
int amplitude;
int old_cMin;
int old_cMax;
int linha[40];
int extremoAlto=0;
int extremoBaixo=1024;
int old_extremoAlto=1024;
int old_extremoBaixo=0;
int pot1val;
int pot2val;
int old_pot1val;
int old_pot2val;
boolean botaoMudou=true;
if (limpar) {
if (X<xMax-10) display.drawLine(X+10,5,X+10,40,WHITE);
if (X==0) display.fillRect(X,5,X+10,40,WHITE);
linha[X]=YY;
if (YY>extremoAlto) extremoAlto=YY;
if (YY<extremoBaixo) extremoBaixo=YY;
if (X==40) {
old_extremoAlto=extremoAlto;
extremoAlto=0;
old_extremoBaixo=extremoBaixo;
extremoBaixo=1024;
if (cMax-cMin!=1023) {
cY=constrain(YY,cMin,cMax)-cMin;
cY=map(cY,0,cMax-cMin,0,30);
else cY=map(YY,0,1024,0,35);
if (X>0) display.drawLine(oldX,oldY,X,39-cY,BLACK);
else display.drawPixel(X,39-cY,BLACK);
X++;
if (X==80) X=0;
oldX=X;
oldY=39-cY;
void replota() {
int Xsave=X;
X=0;
display.fillRect(0,8,84,40,WHITE);
plotaPonto(linha[i],false);
X=Xsave;
void autoEscala() {
display.setCursor(75,40);
display.print("x");
int _dAmp;
if (X<10) {
_dAmp=(old_extremoAlto-old_extremoBaixo)/20;
if (_dAmp<30) _dAmp=30;
cMin=old_extremoBaixo-_dAmp;
cMax=old_extremoAlto+_dAmp;
} else {
_dAmp=(extremoAlto-extremoBaixo)/20;
if (_dAmp<30) _dAmp=30;
cMin=extremoBaixo-_dAmp;
cMax=extremoAlto+_dAmp;
cCentro=cMin+((cMax-cMin)/2);
old_cMin=cMin;
old_cMax=cMax;
replota();
void atualizaEscala() {
cCentro=1024-int(pot1val*1.0/pot1max*1024);
int folga=cCentro;
if ((1024-cCentro)<folga) folga=1024-cCentro;
amplitude=1024-int(pot2val*1.0/pot2max*1024);
cMin=cCentro-amplitude/2;
cMax=cCentro+amplitude/2;
if (abs((old_cMin-cMin)>2) | (abs(old_cMax-cMax)>2)) {
if (X>0) replota();
old_cMin=cMin;
old_cMax=cMax;
void processaEscala() {
if (botaoMudou==true) {
autoEscala();
botaoUltimoM=millis();
botaoMudou=false;
if ( (abs(old_pot1val-pot1val)>10) | (abs(old_pot2valpot2val)>10) ) {
atualizaEscala();
old_pot1val=pot1val;
old_pot2val=pot2val;
void atualizaPlacares() {
display.fillRect(0,40,84,8,WHITE);
display.setCursor(5,40);
display.print(cY);
display.setCursor(40,40);
display.print(Y);
display.fillRect(0,0,84,8,WHITE);
display.setCursor(0,0);
display.print(cMin);
display.setCursor(32,0);
display.print(cCentro);
display.setCursor(58,0);
display.print(cMax);
void loop() {
delay(100);
Y=analogRead(A0);
plotaPonto(Y);
pot1val=analogRead(pot1Analogico);
pot2val=analogRead(pot2Analogico);
processaEscala();
atualizaPlacares();
display.display();
/*
you may not use this file except in compliance with the
License.
http://www.apache.org/licenses/LICENSE-2.0
*/
De cima para baixo, comeamos pelo trecho em salmo, que tem a incluso das
bibliotecas de comunicao e de suporte ao display, seguida da definio de constantes
de posio e calibrao do boto e dos potencimetros, da importante instanciao do
objeto display (quando informamos para a biblioteca quais os pinos do Arduino que
esto conectados aos pinos relevantes do LCD), e do
setup
restringe a deixar a tela pronta para uso e definir o modo do pino conectado ao boto (os
pinos em uso pelos potencimetros so analgicos e no precisam ser inicializados, e os
do display so inicializados pela biblioteca).
A seguir, em verde, temos a definio das variveis globais que governam quase tudo
que acontece no (no-)osciloscpio. Por exemplo:
plotado o prximo ponto,
e
linha[40]
cMin
cMax
onde fica gravada a srie de pontos da volta atual do grfico. Voc ver
plotaPonto ,
YY
loop()
parmetro
limpar
replota()
limpar
como false).
Note que o comeo da funo tem um grande bloco de cdigo executado apenas
quando
do
limpar=true ,
loop() .
Em seguida, as funes
constrain()
map()
plotaPonto ,
a funo
replota()
plotaPonto )
trivial: ela
autoEscala() ,
atualizaEscala()
replota() .
processaEscala()
debounce ,
atualizaPlacares() ,
loop()
terceirizada para as funes que j vimos, ele ficou bem simples, limitando-se a ler e
plotar periodicamente o valor do sensor, ler os potencimetros e processar a escala,
atualizar os placares e chamar a importante funo
display.display() ,
nico