Utilizando o conversor Delta-Sigma do MSP430F2013

conversor Delta-Sigma
Este post faz parte da série Conversor Delta-Sigma do MSP430

Caro leitor, neste artigo abordarei as características e configurações básicas do conversor ΔΣ (Delta-Sigma) de 16 bits (SD16_A) presente em diversos microcontroladores da família MSP430 da Texas Instruments, com foco especial no modelo MSP430F2013.

Para o desenvolvimento da minha dissertação de mestrado acabei precisando pesquisar sobre conversores ADC e AFE’s (Analog Front End) com mais resolução que os usuais 10-bit presente na maioria dos microcontroladores. Nesta procura um colega indicou o modelo MSP430F2013 que tinha uma característica bastante importante para mim, era compatível com a Launchpad G2, ou seja, eu poderia tomar proveito do SD16_A utilizando uma launchpad como base de testes, o que foi excelente. Fica aqui a dica, se você tiver uma launchpad G2 é possível trocar o uC e brincar com o SD16_A.

Características do SD16_A

  • Arquitetura ΣΔ de 16-bit de segunda ordem;
  • Entradas diferenciais ou single-ended (referenciadas ao GND);
  • Referência interna de 1,2 V;
  • Entrada para referência externa (selecionável por software);
  • Sensor de temperatura interno;
  • Modulador operando a até 1,1 MHz;
  • Modo low power.

A estrutura geral do SD16_A pode ser vista na figura a seguir:

conversor Delta-Sigma
Figura 01 – Estrutura geral do SD16_A

O conversor Delta-Sigma

Existem diversos tipos de conversores ADC, sendo o SAR (sucessivas aproximações) o mais comum na maioria dos uC’s bem como dos conversores de uso padrão. Além do SAR podemos listar os tipos Flash, Pipeline, Single-Slope, Dual-Slope (e Multi-slope) e Delta-Sigma.

Cada conversor possui uma característica específica, geralmente ponderando entre frequência de amostragem e resolução, onde a escolha de modelo ideal dependerá das características da aplicação foco.

conversor Delta-Sigma
Figura 02 – Resolução VS amostragem. Fonte: Tearing Into Delta Sigma ADC’s

Os conversores delta-sigma são bastante populares nas aplicações de instrumentação de precisão devido a sua excelente resolução e custo, já que são mais baratos e simples de serem implementados quando comparados a um conversor dual-slope, como os tradicionalmente utilizados em multímetros de bancada de precisão. A estrutura básica de um conversor delta-sigma é apresentada na figura a seguir.

Estrutura de um conversor delta-sigma
Figura 03 – Estrutura de um conversor delta-sigma. Fonte: Delta-sigma ADC basics: Understanding the delta-sigma modulator

São conhecidos como conversores 1-bit já que sua saída é um trem de pulsos (1/0) em alta frequência, também conhecida como PDM (pulse density modulation). Esse trem de pulsos passa por um filtro digital, geralmente um filtro Sync3 ou WideBand, e por fim por um decimador que irá diminuir a quantidade de bits para um tamanho mais eficiente, conforme pode ser visto na figura a seguir.

Filtro digital e Decimador
Figura 04 – Filtro digital e Decimador. Fonte: Choose the right A/D converter for your application – TI

Quanto maior for o oversampling utilizado, tradicionalmente apresentado como OSR (oversampling ratio) nos datasheets, maior será o número de bits úteis do conversor e consequentemente a resolução obtida.

A animação a seguir apresenta o efeito do oversampling aplicado diretamente na saída do modulador, demonstrando o efeito de reconstrução do sinal. Deixo aqui a indicação de leitura do artigo no Hackaday além de assistirem ao vídeo.

Aplicando média na saída do modulador - reconstrução do sinal na entrada
Figura 05 – Aplicando média na saída do modulador – reconstrução do sinal na entrada. Fonte: Tearing Into Delta Sigma ADC’s

SD16_A do MSP430F2013

O MSP430F2013 é um microcontrolador com foco no baixo consumo baseado em uma arquitetura RISC de 16-bit, podendo operar a até 16 MHz. A quantidade de memória RAM e Flash disponível pode se tornar um desafio dependendo da aplicação, com valores de 128 Bytes e 2 KB, respectivamente.

O SD16_A deste modelo possui 4 canais analógicos (externos) multiplexados, podendo operar na configuração single-ended ou diferencial. O pinout deste uC é apresentado a seguir.

Pinout do uC
Figura 06 – Pinout do uC. Fonte: Datasheet.

O ADC possui uma tensão de referência interna de 1,2 V, entretanto, pode-se utilizar uma referência externa caso necessário.

A tensão máxima (VFSR)suportada na entrada de cada canal depende tanto da tensão de referência como do ganho configurado no PGA (programmable gain amplifier) interno. Considerando a referência interna com ganho 1x no PGA, a tensão máxima possível é de ±0,6 V.

Os principais registradores para configuração do SD16_A são: SD16CTL, SD16CCTL0, SD16INCTL0 e SD16AE.

SD16CTL

Figura SD16CTL
Figura 07 – SD16CTL

Dentre os principais bits podemos destacar:

  • SD16REFON: habilitar a referência interna de 1,2 V;
  • SD16SSELx: seleção da fonte de clock;
  • SD16DIVx: divisor do clock;
  • SD16XDIVx: segundo divisor de clock.

SD16CCTL0

SD16CCTL0
Figura 08 – SD16CCTL0

Dentre os principais bits podemos destacar:

  • SD16SC: bit utilizado para iniciar a conversão (e paralisar no modo contínuo);
  • SD16IE: habilita a interrupção;
  • SD16DF: seleciona o formato de saída da conversão. Offset (positivo) ou complemento de dois (2’s);
  • SD16OSRx e SD16XOSR: controlam a taxa de oversampling;
  • SD16SNGL: conversão simples ou  contínua;
  • SD16UNI: modo unipolar (single-ended) ou diferencial.

SD16INCTL0

Figura SD16INCTL0
Figura 09 – SD16INCTL0

Dentre os principais bits podemos destacar:

  • SD16INCHx: seleciona qual o canal a ser utilizado;
  • SD16GAINx: controla o ganho do PGA interno, de 1x a 32x;
  • SD16INTDLYx: geração de interrupção após quantas conversões.

SD16AE

SD16AE
Figura 10 – SD16AE
  • realiza a conexão do canal com o pino externo.

SD16MEM0

Além disso, utilizamos o registrador SD16MEM0 para ler o resultado das conversões após a interrupção, ou após a verificação do flag via pooling.

Figura SD16MEM0
Figura 11 – SD16MEM0

As configurações completas devem ser verificadas no Users Guide da família MSP430x2xx.

A seguir irei apresentar dois exemplos, um com conversões contínuas na configuração de entrada single-ended, o outro com conversão simples no modo diferencial disparado pela chave S2 da Launchpad. Os exemplos foram desenvolvidos com a IDE Code Composer Studio v8.

Exemplo 1

No primeiro exemplo o SD16_A é configurado para realizar conversões contínuas no modo single-ended utilizando o canal 1 (P1.2 em referência ao GND interno). No loop é dado início na conversão pelo ADC e então a CPU é colocada no modo Low Power Mode 0 (LPM0), sendo acordada/requisitada a cada interrupção gerada pelo conversor ADC. Com todas as amostras salvas a o ADC é paralisado e a CPU volta ao modo normal, finalizando o processamento necessário para então reiniciar o processo.

Cada conversão gera uma interrupção que é tratada em seu respectivo vetor. As amostras são salvas em um array com 32 posições ao mesmo tempo em que cada amostra é acumulada (somada). Ao final do processo calculamos a média das amostras e convertermos o valor para a respectiva tensão na entrada do ADC (float). Como o total de amostras é compatível com a base 2, podemos realizar a divisão através do rotacionamento da variável para direita, neste caso rotacionando 5 vezes para direita.

Os resultados devem ser avaliados através do debuger.

/******************************************************************************
 * SD16_A continuous conversion - single-ended
 * Based on MSP430ware example
 * - MSP430F20x3 Demo - SD16A, Sample A1+ Continuously, Set P1.0 if > 0.3V
 ******************************************************************************
 *
 *                MSP430F20x3
 *             ------------------
 *         /|\|              XIN|-
 *          | |                 |
 *          --|RST          XOUT|-
 *            |                 |
 *    Vin+ -->|A1+ P1.2         |
 *            |A1- = VSS    P1.0|-->LED
 *            |                 |
 *
 * Haroldo Amaral - 2019
 * www.github.com/agaelema
 ******************************************************************************/

#include <msp430.h>
#include <stdint.h>


/******************************************************************************
 * Definitions and macros
 ******************************************************************************/
#define     ADC_GAIN        (1)                             // pga gain
#define     VREF            (double)(1.2)                   // reference voltage
#define     VFSR            (double)((VREF/2.0)/ADC_GAIN)   // full scale range
#define     ADC_BITS        ((1UL << 16) - 1)               // 2^16-1 - unipolar max count
#define     ADC_VBIT        (float)(VFSR/ADC_BITS)          // voltage per bit


/******************************************************************************
 * Variables
 ******************************************************************************/
uint16_t    array[32];              // array to save ADC readings
uint8_t     counter = 0;            // conversion counter
uint32_t    temp = 0;               // temporary variable
uint16_t    average = 0;            // average value
float       Vadc = 0;               // input adc voltage


/******************************************************************************
 * main code
 ******************************************************************************/
int main(void)
{
    WDTCTL = WDTPW + WDTHOLD;		// Stop watchdog timer

    BCSCTL1 = CALBC1_1MHZ;          // Internal clock calibration
    DCOCTL = CALDCO_1MHZ;           // Internal clock calibration

    P1DIR |= BIT0;                  // Set P1.0 to output direction

    /******************************************************************************
     * SD16_A configuration
     ******************************************************************************/
    /* 1.2V ref, SMCLK, div 1x, div 1x */
    SD16CTL = SD16REFON | SD16SSEL_1 | SD16DIV_0 | SD16XDIV_0;
    /* interrupt enable, 1024 OSR, continuous conv, unipolar (single ended) */
    SD16CCTL0 =  SD16IE | SD16OSR_1024 | SD16UNI;
    /* A1 +, gain 1x, interrupt after fourth sample */
    SD16INCTL0 = SD16INCH_1 | SD16GAIN_1 | SD16INTDLY_0;
    /* P1.2 A1+, A1- = VSS */
    SD16AE = SD16AE2;

    while(1)
    {
        SD16CCTL0 |= SD16SC;            // start conversion - continuous conversion
        __no_operation();               // DEBUGER BREAKPOINT

        _BIS_SR(LPM0_bits + GIE);       // go to low power mode 0

        temp = temp >> 5;               // do the average
        average = (uint16_t)temp;
        Vadc = average * ADC_VBIT;      // convert to voltage

        /* reset variables auxiliary variables */
        counter = 0;
        temp = 0;
    }
}


#pragma vector = SD16_VECTOR
__interrupt void SD16ISR(void)
{
    // save and accumulate sample N samples
    if ( counter < (1<<5) )			// 32 samples array
    {
        array[counter] = SD16MEM0;	// save the sample
        counter++;
        temp += SD16MEM0;			// accumulate
    }
    else
    {
        SD16CCTL0 &= ~SD16IFG;      // clear interruption flag
        SD16CCTL0 &= ~SD16SC;       // stop conversion

        LPM0_EXIT;
    }
}

A seguir temos o resultado das conversões quando atingimos um breakpoint colocado em “__no_operation()”. é possível verificar o valor da tensão presente na entrada single-ended, a média das 32 amostras e também os valores do array, plotados no gráfico à direita.

Resultado do Exemplo 1
Figura 12 – Resultado do Exemplo 1

Exemplo 2

No segundo exemplo o SD16_A é configurado para realizar conversões simples no modo diferencial utilizando o canal 2 (V+ em P1.4, V- em P1.5). A CPU é mantida no modo Low Power Mode 0 (LPM0), sendo acordada/requisitada a cada interrupção gerada pelo GPIO P1.3 (conectado a chave S2 da launchpad) e pelo conversor ADC.

Cada vez que a chave S2 é pressionada é gerada uma interrupção que dará início à conversão do SD16_A. Ao final da conversão uma nova interrupção é gerada, sendo tratada em seu respectivo vetor.

O resultado da conversão é convertido na tensão presente na entrada diferencial, caso o valor for maior ou igual que zero o LED1 (P1.0) é setado, caso contrário é resetado, fornecendo um feedback sobre a tensão na entrada.

Neste exemplo é possível uma interação direta sem a necessidade de avaliar os resultados no debugger.

/******************************************************************************
 * SD16_A single conversion - differential
 * - triggered by switch S2 of launchpad (P1.3)
 ******************************************************************************
 *
 *                MSP430F20x3
 *             ------------------
 *         /|\|              XIN|-
 *          | |                 |
 *          --|RST          XOUT|-
 *            |                 |
 *    Vin+ -->|A2+ P1.4         |
 *    Vin- -->|A2- P1.5     P1.0|-->LED
 *            |                 |
 *
 * Haroldo Amaral - 2019
 * www.github.com/agaelema
 ******************************************************************************/

#include <msp430.h>
#include <stdint.h>


/******************************************************************************
 * Definitions and macros
 ******************************************************************************/
#define     ADC_GAIN        (1)                             // pga gain
#define     VREF            (double)(1.2)                   // reference voltage
#define     VFSR            (double)((VREF/2.0)/ADC_GAIN)   // full scale range
#define     ADC_BITS        ((1UL << 15) - 1)               // 2^15-1 - bipolar max count - one bit to signal
#define     ADC_VBIT        (float)(VFSR/ADC_BITS)          // voltage per bit


/******************************************************************************
 * Variables
 ******************************************************************************/
int16_t     temp = 0;               // temporary variable
float       Vadc = 0;               // input adc voltage


/******************************************************************************
 * main code
 ******************************************************************************/
int main(void)
{
	WDTCTL = WDTPW + WDTHOLD;               // Stop watchdog timer

	BCSCTL1 = CALBC1_1MHZ;					// internal clock calibration
	DCOCTL = CALDCO_1MHZ;					// internal clock calibration

    P1DIR |= BIT0;                          // P1.0 as output
    P1OUT &= ~BIT0;                         // reset output

    P1REN |= BIT3;                          // enable internal resistor
    P1OUT |= BIT3;                          // configure resistor as pullup

    P1IE |= BIT3;                           // enable pin interruption
    P1IES |= BIT3;                          // falling edge - high>low
    P1IFG &= ~BIT3;                         // clear flag

    /******************************************************************************
     * SD16_A configuration
     ******************************************************************************/
	/* 1.2V ref, SMCLK, div 1x, div 1x */
	SD16CTL = SD16REFON | SD16SSEL_1 | SD16DIV_0 | SD16XDIV_0;
	/* interrupt enable, 2's format, 1024 OSR, single conv, differential; */
    SD16CCTL0 =  SD16IE | SD16DF | SD16OSR_1024 | SD16SNGL;
	/* A1 +, gain 1x, interrupt after fourth sample */
	SD16INCTL0 = SD16INCH_2 | SD16GAIN_1 | SD16INTDLY_0;
	/* A1+ = P1.2, A1- = P1.3 */
	SD16AE = SD16AE4 | SD16AE5;

	_BIS_SR(LPM0_bits + GIE);				// go to low power mode 0
}


#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
    P1IFG &= ~BIT3;                         // clear flag
    SD16CCTL0 |= SD16SC;                    // Set bit to start conversion
}


#pragma vector = SD16_VECTOR
__interrupt void SD16ISR(void)
{
    temp = SD16MEM0;                        // save SD16 sample
    Vadc = temp * ADC_VBIT;                 // convert to voltage

    if (Vadc >= 0)
    {
        P1OUT |= BIT0;
    }
    else
    {
        P1OUT &= ~BIT0;
    }

    __no_operation();
}

Conclusão

Com estes dois exemplos se tornará mais simples a utilização deste periférico presente em diversos microcontroladores da linha MSP430.

No próximo artigo irei apresentar uma abordagem mais prática, unindo o SD16_A com a comunicação I2C, tornando o MSP430F2013 em um conversor ADC de 16-bit externo com funções programáveis.

Referências

Tearing Into Delta Sigma ADC’s

Delta-sigma ADC basics: Understanding the delta-sigma modulator. 

Pulse Density Modulation

MSP430F2013 product page.

Conversor Delta-Sigma do MSP430

Controlando o SD16A do MSP430F2013 pela I2C
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
5 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Alfonsoff
13/05/2019 14:18

Anexo

Alfonsoff
13/05/2019 14:15

Prezado Dr.Haroldo Amaral, boa tarde! Gostei bastante do seu artigo, parabéns! Possuo a Placa MSP430G2xxx e consegui o MSP430F2013 no intuito de replicar os testes e laboratórios. Suas orientações são bem ilustrativas e me ajudam a melhor compreender esse mundo dos conversores DAC/ADC. Gostaria no entanto de, se possível, solicitá-lo a informação de qual aplicativo/ferramenta foi usada para plotar o gráfico com os valores das saídas do exemplo 1 do artigo acima. Estou aguardando chegar a placa com o conversor ADS1115, para continuar o meu aprendizado com o seu segundo trabalho postado. Mais uma vez, parabéns e sucesso na sua… Leia mais »

Alfonsoff
Reply to  Haroldo Amaral
20/05/2019 16:55

Prezado Prof. Haroldo, muito boa tarde! Consegui plotar o gráfico referente a saída do conversor para o exemplo 1, conforme sua explicação acima. Gostei do trabalho e dos resultados. Aproveito para deixar também os resultados do exemplo 2. Fiz uma pequena alteração para o valor do “if” para a saída Vadc. Uma vez que não entrei no pinos P1.4 e P1.5 com uma tensão simétrica (V+ 0 V-) nas entradas diferenciais. Coloquei P1.4 (+V variável) e P1.5 (GND) e, dado que o ganho do PGA está setado em 1x, coloquei a condição de verificação para a saída de tensão e… Leia mais »

Home » Hardware » Utilizando o conversor Delta-Sigma do MSP430F2013

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: