有些DAC芯片中有校准用的寄存器(offset、gain),比如AD5764,而有些ADC芯片则没有,比如ads8689,那么就需要进行人为校准了。其实ads8689的线性度还是非常好的。 校准的时候需要ADC芯片对DAC芯片的输出进行测量,并将反馈结果记录在表中。通过excel中的折线图也可以对比看它们的线性度,之后利用python或者其他语言进行一元线性回归,即可求出k和b的值。 adc列是未校准的测量数据,meter列是高精度万用表的测量数据(以此为准),dac列则是校准过offset与gain寄存器的输出电压,现在通过python就可以很快的求出斜率跟截距了。公式就是最小二乘法。
import pandas as pd import os X = [] Y = [] def get_data(file_name): global X, Y data = pd.read_csv(file_name) X = data['adc'].values Y = data['meter'].values if __name__ == '__main__': proj_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) # 获取上级路径,这里根据个人需求自行修改 file_path = proj_path + r'\Fluke8845A_V1\dist\LCC1_Volt_Test Thu Sep 3 10_34_49 2020.csv' get_data(file_path) Xsum = 0.0 X_2sum = 0.0 Ysum = 0.0 XY = 0.0 n = len(X) for i in range(n): Xsum += X[i] Ysum += Y[i] XY += X[i] * Y[i] X_2sum += X[i]**2 k = (Xsum * Ysum / n - XY) / (Xsum**2 / n - X_2sum) b = (Ysum - k * Xsum) / n print('y = %f*x + (%f)' % (k, b))最后将k与b带入到adc芯片的测量函数中就行了。
float ADS8689_Analog_Digital(void) { static uint16_t temp; static double x; const float w = 3.0; if (mutex == 0) { memset(receive, 0, sizeof(receive)); VOLT_OR_TEMP = 1; CLK_SysTickDelay(100); ADS8689_ReadWrite(ADS8689_NOP, 0x00, 0x0000); ADS8689_ReadWrite(ADS8689_NOP, 0x00, 0x0000); temp = ((uint16_t)receive[0] << 8) + receive[1]; x = (float)((((temp - 32768) * range) * reference_voltage) / 65536); x *= w; if (PD10 == 1) // channel A { x = ((x * 0.999232) - 0.000520363); } else { x = ((x * 0.999240) - 0.000354834); } VOLT_OR_TEMP = 0; mutex = 1; } return x; }最后可以看到,校准后adc与meter之间的误差是很小的,比未校准之前效果好了很多。(这里单位都是mv)