DAC

Lab 3) Gerador de Senóide usando DAC

A idéia agora é usar um DAC real, placa sugerida: módulo DAC MPC 4725 que é de 12-bits. Isto implica que esta placa aceita valores variando na faixa ìnt de 0 até 4025 (). Esta placa trabalha com comunicação I2C. Ver página Trabalhar com o Módulo DAC, para ver maiores detalhes e saber como instalar o driver para esta placa na IDE do Arduino.

Lab 3) Gerador de Senóide usando DACObjetivoProcedimentoHardware necessarioMontagem sugeridaDetalhes de SoftwareDica No. 1Dica No. 2Teste de "Desempenho Puro"AnexosA. Instalação da Biblioteca Adafruit MCP4725B. Em caso de erro associado com "Adafruit_BusIO_Register.h"C. Geração dos NPOINTS da senoide


Objetivo

Tentar gerar uma onda senoidal o mais rápido possível usando placa Arduino Uno e ISR para garantir sua frequência.

Procedimento

  1. Programar uma ISR para rodar com taxa de amostragem de 10 KHz.

  2. Programar a rotina ISR para gerar 20 ou 10 pontos de uma seníde.

  3. Comprovar usando osciloscópio:

    1. A frequência da seníde sendo gerada (Canal 1 do osciloscópio);
    2. O tempo de processamento decorrido com a ISR. Para tanto, no início da ISR "subir" o nível lógico de certo pino do Arduíno e uma vez saindo da ISR, "baixar" o nível lógico neste pino. Se esta saída for verificada no osciloscópio (Canal 2), deve ser comprovada a frequência de amostragem de 10 KHz e o correspondente "duty-cycle" vai corresponder ao tempo de processamento dedicado à ISR. Tentar medir este valor.
  4. Montar relatório final documentando:

    1. Ligações elétricas efetuadas;
    2. Cálculos dos registradores/timers associados com a ISR para gerar a taxa de interrupção à 10 KHz.
    3. Explicar a forma como foram sintetizados os pontos da senóide;
    4. Mostrar os gráficos capturados via osciloscópio.

Hardware necessario

Montagem sugerida

  1. Fixar o módulo DAC no Proto-board;

  2. Realizar as devidas conexões ao DAC:

    Pino no
    DAC
    Pino no
    Arduíno
    VccAlgum pino Vcc
    GNDGND
    SDA (Data)A4
    SCL (Clock)A5 *
    VOUTSaída analógica
    [0 .. 5 Volts ]

* pino A5 do Arduino (aparentemente já contêm resistor pullup de 10K para 5 Volts no DAC, e esta saída já trabalha com um sinal de 440 KHz).

Diagrama elétrico:

gerador_senoidal_DAC_Esquematico

Detalhe da ligação do IRF640 ao alto-falante:

ligacao_speaker_IRF640_bb

 

Detalhes de Software

  1. Será necessário programar a ISR para ser chamada na taxa de 10 KHz, ou a cada: segundos ou à cada 0,1 ms. Lembre que o clock do Arduíno Uno normalmente é de 16 MHz e considere que seu uP gasta 4 ciclos de clock para executar uma instrução (típico de processadores RISC), o que significa que cada instrução mínima leva segundos para ser executada ou 0,375 ms. Ou seja, sim, estamos tentando colocar o Arduíno no limite de sua capacidade de processamento.

  2. A fim de reduzir custos computacionais, se sugere que o próprio Arduíno no bloco void setup() {...} calcule os NPOINTS necessários para gerar os pontos da senóide e os armazene num array (deverá ser uma variável global). Considerar que devem ser gerados valores int na faixa de [0, 4095] que correspondem aos 12-bits do DAC sendo usado.

  3. A rotina ISR deve bem "enxuta", isto é, exigir o menor esforço computacional possível e realizar apenas 3 coisas:

    1. Enviar para o DAC o valor atual do vetor que armazena os pontos da senóide;
    2. Incrementar o índice que aponta para a próxima posição neste vetor;
    3. Testar se alcançou o fim do vetor (NPOINTS) e se sim, voltar o (valor do) índice à zero.
    4. Não esquecer de alternar o nível lógico de um pino qualquer do Arduíno para verificar com auxílio do osciloscópio se a rotina ISR está realmente sendo executada na taxa requerida e quanto de processamento ocupa a mesma.
  4. Realizar testes, documentando os resultados. O ideal seria apresentar um gráfico obtido com auxílio do osciloscópio que mostre no canal 1, a onda senoidal sendo gerada e no canal 2, o pino que muda de estado indicando a execução da ISR.

Dica No. 1

Para minimizar o esforço computacional dentro da ISR, é melhor evitar if pesados e usar o operador módulo (%) apenas se o compilador não transformar isso em instruções mais simples. Outra alternativa é um teste condicional simples (que tende a ser mais rápido em uC's sem divisão rápida).

Segue sugestão de código compacto em C:

Observações:

Dica No. 2

Existe uma forma ainda mais rápida de exceutar a ISR, mas envolve o uso de "máscara binária" e só funciona se NPOINTS for compatível com potência de 2. Por exemplo, suponha que NPOINT = 16, então podemos fazer algo como:

Nesse caso não há if nem divisão, só uma operação AND bit a bit. Mas para isto NPOINTS deve ser potência de 2.

Teste de "Desempenho Puro"

Outro teste que poderia ser realizado, mas que não garante nenhum compromisso com a taxa de amostragem, seria usar a seção void loop() {..} do Arduíno apenas para comandar o DAC e atualizar a variável índice do vetor. Eventualmente se poderia acrescentar neste código, instrução para alternar o nível de algum pino de "controle" do Arduino, assim, usando o osciloscópio, se poderia comprovar a máxima frequência da senóide possível de ser gerada (canal 1). E no canal 2 do osciliscópio, conectado no pino de controle seria observada uma onda quadrada cujos ciclos (em nível lógico baixo e em nível lógico alto) corresponderiam ao tempo gasto pela Arduíno para processar esta seção de código. Este teste resultaria algo como:

A execução deste código gera a seguine saída no terminal (porta serial):

Note que os valores calculados pelo Arduino são praticamente os mesmos calculados testando o código via MATLAB (Anexo C (final da página)):

Simulação
Matlab:
Captura real
(Osciloscópio)
senoide_20_ptsTEK00004

Pela medição realizada pelo osciloscópio se percebe que a frequência máxima atingida foi pouco além de 300 Hz. Apenas! (E sim, a resoluçao e UX com usuário do osciloscópio da Tektronix é "sofrível").

Detalhe: se esta mesma senóide for implementada via ISR sendo executada a taxa de 10 KHz (período de amostragem de 100 s), ao sintetizar um ciclo de senóide usando 20 pontos, pode-se alcançar frequência um pouco superior à 400 Hz. O que significa que a ISR é executada de forma mais rápida que o bloco void loop() { ... }. Mas a ISR vai ocupar pouco mais de 80% do período de tempo dos 10 KHz para repassar os valores do vetor da senóide para o DAC. Isto significa que aproximadamente 82 s para sua execução, sobrando menos de 20 s para o Arduíno recuperar "contexto" após execução da ISR. Na prática, o mesmo ficaria insensível talvez à leitura do simples nível lógico de um push-bottom conectado à alguma porta I/O inviabilizando até uma interface mínima com o usuário.

Fim.


Anexos

A. Instalação da Biblioteca Adafruit MCP4725

Vá até a página https://github.com/adafruit/Adafruit_MCP4725, acesse o botão verde contendo " <> Code v " e com o botão direito do mouse sobre este botão, faça abrir um menu pull-down e selecione: , como mostra a figura abaixo:

baixar_Adafruit_MCP4725

Cliando em "Download ZIP" será baixado um arquivo compactado ZIP.

Basta ir para a IDE do Arduíno e buscar por: Menu >> Rascunho > Incluir Biblioteca > Adicionar biblioteca .ZIP..., como mostra a figura abaixo:

instalar_biblioteca_IDE_Arduino

E então selecionar a pasta (provavelmente /Downloads) onde antes você baixou o arquivo zipado.

Pronto.

B. Em caso de erro associado com "Adafruit_BusIO_Register.h"

Em caso de erro do tipo:

Esta mensagem de erro:

indica que o IDE do Arduino não conseguiu localizar o arquivo de cabeçalho especificado, Adafruit_BusIO_Register.h. Isso normalmente ocorre quando uma biblioteca necessária não está instalada ou não é reconhecida corretamente pela IDE.

Faltaria instalar a biblioteca faltante:

C. Geração dos NPOINTS da senoide

Os NPOINTS da senóide podem ser gerados de forma simples e antecipada, gerando valores dentro um vetor. Testando um código no MATLAB

Os pontos calculados para a senóide podem ser vistos no gráfico à seguir:

senoide_20_pts

Se espera ver esta forma de onda na saída do DAC.


Fernando Passold, em 27/08/2025