Arduino Giga: Conversão Analógica-Digital e Digital-Analógico

Arduino Giga: Conversão Analógica-Digital e Digital-Analógico Deixe um comentário

Olá pessoal! Você sabia que é possível ler e gerar ondas quadradas, senoidais, triangulares e dente-de-serra utilizando o Arduino Giga R1? Neste artigo, conheceremos o uso da conversão analógica-digital e digital-analógica para ler ou gerar principais tipos de ondas. Vamos lá?

Arduino Giga conversão Analógica-Digital e Digital-Analógico

Lista de materiais

Conversão Analógica-Digital usando Arduino Giga

Quando nos referimos a sinais, temos:

  • Sinal analógico, que varia ao longo do tempo e pode assumir um valor qualquer dentro de um intervalo de valores;
  • Sinal digital, que varia somente entre dois valores, pulsos binários.

Conversores Analógico-Digital

No caso do Arduino e outras plataformas, seus sinais de operação são digitais. Para leitura de sinais analógicos, o sinal deve passar por um conversor. O conversor analógico-digital (ADC), como o próprio nome diz, realiza a conversão de um sinal analógico em sinal digital.

No Arduino Giga, temos os pinos A0 a A11, podendo estender para o A12 (DAC0), A13 (DAC1), A14 (CANRX) e A15 (CANTX) se necessário.

Para as placas Arduino Giga R1 e Arduino Portenta H7, existe uma biblioteca chamada Arduino_AdvancedAnalog, para lidar com sinais analógicos de entrada e de saída.

Através da biblioteca é possível configurar:

  • Resolução (8, 10, 12, 14 ou 16 bits)
  • Taxa de amostragem
  • Número de amostras por canal
  • Número de dados armazenados em buffer

Mostraremos aqui como realizar a leitura de uma onda quadrada de 8 kHz através de um canal ADC do Arduino Giga.

Esquemático do circuito ADC com Arduino Giga

A montagem do circuito encontra-se na imagem a seguir:

Conversão Analógica-digital com Arduino Giga

Onde:

Osciloscópio Arduino Giga R1 Gerador de sinais
Negativo (com garra) GND Negativo (preto)
Positivo (sonda) A0 Positivo (vermelho)

Ajuste a onda de saída para:

  • Onda quadrada (square) com 5 Vpp (pico a pico)
  • Frequência: 8 kHz
  • Offset: 2.5 VDC (Arduino Giga trabalha com a parte positiva da onda, por isto o offset deve ser ajustado)

osciloscópio com o gerador de sinais

Verifique se a onda gerada está correta conectando as pontas de prova do osciloscópio com o gerador de sinais. O meu osciloscópio está configurado com 1.00 V no vertical (amplitude) e 50.0 us no horizontal (tempo).

Sketch exemplo ADC

Você deve realizar a instalação da biblioteca Arduino_AdvancedAnalog em sua versão Arduino IDE. Para isto, acesse o menu Sketch => Incluir Biblioteca => Gerenciar Bibliotecas…

Sketch ADC no arduino giga 1

Digite o nome Arduino_AdvancedAnalog e clique em Install. Ao terminar, será mostrada a mensagem INSTALLED como mostrada a seguir. Clique em Fechar.

Sketch ADC no arduino giga 2

Utilize o sketch a seguir:

#include <Arduino_AdvancedAnalog.h>
// Uso do conversor ADC1 no pino A0 
AdvancedADC adc1(A0);
// Uso de millis 
uint64_t last_millis = 0;

void setup() {
  // Serial com 9600 bits por segundo
    Serial.begin(9600);

    // Resolução, taxa de amostragem, número de amostras, buffer
    if (!adc1.begin(AN_RESOLUTION_16, 16000, 32, 64)) {
        Serial.println("Falha no inicio da aquisicao analogica!");
        while (1);
    }
}
// Função para armazenar leitura em buffer 
void adc_print_buf(AdvancedADC &adc) {
    if (adc.available()) {
      // Le ADC e guarda em buf
        SampleBuffer buf = adc.read();

        // Imprime valor na serial
        Serial.println(buf[0]);

        // Retorna valor do buf
        buf.release();
    }
}

void loop() {
  // Uso da função millis
    if (millis() - last_millis > 1) {
      // Imprime valor de ADC1
        adc_print_buf(adc1);
        // Atualiza last_millis
        last_millis = millis();
    }
}

Ao carregar o sketch no Arduino Giga, abra o Plotter Serial no menu Ferramentas => Plotter Serial. Será mostrada uma janela como esta:

Sketch no arduino giga

Utilizamos a resolução de 16 bits do conversor AD com 32 amostras e taxa de amostragem de 16000 para exibição desta onda quadrada no Plotter Serial. Isto significa que o valor máximo da onda é 2^16 = 65536, ou seja, 65536 possibilidades ao se dividir a tensão de 5V.

Se mudarmos a resolução de 16 bits para 10 bits:

 if (!adc1.begin(AN_RESOLUTION_10, 16000, 32, 64)) {

Teremos uma onda com uma resolução de 2^10 = 1023, o mesmo valor de leitura analógica no Arduino Uno e Mega 2560. Portanto, o Arduino Giga nos possibilita ter leituras mais fieis às originais, com escolha do valor de resolução, taxa de amostragem e afins.

Sketch no arduino giga

Obs: O resultado é bom para ondas quadradas, porém, para ondas senoidais, há um corte na onda (saturação) quando é mostrado no Plotter Serial.

Conversores Digital-Analógico usando Arduino Giga

O conversor digital-analógico (DAC), como o próprio nome diz, realiza a conversão de um sinal digital em sinal analógico. Em versões Arduino como Uno e Mega 2650, não há DAC, somente a opção de PWM. Na prática, o PWM é uma saída digital que varia o tempo em nível alto e a média desta saída nos dá valores entre 0 e 5V. Porém, trata-se de uma onda quadrada e não de fato uma saída anlógica.

No Arduino Giga, temos os pinos A12 (DAC0) e A13 (DAC1), dois canais disponíveis para o DAC. Faremos um gerador de ondas diversas, onde a escolha será realizada pelo Monitor Serial.

Esquemático do circuito DAC com Arduino Giga

A montagem do circuito encontra-se na imagem a seguir:

Esquemático do circuito DAC com arduino

Onde:

Osciloscópio Arduino Giga R1
Negativo (com garra) GND
Positivo (sonda) A12 (DAC0)

Ajuste o osciloscópio para 1.00 V no vertical (amplitude) e 10.0 us no horizontal (tempo).

Sketch exemplo DAC

Com a biblioteca Arduino_AdvancedAnalog é possível gerar diversos formatos de onda: quadrada, senoidal, triangular e afins. Faremos uso de um exemplo já incluso na biblioteca. Para acessá-lo, clique em Arquivo => Exemplos => Arduino_AdvancedAnalog => Beginner => Waveform_generator. A seguir temos o sketch traduzido:

// Exemplo Waveform_Generator para produzir ondas no DAC0
// Traduzido por Gedeane Kenshima
#include <Arduino_AdvancedAnalog.h>
#include <mbed_stats.h>

// Constantes
#define N_SAMPLES           (64)
#define DEFAULT_FREQUENCY   (32000)

// Uso do conversor DAC1 no pino A12 
AdvancedDAC dac1(A12);
// Uso da função para número de amostras
uint8_t SAMPLES_BUFFER[N_SAMPLES];

// Função para placas MBED (Giga e Portenta)
uint32_t get_current_heap() {
    mbed_stats_heap_t heap_stats;
    mbed_stats_heap_get(&heap_stats);
    return heap_stats.current_size;
}
// Função menu para Monitor Serial
void print_menu() {
    Serial.println();
    Serial.println("Digite um comando:");
    Serial.println("t: Onda triangular");
    Serial.println("q: Onda quadrada");
    Serial.println("s: Onda senoidal");
    Serial.println("r: Onda dente-de-serra");
    Serial.println("k: Parar DAC");
    Serial.println("+: Aumentar frequencia");
    Serial.println("-: Diminuir frequencia");
}
// Função para gerar onda escolhida
void generate_waveform(int cmd) {
    static bool dac_started = false;
    static size_t dac_frequency = DEFAULT_FREQUENCY;
    static size_t starting_heap = get_current_heap();

    // Uso de switch/case para escolha da forma de onda
    switch (cmd) {
        case 't':
            // Onda triangular
            Serial.print("Forma de onda: Triangular ");
            for (int i=0, j=N_SAMPLES-1; i<N_SAMPLES; i++, j--){
                SAMPLES_BUFFER[i] = abs((i - j) * 256 / N_SAMPLES);
            }
            break;

        case 'q':
            // Onda senoidal
            Serial.print("Forma de onda: Quadrada ");
            for (int i=0; i<N_SAMPLES; i++){
                SAMPLES_BUFFER[i] = i < (N_SAMPLES / 2) ? 0 : 255;
            }
            break;

        case 's':
            // Sine wave
            Serial.print("Forma de onda: Senoidal ");
            for (int i=0; i<N_SAMPLES; i++){
                SAMPLES_BUFFER[i] = sin(2 * 3.14 * (i / (float) N_SAMPLES)) * 127 + 127;
            }
            break;

        case 'r':
            // Sawtooth
            Serial.print("Forma de onda: Dente-de-serra ");
            for (int i=0; i<N_SAMPLES; i++){
                SAMPLES_BUFFER[i] = i * (256 / N_SAMPLES);
            }
            break;

        case '+':
        case '-':
            Serial.print("Frequencia atual: ");

            if (cmd == '+' && dac_frequency < 128000) {
                dac_frequency *= 2;
            } else if (cmd == '-' && dac_frequency > 1000) {
                dac_frequency /= 2;
            } else {
                break;
            }
            // Mudar frequencia.
            dac1.frequency(dac_frequency * N_SAMPLES);
            break;
        case 'k':
            // Parar DAC1
            dac1.stop();
            dac_started = false;
            break;
        default:
            Serial.print("Comando desconhecido ");
            Serial.println((char) cmd);
            return;
    }
    if (cmd == 'k') {
        Serial.println("Parar DAC!");
        print_menu();
    } else {
        Serial.print(dac_frequency/1000);
        Serial.println("KHz");

        if (dac_started == false) {
            // Inicializar DAC1
            if (!dac1.begin(AN_RESOLUTION_8, dac_frequency * N_SAMPLES, N_SAMPLES, 32)) {
                Serial.println("Falha ao iniciar DAC1 !");
                while (1);
            }
            dac_started = true;
        }
    }
    Serial.print("Memoria utilizada: ");
    Serial.print(get_current_heap() - starting_heap);
    Serial.println(" bytes");
}
void setup() {
    // Início da comunicação serial
    Serial.begin(115200);

    while (!Serial) {
    }

    // Listar comandos aceitos.
    print_menu();
    // Iniciar gerando uma senoide.
    generate_waveform('s');
}

void loop() {
    if (Serial.available() > 0) {
        int cmd = Serial.read();
        if (cmd != '\n') {
            generate_waveform(cmd);
        }
    } 

    if (dac1.available()) {
        // Get a free buffer for writing.
        SampleBuffer buf = dac1.dequeue();

        // Write data to buffer.
        for (size_t i=0; i<buf.size(); i++) {
            buf[i] =  SAMPLES_BUFFER[i];
        }

        dac1.write(buf);
    }
}

Ao carregar o sketch no Arduino Giga, abra o Monitor Serial no menu Ferramentas => Monitor Serial ou use o ícone de lupa no canto superior à esquerda. Será mostrada uma janela como esta:

Sketch DAC no arduino giga 1

Ao digitar o caractere e clicar em Enviar (ou apertar a tecla Enter), será mostrado o nome da forma de onda, sua frequência (em kHz) e quanto foi utilizado de memória para gerar a onda.

Sketch DAC no arduino giga 2

Você pode digitar os comandos conforme listados e verificar se as saídas em A12 correspondem. Caso queira aumentar ou diminuir a frequência da onda, utilize as teclas (-) e (+).

conversão analógica-digital com arduino giga

OBS: Este artigo foi realizado através de uma Raspberry Pi 400, que pode ser usada como um desktop. Para saber seus recursos, veja este artigo aqui.


Gostou de conhecer um pouco mais sobre o Arduino Giga e suas possibilidades para leitura e geração de ondas analógicas? Deixe um comentário abaixo contando o que achou. Para mais sobre os lançamentos do universo maker, acompanhe as novidades no nosso blog. E não esqueça de nos seguir no Instagram para não perder nenhuma novidade.

Faça seu comentário

Acesse sua conta e participe