|
以前在X寶上買過一個(gè)稱重放大器,180+大洋。原理基本上就是把橋式拉力傳感器輸出的mV級(jí)信號(hào)放大到5V供單片機(jī)讀取。連接實(shí)驗(yàn)電路的時(shí)候很完美,能
實(shí)現(xiàn)重量的轉(zhuǎn)換,但是實(shí)際組裝后卻發(fā)現(xiàn)這種A/A模塊受到的干擾太嚴(yán)重了,包括電源的干擾,導(dǎo)線長(zhǎng)短的干擾,導(dǎo)線位置變化的干擾,無線電的干擾等等等
等……實(shí)在是惱人。
后來感覺是思路錯(cuò)誤了,就不該用模擬信號(hào)來傳輸,于是決定使用A/D模塊來把重量轉(zhuǎn)換成數(shù)字信號(hào)傳輸,A/D模塊就固定在離傳感器最近的地方,將輸出的數(shù)字信號(hào)用導(dǎo)線傳輸給單片機(jī),這樣能很大程度減小各種干擾。
在網(wǎng)上搜了一下A/D模塊,基本上有兩種廉價(jià)成品:HX711和PCF8591,它們分別是8位轉(zhuǎn)換模塊和24位轉(zhuǎn)換模塊。
PCF8591:
113403yljygeouubgbooyo.png (319.11 KB, 下載次數(shù): 244)
下載附件
2016-1-23 00:58 上傳
功能簡(jiǎn)介: 基于I2C接口的AD/DA轉(zhuǎn)換模塊,8位精度,四通道AD,單通道DA,電壓輸出型
最大特點(diǎn): 1. 支持兩種接口類型接入目標(biāo)板:排針或排座
2. 支持I2C總線級(jí)聯(lián)(通過排針、排座對(duì)接的方法,可同時(shí)使用多個(gè)I2C模塊)
典型應(yīng)用: 低速AD/DA轉(zhuǎn)換
主要資源: PCF8591,I2C接口排針,I2C接口排座,可調(diào)電阻,AD輸入口,DA輸出口,地址跳線端口
HX711:
233501r6766iuo0csk0o1u.jpg (149.81 KB, 下載次數(shù): 225)
下載附件
2016-1-23 00:58 上傳
模塊工作電壓:4.8-5.5v
典型電流 1.6mA
體積:長(zhǎng) 2.9cm * 寬 1.7cm * 高 0.4cm
● 帶金屬屏蔽,強(qiáng)抗干擾,預(yù)留MCU(STC15F104)位置,可自行升級(jí)二次開發(fā)。
● 兩路可選擇差分輸入
● 片內(nèi)低噪聲可編程放大器,可選增益為32、64 和128
● 片內(nèi)穩(wěn)壓電路可直接向外部傳感器和芯片內(nèi)A/D 轉(zhuǎn)換器提供電源
● 片內(nèi)時(shí)鐘振蕩器無需任何外接器件,必要時(shí)也可使用外接晶振或時(shí)鐘
● 上電自動(dòng)復(fù)位電路
● 簡(jiǎn)單的數(shù)字控制和串口通訊:所有控制由管腳輸入,芯片內(nèi)寄存器無需編程
● 可選擇10Hz 或80Hz 的輸出數(shù)據(jù)速率
● 同步抑制50Hz 和60Hz 的電源干擾
● 耗電量(含穩(wěn)壓電源電路):
典型工作電流:< 1.7mA, 斷電電流:< 1μA
● 工作電壓范圍:2.6 ~ 5.5V
● 工作溫度范圍:-20 ~ +85℃
114637shy565thz23nfzfx.jpg (77.27 KB, 下載次數(shù): 229)
下載附件
2016-1-23 00:58 上傳
===============================我叫分割線=================================
我要使用的拉力傳感器為傳統(tǒng)的橋式傳感器,量程1kg,想要達(dá)到1g的精度,這就要求模塊輸出位數(shù)至少為10位(2^10=1024),8位的
PCF8591無法勝任,因?yàn)樗木戎挥?^8=256位。所以決定使用HX711作為我的A/D模塊,而且我選的HX711模塊還帶屏蔽殼,正符合我
的要求。
先來看一下該模塊的常用接法:
114513lmwalwvc5wj1j1j5.jpg (168.8 KB, 下載次數(shù): 208)
下載附件
2016-1-23 00:58 上傳
模擬輸入
通道 A 模擬差分輸入可直接與橋式傳感器的差分輸出相接。由于橋式傳感器輸出的信號(hào)較小,為了充分利用A/D 轉(zhuǎn)換器的輸入動(dòng)態(tài)范圍,該通道的可編程增益較大,為128 或64。這些增益所對(duì)應(yīng)的滿量程差分輸入電壓分別±20mV 或±40mV。
通道B 為固定的32 增益,所對(duì)應(yīng)的滿量程差分輸入電壓為±80mV。通道B 應(yīng)用于包括電池在內(nèi)的系統(tǒng)參數(shù)檢測(cè)。
供電電源
數(shù)字電源(DVDD)應(yīng)使用與MCU 芯片相同的的數(shù)字供電電源。HX711 芯片內(nèi)的穩(wěn)壓電路可同時(shí)向 A/D
轉(zhuǎn)換器和外部傳感器提供模擬電源。穩(wěn)壓電源的供電電壓(VSUP)可與數(shù)字電源(DVDD)相同。穩(wěn)壓電源的輸出電壓值(VAVDD)由外部分壓電阻
R1、R2 和芯片的輸出參考電壓VBG
決定(圖1),VAVDD=VBG(R1+R2)/R2。應(yīng)選擇該輸出電壓比穩(wěn)壓電源的輸入電壓(VSUP)低至少100mV。
如果不使用芯片內(nèi)的穩(wěn)壓電路,管腳VSUP應(yīng)連接到DVDD 或AVDD 中電壓較高的一個(gè)管腳上。管腳VBG 上不需要外接電容,管腳VFB
應(yīng)接地,管腳BASE 為無連接。時(shí)鐘選擇如果將管腳 XI 接地,HX711
將自動(dòng)選擇使用內(nèi)部時(shí)鐘振蕩器,并自動(dòng)關(guān)閉外部時(shí)鐘輸入和晶振的相關(guān)電路。這種情況下,典型輸出數(shù)據(jù)速率為10Hz
或80Hz。如果需要準(zhǔn)確的輸出數(shù)據(jù)速率,可將外部輸入時(shí)鐘通過一個(gè)20pF 的隔直電容連接到XI管腳上,或?qū)⒕д襁B接到XI 和XO
管腳上。這種情況下,芯片內(nèi)的時(shí)鐘振蕩器電路會(huì)自動(dòng)關(guān)
閉,晶振時(shí)鐘或外部輸入時(shí)鐘電路被采用。此時(shí),若晶振頻率為11.0592MHz, 輸出數(shù)據(jù)速率為準(zhǔn)確的10Hz
或80Hz。輸出數(shù)據(jù)速率與晶振頻率以上述關(guān)系按比例增加或減少。使用外部輸入時(shí)鐘時(shí),外部時(shí)鐘信號(hào)不一定需要為方波�?蓪CU
芯片的晶振輸出管腳上的時(shí)鐘信號(hào)通過20pF 的隔直電容連接到XI管腳上,作為外部時(shí)鐘輸入。外部時(shí)鐘輸入信號(hào)的幅值可低至150mV。
串口通訊
串口通訊線由管腳PD_SCK 和DOUT 組成,用來輸出數(shù)據(jù),選擇輸入通道和增益。當(dāng)數(shù)據(jù)輸出管腳DOUT 為高電平時(shí),表明
A/D 轉(zhuǎn)換器還未準(zhǔn)備好輸出數(shù)據(jù),此時(shí)串口時(shí)鐘輸入信號(hào)PD_SCK 應(yīng)為低電平。當(dāng)DOUT 從高電平變低電平后,PD_SCK 應(yīng)輸入25 至27
個(gè)不等的時(shí)鐘脈沖(圖二)。其中第一個(gè)時(shí)鐘脈沖的上升沿將讀出輸出24 位數(shù)據(jù)的最高位(MSB),直至第24 個(gè)時(shí)鐘脈沖完成,24
位輸出數(shù)據(jù)從最高位至最低位逐位輸出完成。第25至27 個(gè)時(shí)鐘脈沖用來選擇下一次A/D 轉(zhuǎn)換的輸入通道和增益,參見表三。
114746w2jwooj4cew4d99o.jpg (28.18 KB, 下載次數(shù): 235)
下載附件
2016-1-23 00:58 上傳
PD_SCK 脈沖數(shù)輸入通道 增益
114820jxy141ixdiee34e4.jpg (63.93 KB, 下載次數(shù): 234)
下載附件
2016-1-23 00:58 上傳
時(shí)序圖
PD_SCK 的輸入時(shí)鐘脈沖數(shù)不應(yīng)少于25 或多于27,否則會(huì)造成串口通訊錯(cuò)誤。當(dāng)A/D 轉(zhuǎn)換器的輸入通道或增益改變時(shí),A/D 轉(zhuǎn)換器需要4 個(gè)數(shù)據(jù)輸出周期才能穩(wěn)定。DOUT 在4 個(gè)數(shù)據(jù)輸出周期后才會(huì)從高電平變低電平,輸出有效數(shù)據(jù)。
==============================我也是分割線================================
好了,看了這么多原理很多人一定已經(jīng)暈了,下面來簡(jiǎn)單的:HX711在Arduino上的使用!
經(jīng)過各種搜索,僅僅在Google Project上找到了一個(gè) phk@FreeBSD.ORG 寫的 Arduino 庫(感謝�。。δ芎芡晟�,而且支持多版本的Arduino。
我備份在這里吧,以免以后找不到:
hx711-arduino-v0.01.tar.gz
(1.3 KB, 下載次數(shù): 179)
2016-1-23 00:59 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
再來看一下接線:
115526uh8es1vuwu11ob4x.jpg (76 KB, 下載次數(shù): 242)
下載附件
2016-1-23 00:58 上傳
1. VCC 可以是 2.6-5.5 中的任意值,因?yàn)槲覀兪褂玫氖?Arduino ,所以直接5V供電,GND 接地。
2. SCK 接 Arduino 的 Pin 9,DT 接 Pin10,這兩個(gè)接腳可以在程序中改變。
3. E+、E-、A+ 和 A- 分別接橋式傳感器的:激勵(lì)電壓正、負(fù),輸出電壓正、負(fù)
(E+ 接紅線;E- 接黑線;A+ 接綠或藍(lán)線;A- 接白線)。
4. B+ 和 B- 接通道B的傳感器,也可以通過分壓電路接電源,用來檢測(cè)電源電壓。不用的話最好接GND,不過我試驗(yàn)不接也沒問題。
在 Arduino 中打開示例代碼,可以看到非常簡(jiǎn)單:- #include <HX711.h> // 包含庫的頭文件
- HX711 hx(9, 10); // 數(shù)據(jù)接腳定義
- void setup() {
- Serial.begin(9600);
- }
- void loop()
- {
- double sum = 0; // 為了減小誤差,一次取出10個(gè)值后求平均值。
- for (int i = 0; i < 10; i++) // 循環(huán)的越多精度越高,當(dāng)然耗費(fèi)的時(shí)間也越多
- sum += hx.read(); // 累加
- Serial.println(sum/10); // 求平均值進(jìn)行均差
- }
復(fù)制代碼 給的示例程序非常簡(jiǎn)單,但是我查看庫中含有很多示例沒有給出的函數(shù):- HX711(byte sck, byte dout, byte amp = 128, double co = 1); // 定義 sck、dout 接腳,增益倍數(shù)(默認(rèn)128)和修正系數(shù)(默認(rèn)1)
- void set_amp(byte amp); // 改變?cè)鲆姹稊?shù)和對(duì)應(yīng)的通道,至少調(diào)用一次 read() 后起作用
- bool is_ready(); // 返回 hx711 是否可用,在 read() 函數(shù)中會(huì)被調(diào)用
- long read(); // 返回傳感器電壓值,如果 hx711 不可用則程序會(huì)暫停在此函數(shù)
- double bias_read(); // 返回:(read() - 偏移值) * 修正系數(shù)
- void tare(int t = 10); // 將皮重添加到偏移值,影響每次 read(); 的調(diào)用
- void set_co(double co = 1); // 修改修正系數(shù)(默認(rèn)為1)
- void set_offset(long offset = 0); // 修改偏移值(默認(rèn)為0)
復(fù)制代碼 可以看到,HX711還可以使用四參數(shù)方式定義,同時(shí)指定增益倍數(shù)及修正系數(shù)。在程序運(yùn)行中還可以隨時(shí)改變?cè)鲆姹稊?shù),修正系數(shù)以及利用偏移值實(shí)現(xiàn)去皮重等功能,非常實(shí)用。
這里唯一需要解釋的是第一個(gè)函數(shù),- HX711 hx(9, 10); // 這樣用說明只定義SCK和DOUT接腳,AMP默認(rèn)使用A通道的128位增益,修正系數(shù)默認(rèn)為1;
- HX711 hx(9, 10, 64); // 這樣用說明定義SCK和DOUT接腳,AMP使用A通道的64增益,修正系數(shù)默認(rèn)為1;
- HX711 hx(9, 10, 32, 1.4); // 這樣用說明定義SCK和DOUT接腳,AMP使用B通道的32位增益,修正系數(shù)為1.4;
復(fù)制代碼 這
里有關(guān)通道和增益倍數(shù)的選擇,資料中已經(jīng)提及過,A通道只有128和64位兩種增益倍數(shù),對(duì)應(yīng)滿載電壓為 20mV 和
40mV,B通道只有固定的32位增益倍數(shù),滿載電壓為
80mV,使用時(shí)各個(gè)通道輸入電壓不要超過對(duì)應(yīng)增益倍數(shù)的滿載電壓。當(dāng)然,程序中額可以隨時(shí)切換增益倍數(shù)和通道,使用set_amp(amp)函數(shù)即可,
當(dāng)然,amp 的值只能是 128、64或32。
再強(qiáng)調(diào)一句,如果增益倍數(shù)選擇32位增益,那么讀出的數(shù)據(jù)就是B通道的。
==============================我真的是分割線================================
下面寫一個(gè)具體應(yīng)用示例:
我選擇的傳感器參數(shù)如下:
滿量程輸出電壓=激勵(lì)電壓x靈敏度1.0mV/V
例如:供電電壓是5V乘以靈敏度1.0mV/V=滿量程5mV
實(shí)際上我選用的這個(gè)模塊,當(dāng)電源電壓是5V時(shí),供給傳感器的供電電壓是4V,于是我的傳感器滿量程電壓為4mV。
這樣我就完全可以選擇增益倍數(shù)最高的A通道128位增益來得到最高的精度。
電子稱連接圖示:
155242qc8j9dbvb9bzvvjc.jpg (51.43 KB, 下載次數(shù): 237)
下載附件
2016-1-23 00:58 上傳
圖中綠色的為HX711模塊,右下角為Arduino
UNO,吊臂上掛著的就是橋式傳感器(我連接的方式為懸吊式測(cè)拉力值),AD模塊與傳感器間的電線越短越好,過長(zhǎng)的話會(huì)受到各種干擾,AD模塊與
Arduino之間的連線最好也不要超過30cm,如果必須加長(zhǎng)的話,可以考慮使用帶電磁屏蔽的線以及信號(hào)放大器。
首先使用庫自帶的例子測(cè)試一下,可以看到懸掛上1kg砝碼以及托盤等部件后得到的值為:- 1315588.75
- 1315597.75
- 1315607.37
- 1315606.75
- 1315604.75
- 1315589.62
- 1315579.62
- 1315594.25
- 1315588.75
- 1315580.25
- 1315589.00
- 1315584.25
- 1315605.50
- 1315596.12
- 1315592.25
- 1315607.75
- 1315585.75
- 1315582.87
- 1315568.75
- 1315574.75
- 1315578.00
- 1315583.12
- 1315604.62
- 1315573.50
- 1315584.25
復(fù)制代碼 去掉一個(gè)500g砝碼后值為:- 742865.50
- 742847.87
- 742869.00
- 742879.12
- 742873.68
- 742858.81
- 742867.81
- 742843.37
- 742862.18
- 742844.87
- 742856.50
- 742834.31
- 742831.31
- 742825.12
- 742842.31
- 742821.31
- 742816.12
- 742846.00
- 742844.00
- 742826.87
- 742818.12
- 742812.87
- 742807.18
- 742835.00
復(fù)制代碼 可以粗略的計(jì)算:
1315500 - 742800 = 572700
所以修正系數(shù)大概為: 500 / 572700 = 0.00087305
那么程序就可以寫成(這時(shí)可以適當(dāng)?shù)臏p小些讀取速度,增加個(gè)delay,比如讓程序半分鐘一讀�。�
- #include <HX711.h>
- HX711 hx(9, 10, 128, 0.00087305);
- void setup() {
- Serial.begin(9600);
- }
- void loop() {
- delay(500);
- double sum = 0;
- for (int i = 0; i < 10; i++)
- sum += hx.read();
- Serial.println(sum/10);
- }
復(fù)制代碼 編譯寫入Arduino后,將砝碼全部取下,僅保留稱體,得到結(jié)果是:- 169640.70
- 169632.59
- 169632.90
- 169640.90
- 169632.79
- 169623.59
- 169649.79
- 169610.40
- 169615.20
- 169659.40
- 169619.90
- 169624.79
- 169614.79
- 169624.29
- 169617.79
- 169629.20
- 169604.00
- 169617.50
- 169628.20
- 169589.40
- 169602.29
- 169598.40
- 169596.40
- 169604.00
- 169612.40
- 169592.20
復(fù)制代碼 說明偏移值近似為 169600,那么我們?cè)趕etup中調(diào)用偏移值的函數(shù)(使用bias_read()讀取帶修正系數(shù)及偏移值的讀數(shù),與read()對(duì)比作參考):- #include <HX711.h>
- HX711 hx(9, 10, 128, 0.00087305);
- void setup() {
- Serial.begin(9600);
- hx.set_offset(169600);
- }
- void loop() {
- delay(500);
- double sum0 = 0;
- double sum1 = 0;
- for (int i = 0; i < 10; i++) {
- sum0 += hx.read();
- sum1 += hx.bias_read();
- }
- Serial.print(sum0/10);
- Serial.print(" ");
- Serial.println(sum1/10);
- }
復(fù)制代碼 這時(shí)讀出的數(shù)據(jù)變?yōu)椋?div id="kgkimjz" class="blockcode">
- 169615.20 0.01
- 169616.70 0.02
- 169613.40 0.02
- 169636.50 0.03
- 169620.70 0.02
- 169638.09 0.04
- 169625.29 0.02
- 169620.50 0.02
- 169612.29 0.01
- 169609.79 0.01
- 169624.40 0.02
- 169625.20 0.02
- 169630.00 0.03
- 169628.29 0.03
- 169606.29 0.00
- 169617.79 0.02
- 169637.90 0.03
- 169603.70 0.00
- 169605.29 0.01
- 169636.50 0.03
復(fù)制代碼然后再放上500g砝碼查看一下數(shù)據(jù):
- 742492.68 500.16
- 742499.81 500.17
- 742503.81 500.17
- 742505.18 500.18
- 742507.18 500.17
- 742499.31 500.17
- 742499.50 500.17
- 742512.37 500.18
- 742521.87 500.19
- 742497.87 500.17
- 742518.12 500.18
- 742518.81 500.18
- 742520.87 500.19
- 742520.68 500.19
- 742530.18 500.20
- 742532.87 500.20
- 742543.00 500.20
- 742540.12 500.21
- 742517.00 500.19
復(fù)制代碼 再放上一個(gè)500g砝碼試試:- 1315286.75 1000.25
- 1315304.62 1000.25
- 1315296.62 1000.25
- 1315302.25 1000.26
- 1315302.12 1000.26
- 1315294.25 1000.25
- 1315310.00 1000.26
- 1315277.37 1000.24
- 1315283.75 1000.24
- 1315280.25 1000.23
- 1315286.75 1000.24
- 1315293.25 1000.25
- 1315309.87 1000.26
- 1315299.50 1000.25
- 1315307.12 1000.26
- 1315304.50 1000.25
- 1315301.50 1000.25
- 1315296.75 1000.25
- 1315284.50 1000.23
- 1315284.37 1000.24
- 1315308.75 1000.26
- 1315291.62 1000.25
- 1315312.75 1000.26
- 1315312.25 1000.26
復(fù)制代碼 可以看到第一位小數(shù)發(fā)生了大概0.2的變化,這說明我們粗略取的修正系數(shù)還不夠精確,但是完全符合1g精度的要求。
接下來就是完善程序,增加去皮重的功能了,在Arduino上接一個(gè)按鈕,為了阻止電磁干擾發(fā)生誤判斷,我采用了常輸出高電平的按鈕,當(dāng)按下按鈕的時(shí)候輸出低電平,按鈕接在 4 號(hào)口上:- #include <HX711.h>
- HX711 hx(9, 10, 128, 0.00087305);
- void setup() {
- Serial.begin(9600);
- hx.set_offset(169600);
- }
- void loop() {
- if(digitalRead(4) == LOW) hx.tare();
- double sum0 = 0;
- double sum1 = 0;
- for (int i = 0; i < 10; i++) {
- sum0 += hx.read();
- sum1 += hx.bias_read();
- }
- Serial.print(sum0/10);
- Serial.print(" ");
- Serial.println(sum1/10);
- }
復(fù)制代碼 這樣每次按下按鈕的時(shí)候就可以去皮重了。
============================不要懷疑我是分割線=============================
去皮重也實(shí)現(xiàn)了,可是最求完美的我發(fā)現(xiàn)每次掉電后都要重新設(shè)置皮重,很是麻煩,于是決定將皮重信息存到EEPROM中保存,這樣每次上電后就會(huì)自動(dòng)讀取存儲(chǔ)的皮重信息,從0點(diǎn)開始稱量了!
看了一下 HX711 的庫,在去皮重的時(shí)候只需調(diào)用 hx.tare();,tare() 函數(shù)內(nèi)容如下:- void HX711::tare(int t) {
- double sum = 0;
- for (int i = 0; i < t; i++) {
- sum += read();
- }
- set_offset(sum / t);
- }
復(fù)制代碼 里面又調(diào)用了 read() 和 set_offset(),read() 不用看了,就是讀取一次不帶修正系數(shù)和偏移量的傳感器數(shù)據(jù)。set_offset() 如下:- void HX711::set_offset(long offset) {
- OFFSET = offset;
- }
復(fù)制代碼 僅僅是把偏移量賦值給OFFSET,而OFFSET會(huì)在 bias_read() 中起作用:- double HX711::bias_read() {
- return (read() - OFFSET) * COEFFICIENT;
- }
復(fù)制代碼 也就是說,我們?cè)谡{(diào)用 tare() 的時(shí)候如果能返回 OFFSET 值就可以存儲(chǔ)它用作去皮重了。
不幸的是,HX711庫并不允許我們這么做。也許有人要說了,那就調(diào)用 tare() 后 再調(diào)用一次 read() 來獲取
OFFSET唄。這樣可不行,首先調(diào)用 tare() 的時(shí)候本身就會(huì)調(diào)用 10 次 read() 并求平均值作為 OFFSET
來使用,我們?cè)僬{(diào)用一次 read() 讀出的數(shù)既不是之前那個(gè)平均值,精度也不如前面的平均值高,就算再求一次 10個(gè) 數(shù)的平均值,也得不到之前那個(gè)
OFFSET了,精度會(huì)大打折扣的。
看來唯一的辦法就是自己手動(dòng)改一下 HX711 的庫,讓它在調(diào)用 tare() 的時(shí)候直接返回個(gè)
OFFSET,這樣就解決了我們的需求。為了和官方庫區(qū)分,我們改一下庫的名字,將 HX711 庫文件夾復(fù)制一份改名為 HX711A ,然后將
HX711.cpp 改為 HX711A.cpp,同樣 HX711.h 改為 HX711A.h。然后打開 HX711A.cpp 和 HX711A.h,作出修改。改動(dòng)如下:
HX711A.cpp:- #include <HX711.h> -> #include <HX711A.h>
- void HX711::tare(int t) { - > double HX711::tare(int t) {
- 并在 tare 函數(shù)結(jié)尾加入: return sum / t;
復(fù)制代碼 HX711A.h:
- #ifndef HX711_H -> #ifndef HX711A_H
- #define HX711_H -> #define HX711A_H
- void tare(int t = 10); -> double tare(int t = 10);
復(fù)制代碼 這樣在調(diào)用 tare() 的時(shí)候就可以返回 OFFSET 值了,我們存儲(chǔ) OFFSET值就可以了。
可是新的問題又出現(xiàn)了,OFFSET 值是 double 類型的,而我們 Arduino 提供的 EEPROM 庫一次僅能存儲(chǔ)1個(gè) char
類型數(shù)據(jù)。于是上網(wǎng)查資料,發(fā)現(xiàn)弘版有個(gè)帖子提到了多類型存儲(chǔ),可是相應(yīng)的庫編譯后有點(diǎn)龐大,還是自己解決吧,寫了個(gè)共用體實(shí)現(xiàn)的double類型存儲(chǔ),
見我的帖子,可以在程序里加入這一部分內(nèi)容。
----帖子內(nèi)容引用------------------------ 有的時(shí)候我們需要將float或者double類型的數(shù)據(jù)存到EEPROM中以備下次利用,比如制作電子稱存儲(chǔ)皮重等信息時(shí)。
但是Arduino的EEPROM僅僅能以8bit一位存儲(chǔ)1024位。
在網(wǎng)上查了一下,貌似使用共用體的方法很火,于是寫了個(gè)代碼:
數(shù)據(jù)拆分存儲(chǔ)部分:- dvalue.v = 169600.00;
- unsigned char *dpointer;
- dpointer = dvalue.dchar;
- for(int i = 0; i < 8; i++) {
- EEPROM.write(i,*dpointer);
- dpointer++;
- }
復(fù)制代碼 數(shù)據(jù)讀取部分:- for(int i = 0; i < 8; i++) dvalue.dchar[ i] = EEPROM.read(i);
- Serial.println(dvalue.v);
復(fù)制代碼 完整示例代碼:- #include <EEPROM.h>
- union data {
- double v;
- unsigned char dchar[8];
- } dvalue;
- void setup() {
- Serial.begin(9600);
-
- //數(shù)據(jù)拆分
- dvalue.v = 169600.00;
- unsigned char *dpointer;
- dpointer = dvalue.dchar;
- for(int i = 0; i < 8; i++) {
- EEPROM.write(i,*dpointer);
- dpointer++;
- }
- }
- void loop()
- {
- //數(shù)據(jù)還原
- for(int i = 0; i < 8; i++) dvalue.dchar[ i] = EEPROM.read(i);
- Serial.println(dvalue.v);
- delay(1000);
- }
復(fù)制代碼 當(dāng)僅僅要存取float類型時(shí),只需要把v前面的double改為float,把循環(huán)和聲明dchar中的8改為4即可。
EEPROM庫中貌似還有個(gè)put方法可以存各種數(shù)據(jù)類型,感謝18# 蔥拌豆腐 提供
http://www.arduino.cc/en/Reference/EEPROM ----------------------------
另外,經(jīng)過查詢資料,橋式傳感器受溫度影響的偏移量也不容忽視,可以在系統(tǒng)中加入溫度傳感器(例如DS18B20),并在計(jì)算重量的時(shí)候加入線性溫度漂移修正,這里我就不寫溫度相關(guān)代碼了,僅給出溫度漂移修正的函數(shù)供大家參考:- #include <HX711A.h>
- #include <EEPROM.h>
- HX711 hx(9, 10, 128, 0.00087305);
- int i=0;
- // 用于在 EEPROM 中儲(chǔ)存 double 類型數(shù)據(jù)的共用體
- unsigned char *dpointer;
- union data {
- double v;
- unsigned char dchar[8];
- } dvalue;
- void setup() {
- Serial.begin(9600);
- for(i = 0; i < 8; i++) dvalue.dchar[ i] = EEPROM.read(i); // 從 EEPROM 讀取偏移量
- hx.set_offset(dvalue.v); // 設(shè)置已讀取的偏移量
- }
- void loop() {
- if(digitalRead(4) == LOW) {
- dvalue.v = hx.tare(); // 去皮重并讀取偏移量
- hx.set_offset(dvalue.v); // 設(shè)置已讀取的偏移量
- dpointer = dvalue.dchar; // 以下程序?qū)⑵屏糠纸獠?chǔ)存到 EEPROM
- for(i = 0; i < 8; i++) {
- EEPROM.write(i,*dpointer);
- dpointer++;
- }
- }
- double sum = 0;
- for (i = 0; i < 10; i++) {
- sum += hx.bias_read();
- }
- Serial.println(sum/10);
- //Serial.println(sum / 10 * (1 + (20 - temprature) / 10 * 0.02)); // 帶線性溫度補(bǔ)償?shù)妮敵�,注意temprature單位為攝氏度。
- }
復(fù)制代碼 ============================我分割線又回來啦=============================
此外,程序可以增加的功能還有:
1.LCD顯示
2.鍵盤輸入及語音功能
3.標(biāo)準(zhǔn)砝碼校準(zhǔn)功能(如500g),其實(shí)就是修正系數(shù)的自我修正功能。
這幾個(gè)功能我就不再研究了,都不難,留給各位自己發(fā)揮的空間吧
全文完 |
|