O ESP32 é, sem dúvidas, um dos preferidos quando se fala em protótipos e produtos em sistemas embarcados e/ou Internet das Coisas. Aliando ótimo custo/benefício, comunidade vasta e muito ativa e suporte a ser programado no ecossistema Arduino, o ESP32 é uma das primeiras - senão a primeira - opção que vem à mente quando é a hora de se escolher o hardware de um projeto atualmente.

O ESP32 possui recursos muito populares, como por exemplo: ADC (conversor analógico-digital), conectividade wi-fi e conectividade Bluetooth (clássico e BLE). Porém, ele possui também recursos não tão falados e que são muito importantes para projetos em geral, como o DAC (conversor digital-analógico).

Este artigo irá explorar o uso do DAC nativo do ESP32, de forma a contextualizar você, leitor, no que é um DAC e como utilizá-lo no ESP32.

 

O que é um DAC?

DAC é um acrônimo para Digital-to-Analog Converter (em português, conversor digital-analógico. O DAC é um elemento capaz de converter um dado digital em uma tensão (ou sinal) analógica, processo exatamente inverso ao do ADC. Isso significa dizer que, se você deseja aplicar um determinado nível de tensão em um circuito / componente a partir de um sistema eletrônico ou gerar um sinal analógico com características específicas, o DAC é o elemento ideal para te atender. O DAC é especialmente útil quando lidamos com geração de sinais de áudio ou de tensões de controle / referência para circuitos externos.

O DAC, assim como o ADC, possui também uma resolução. Ou seja, nível de tensão mínimo configurável por bit do dado digital. Exemplo: se um DAC é dado com resolução de 8 bits em um sistema onde a alimentação do DAC é 3,3V, significa dizer que há 256 (2^8) níveis entre a tensão mínima (0V) e a tensão máxima (3,3V) deste DAC. Logo, a resolução do DAC é igual a 3,3V/256 = 12,9 mV / bit.

De forma geral, o valor analógico é, em função do valor digital, determinado pela seguinte fórmula:

 

Vanalógico = Valimentação * Vdigital / (2bits - 1)

 

Supondo um DAC de 8 bits e tensão de alimentação do DAC igual a 3,3V:

 

Vanalógico = Valimentação * Vdigital / (2bits - 1)

Vanalógico = Valimentação * Vdigital / (28 - 1)

Vanalógico = Valimentação * Vdigital / 255

 

 Na prática:

Valor digital Valor analógico (após conversão do DAC)
0 (0/255) * 3,3V = 0V
127 (127/255)*3,3V = 1,64V
255 (255/255)*3,3V = 3,3V

 

DAC no ESP32

O ESP32 possui dois canais de DAC: DAC0 e DAC1. Isso significa que você, desenvolvedor, tem a possibilidade de gerar dois sinais analógicos com um só ESP32. Ambos os canais de DAC tem resolução de 8 bits, ou seja, resolução de 12,9mV/bit.

No ESP32, os canais de DAC estão disponíveis nos seguintes GPIOs:

 

Canal do DAC GPIO utilizado
DAC0 GPIO 25
DAC1 GPIO 26

 

Veja a figura 1, onde estão destacados ambos os canais do DAC em um kit de desenvolvimento com o ESP32.

 

Figura 1 - DAC0 e DAC1 (do kit ESP32 DevKit 1) em destaque. Fonte da imagem: https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
Figura 1 - DAC0 e DAC1 (do kit ESP32 DevKit 1) em destaque. Fonte da imagem: https://randomnerdtutorials.com/esp32-pinout-reference-gpios/ | Clique na imagem para ampliar |

 

 

Uso do DAC do ESP32 com a Arduino IDE

Para utilizar o DAC do ESP32 com a Arduino IDE, apenas uma função é necessária:

 

dacWrite(Canal_DAC, Valor);

 

Onde:

Canal_DAC: qual canal do DAC será utilizado (lembrando que: DAC0 no GPIO 25 e DAC1 no GPIO 26)

Valor: valor digital (0 até 255) para ser convertido em tensão (ou sinal) analógico. Como exemplos: valor 0 resultará em 0V e valor 255 em 3,3V.

 

Abaixo, como exemplo de uso, está a geração de um sinal crescente, de 0 a 3,3V, similar a um sinal do tipo dente-de-serra nos canais DAC0 (GPIO 25) e DAC1 (GPIO 26).

 

/* Definição do canal DAC0 (GPIO 25) */
#define CANAL_DAC0 25  

/* Definição do canal DAC1 (GPIO 26) */
#define CANAL_DAC1 26  


void setup() 
{
  
}

void loop() 
{ 
    int i;
  
    for(i=0; i<=255; i++)
    {
        dacWrite(CANAL_DAC0, i);  
        dacWrite(CANAL_DAC1, i);  
    }
}

 

Ainda, segue abaixo um exemplo de geração de sinal senoidal com ambos os canais DAC0 e DAC1. Neste caso, note que os valores digitais a serem convertidos para tensões analógicas são tabelados no array chamado senoide. Tomando como base este exemplo, você pode tabelar / criar seus próprios sinais customizados. Este código foi baseado no exemplo disponível em: https://github.com/G6EJD/ESP32-DAC-Examples/blob/master/ESP32_DAC_Advanced.ino

 

 

/* Definição do canal DAC0 (GPIO 25) */
#define CANAL_DAC0 25  

/* Definição do canal DAC1 (GPIO 26) */
#define CANAL_DAC1 26  

/* Definição - número de amostras da senoide */
#define NUMERO_AMOSTRAS_SENOIDE     112

char senoide[NUMERO_AMOSTRAS_SENOIDE] = {0x80, 0x83, 0x87, 0x8A, 0x8E, 0x91, 0x95, 0x98, 0x9B, 0x9E, 0xA2, 0xA5, 0xA7, 0xAA, 0xAD, 0xAF,
                                         0xB2, 0xB4, 0xB6, 0xB8, 0xB9, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xBF, 0xBF, 0xC0, 0xBF, 0xBF, 0xBF,
                                         0xBE, 0xBD, 0xBC, 0xBB, 0xB9, 0xB8, 0xB6, 0xB4, 0xB2, 0xAF, 0xAD, 0xAA, 0xA7, 0xA5, 0xA2, 0x9E,
                                         0x9B, 0x98, 0x95, 0x91, 0x8E, 0x8A, 0x87, 0x83, 0x80, 0x7C, 0x78, 0x75, 0x71, 0x6E, 0x6A, 0x67,
                                         0x64, 0x61, 0x5D, 0x5A, 0x58, 0x55, 0x52, 0x50, 0x4D, 0x4B, 0x49, 0x47, 0x46, 0x44, 0x43, 0x42,
                                         0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x42, 0x43, 0x44, 0x46, 0x47, 0x49, 0x4B,
                                         0x4D, 0x50, 0x52, 0x55, 0x58, 0x5A, 0x5D, 0x61, 0x64, 0x67, 0x6A, 0x6E, 0x71, 0x75, 0x78, 0x7C };

void setup() 
{
  
}

void loop() 
{ 
    int i;
  
    for(i=0; i<=NUMERO_AMOSTRAS_SENOIDE; i++)
    {
        dacWrite(CANAL_DAC0, senoide[i]);  
        dacWrite(CANAL_DAC1, senoide[i]);  
    }
}

 

Conclusão

O ESP32 é um SoC completo para projetos em sistemas embarcados e/ou Internet das Coisas, contando com diversos recursos de forma já nativa (sem necessidade de circuitos externos), como o DAC, por exemplo.

Desta forma, é possível fazer projetos que tenham como requisito a geração de sinais analógicos customizados (de 0 a 3,3V), algo especialmente útil para a geração de sinais de áudio e sinais analógicos de referência para circuitos externos.