改造体重秤

Weight Scale Hack


Project maintained by lly8877 Hosted on GitHub Pages — Theme by mattgraham

项目简介

我做这个项目的是因为想把身边的普通体重秤变得更聪明一点,能够记录自动记录体重,并且绘制曲线。 这样就能够直观的看到自己体重变化的趋势,对自己的体重状况更加了解了。

技术上,为了实现这个效果,基本思路是每一次用户称重的时候,体重秤就会自动把数据传到远程的服务器保存下来,然后用户可以通过电脑或者智能手机看到直观的体重变化曲线。 费这么大劲要把数据传到云端,是因为在本地记录数据不是很可靠,而且如何显示数据也是很大的问题。 所以这个把数据传到网上,用服务器进行数据的记录,分析和显示的方法应该是比较自然的方案。

总的流程简单来说就是用单片机读出体重,用无线芯片发到云端服务器,在服务器端进行记录和图标的绘制,用户访问网页登陆之后就能看到曲线了。目前的计划是用 Arduino + Electric Imp + Ruby on Rails + Heroku


数字体重计的原理

第一步,想要记录体重,先要搞清现有的体重计原理。现在家里常见的基本都是数字体重计,模拟的体重计可以先不考虑了。在网上搜了一下,体重计的原理有很多,其中这个视频就讲的很简单明了。简单概括就是上边一定有一个压力传感器(load cell)。在我理解就是一形变,阻值就变的电阻,变化量基本和压力成线性关系。

然后买了一个在亚马逊上销量不错的体重计,拆了研究一下里边的原理,看看到底和网上说的原理一样不一样。

拆开的体重秤

果然结构和前边视频里拆的那个差不多,四个压力传感器,每个传感器引出了红黑白三根线,都连接到电路板上。传感器上重量一增加,红和白线之间的阻值就变小,白和黑线之间的阻值就增大。

前排的两个传感器每一个里边还另外有个触碰开关,每个引出两根线。这一定是用来唤醒芯片的。电路板后边是背光板和类似七段式的液晶屏。背光板是蓝色的,显示屏里液晶一改变朝向就遮挡住了蓝光,呈现出黑色的数字。

下边是一些细节图

压力传感器特写

压力传感器

电路板特写

电路板特写

这是电路板背面,液晶屏和背光板

电路板背面,液晶屏和背光板

电路板和液晶屏是用这样一个海绵状的排线连接的

海绵状的排线

到这里数字体重计的几个模块已经很清晰了:电路板上的芯片直接读传感器的电压,然后经过内部的分析处理,驱动液晶屏的13个管脚,显示数字。


Arduino读取体重的方法

目前要想要用单片机读到体重示数,有两个办法:一,是通过读液晶屏驱动管脚的电压来得到最终体重。二,是直接读传感器的阻值,自己用Arduino来算体重。第一个方案直接读液晶屏看起来简单一些,因为涉及到的都是数字量,所以我们先走一号路线。


从液晶屏管脚读示数

先用示波器看看这13个管脚在我们称重的时候都是什么波形呢?

测了两个管脚,大概是这样的波形:

液晶屏管脚波形 这个结果和我最初想象的不一样,我以为这种液晶屏和七段式的LED数码管原理差不多,有一条线选择数字,另外七根线来用高低控制液晶。可是这里液晶屏的电压是阶梯状的,和LED显示屏很不一样。这里找到一个液晶控制芯片的Datasheet很有帮助,里边讲了这种液晶屏的工作原理。

Datasheet里边讲的很清楚了,这张插图尤其说明问题

datasheet中其中一张插图

目前我的理解是液晶屏如果要改变透光性,每一个模子里的液晶两极需要加电压。而且这种液晶不超过阈值电压基本不翻转。由于这种简单的液晶屏由于不需要呈现不同亮度,每一片液晶只要用两根线就能驱动了。屏幕里边的走线分行列两种,每个行列的交叉点就是一块液晶,上边的电压就是当前行列两根线的电压差。这里我说的行列对应了图中的COM和SEG。可以看到左右两个图分别是两个同列(都是SEG0)不同行的(COM0 和 COM1)液晶,加在左边的电压有时候能达到V_LCD,也就是一个能改变液晶性质的阈值电压。右边的达不到这个阈值,因此应该一直是透光的。这里还有一个小细节是液晶一般都需要直流分量是零的电压,因为长期的直流分量会损害液晶。 回到正题,也就是我们要读数的这块液晶上。通过观察发现每个管脚的电压都是在0-3.3V之间变化的。当COM是3.3V,SEG是0V或者COM是0V,SEG是3.3V的时候这个液晶上的电压的绝对值就能到3.3V,相当于被选中。我们只要捕捉到这个瞬间就可以了。于是我们来搭一个简单的电路

这个电路的特点是当SEG管脚输出是0的时候我们转化的输出是高,其他时候是低。COM管脚输出是3.3的时候我们转化的输出输出是低,其他时候都输出高。由于液晶加载的电压是对称的,这样我们就能捕捉到一半液晶被点亮的时刻了。

读LCD的电路

然后照着这个焊了个板子

焊的电路板

然后把液晶的管脚都接出来连到Arduino上。

最终读数据的图

Arduino程序

于是我们已经能让Arduino知道液晶屏的每一个像素点是否被选中了。不过具体这些像素到底对应的是实际数字的哪一笔我们还是不知道。要破解这个疑问,也就是找出行列组合和实际笔画的对应关系,我们有两个事实我们可以借助。第一个是秤空载的时候,示数是0.0。第二个是如果仔细看液晶屏,其实还是能看到一些里边的走线的。最终配合Arduino读数的输出,能够大概猜出液晶屏上每一个像素的行和列的序号。

画在纸上就是这样: 像素对应关系

Arduino程序中加入破解液晶编码的部分, 输出如下:

0011100000
1101110000
0110110000
0101110000
weight: 76.3

到此为止,我们已经精确地读出液晶显示屏的示数了。在我们把它用Electric Imp传到网上前,我们还是也评估一下另一个方案的优略,也就是直接读压力传感器的示数。


直接读压力传感器示数

为什么还要直接读示数呢?通过读液晶屏输出很不错,节省了读模拟电压,数据处理的烦恼。不过要焊的线真的很多,而且想再复制一个的话,必须要用一个完全一样的液晶屏的秤。因此我觉得还是有必要采用直接读实数的方法。

压力传感器的在不受压力的自然状态下阻值是1k,人站上去时候阻值大概变化了1欧左右,也就是千分之一的变化。显然直接测这个变化量是不可能的。又搜了一下怎么测这么小的变化量呢?标准答案是用惠斯通电桥(WheatStone Bridge)。体重秤已经是很成熟的技术了,有很多现成的设计了。在网上随便搜一把就能找到不少芯片和设计电路。比如这个TI的ADS1234/1232专门就是做这种传感器电桥的ADC采样的。不得不说TI做的这一套东西真的是太齐全了,连加小电容的考虑分析以及如何布线,模拟地数字地如何分开都手把手的教,就用它了吧。用电阻传感器两两搭出电桥来,两臂接这个ADS1234上,然后用Arduino读。程序在这里。现在我们首先大概假设体重传感器的阻值变化是线性的,然后导致的电桥臂上的电压变化也是一定的。ADC读出来的数字减去零点的电压再乘以一个系数基本就是最终体重了。初步的结果不是很乐观,数据抖动非常大

抖动的数据 横轴是单位是10ms,最大的2500代表25秒。纵轴单位是千克。下边两条曲线是左边两个传感器的重量和,和右边传感器的重量和。可以看出人在站称上左右的中心的移动还是很明显的。

我们现在需要用低通平滑一下这些数据。于是还是按照TI给的参考设计电路加上电容,然后并且在Arudino的程序中取平均,这样得到的结果就好多了,可以看到最上边浅蓝色的经过Arduino平滑之后的曲线基本上很平了。(画曲线的Matlab代码在) 平滑的数据

平滑过后之后结果的标准差基本上在0.04kg左右,这样就基本能确定精确到100g了.

这是直接读传感器阻值的照片,线减化了不少。如果把电路放到秤里排线也可以省了。 直接读传感器

其实现在我们还留下了不少疑问。比如如何知道压力传感器的零点阻值没有漂移呢?如何知道压力传感器的线性变化范围呢?这些问题我们到后边再来解决。

到这里我们自己用单片机度数也就基本告一段落了,剩下还需要完善的地方还很多,比如平均的算法现在收敛的太慢,需要5秒,而且单片机还没有休眠机制(秤上的触碰开关没有利用上)。还有秤的结果校准问题也没有完全弄清楚。不过据我实际测试,至少每一次的误差都在0.1kg以内,核心的功能算是告一段落了。下边我们还是继续推进,让数字能够在本地显示,并且传到远程服务器绘制图表。

未完待续


参考资料

0.Withings的体重计fitbit的aria体重计

1.数字体重计原理视频

2.讲了液晶屏原理液晶屏驱动Datasheet

3.TI 电桥传感器芯片ADS1234/1232参考电路设计


代码和电路图 (都在项目目录下)

1.读LCD的辅助电路(Eagle文件)

2.读LCD示数的Arduino程序

3.读传感器的Arduino程序

4.分析数据的MatLab程序