找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

帖子
查看: 41595|回復(fù): 19
打印 上一主題 下一主題
收起左側(cè)

基于24位AD轉(zhuǎn)換模塊HX711的重量稱量實(shí)驗(yàn)

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
以前在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:








功能簡(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:







模塊工作電壓: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℃







===============================我叫分割線=================================



我要使用的拉力傳感器為傳統(tǒng)的橋式傳感器,量程1kg,想要達(dá)到1g的精度,這就要求模塊輸出位數(shù)至少為10位(2^10=1024),8位的
PCF8591無法勝任,因?yàn)樗木戎挥?^8=256位。所以決定使用HX711作為我的A/D模塊,而且我選的HX711模塊還帶屏蔽殼,正符合我
的要求。





先來看一下該模塊的常用接法:








模擬輸入

通道 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)換的輸入通道和增益,參見表三。











PD_SCK 脈沖數(shù)輸入通道 增益













時(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)



再來看一下接線:







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)單:
  1. #include <HX711.h> // 包含庫的頭文件



  2. HX711 hx(9, 10); // 數(shù)據(jù)接腳定義



  3. void setup() {

  4.   Serial.begin(9600);

  5. }



  6. void loop()

  7. {

  8.   double sum = 0;    // 為了減小誤差,一次取出10個(gè)值后求平均值。

  9.   for (int i = 0; i < 10; i++) // 循環(huán)的越多精度越高,當(dāng)然耗費(fèi)的時(shí)間也越多

  10.     sum += hx.read();  // 累加

  11.   Serial.println(sum/10); // 求平均值進(jìn)行均差

  12. }
復(fù)制代碼
給的示例程序非常簡(jiǎn)單,但是我查看庫中含有很多示例沒有給出的函數(shù):
  1. HX711(byte sck, byte dout, byte amp = 128, double co = 1); // 定義 sck、dout 接腳,增益倍數(shù)(默認(rèn)128)和修正系數(shù)(默認(rèn)1)

  2. void set_amp(byte amp); // 改變?cè)鲆姹稊?shù)和對(duì)應(yīng)的通道,至少調(diào)用一次 read() 后起作用

  3. bool is_ready(); // 返回 hx711 是否可用,在 read() 函數(shù)中會(huì)被調(diào)用

  4. long read(); // 返回傳感器電壓值,如果 hx711 不可用則程序會(huì)暫停在此函數(shù)

  5. double bias_read(); // 返回:(read() - 偏移值) * 修正系數(shù)

  6. void tare(int t = 10); // 將皮重添加到偏移值,影響每次 read(); 的調(diào)用

  7. void set_co(double co = 1); // 修改修正系數(shù)(默認(rèn)為1)

  8. 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ù),
  1. HX711 hx(9, 10); // 這樣用說明只定義SCK和DOUT接腳,AMP默認(rèn)使用A通道的128位增益,修正系數(shù)默認(rèn)為1;

  2. HX711 hx(9, 10, 64); // 這樣用說明定義SCK和DOUT接腳,AMP使用A通道的64增益,修正系數(shù)默認(rèn)為1;

  3. 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位增益來得到最高的精度。



電子稱連接圖示:











圖中綠色的為HX711模塊,右下角為Arduino
UNO,吊臂上掛著的就是橋式傳感器(我連接的方式為懸吊式測(cè)拉力值),AD模塊與傳感器間的電線越短越好,過長(zhǎng)的話會(huì)受到各種干擾,AD模塊與
Arduino之間的連線最好也不要超過30cm,如果必須加長(zhǎng)的話,可以考慮使用帶電磁屏蔽的線以及信號(hào)放大器。



首先使用庫自帶的例子測(cè)試一下,可以看到懸掛上1kg砝碼以及托盤等部件后得到的值為:
  1. 1315588.75

  2. 1315597.75

  3. 1315607.37

  4. 1315606.75

  5. 1315604.75

  6. 1315589.62

  7. 1315579.62

  8. 1315594.25

  9. 1315588.75

  10. 1315580.25

  11. 1315589.00

  12. 1315584.25

  13. 1315605.50

  14. 1315596.12

  15. 1315592.25

  16. 1315607.75

  17. 1315585.75

  18. 1315582.87

  19. 1315568.75

  20. 1315574.75

  21. 1315578.00

  22. 1315583.12

  23. 1315604.62

  24. 1315573.50

  25. 1315584.25


復(fù)制代碼
去掉一個(gè)500g砝碼后值為:
  1. 742865.50

  2. 742847.87

  3. 742869.00

  4. 742879.12

  5. 742873.68

  6. 742858.81

  7. 742867.81

  8. 742843.37

  9. 742862.18

  10. 742844.87

  11. 742856.50

  12. 742834.31

  13. 742831.31

  14. 742825.12

  15. 742842.31

  16. 742821.31

  17. 742816.12

  18. 742846.00

  19. 742844.00

  20. 742826.87

  21. 742818.12

  22. 742812.87

  23. 742807.18

  24. 742835.00


復(fù)制代碼
可以粗略的計(jì)算:

1315500 - 742800 = 572700

所以修正系數(shù)大概為: 500 / 572700 = 0.00087305

那么程序就可以寫成(這時(shí)可以適當(dāng)?shù)臏p小些讀取速度,增加個(gè)delay,比如讓程序半分鐘一讀�。�


  1. #include <HX711.h>

  2. HX711 hx(9, 10, 128, 0.00087305);

  3. void setup() {

  4.   Serial.begin(9600);

  5. }

  6. void loop() {

  7.   delay(500);

  8.   double sum = 0;

  9.   for (int i = 0; i < 10; i++)

  10.     sum += hx.read();

  11.   Serial.println(sum/10);

  12. }


復(fù)制代碼
編譯寫入Arduino后,將砝碼全部取下,僅保留稱體,得到結(jié)果是:
  1. 169640.70

  2. 169632.59

  3. 169632.90

  4. 169640.90

  5. 169632.79

  6. 169623.59

  7. 169649.79

  8. 169610.40

  9. 169615.20

  10. 169659.40

  11. 169619.90

  12. 169624.79

  13. 169614.79

  14. 169624.29

  15. 169617.79

  16. 169629.20

  17. 169604.00

  18. 169617.50

  19. 169628.20

  20. 169589.40

  21. 169602.29

  22. 169598.40

  23. 169596.40

  24. 169604.00

  25. 169612.40

  26. 169592.20


復(fù)制代碼
說明偏移值近似為 169600,那么我們?cè)趕etup中調(diào)用偏移值的函數(shù)(使用bias_read()讀取帶修正系數(shù)及偏移值的讀數(shù),與read()對(duì)比作參考):
  1. #include <HX711.h>

  2. HX711 hx(9, 10, 128, 0.00087305);

  3. void setup() {

  4.   Serial.begin(9600);

  5.   hx.set_offset(169600);



  6. }

  7. void loop() {

  8.   delay(500);

  9.   double sum0 = 0;

  10.   double sum1 = 0;

  11.   for (int i = 0; i < 10; i++) {

  12.     sum0 += hx.read();

  13.     sum1 += hx.bias_read();

  14.   }

  15.   Serial.print(sum0/10);

  16.   Serial.print(" ");

  17.   Serial.println(sum1/10);

  18. }
復(fù)制代碼
這時(shí)讀出的數(shù)據(jù)變?yōu)椋?div id="kgkimjz" class="blockcode">


  1. 169615.20 0.01

  2. 169616.70 0.02

  3. 169613.40 0.02

  4. 169636.50 0.03

  5. 169620.70 0.02

  6. 169638.09 0.04

  7. 169625.29 0.02

  8. 169620.50 0.02

  9. 169612.29 0.01

  10. 169609.79 0.01

  11. 169624.40 0.02

  12. 169625.20 0.02

  13. 169630.00 0.03

  14. 169628.29 0.03

  15. 169606.29 0.00

  16. 169617.79 0.02

  17. 169637.90 0.03

  18. 169603.70 0.00

  19. 169605.29 0.01

  20. 169636.50 0.03




復(fù)制代碼然后再放上500g砝碼查看一下數(shù)據(jù):


  1. 742492.68 500.16

  2. 742499.81 500.17

  3. 742503.81 500.17

  4. 742505.18 500.18

  5. 742507.18 500.17

  6. 742499.31 500.17

  7. 742499.50 500.17

  8. 742512.37 500.18

  9. 742521.87 500.19

  10. 742497.87 500.17

  11. 742518.12 500.18

  12. 742518.81 500.18

  13. 742520.87 500.19

  14. 742520.68 500.19

  15. 742530.18 500.20

  16. 742532.87 500.20

  17. 742543.00 500.20

  18. 742540.12 500.21

  19. 742517.00 500.19


復(fù)制代碼
再放上一個(gè)500g砝碼試試:
  1. 1315286.75 1000.25

  2. 1315304.62 1000.25

  3. 1315296.62 1000.25

  4. 1315302.25 1000.26

  5. 1315302.12 1000.26

  6. 1315294.25 1000.25

  7. 1315310.00 1000.26

  8. 1315277.37 1000.24

  9. 1315283.75 1000.24

  10. 1315280.25 1000.23

  11. 1315286.75 1000.24

  12. 1315293.25 1000.25

  13. 1315309.87 1000.26

  14. 1315299.50 1000.25

  15. 1315307.12 1000.26

  16. 1315304.50 1000.25

  17. 1315301.50 1000.25

  18. 1315296.75 1000.25

  19. 1315284.50 1000.23

  20. 1315284.37 1000.24

  21. 1315308.75 1000.26

  22. 1315291.62 1000.25

  23. 1315312.75 1000.26

  24. 1315312.25 1000.26


復(fù)制代碼
可以看到第一位小數(shù)發(fā)生了大概0.2的變化,這說明我們粗略取的修正系數(shù)還不夠精確,但是完全符合1g精度的要求。



接下來就是完善程序,增加去皮重的功能了,在Arduino上接一個(gè)按鈕,為了阻止電磁干擾發(fā)生誤判斷,我采用了常輸出高電平的按鈕,當(dāng)按下按鈕的時(shí)候輸出低電平,按鈕接在 4 號(hào)口上:
  1. #include <HX711.h>

  2. HX711 hx(9, 10, 128, 0.00087305);

  3. void setup() {

  4.   Serial.begin(9600);

  5.   hx.set_offset(169600);

  6. }

  7. void loop() {

  8.   if(digitalRead(4) == LOW) hx.tare();

  9.   double sum0 = 0;

  10.   double sum1 = 0;

  11.   for (int i = 0; i < 10; i++) {

  12.     sum0 += hx.read();

  13.     sum1 += hx.bias_read();

  14.   }

  15.   Serial.print(sum0/10);

  16.   Serial.print(" ");

  17.   Serial.println(sum1/10);

  18. }
復(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)容如下:
  1. void HX711::tare(int t) {

  2.     double sum = 0;

  3.     for (int i = 0; i < t; i++) {

  4.         sum += read();

  5.     }

  6.     set_offset(sum / t);

  7. }
復(fù)制代碼
里面又調(diào)用了 read() 和 set_offset(),read() 不用看了,就是讀取一次不帶修正系數(shù)和偏移量的傳感器數(shù)據(jù)。set_offset() 如下:
  1. void HX711::set_offset(long offset) {

  2.     OFFSET = offset;

  3. }
復(fù)制代碼
僅僅是把偏移量賦值給OFFSET,而OFFSET會(huì)在 bias_read() 中起作用:
  1. double HX711::bias_read() {

  2.     return (read() - OFFSET) * COEFFICIENT;

  3. }
復(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:
  1. #include <HX711.h>  ->  #include <HX711A.h>

  2. void HX711::tare(int t) {      - >  double HX711::tare(int t) {

  3. 并在 tare  函數(shù)結(jié)尾加入: return sum / t;


復(fù)制代碼
HX711A.h:


  1. #ifndef HX711_H    ->   #ifndef HX711A_H

  2. #define HX711_H    ->   #define HX711A_H

  3. 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ǔ)部分:
  1.   dvalue.v = 169600.00;

  2.   unsigned char *dpointer;

  3.   dpointer = dvalue.dchar;

  4.   for(int i = 0; i < 8; i++) {

  5.     EEPROM.write(i,*dpointer);

  6.     dpointer++;

  7.   }
復(fù)制代碼
數(shù)據(jù)讀取部分:
  1.   for(int i = 0; i < 8; i++) dvalue.dchar[ i] = EEPROM.read(i);

  2.   Serial.println(dvalue.v);
復(fù)制代碼
完整示例代碼:
  1. #include <EEPROM.h>



  2. union data {

  3.   double v;

  4.   unsigned char dchar[8];

  5. } dvalue;



  6. void setup() {

  7.   Serial.begin(9600);

  8.   

  9.   //數(shù)據(jù)拆分

  10.   dvalue.v = 169600.00;

  11.   unsigned char *dpointer;

  12.   dpointer = dvalue.dchar;

  13.   for(int i = 0; i < 8; i++) {

  14.     EEPROM.write(i,*dpointer);

  15.     dpointer++;

  16.   }

  17. }



  18. void loop()

  19. {

  20.   //數(shù)據(jù)還原

  21.   for(int i = 0; i < 8; i++) dvalue.dchar[ i] = EEPROM.read(i);

  22.   Serial.println(dvalue.v);

  23.   delay(1000);

  24. }


復(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ù)供大家參考:
  1. #include <HX711A.h>

  2. #include <EEPROM.h>

  3. HX711 hx(9, 10, 128, 0.00087305);

  4. int i=0;



  5. // 用于在 EEPROM 中儲(chǔ)存 double 類型數(shù)據(jù)的共用體

  6. unsigned char *dpointer;

  7. union data {

  8.   double v;

  9.   unsigned char dchar[8];

  10. } dvalue;



  11. void setup() {

  12.   Serial.begin(9600);

  13.   for(i = 0; i < 8; i++) dvalue.dchar[ i] = EEPROM.read(i); // 從 EEPROM 讀取偏移量

  14.   hx.set_offset(dvalue.v);                                 // 設(shè)置已讀取的偏移量

  15. }

  16. void loop() {

  17.   if(digitalRead(4) == LOW) {

  18.     dvalue.v = hx.tare();     // 去皮重并讀取偏移量

  19.     hx.set_offset(dvalue.v);  // 設(shè)置已讀取的偏移量

  20.     dpointer = dvalue.dchar;  // 以下程序?qū)⑵屏糠纸獠?chǔ)存到 EEPROM

  21.     for(i = 0; i < 8; i++) {

  22.       EEPROM.write(i,*dpointer);

  23.       dpointer++;

  24.     }

  25.   }

  26.   double sum = 0;

  27.   for (i = 0; i < 10; i++) {

  28.     sum += hx.bias_read();

  29.   }

  30.   Serial.println(sum/10);

  31.   //Serial.println(sum / 10 * (1 + (20 - temprature) / 10 * 0.02)); // 帶線性溫度補(bǔ)償?shù)妮敵�,注意temprature單位為攝氏度。

  32. }


復(fù)制代碼
============================我分割線又回來啦=============================











此外,程序可以增加的功能還有:

1.LCD顯示

2.鍵盤輸入及語音功能

3.標(biāo)準(zhǔn)砝碼校準(zhǔn)功能(如500g),其實(shí)就是修正系數(shù)的自我修正功能。



這幾個(gè)功能我就不再研究了,都不難,留給各位自己發(fā)揮的空間吧



全文完
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏8 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:106553 發(fā)表于 2016-8-17 21:13 | 只看該作者
太強(qiáng)大了
回復(fù)

使用道具 舉報(bào)

板凳
ID:24730 發(fā)表于 2017-3-2 16:48 | 只看該作者
厲害厲害厲害厲害厲害
回復(fù)

使用道具 舉報(bào)

地板
ID:171726 發(fā)表于 2017-3-21 16:41 | 只看該作者
能將數(shù)據(jù)的轉(zhuǎn)化貼出來嗎,為什么我算出來的和實(shí)際差好多?
回復(fù)

使用道具 舉報(bào)

5#
ID:185896 發(fā)表于 2017-4-3 23:24 | 只看該作者
非常感謝,很需要!
回復(fù)

使用道具 舉報(bào)

6#
ID:186127 發(fā)表于 2017-4-4 21:34 | 只看該作者
你好,我想請(qǐng)問一下,這個(gè)傳感器是懸掛測(cè)壓還是放東西去壓它?為什么我按照賣家的教程做出來的顯示錯(cuò)誤,數(shù)據(jù)也有誤,可以指點(diǎn)一下嗎?
可以留一個(gè)QQ嗎?
回復(fù)

使用道具 舉報(bào)

7#
ID:189792 發(fā)表于 2017-4-15 12:13 | 只看該作者

 好資料,謝謝樓主分享
回復(fù)

使用道具 舉報(bào)

8#
ID:217792 發(fā)表于 2017-7-7 08:42 | 只看該作者
學(xué)到了
回復(fù)

使用道具 舉報(bào)

9#
ID:92231 發(fā)表于 2017-7-19 06:50 來自觸屏版 | 只看該作者
這個(gè)太強(qiáng)大了
回復(fù)

使用道具 舉報(bào)

10#
ID:221051 發(fā)表于 2017-7-23 12:06 | 只看該作者
很全面的文章,謝謝樓主,正在做個(gè)電子秤,正好用上這些資料!
回復(fù)

使用道具 舉報(bào)

11#
ID:237817 發(fā)表于 2017-10-8 15:22 | 只看該作者

nb,很好,厲害了
回復(fù)

使用道具 舉報(bào)

12#
ID:242054 發(fā)表于 2017-10-23 13:09 | 只看該作者
厲害啊
回復(fù)

使用道具 舉報(bào)

13#
ID:248689 發(fā)表于 2017-11-18 23:08 | 只看該作者
樓主,為什么我出來的數(shù)據(jù)很雜亂,負(fù)的、正的、零都有
回復(fù)

使用道具 舉報(bào)

14#
ID:248689 發(fā)表于 2017-11-19 15:37 | 只看該作者
樓主,按照上面的教程做數(shù)據(jù)為什么會(huì)有很大的跳變,正負(fù)零都有??采樣率要考慮嗎?直接用自帶的hx711示例應(yīng)該出不來吧
回復(fù)

使用道具 舉報(bào)

15#
ID:257864 發(fā)表于 2017-12-5 20:07 | 只看該作者
問問大神,這個(gè)每克對(duì)應(yīng)的ad數(shù)值怎么確定,標(biāo)定怎么做的呢
回復(fù)

使用道具 舉報(bào)

16#
ID:257864 發(fā)表于 2017-12-5 20:10 | 只看該作者
987675539 發(fā)表于 2017-3-21 16:41
**** 作者被禁止或刪除 內(nèi)容自動(dòng)屏蔽 ****

對(duì)對(duì)對(duì) 想看看ad數(shù)值和每克對(duì)應(yīng)關(guān)系
回復(fù)

使用道具 舉報(bào)

17#
ID:239426 發(fā)表于 2017-12-15 13:34 | 只看該作者
厲害,厲害,厲害,厲害,厲害,厲害,厲害,厲害,厲害,
回復(fù)

使用道具 舉報(bào)

18#
ID:284872 發(fā)表于 2018-2-23 05:20 | 只看該作者
樓主簡(jiǎn)直太厲害了
回復(fù)

使用道具 舉報(bào)

19#
ID:19440 發(fā)表于 2018-7-11 11:00 | 只看該作者
這是轉(zhuǎn)發(fā)的吧,樓主測(cè)過么?
回復(fù)

使用道具 舉報(bào)

20#
ID:382195 發(fā)表于 2018-8-8 10:24 | 只看該作者
請(qǐng)問HX711 hx(9,10);總是報(bào)錯(cuò)是什么原因;Arduino:1.8.5 (Windows 10), 開發(fā)板:"Arduino/Genuino Uno"

sketch_aug07b:5: error: 'HX711' does not name a type

HX711 hx(9,10);

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表