According to the nRF51822 PS v3.1, table 51, offset error for the internal ADC is up to 2% and the gain error can be up to 2%. Is it possible to correct this error to obtain better accuracy for the ADC?
According to the nRF51822 PS v3.1, table 51, offset error for the internal ADC is up to 2% and the gain error can be up to 2%. Is it possible to correct this error to obtain better accuracy for the ADC?
Hi stefan, Does the nRF52840 have a memory address that can be read the gain error and offset error numbers for ADC calibration?
The above sample code doesn't look good to me. I suspect it falls to the 3rd case below.
C99 6.3.1.3 Signed and unsigned integers
When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.49)
Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.
A proposed alternative:
int8_t offset_error = *(int8_t*)0x10000024;
int8_t gain_error = *(int8_t*)0x10000025;
Hello,
after this thread is already 8 years old, have there been some changes with offset and gain error calculations?
Does ADC already work with the stored error values automatically or does it still be have to be applied manually?
I am asking this because measurement seems to be more accurate if the errors are not calibrated to the measurement calculation.
for explanation:
I have a signal to be measured, it is in the range of 10-30mV. Depends a little bit on the PCBA and components used,
as we are measuring the voltage drop across a MOSFET device. We apply 1A to the output and measure the Voltage
across the MOSFET (same goes for a measurement of a voltage drop over a resistor).
So if I use our FLUE TRMS, I can read values of ~23-24mV on the PCB Testpoints.
A) Now if I use this code to measure the voltage, it gets me a value of ~32mV. (already tried to implement a TRMS calculation)
note: "1.171875" is the calculated value of the ADC to mV conversion (1200/1024). the voltages are measured, calculated,
squared (voltage_squared) and summed until the "SAMPLES_IN_BUFFER" value is reached - in this case 20. Then the sum (sum_squares)
is divided through the amount of samples taken (SAMPLES_IN_BUFFER) and from this value the square root is calculated:
void get_fetstate_voltage(void) { U_STATE = 0; float voltage = 0; float sum_squares = 0; float voltage_squared = 0; float mean_squares = 0; for (int i = 0; i < SAMPLES_IN_BUFFER; i++) { nrf_delay_ms(1); nrf_drv_adc_sample_convert(&ADC_U_STATE, &adc_buffer[i]); voltage = adc_buffer[i] * 1.171875; voltage_squared = voltage * voltage; sum_squares += voltage_squared; } mean_squares = sum_squares / SAMPLES_IN_BUFFER; U_STATE = sqrt(mean_squares);
void get_fetstate_voltage(void) { U_STATE = 0; float voltage = 0; float sum_squares = 0; float voltage_squared = 0; float mean_squares = 0; static uint32_t ficr_value_32; static int8_t offset_error; static int8_t gain_error; ficr_value_32 = *(uint32_t*)0x10000024; offset_error = ficr_value_32; gain_error = ficr_value_32 >> 8; for (int i = 0; i < SAMPLES_IN_BUFFER; i++) { nrf_delay_ms(1); nrf_drv_adc_sample_convert(&ADC_U_STATE, &adc_buffer[i]); voltage = adc_buffer[i] * (ADC_RES_10BIT + gain_error) / ADC_RES_10BIT + offset_error - 0.5; voltage = voltage * 1.171875; voltage_squared = voltage * voltage; sum_squares += voltage_squared; } mean_squares = sum_squares / SAMPLES_IN_BUFFER; U_STATE = sqrt(mean_squares); }
void get_fetstate_voltage(void) { U_STATE = 0; float voltage = 0; static uint32_t ficr_value_32; static int8_t offset_error; static int8_t gain_error; ficr_value_32 = *(uint32_t*)0x10000024; offset_error = ficr_value_32; gain_error = ficr_value_32 >> 8; nrf_drv_adc_sample_convert(&ADC_U_STATE, &adc_buffer[0]); // get HE current U_STATE = adc_buffer[0] * (ADC_RES_10BIT + gain_error) / ADC_RES_10BIT + offset_error - 0.5; U_STATE = U_STATE * 1.171875; }
void get_fetstate_voltage(void) { U_STATE = 0; float voltage = 0; nrf_drv_adc_sample_convert(&ADC_U_STATE, &adc_buffer[0]); U_STATE = adc_buffer[0] * 1.171875; }
Hello,
I am sorry, but we are short staffed this week due to Public Holidays in Norway. We will be back on Monday 22nd and hope to be able to answer all incoming requests within a couple of days, depending on the backlog. I am sorry for the inconvenience.
Best regards,
Edvin
Hi Philip,
Could you please open a new case for your topic? This will both increase the likelihood of someone on the forum answering your question, as it shows up as a new case, and help us with case separation of old and new cases.
Kind regards,
Andreas