单点多点称重技术,网上搜不到的重点(二):编程要点

上篇帖子主要说道了物理性的硬件方面的东西,当然,那不是全部,还有些可能遇到的情况以后还会慢慢提及。现在开始说编程 

  • 预定义        

为了以后说明方便,先预定义一些需要用到的东西。不过这里没什么好研究的,有经验的坛友也可以通过常量的名字进行望文生义。

#define P_WEIGHT_CLK                                RCC_AHBPeriph_GPIOA

#define P_WEIGHT                                                GPIOA

#define PP_WEIGHT_SDA                                GPIO_Pin_0

#define PP_WEIGHT_SCL                                GPIO_Pin_1

#define PP_WEIGHT_ADRST                        GPIO_Pin_2

#define SDA_0    GPIO_ResetBits(P_WEIGHT, PP_WEIGHT_SDA)

#define SDA_1    GPIO_SetBits(P_WEIGHT, PP_WEIGHT_SDA)

#define SCL_0   GPIO_ResetBits(P_WEIGHT, PP_WEIGHT_SCL)

#define SCL_1   GPIO_SetBits(P_WEIGHT, PP_WEIGHT_SCL)

#define RST_0   GPIO_ResetBits(P_WEIGHT, PP_WEIGHT_ADRST)

#define RST_1   GPIO_SetBits(P_WEIGHT, PP_WEIGHT_ADRST)

  • 取值

ADS1230是一个20bit的ADC芯片,取值前,初始化时,需要先对ADC进行复位,并等待数据就绪。以下的代码只是参考,关于信号脉宽方面的问题,大家自行调试,这个涉及到PCB板整板的特性方面的问题,我无法总而言之。

ADC复位:

RST_0;

Nop(5);

RST_1;

Nop(50);

       等待数据就绪:

uint8 i;

       

while(GPIO_ReadInputDataBit(P_WEIGHT, PP_WEIGHT_SDA)==Bit_SET);

for(i=0; i<26; i++)

{

        SCL_1;

        SCL_0;

}

初始化完成后,我们就可以坐等外中断发生了。一旦发生外中断,我们就赶紧取数。

SCL_0;

                AdWeight = 0;

                for(i=0; i<20; i++)

                {

                        SCL_1;

                        AdWeight <<= 1;

                        SCL_0;

                        if(GPIO_ReadInputDataBit(P_WEIGHT, PP_WEIGHT_SDA)==Bit_SET) AdWeight++;

                }

                for(i=0; i<4; i++) { SCL_1; SCL_0; }

ADC的值被保存在int32类型的变量AdWeight中。对于AdWeight值的含义,我们需要仔细阅读相关手册。这里,小于2.5V的信号会被解释为负值。但是,我们只接收了20bit的值,却放在一个32bit的变量中,这样就成了正值。这不对,我们得处理一下。

if(AdWeight > 0x7ffff) AdWeight |= 0xFFF00000;

  • 处理零抖        

能取值你以为就完事了吗?        

在称重秤上不放任何东西,你会发现,这些值并不固定,完全不是零的样子。

当然这些值不是零的样子!如果多换几个传感器试试,甚至还有可能出现负值,而且至少,你的秤盘自重在传感器上还施加了一个力!

不过这些都不是最可怕的!最可怕的是,这些值会不断地发生变化!

这是什么梗?其实,这也不是什么大梗。做传感器做多了,大抵应该能适应,一些物理量在环境不稳定的时候会出现抖动或漂移。去掉就行了。

去零抖怎么去?天知道取出来的值,是信号抖动,还是称重?        

嗯!没错!天是不知道的,但是你知道!        

我们都可以这样知道:零抖信号的特点就是一不稳定,二不会突变,三是小到一个境界。记住这个原则,你在即时取值的时候,判断并减去,你就会发现,你的称重零的样子,出现了!   

三、标定确定传感器的线性参数

有效去掉零抖后,我们所获得的测值,就纯净多了!接下来,我们就要将ADC的转换值,与实际的重量相对应。这里我们所说的实际重量,不能用随意的重量来制造,我们得用标准砝码。砝码取决于你自己购买,我买的砝码是5kg、10kg、20kg等这样的一组。        

有了砝码,写一段ADC读数代码,再采集一组数,为了便于分析处理,将这组数据输入到EXCEL表格里,如图2-1(参考样例):

图2-1

计算平均值是统计学的一种常态,我就不解释了。        

有了这些数据后,我们就要放大招了。先将各重量的AD值去0kg,如图2-2(参考样例):

图2-2

相信眼尖的人能从这组数据中看到一些欣喜。如果看不到也没关系,我们还可以继续分析。下面我们再看一下对5kg的倍数,如图2-3(参考样例):

图2-3

也许,尽管,我们处理数据,但是我们未必对数据有那么高的兴趣,那么我们就搞各有兴趣的图表看看。为了做图标,我们将图2-3的0数据做一个补全,如图2-4(参考样例):

图2-4

我相信excel能给我们来一张砝码-AD均值分析曲线图,不过我这里截图来自OriginPro,如图2-5(参考样例)。请大家不要指责我excel做图表的失败。

图2-5

再来一张砝码-去0AD均值分析曲线图,如图2-6(参考样例):

图2-6

这图乍一看,线性度很好,这显然值得欣喜。当然,我们体重称重常常只只要0.1kg的精度,如果不吹毛求疵的话,这个欣喜我们可以保持下去,因为我们可以使用公式y=kx+a了。       

对于不同的物理结构装上传感器,k、a值是不一样的。所以我们得为每个产品进行k、a的确定。这个确定的过程在生产上就叫标定。对于线性函数控制的测量自然需要进行两点标定了。我这里选择的是0kg标定与20kg标定。

对于编程而言,保存参数也是一个活儿。建议大家多用一些struct、union的结合,让数据的涵义与字节的操作不至于转换来转换去的。例如,针对斯它姆32的字存储函数,我就定义了如下一个复合类型。

#pragma   pack(2)

typedef union _ycj

{

        struct

        {

                int32 ad20;

                int16 wr;

                int32 ad0;

        } c;

        struct

        {

                uint16 w[5];

        } w;

}ycj;

#pragma   pack(1)

这样做的好处我就不说了。我要说的是,我直接保存的是0kg的AD值与20kg的AD值,然后在初始化的时候,计算一下k,通常a就是ad0了。

当然,如果你要保存一个浮点数也是没有问题的,我相信你也能做到。四、如何在取均值的时候避免除法运算

我们都知道,除法运算是一个坑单片机的运算。如果多个除法运算高频率运用,会让单片机殚精竭虑的。所以消除除法运算很重要。让单片机的CPU使用率降低,对保证单片机各部件运行时序有很大的帮助。       

对于统计求均值的除法运算,是完全可以避免的。例如,你需要取10次求一次均值,你毫无悬念的需要除以10,这无法避免。但是,你可以修改策略。例如,你可以降低一些性能,改为取8求均,这样除以8就可以用右移3位二进制位来完成了。当然,如果你想提高性能,那就取16求均好了,为什么非要用10呢?五、计算重量       

计算重量没什么难事,就是在公式中要处理一下动态的0抖与你可能需要设置的去皮。       

0抖的取值建议使用AD值,而去皮呢?用重量值也挺好的。因为从倍率上将,AD值较为敏感,而重量值则较为稳定。       

重量计算参考公式如下:

Weight = ((double)(AD - AD0 - AD0Shake)) / k - Tare;

六、关于精度        

对于重量的处理,要注意符合精度要求的数字表达形式,例如你可以全部用双精度数来表示所有数字,也可以用整型数处理一部分,用双精度数处理一部分,甚至可以将所有小数以x10的倍率全部转为整形运算。但是无论你是为了方便,或为了速度,你都要保证有效数字不能被丢弃,运算结果不溢出。七、调试中的问题      

由于这是一个线性度很好的传感器,所以调试时主要代码并不有多难,但是这并不表示调试过程会有多简单。因为这是一个跟物理力**系紧密的应用,所以,任何一个制作上的不讲究,都会让你麻烦缠身,甚至焦头烂额。这个时候你一定要保持冷静,思路开阔,不要只想着撸码解决一切。       

常见的问题大致如下:       

1、代码造成的问题,修改代码;       

2、零抖,优化零抖算法;       

3、砝码称重稳定,人多次称重数值不一,检查传感器安装是否可靠,固定螺纹孔是否有很好的同心度与垂直度,秤盘刚性是否足够,如果因为踩踏变形导致传感器承受扭剪力,测值是不可能如一的;       

4、因为秤盘四脚不同面,不水平,都会不同程度的造成测值不准;

5、因为环境有机械振动干扰,会造成测值不稳定;       

6、电磁干扰,会造成测值偏差,甚至是大幅度偏差;       

7、其他原因,有待你自己发现。八、结果展示        

控制好了各个细节,我们就可以坐想其成了。下面是20kg、30kg砝码的测量结果(如图2-7):

图2-7

这是身高体重0.1公斤分辨率下的测试结果。砝码检测,非常准确。当然,人站上去就不一定了,所以一个东西的好坏判断,不能急于下结论,要多实践,问题出在哪里,要能精确定位。
---------------------
作者:yyy71cj
链接:https://bbs.21ic.com/icview-3213960-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值