Você está na página 1de 8

Engenharia de Sistemas Microprocessados

Professor: Márcio Gil Faccin


Aula 14 - Laboratório 6

Objetivos
Conversão analógico-digital.
Datalogger simples.
Conversão digital-analógico PWM.
PWM controlado por potenciômetro e por teclado.

Orientações
Os alunos, em grupos de no máximo 3, deverão ter o material necessário para a execução da
prática de laboratório proposta, incluindo o datasheet dos CIs utilizados e o computador com a IDE
de programação. Após a montagem e as medições, os alunos deverão discutir as dúvidas com o
professor, comprovando os conceitos apresentados pelo professor ao longo da atividade.

Material de Apoio
A conversão analógica-digital (normalmente designada por A/D) consiste na geração de um valor
numérico discreto, composto por um conjunto de bits, capaz de representar (com uma resolução
aceitável) o valor analógico original. Os microcontroladores mais antigos não possuíam conversores
integrados, e utilizavam conversores externos. Mas todas as famílias mais modernas possuem
conversores com diversas portas, selecionáveis através de um multiplexador analógico.
Engenharia de Sistemas Microprocessados
Professor: Márcio Gil Faccin
Aula 14 - Laboratório 6

Uma importante informação sobre os conversores A/D é o número total de bits de resolução da
informação digital. No caso do Arduino, os conversores possuem 10 bits, podendo representar
valores entre 0 e 1023.
Numa estrutura normal de conversão A/D, alguns registradores devem ser configurados para
selecionar o canal a ser convertido e para definir alguns parâmetros da conversão, habilitando uma
função de interrupção para tratar o final da conversão (a conversão A/D não é uma operação
instantânea).
No Arduino, a operação através de registradores não é necessária, visto que a biblioteca oferece
uma função que faz todo o tratamento e que opera de forma bloqueante até que a conversão termine
(a função analogRead( pin )). O fato da função ser bloqueante pode causar perda de performance,
mas como o conversor é relativamente rápido, essa perda não é tão significativa.
Além da função de leitura, a biblioteca do Arduino também disponibiliza a função
analogReference ( ref ), que faz a configuração do sinal AREF de modo a garantir o fundo de escala
do conversor A/D (ou seja, a máxima tensão de entrada que irá corresponder ao valor digital 1023).
Por padrão, a tensão AREF está conectada na tensão interna de Vcc (5 volts). Mudanças na tensão de
referência devem ser feitas com cuidado para evitar que o pino de AREF entre em curto com outros
níveis de tensão. Além disso, as primeiras conversões após a mudança de referência podem
apresentar valores inconsistentes.
A única operação importante que não está disponível nas funções da biblioteca é o ajuste do
prescaler do conversor A/D, permitindo que a operação de conversão seja feita de forma mais rápida
em sinais estáveis. Por padrão, a biblioteca configura o prescaler em 1/128, setando os bits
ADPS[2:0] do registrador ADCSRA.

PWM

A conversão digital-analógica (normalmente designada por D/A) consiste na geração de um sinal


elétrico analógico que corresponda (com uma precisão aceitável) ao valor numérico discreto
originalmente armazenado em memória. Os microcontroladores mais antigos não possuíam
conversores integrados, e utilizavam conversores externos. Mas todas as famílias mais modernas
possuem conversores PWM (Pulse Width Modulation) e alguns modelos possuem conversores DAC
verdadeiros (como é o caso dos pinos DAC0 e DAC1 do Arduino Due).
A técnica de conversão por PWM é bastante simples, no sentido de obter um sinal de amplitude
variável, mesmo operando com pinos de saída na região de saturação, característica dos sinais
digitais, conforme figura abaixo. Desse modo, instantaneamente, a tensão de saída em um pino será
sempre igual a 0 ou Vcc, mas o valor médio ao longo do tempo definirá o nível de tensão aplicado na
saída.
Uma importante informação sobre os conversores PWM é que eles são, normalmente, aplicados
apenas em processos lentos, como sistemas de aquecimento, servo motores ou sistemas luminosos,
nos quais o próprio processo se encarrega de apresentar o comportamento médio, desprezando o
efeito das componentes de alta frequência geradas pelas transições de nível no sinal de saída. Caso
contrário, o sinal PWM deverá ser condicionado através de filtros analógicos, entregando ao processo
um sinal de comportamento mais estável.
Para geração de um sinal PWM é necessário a configuração de uma base de tempo, que
representará o período do PWM. No caso do Arduino, esta base de tempo é dada pelos Timers (cada
Timer é usado para acionamento de um conjunto específico de pinos).
Engenharia de Sistemas Microprocessados
Professor: Márcio Gil Faccin
Aula 14 - Laboratório 6

Figura 1 - Sinais PWM característicos e exemplo de cálculo da tensão média (créditos da figura:
http://www.mecaweb.com.br/eletronica/content/e_pwm)

O Arduino possui diversos modos de configuração do PWM, de acordo com a configuração dos
bits WGMnX, presente nos registradores TCCRnA e TCCRnB. Mas a biblioteca do Arduino se
encarrega de fazer a configuração básica de todos os Timers e de todos os registradores para que eles
operem no modo PWM de 8 bits com correção de fase, e com prescaler de 1/64, simplificando a
operação, conforme a figura abaixo.
Engenharia de Sistemas Microprocessados
Professor: Márcio Gil Faccin
Aula 14 - Laboratório 6

É possível alterar a configuração de prescaler, de modo a conseguir bases de

⚠ tempo diferentes, apenas sobreescrevendo os bits CSSnX do registrador TCCRnB


na função setup( ). Também é possível configurar outros modos, incluindo o
modo de 10-bits, apenas ajustando os valores de WGMnX.

Mantendo a configuração default, ou ajustando a configuração para valores mais adequados ao


caso particular de uso, a biblioteca do Arduíno permite que o usuário utilize apenas a chamada da
função analogWrite ( pin, value ); para definir o ponto de comparação em que será feita a mudança
de nível do pino de saída. Nesta função, pin indica o número do pino externo a ser usado, conforme a
figura abaixo, e value indica um valor entre 0 e 255 (ou valores maiores do que 255 nos modos com
maior resolução) que configura o instante de comparação do timer em que a saída PWM muda de
valor.

Imagem adaptada de http://br-arduino.org/2016/01/arduino-standalone-protoboard.html


Por exemplo, o pino 11 do Arduino Uno será acionado pelo Timer 2, através da comparação com
o registrador OCR2A; e o pino 5 será acionado pelo Timer 0, através da comparação com o registrador
OCR0B.

É possível usar um Timer para geração da base de tempo do PWM e ao mesmo


tempo usá-lo como fonte de interrupção, mas um modo irá afetar o
comportamento do outro. Além disso, é importante que as operações de
configuração do Timer não desconfigurem o modo de operação PWM; ou então
que esse modo seja reconfigurado manualmente quando necessário.

Exemplo
1. Faça um programa que leia dois canais de entrada analógica e envie os dados lidos para
a porta serial do PC.

void setup() {
Serial.begin(9600);
// Reduz o divisor de prescaler de 1/128 (7) para 1/64 (6) fazer a conversão mais rápida
ADCSRA = ADCSRA & (B11111000 | 6);
}
void loop() {
static int timestamp = 0;
int x, y;
int cur = millis();
Engenharia de Sistemas Microprocessados
Professor: Márcio Gil Faccin
Aula 14 - Laboratório 6

if ((cur - timestamp) >= 500)


{
x = analogRead(0);
y = analogRead(1);
timestamp = cur;
Serial.print(5.0*x/1024);
Serial.print(",");
Serial.println(5.0*y/1024);
}
}
}

2. Faça um programa que armazene um conjunto de 720 leituras de dois canais analógicos,
com 8 bits de resolução, registrados com um intervalo de amostragem de 50ms. Utilize
a borda de descida de um pino de entrada digital para disparar o início das leituras e
encerre as leituras ao encher o conjunto de amostras. Utilize um pino de saída
(conectado em um LED) para sinalizar que o sistema está adquirindo dados e utilize
outro pino para sinalizar que existem dados adquiridos prontos para serem
transmitidos. Após o término da leitura, aguarde pelo recebimento de um comando ‘S’
na porta serial e transmita os dados armazenados separando os canais por vírgula e as
amostras pelo símbolo de nova linha. Enquanto não forem transmitidos os dados, ignore
novos sinais de entrada. Assim que os dados forem transmitidos, faça com que a
próxima borda de subida da entrada dispare um novo ciclo de digitalizações.

#define LED1 13
#define LED2 12
#define TRIGGER 3
#define SAMPLES 720
#define TS 50

byte amostras[2][SAMPLES];

void setup() {
Serial.begin(115200);
pinMode ( LED1, OUTPUT );
digitalWrite ( LED1, LOW );
pinMode ( LED2, OUTPUT );
digitalWrite ( LED2, LOW );
pinMode ( TRIGGER, INPUT_PULLUP );
// Reduz o divisor de prescaler de 1/128 (7) para 1/64 (6) fazer a conversão mais rápida
ADCSRA = ADCSRA & (B11111000 | 6);
}

void captura (int n) {


amostras[0][n] = (byte)(analogRead(0)>>2);
Engenharia de Sistemas Microprocessados
Professor: Márcio Gil Faccin
Aula 14 - Laboratório 6

amostras[1][n] = (byte)(analogRead(1)>>2);
}

void loop() {
static unsigned long timestamp = 0;
static int n_amostra = 0;
static bool ready = false;
int i;
char msg[20];
if ((n_amostra == 0) && ( digitalRead ( TRIGGER ) == LOW )) {
timestamp = millis();
captura (n_amostra);
n_amostra++;
digitalWrite ( LED1, HIGH );
}
else if ((n_amostra > 0)&&(n_amostra < SAMPLES)) {
unsigned long cur = millis();
if ((cur - timestamp) >= TS) {
timestamp = cur;
captura (n_amostra);
n_amostra++;
if (n_amostra == SAMPLES) {
digitalWrite ( LED1, LOW );
digitalWrite ( LED2, HIGH );
ready = true;
}
}
}
else if (n_amostra == SAMPLES) {
if (ready) {
if (Serial.read() == 'S') {
for (i = 0; i < SAMPLES; i++) {
sprintf ( msg, "%d,%d,%d", i, amostras[0][i], amostras[1][i]);
Serial.println(msg);
}
ready = false;
digitalWrite ( LED2, LOW );
}
}
else if ( digitalRead ( TRIGGER ) == HIGH ) {
n_amostra = 0;
}
}
}
Engenharia de Sistemas Microprocessados
Professor: Márcio Gil Faccin
Aula 14 - Laboratório 6

3. Faça um programa que configure um sinal de PWM com resolução de 10 bits a partir do
valor recebido pela interface serial.

// Para operar com 10 bits de resolução, a configuração deve ser feita no Timer 1
#define PWM_PIN 10

void setup() {
// Inicializa a comunicação serial
Serial.begin (115200);
// Configura o pino do PWM como saída
pinMode (PWM_PIN, OUTPUT);
// E configura o Timer para operar em PWM phase-correct com 10-bits de resolução:
TCCR1A = B00100011;
}

void loop() {
static int level = 0;
static int bytesReceived = 0;
// Recebe um comando pela interface serial para atualizar o PWM
if (Serial.available() > 0)
{
int x = Serial.read();
// Se o comando lido não é um valor numérico, encerra o valor anterior
if ((x < '0')||(x > '9'))
{
// Se estava recebendo um valor, seta o PWM
if (bytesReceived > 0)
{
analogWrite (PWM_PIN, level);
// Transmite o valor configurado para depuração
Serial.println (level);
// E prepara para receber o próximo comando
bytesReceived = 0;
level = 0;
}
}
else
{
// Se o valor recebido é numérico, atualiza o level
level = level*10 + x - '0';
bytesReceived ++;
}
}
}
Engenharia de Sistemas Microprocessados
Professor: Márcio Gil Faccin
Aula 14 - Laboratório 6

Exercícios Propostos
1. Faça um programa que leia um canal analógico, com leituras espaçadas de 100 ms,
enviando o valor lido para a porta serial. Conecte a entrada analógica no pino central de
um potenciômetro, cujos terminais externos estejam conectados, respectivamente, em
GND e Vcc e observe a tela de Plotter Serial do Arduino enquanto a posição do
potenciômetro varia do início ao fim do curso e depois retornando ao início. Mantendo
o potenciômetro fixo em uma posição qualquer, compare o valor lido pelo Arduino com
o valor real medido com o uso de um instrumento.
2. Altere o programa para identificar o valor mínimo e o valor máximo da leitura em cada
conjunto de 600 medidas, enviando estes valores pela interface serial. Monitore o
comportamento desses limites para configuração do ADPS nos valores 7 (default), 6, 5,
4, 3 e 2.
3. Altere o programa para acionar um pino de saída antes de iniciar a leitura e desligar esse
pino assim que a leitura for concluída. Monitore o comportamento desse tempo para
configuração do ADPS nos valores 7 (default), 6, 5, 4, 3 e 2.
4. Conecte um LED ao pino do PWM acionado pelo programa do exemplo 3 (com uma
resistência série entre 220Ω e 470Ω) e observe (através da análise do brilho e pelo sinal
no osciloscópio) qual o efeito de comandos com os valores 0, 127, 254, 255, 511, 512,
640 e 1023. Meça o período total do PWM, o duty cycle e a tensão média para cada um
dos valores configurados.
5. Repita as medições de período total, duty cycle e tensão média do exercício 1 para o
caso em que o comando de configuração do modo PWM (TCCR1A = B00100011;) seja
removido da função setup ( ).
6. Repita a medição de período total do PWM para um valor de 254 para o caso de, no final
da função setup ( ), inserirmos a reconfiguração do Prescaler do Timer 1 para 1/1 (TCCR1B
= B00000001;).
7. Repita a medição de período total do PWM para um valor de 254 para o caso de, no final
da função setup ( ), inserirmos a reconfiguração do Prescaler do Timer 1 para 1/1024
(TCCR1B = B00000101;).
8. Repita o exercício 1 alterando o pino do PWM para um pino controlado pelo Timer 2.
9. Faça um programa que leia uma entrada analógica a partir de um divisor resistivo com
um potenciômetro (gerando um nível de tensão variável entre 0 e 5V) e use o valor lido
para controlar o brilho de um LED, através da configuração de um PWM. Mantenha o
PWM no modo default (8 bits) e faça a conversão necessária do sinal lido da entrada
analógica para que a tensão máxima na entrada corresponda ao brilho máximo do LED.
Monitore, com a ajuda de um multiteste, a tensão média da entrada e da saída.

Você também pode gostar