Project

Ambient Light Monitor: Understanding and Implementing the ADC

August 05, 2015 by Robert Keim

Part 2 in the "How to Make an Ambient Light Monitor" Series. Our smart ambient light monitor will need to digitize and analyze signals from an optical detector, so it is time to explore the EFM8’s integrated analog-to-digital conversion functionality.

Part 2 in the "How to Make an Ambient Light Monitor" Series

Recommended Level

Beginner/Intermediate

Previous Articles in This Series

Required Hardware/Software

Description Quantity Digi-Key p/n
Breadboard 1 377-2094-ND
Receptacle-to-plug jumper wires 3 1471-1231-ND
100 kΩ resistors 2 100KQBK-ND

Project Overview

Our smart ambient light monitor will need to digitize and analyze signals from an optical detector, so it is time to explore the EFM8’s integrated analog-to-digital conversion functionality. It is tempting to treat the ADC as a magic box that seamlessly transforms an analog voltage signal into a binary number whenever we flip the right bit in the ADC control register, but that sort of superficial approach is risky. In engineering as in life, a thorough and thoughtful understanding of the matter at hand is insurance against subtle, evasive problems down the road. So this project will serve as a guide to using the EFM8’s onboard ADC and understanding its architecture and signal interface.

There is more than one way to turn a voltage into a sequence of bits in a register. Common ADC options include the pipeline, sigma-delta, and successive approximation register (SAR) topologies. The EFM8’s ADC is of the SAR variety. This architecture could be described as “general purpose.” Sigma-delta ADCs are favored for very-high-resolution applications, and pipelined ADCs offer higher sampling rates. SAR ADCs are appropriate for medium-to-high resolution and medium-to-high sampling rates, and they are often integrated into microcontrollers because this architecture is compact and compatible with low-power designs. A simplified SAR functional diagram is the following:

The ADC register starts with the most significant bit logic high and the rest logic low, so that the DAC initially produces a voltage that is one-half of the reference voltage. The MSb is kept high or set low depending on the output of the comparator, and this process repeats through all the bits until the ADC register value corresponds to the analog input voltage. The most important things to take away right now are (1) that the ADC is synchronous—one register bit is updated for every cycle of the input clock—and (2) that the analog input voltage is stored in a sample-and-hold circuit during the SAR procedure.

ADC Timing

Consider the following timing diagram for the EFM8’s ADC:

Two modes are represented here: “delayed tracking mode”  and “normal mode.” We will be using normal mode in this project, and delayed tracking mode is discussed briefly in the conclusion of this article. In this case a conversion is initiated by writing one to the ADBUSY bit (there are other ways to start a conversion), and the conversion procedure is then governed by the SAR clock. This diagram should help you to understand that there is no simple answer to “how long does a conversion take” or “what is the maximum sample rate.” The duration of the conversion process is determined by the frequency of the SAR clock and whether the ADC is configured for 8, 10, or 12 bits, and the maximum sample rate is influenced by the conversion duration and how much tracking time is provided before the conversion procedure begins.

Tracking Time vs. Settling Time

The EFM8 incorporates only one ADC module, but this one ADC module can be connected to one of 20 different port pins by setting the appropriate bits in the register that controls the analog multiplexer. You can also connect the ADC to various internal signals, such as ground, VDD, and the output of an integrated temperature sensor. This valuable multiplexer feature greatly enhances the flexibility and usefulness of the ADC, but it also leads to an important issue: settling time. Consider the following diagram representing the ADC’s input stage:

When the multiplexer closes the connection between a particular pin and the ADC input circuitry, the analog voltage at the pin starts to charge the sampling capacitor through the multiplexer resistance. In other words, the actual signal presented to the ADC is an exponentially increasing voltage governed by the RC time constant of the input stage. If you initiate the conversion process too soon after setting the multiplexer, the conversion result will be too low. This problem gets worse if you have significant resistance in series with the ADC input pin, because this contributes to the total input resistance and makes the voltage on Csample rise more slowly toward the final value. “Settling time” refers to how long it takes for the input voltage to reach the final value, and “tracking time” refers to how long you allow the voltage to settle before initiating a conversion. Clearly, then, if you want an accurate measurement, the tracking time must exceed the settling time.

The objective of this project is to perform analog-to-digital conversions in such a way as to demonstrate the effect of ADC settling time. We are using a breadboard, some terminated jumper wires, and two resistors, as follows:

The jumper wires are connected to the appropriate pins on the expansion header:

This simple circuit sends a steady 1.65 V to the ADC. The large resistors facilitate our analysis by exaggerating the effect of the ADC input capacitance.         

Port I/O

The port I/O configuration is the same as what we used in the previous article, except that P1.1 is configured as an analog input.

Peripherals and Interrupts

SPI is configured as in the previous article. Timer4 is again used for short delays (on the order of microseconds), and now we also have Timer3 for long delays (on the order of milliseconds or seconds).

We need to enable the integrated low frequency oscillator (abbreviated LFOSC) if we want it to serve as the clock source for Timer3.

The ADC is enabled and configured as follows:

We are using the EFM8’s internally generated reference voltage, set to 2.4 V:

The SPI interrupt is enabled because SPI transfers are governed by a state machine in the SPI interrupt service routine. The interrupt fires after each byte is transmitted. For this project we also enable the “ADC0 conversion complete interrupt.” As you might have guessed, this interrupt indicates that the ADC register holds a new conversion value that is ready to be processed. 

Firmware

The new firmware in this project consists of a simple interrupt service routine for the ADC and code in “AmbientLightMonitor_main.c” that we use to control the ADC and process conversion values.


ADCFactor = (float)ADC_VREF_MILLIVOLTS/ADC_2POWER10;

for(delay = 0; delay < 16; delay++)
{
	//connect the ADC input to ground
	SFRPAGE = ADC0_PAGE;
	ADC0MX = ADCMUXIN_GND;

	//delay about 20 us
	SFRPAGE = TIMER4_PAGE; TMR4L = 0; while(TMR4L < 40);

	//connect the ADC input to P1.1 and initiate a conversion
	/*the delay between setting the multiplexer and 
        starting the conversion increases with each loop iteration*/
	SFRPAGE = ADC0_PAGE;
	ADC0MX = ADCMUXIN_P1_1;
	SFRPAGE = TIMER4_PAGE; TMR4L = 0; while(TMR4L < delay);
	SFRPAGE = ADC0_PAGE;
	ADC0CN0_ADBUSY = START_CONV;

	//wait until the conversion is complete
	while(ADC_CONV_COMPLETE == FALSE);
	ADC_CONV_COMPLETE = FALSE;

	//Retrieve the 10-bit ADC value, convert it to a voltage amplitude, and display the measurement
	SFRPAGE = ADC0_PAGE;
	RawADCResult = ADC0;

	ADCMeasurement = RawADCResult*ADCFactor;

	ConvertMeasurementandDisplay(VOLTAGE, ADCMeasurement);

	//delay for about 1 second
	SFRPAGE = TIMER3_PAGE; TMR3 = 0; while(TMR3 < 10000);
}


AmbientLightMonitor_Part2.zip

The purpose of this code is to repeatedly sample the input voltage, with each sample allowing more time between setting the multiplexer and initiating the conversion. Before each conversion, the multiplexer is first configured for a ground connection to discharge any voltage on Csample. The first conversion uses the minimum possible tracking time, because the conversion is initiated immediately after setting the multiplexer for P1.1. The next 16 conversions are performed in a for loop, and the tracking time increases by about 500 ns with each iteration. Each measurement is displayed on the LCD after applying the standard formula for interpreting ADC values as physical measurements:

A one-second delay is included after each conversion so that we have time to observe and ponder the measurements.  

Analysis

First we will use LTSpice to predict the voltage on Csample, assuming our circuit is the following:

Here are the results:

As expected, we have an exponentially increasing voltage that approaches the nominal value of 1.65 V according to the overall RC time constant of the circuit. Now let’s run the firmware (refer to the video below). We see that the displayed measurement gradually increases as the tracking time increases; the first measurement is 1.04 V because the voltages below this level occur during the unavoidable delays involved in executing CPU instructions and synchronizing with the SAR logic. Your intuition should be saying “exponential growth” as you observe that the amount of increase from one measurement to the next gradually decreases over time. If we plot the 17 measurements assuming a time step of 490 ns between samples, we get the following:

It is pleasing to see that the shape of the curve corresponds to exponential growth. However, in the measured data, the time required to increase from 1 V to 1.6 V is about 4 µs, whereas the simulation predicts 640 ns. Why the major discrepancy? First, the ADC input stage used in the simulation is based on ideal values and does not take into account additional sources of impedance. An application note from Silicon Laboratories indicates that a more realistic model for the ADC input stage is 5 kΩ in series with 10 pF, instead of 550 Ω in series with 5 pF. If we use these values in the simulation, the time difference from 1 V to 1.6 V is 1.4 µs. There is still significant discrepancy between 4 µs and 1.4 µs; to make the experimental and simulated results consistent, we need to include parasitic capacitance external to the ADC module. If we assume 20 pF of stray capacitance from the input pin (this is the value given in the datasheet) and another 2 pF from the connector pad, the PCB trace, or any other sources, we have the following equivalent circuit:

The external capacitance cannot be simply added to the sampling capacitance because the external capacitance is fully charged when the multiplexer closes the switch. Instead, the voltage on Csample rises very quickly as the external capacitance discharges through RMUX, then when the voltage on Csample matches the voltage on Cexternal, the voltage on Csample rises much more slowly than in the previous simulation because the available current must charge 32 pF instead of 10 pF. As indicated by the cursor labels in the next plot, the time required for the voltage to increase from 1 V to 1.6 V is now 3.8 µs, which agrees quite well with our experimental value of approximately 4 µs.

Recap

We successfully implemented the EFM8’s ADC functionality and at the same time explored limitations related to the resistance and capacitance in the ADC’s input stage. The large resistors used in our voltage divider and the effect of external parasitic capacitance remind us that the external circuit influences the settling time. The EFM’s ADC includes a delayed tracking mode (mentioned above) that incorporates a tracking period of 4 SAR clock cycles, but you cannot always rely on delayed tracking mode because this 4-clock delay may not be sufficient when the external circuit contains large amounts of resistance. Thus, precise ADC measurements depend upon understanding how your circuit interacts with the ADC input stage and then ensuring an adequate delay between choosing the ADC input via the multiplexer and initiating a conversion.           

Video

Next Article in Series: Ambient Light Monitor: Measuring and Interpreting Ambient Light Levels

 

Give this project a try for yourself! Get the BOM.

1 Comment
  • Wouter Visee October 29, 2018

    Great article! Helped me a lot to understand the behaviour of the EFM8 ADC. It seems that some register names have changed since this article was published (for example, checking if the ADC is ready is now done by checking the adc interrupt flag, ADC0CN0_ADINT) but with this article and the datasheet it couldn’t be easier.

    Like. Reply