Lesson 008: Basic ADC

The S7G2 chip has a built in 12-bit ADC with 16 to 25 channels, up to 6 sample and hold circuits, up to 6 programmable gain amplifiers, and up to 6 analog comparators. The ADC runs up to 60MHz, allowing signals up to 30MHz to be sampled. It’s accuracy however is not fantastic.

When not using the sample and hold circuitry, channels AN000 to AN006 have an absolute accuracy of ±4.5LSB. Using a reference voltage of 3.3V, this corresponds to ~3.625mV.

ADCAbsoluteAccuracy_AN000toAN006

Channels AN016 to AN021 have an absolute accuracy of ±7.5LSB. Using a reference voltage of 3.3V, this corresponds to ~6.042mV.

While the accuracy of the integrated ADC may not be great, it is sufficient for many applications, and you get 16-25 channels for free. If you need more accuracy, you have a few options. First, you can a higher accuracy discrete ADC. Second, you can employ some digital signal processing (DSP) to increase the accuracy (taking several samples then taking their average is one simple way, see Texas Instruments Application Note titled Oversampling the ADC12 for Higher Resolution for more information).

To get started with the ADC, you will need to add a few drivers to your application.

First, add a UART and Timer driver and set them up the same as previous lessons. Next, add an ADC driver with the following settings (only changes from the default are shown):

Module > Resolution: 12-bit
Module > Mode: Continuous Scan
Channel Scan Mask > Channel 0: Use in Normal/Group A
Channel Scan Mask > Channel 1: Use in Normal/Group A
Channel Scan Mask > Temperature Sensor: Use in Normal/Group A
Channel Scan Mask > Voltage Sensor: Use in Normal/Group A

In this, we are using the on-chip temperature sensor and the built a built in voltage reference. The voltage reference is NOT the reference voltage for the ADC however.

To convert the temperature from volts to degrees C, you have to look up the specifications in the datasheet.

The specified slope is 4.1mV/°C with a voltage of 1.24V at 25°C. To find the actual temperature, you have to account for both the slope and voltage offset. Section 48.3 Using the Temperature Sensor of the datasheet shows how to do this.

From this section, the temperature equals:

T = (Vs – V1)/slope + T1
T: Measured temperature (°C)
Vs: Voltage output by the temperature sensor when temperature is measured (V)
T1: Temperature experimentally measured at one point (°C)
V1: Voltage output by the temperature sensor when T1 is measured (V)

Vs = Measured voltage from ADC
T1 = 25°C
V1 = 1.24V
slope = 4.1mV/°C

TempEqu1

TempEqu2

UPDATE

In previous versions of this page, I had said that the above equation was incorrect and that you actually needed to subtract 25°C. However, unknown to me, there was a bug in the SSP v1.1.0 that was causing erroneous temperature readings. The bug caused the temperature voltage to track the ADC channel 0 (potentiometer in the DK) causing me to incorrectly offsetting the temperature reading (subtracting 25°C put the temperature at a “reasonable” point based on the position of the potentiometer).

 

In this lesson, we will be printing out several voltages to the UART device.

These include the on-board potentiometer, the integrated temperature sensor, and the integrated voltage reference.

The potentiometer will be on channel 0 of the ADC (as given in the datasheet for the development kit), the temperature sensor is on channel 28, and the voltage reference on channel 29.

When initially reading the datasheet, the text is written in such a way as to make you think the temperature sensor and voltage reference are recorded after the last configured ADC channel. This led me to believe that the temperature would be on channel 1, and the voltage reference on channel 2 (since we are only using channel 0 of the ADC).

Although I think it’s a good idea to keep the temperature sensor and voltage reference on fixed channels (that way you don’t have to keep track of how many ADC channels are in use, and remember to add to get the temperature/reference readings). However, it would be nice if the datasheet were explicit saying that the temperature sensor is fixed to channel 28 and the voltage reference is fixed at channel 29.

To start things off, we will create a couple of #defines so we don’t need to use “magic strings” in our code.

At the top of our hal_entry.c, put the following definitions:

#define POT_CHANNEL 0
#define TEMP_CHANNEL 28
#define INTERNAL_VREF_CHANNEL 29

We will also need a few variables to hold our ADC data, converted voltages, and temperature value.

At the start of our hal_entry(), place

 // Variable to hold ADC Data
 uint16_t adcCounts;
 uint16_t temperatureCounts;
 uint16_t internalVRefCounts;
 float adcVoltage;
 float temperatureVoltage;
 float temperatureDegreesC;
 float temperatureDegreesF;
 float internalVRefVoltage;

At some point, we need to open our ADC and configure it the scan mode. Since we are using continuous scan, we only need to call scanStart once before our main loop.

Something I’ve been puzzled over for the last week is that the integrated temperature sensor started changing it’s value with the potentiometer. When I originally wrote this article, this didn’t happen. I recently upgraded to the SSP v1.1.0 and noticed this problem. At first, I thought it was me, or the code, or the hardware. I informally raised the issue with Renesas (IE: I spoke with an FAE but did not submit a bug report) as I was trying to confirm the bug. Just this morning as I was getting ready to submit this lesson code to Renesas and open a bug report, Josh left me a comment with the reported bug and workaround.

This bug has been fixed in SSP v1.1.3.

Thanks Josh for showing me I wasn’t losing my mind or that I hadn’t broke my hardware!

// Open the ADC
g_adc.p_api->open (g_adc.p_ctrl, g_adc.p_cfg); 

// Configure Scan
 g_adc.p_api->scanCfg (g_adc.p_ctrl, g_adc.p_channel_cfg);

// Work around for temperature reading in Scan Mode. Thanks Josh! (http://en-eu.knowledgebase.renesas.com/English_Content/Renesas_Synergy%E2%84%A2_Platform/Renesas_Synergy_Knowledge_Base/ADC_Temperature_Sensor_Issue-_S7G2)
adc_sample_state_t tempsensor_sample_state = {ADC_SAMPLE_STATE_TEMPERATURE, 0x80};
g_adc.p_api->sampleStateCountSet(g_adc.p_ctrl, &tempsensor_sample_state);

// Start ADC Scan
g_adc.p_api->scanStart (g_adc.p_ctrl);

Inside our main loop, we read the ADC values and also perform the conversion from ADC counts to voltages, and finally convert the temperature from volts to degrees C.

// Read ADC
 g_adc.p_api->read (g_adc.p_ctrl, POT_CHANNEL, &adcCounts);
 g_adc.p_api->read (g_adc.p_ctrl, TEMP_CHANNEL, &temperatureCounts);
 g_adc.p_api->read (g_adc.p_ctrl, INTERNAL_VREF_CHANNEL, &internalVRefCounts);

// Convert Counts to Voltage
 adcVoltage = ((adcCounts * 3.3f) / 4095.0f);
 temperatureVoltage = ((temperatureCounts * 3.3f) / 4095.0f);
 internalVRefVoltage = ((internalVRefCounts * 3.3f) / 4095.0f);

// Convert Voltage to Degrees C and Degrees F
 temperatureDegreesC = (float)(((temperatureVoltage - 1.24f) / 0.0041f) + 25.0f);
 temperatureDegreesF = (float)(((temperatureDegreesC * 9.0f) / 5.0f) + 32.0f);

The rest of the code (full source code on GitHub) prints the values out to the UART device, waits 100ms, then starts all over again.

 

Advertisements

5 thoughts on “Lesson 008: Basic ADC

  1. There is a problem with reading the temperature sensor in SSP 1.1.0, at least in scanning mode:

    http://en-eu.knowledgebase.renesas.com/English_Content/Renesas_Synergy%E2%84%A2_Platform/Renesas_Synergy_Knowledge_Base/ADC_Temperature_Sensor_Issue-_S7G2

    Thanks for blogging about Synergy, Eric!
    Some of the UART stuff was helpful while testing serial interface hardware on my S7G2-Board.
    Since I’m somewhat stuck with the SD-Card interface, I’m happy to see that you plan to blog about that as well.

    Like

    1. Thanks for the link Josh, I was about to submit a formal bug report with sample code!

      I’ve updated the blog page with the fix (but have not implemented it yet in the Git repo, I’ll do that tonight.

      Now that the ADC issue is resolved (I’ve spend about a week trying to find out exactly where the bug was and how to get around it), I’m now free to move on. I’ve had some other requests for the SD-CARD/SPI stuff, so I’ll try to write something up this weekend on it.

      Thanks for reading!

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s