This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADC Reads Low

Other Parts Discussed in Thread: HALCOGEN

Hello,

We are using the ADC on the RM48 in continuous conversion mode however we seem to get low values read but do not understand why. I have cut back our configuration to have just one enabled channel but we still get low values read, could this be a timing configuration problem that prevents the ADC reading a complete signal each sample period? Our ADC functions are shown below, an initialization routine is called to start conversions then we periodically call adcGetData to grab the latest values. We have a buffer of reorganized values for use in our application which is what we process in the for loop below. Our reference voltage is 3V and we have 12bit conversions set up. With a test input ranging from 0.57V to 2.7V I only see raw counts of 673 to 1222, could this be due to sample periods being insufficient?

#include "adc.h"

/* adc group 0 data array */
adcData_t adcG0_Data_l[UNI_P_L_NUM_ADC_INPUTS];

/* ADC converted data */
float uni_p_l_adc_raw_f[UNI_P_L_NUM_ADC_INPUTS] = {0,0,0,0,0,0,0,0};
uint32 uni_p_l_adc_raw_i16[UNI_P_L_NUM_ADC_INPUTS] = {0,0,0,0,0,0,0,0};



void uni_p_l_in_adc_init(void)
{
	adcInit();
	adcStartConversion(adcREG1, adcGROUP1);

}/* end uni_p_l_in_adc_init */

void uni_p_l_in_adc_read(void)
{
	uint8 i = 0;

	adcGetData(adcREG1, adcGROUP1, adcG0_Data_l);

	for( i=0; i<UNI_P_L_NUM_ADC_INPUTS; i++)
	{
		uni_p_l_adc_raw_f[uni_p_l_adcG0_ch_map[adcG0_Data_l[i].id]] = ((float)(adcG0_Data_l[i].value) / 4096) * 3;
		uni_p_l_adc_raw_i16[uni_p_l_adcG0_ch_map[adcG0_Data_l[i].id]] = ((uint32)(adcG0_Data_l[i].value * 1000)) / 4096 * 3;
	}
}

  • Hi Jamie,

    What are you setting your ADCCLK and Sample time to be during your init sequence? This sounds like the ADC sample caps are not having enough time to charge completely before the conversion takes place.
  • Hello Chuck,

    We had thought it may be something like that but not sure how to increase that via Halcogen. I have been doubling the sample time under the ADC1 > ADC1 Group1 tab but don't see any improvement.  Here is a screenshot of the ADC1 Group 1 tab

  • Jamie,

    What is your system clock setup? i.e., what is VCLK1 from which the ADCCLK is derived? I am curious because to achieve the 1000ns cycle time I see in your picture, the VCLK1 setup would have to be very slow since the cycle time = (ADC Prescalar/VCLK1).

    Did you have similar issues when you use the default values for cycle Time, tSample, tConversion, etc. from the Halcogen tool?

    Another thing to double check is to put a scope on the DC input to check to see if, perhaps, the voltage is somehow changing due to noise or the charging/discharging of caps (filter caps?).
  • Hello Chuck,

    That was my random messing that left us with those timings, I have restored the defaults and the problem remains. We have measured the voltage at the MCU pin and it is correct which is why we have now focussed on the configuration of the ADC driver.

    Or system clock is 20MHz and VCLK1 is 10MHz.


    Jamie
  • Thanks Jamie,

    Have you always had the ADC Cycle time set to 1000 in your testing? Have you tried setting the ADC Prescalar to 0 such that the ADC Cycle time is 100ns and using the default values for the sample and conversion times?

    In the mean time, I'll forward your post to one of our ADC experts so that they may review the issue that you are seeing and provide additional support.
  • Hello Chuck,


    We ran with the defaults for a long time , it was only the other day prior to my first post that I tried chaning timings to see what impact it would have and it appears to have no impact.

    If necessary I can provide you guys with a full zip of our CCS project for debugging, I would prefer to send this by email rather than attach to the post.


    Jamie

  • Hi Jamie,

    I see two issues with the way the ADC is being used here:

    1. Continuous conversion mode: this mode causes the ADC to repeatedly convert the selected channel(s) and store the results in the memory allocated for this group. The group only needs to be triggered once. As you can imagine there are a limited number of memory buffers allocated for each conversion group. This is selected via the "ADC1 Memory" tab in HALCoGen. Once the ADC stores enough conversion results to fill up this allocated memory, it signals an overrun condition and stops storing any further conversion results until this overrun condition is addressed by reading out the conversion results.
    2. Periodic read out of conversion results: this periodic read by the CPU is asynchronous to the ADC operation and could cause overrun conditions at random depending on how frequently you read the results and how quickly the ADC converts.

    I think you are reading older conversion results, hence the mismatch (too low). I would suggest configuring the ADC in single conversion mode and trigger it periodically so that the conversions can be synchronized to the same time base used for the periodic read function. This will make sure that you don't lose any conversion results. Also, you won't run into overrun conditions and memory limitations.

    Regards, Sunil

  • Hello Sunil,

    I have disabled continuous conversion (left 'Enable channel ID in conversion results' selected). for now I am runnign with a single ADC channel to be converted (23). For our 0.59V to 2.7V input we see counts ranging from 666 to 1160 which I think is still incorrect. Here is my single conversion code change:



    /* * uni_p_l_in_adc_init * * Arguments : None * Returns : None * * Initialization routine * */ void uni_p_l_in_adc_init(void) { adcInit(); //adcStartConversion(adcREG1, adcGROUP1); }/* end uni_p_l_in_adc_init */ void uni_p_l_in_adc_read(void) { /* * uni_p_l_in_adc_read * * Arguments : None * Returns : uint32 converted voltage * * Initialization routine * */ uint8 i = 0; adcStartConversion(adcREG1, adcGROUP1); while(!adcIsConversionComplete(adcREG1, adcGROUP1)); adcGetData(adcREG1, adcGROUP1, adcG0_Data_l); /* example of some float and fixed point conversion from cnts to volts */ /* voltage_f = ((float32)adcData10.value / 4096) * 3;*/ for( i=0; i<UNI_P_L_NUM_ADC_INPUTS; i++) { uni_p_l_adc_raw_f[uni_p_l_adcG0_ch_map[adcG0_Data_l[i].id]] = ((float)(adcG0_Data_l[i].value) / 4096) * 3; uni_p_l_adc_raw_i16[uni_p_l_adcG0_ch_map[adcG0_Data_l[i].id]] = ((uint32)(adcG0_Data_l[i].value * 1000)) / 4096 * 3; } }

  • Hi Jamie,

    I have sent you a "friend request". This allows you to share your project with me privately. Can you please send me your zipped CCS project?

    Regards,
    Sunil
  • Jamie,

    I ran your code on an HDK see the correct results. I checked the full range from 0V to 3.0V (my high-reference voltage).

    Can you check the conversion result directly in the memory at address 0xFF3E0040?

    Regards,
    Sunil
  • I'm seeing approx.

    0.57V : 0x00017295
    2.7V : 0x00017494

    For info, the intent of this input is to handle 4-20mA or 0-5V signals. Our input circuit sends in the 0.57V to 2.7V range, outside that range would be considered sensor fault. This is why i'm not testing from 0V at present. Regardless, we are getting approx 600cnts across the voltage range which cannot be correct.

    Could this be something wrong with the reference votlage pins Vref hi/lo? Should I have something set in the driver for this?

    Thanks

    Jamie
  • Jamie,

    There are two lines of code that use the conversion results:

    uni_p_l_adc_raw_f[uni_p_l_adcG0_ch_map[adcG0_Data_l[i].id]] = ((float)(adcG0_Data_l[i].value) / 4096) * 3;
    uni_p_l_adc_raw_i16[uni_p_l_adcG0_ch_map[adcG0_Data_l[i].id]] = ((uint32)(adcG0_Data_l[i].value * 1000)) / 4096 * 3;

    The last closing bracket on the second line should be placed after the "4096" as on the first line. This is what is causing your voltages to be read as divided-by-3 :-)

    Regards,
    Sunil
  • That change makes no difference. Even the raw counts are lower than expected.

    Our reference voltage is 3V. So the 12bit ADC should give us approx 0.00073V/cnt

    From 0.57 to 2.7V we have 2.13V delta which amounts to magnitude of approx 2917 counts. But the raw conversion read varies from 666 counts to 1166 counts. This cannot be true. Our subsequent calculations based on the raw counts should not be relevant here, it apperas we are not getting full range on our conversion.

    Is there something else I am missing here?

    Jamie
  • Jamie,

    Can you run the ADC internal offset calibration sequence? HALCoGen generates this function for you: adcCalibration

    Please call this function after the adcInit() function and check the contents of the ADCALR register.

    Regards,
    Sunil
  • Hello,

    The CALR register of mibADC1 is now 0x000005D5

    Is the solutions as simple as taking this offset into account in my conversion calculation. Why would it be such a high offset?

    Jamie
  • I just re-read section 19.8.1.2 that states the calibration value in ADCALR is added to any conversion result. I've verified this by removing our load, raw counts now output on the ADC are exactly matching that of ADCALR i.e. 1488

    Still don't see how that helps my situation as the full range voltage change in counts is still going to be same as this is a linear offset. I still won't get 2917 counts of a change?
  • Hi Jamie,

    The adcCalibration routine calculates the inherent offset error of the ADC as an average offset error over four different conversion values: zero, full-scale, and two intermediate values. This error is not expected to be large than +/- 2 counts, as per the part's datasheet.

    It would help us to identify what each of the four conversion results are. You can find this from the conv_val array which is a local variable in the adcCalibration function.

    Do you have another part to test your routine on?

    Regards,
    Sunil
  • Hello Sunil,

    The conv_val arrays is as follows

    [0] 744

    [1] 687

    [2] 3

    [3] 842

    [4] 569

    This was our back up board, we switched them out last week when we started experiencing problems as our other board had an MCU reaching curiously high temperatures (100degC). We attributed this to a failed MCU and the root cause of ADC reads not working albeit a random instance of the temperature issue showing a fault. This MCU is not showing abnormal temps, otherwise seems fully functional.

    So do the calibration results tell us that something is broken?

    JW

  • Jamie,

    The expected values for these 12-bit conversions are:

    [0] 0x955
    [1] 0x6AA
    [2] 0x000
    [3] 0xFFF

    So it looks like the ADC on your part is not working right.

    Regards,
    Sunil
  • Jamie,

    Here are the calibration results I see on a "good" part:

    The sampling time for the calibration conversions is configured via the event group's sample time register. Can you try to increase the sampling time for the event group and repeat your calibration conversions? I do not expect them to get much better, but still worth a shot.

    Regards, Sunil

  • Sunil,

    I increased the EVSAMP setting at line 109 in adc.c to 2 then 16 but the impact on the values is neglible. They are still orders of magnitude different from the numbers you gave.

    So I expect the ADC is for some reason broken. Could you suggest modes of failure from this data or are the possibilities to many to even consider starting to find root cause?

    Jamie
  • Out of curiosity I decided to enable one of the shared ADC pins on ADC 2. It is not our intent to use them but it did show that ADC2 appears to have correct calibration values:

    Altough the values of the calibration seem more in line with your ideal data I still don't seem to get correct values on ADC2 channel[15]. However, I think it is perhaps not worthwhile debugging further until I get new hardware to test on.

  • Jamie,

    That is good news. I think you need to increase the sampling time for the event group in ADC2 to get better calibration results. The AD1IN[23] channel is shared with AD2IN[7], so you have the option to convert the shared channels on ADC2 instead of ADC1. Can you confirm that AD2IN[15] conversion is off even after increasing the sample time for the group used on ADC2?

    Regards,
    Sunil
  • I will test this tomorrow. One question on the sample time - it defaults to 0U; so does that mean a default of 1 ADCLK cycle for sampling and any other setting will be a mutliple thereof?
  • A default register setting of 0 means 2 ADCLK cycles. The formula is (ADGxSAMP + 2) ADCLK cycles.
  • So I received our boards back, fitted with a 144 pin socket to allow easy switching of MCU's and sure enough with a new MCU installed we have correct readings on the ADC - so it looks like the MCU had broken.

    Calibration values are now

    0x955,0x6AD, 0x02, 0xFFF and 0x800 similar to your standard parts.

    I expect it would be sensible to have a diagnostic in our driver that detects the out of range calibration results. Is this the intention of the HALcogen self test routines?

    Jamie
  • Jamie,

    Sorry for not getting back to you sooner on this. The ADC is not expected to have such a large offset error. There must have been some damage to the part that shows this anomaly. You could choose to calibrate the ADC periodically to evaluate if there is a large offset error that has crept in, or if the operating conditions significantly change. However, you should add a limit to how much offset error is okay to correct. The part that was damaged showed a gross error and needs to be removed.

    Regards,
    Sunil