TA的每日心情 | 衰 2020-11-25 22:49 |
---|
签到天数: 10 天 [LV.3]偶尔看看II
|
本帖最后由 沨の痕 于 2019-12-21 21:23 编辑
起因改明纬拿来充电啥的,淘宝便宜的电压电流表线性太差了
表现为低压低,到某个值后开始一直偏高,是一直继续变大
后来隔壁论坛找到了程序,电压是一直偏低,电流又不准,自己买st/link v2烧录调试,因为本身源码电压部分做了分区,参考下改回来,主要电流,可能是采样不是原程序设计,介绍说用2毫欧采样,我买了2毫欧康铜丝换上,手上4个表头,只有2个能校对电流,校对过程是数值大了康铜丝加锡,小了加大两线距离,另外2个校不了,不知道什么原因,1a下偏低1a上一直加大,换过st358,这里说下358真是坑,买的st358,st258,lm358,LM258,全部显示不一样,按道理分压电阻比例固定显示应该差不多,lm258显示到1A,换st358显示0.4A,st258显示0.8A
下面是源码电流部分,请教下是怎么算的,tmpin这个只说了ad采样,百度过ad值计算也没说,隔壁还有自动校准的源码就是不会搞
电路图R6换成1M
#define u8 unsigned char
#define uchar unsigned char
#define uint unsigned int
#define sCnt 104
uint ms_count, tmpin, ADCBuff[6], ADValueV[sCnt], ADValueI[sCnt], ADCData, mA;
u8 pDataV=0, pDataI=0, vDotPS, cDotPS, VGain = 35, ampGain = 129, vFlag=0, iFlag=0;
unsigned long mV; //uint的话,mV最大只能到 65535mV,本电源80V,故用long
float voltRAW, curtRAW, Rs = 0.00218;
float ADVal_Av[2]={0}, Val_Av[2]={0};
float* Ad_Av(u8 ac) //每次只采样一个数据,采完sCnt个数据就更新结果,否则就显示上一次的结果
{
u8 num, pMaxV=0, pMaxV2=0, pMinV=0, pMinV2=0, pMaxI=0, pMaxI2=0, pMinI=0, pMinI2=0;
if(ac==4){ //电压
ADValueV[pDataV] = Get_Adc(ac);
Val_Av[0] += ADValueV[pDataV++];
}else{ //电流
ADValueI[pDataI] = Get_Adc(ac);
Val_Av[1] += ADValueI[pDataI++];
}
if(pDataV>=sCnt){ //电压数据采样完成,去除最大最小求平均
pDataV=0; vFlag=1;
for(num=0;num<sCnt;num++) {
if(ADValueV[num] < ADValueV[pMinV]) pMinV = num;
if(ADValueV[num] > ADValueV[pMaxV]) pMaxV = num;
}
for(num=0;num<sCnt;num++) { //去掉次大次小
if(num != pMinV && ADValueV[num] < ADValueV[pMinV2]) pMinV2 = num;
if(num != pMaxV && ADValueV[num] > ADValueV[pMaxV2]) pMaxV2 = num;
}
ADVal_Av[0] = (Val_Av[0] - ADValueV[pMinV] - ADValueV[pMinV2] - ADValueV[pMaxV] - ADValueV[pMaxV2])/(sCnt-4);
//ADVal_Av[0] = (Val_Av[0] - ADValueV[pMinV] - ADValueV[pMaxV])/(sCnt-2); //只去掉最大最小的话,用这句
Val_Av[0]=0;
}
if(pDataI>=sCnt){ //电流数据采样完成,去除最大最小求平均
pDataI=0; iFlag=1;
for(num=0;num<sCnt;num++) {
if(ADValueI[num] < ADValueI[pMinI]) pMinI = num;
if(ADValueI[num] > ADValueI[pMaxI]) pMaxI = num;
}
for(num=0;num<sCnt;num++) { //如果还要去掉次大次小的话,就去掉注释
if(num != pMinI && ADValueI[num] < ADValueI[pMinI2]) pMinI2 = num;
if(num != pMaxI && ADValueI[num] > ADValueI[pMaxI2]) pMaxI2 = num;
}
ADVal_Av[1] = (Val_Av[1] - ADValueI[pMinI] - ADValueI[pMinI2] - ADValueI[pMaxI] - ADValueI[pMaxI2])/(sCnt-4);
//ADVal_Av[1] = (Val_Av[1] - ADValueI[pMinI] - ADValueI[pMaxI])/(sCnt-2); //只去掉最大最小的话,用这句
Val_Av[1]=0;
}
return(ADVal_Av);
}
/***** 电流数据处理 ***************************************
tmpin:采集的电流数据;
输出:电流值,单位:A
*********************************************************/
float ProcessCurrent(float tmpin)
{
float Temp;
Temp = tmpin * 3.3 / 1023 / ampGain / Rs; //单位:A
//下面是校正,应根据实际情况重新计算。本例中是将运放的反馈电阻 R6(180k)
//改成 1M后,放大系数ampGain由29变为129。
//取样电阻 Rs约为 2mR。
Temp = 1.385042 * Temp - 1.698751;
if(Temp<0) Temp=0;
return (Temp);
curtRAW = Ad_Av(3)[1]; //获取电流数据
if(iFlag==1){ //电流数据采集完成才进行以下计算,否则跳过,将显示上次数据
iFlag=0;
newData[1] = ProcessCurrent(curtRAW);
Noise_Filter(0.5, 1, preCoef, preTrend, ADvalue, newData);
//ADvalue[1] = newData[1]; //不要上面的滤波时使用
mA = (uint)(ADvalue[1]*1000);
if(mA > 9999){
cDotPS=4;
ADCBuff[3] = mA / 100 % 10; //0.1A
ADCBuff[4] = mA / 1000 % 10; //A
ADCBuff[5] = mA / 1000 / 10; //十A
}else{
cDotPS=5;
ADCBuff[3] = mA / 10 % 10; //0.01A
ADCBuff[4] = mA / 100 % 10; //0.1A
ADCBuff[5] = mA / 1000; //A
}
}
I_Show(3);
//asm("rim"); //开系统总中断,准备下次ADC采样
}
}
|
|