树莓派进阶之路 (020) - 基于24位AD转换模块HX711的重量称量实验
参考文档:http://www.geek-workshop.com/thread-2315-1-1.html
参考文档:https://wenku.baidu.com/view/e5d5e4e26529647d26285243.html
先来看一下该模块的常用接法:
模拟输入
通道 A 模拟差分输入可直接与桥式传感器的差分输出相接。由于桥式传感器输出的信号较小,为了充分利用A/D 转换器的输入动态范围,该通道的可编程增益较大,为128 或64。这些增益所对应的满量程差分输入电压分别±20mV 或±40mV。
通道B 为固定的32 增益,所对应的满量程差分输入电压为±80mV。通道B 应用于包括电池在内的系统参数检测。
供电电源
数字电源(DVDD)应使用与MCU 芯片相同的的数字供电电源。HX711 芯片内的稳压电路可同时向 A/D 转换器和外部传感器提供模拟电源。稳压电源的供电电压(VSUP)可与数字电源(DVDD)相同。稳压电源的输出电压值(VAVDD)由外部分压电阻R1、R2 和芯片的输出参考电压VBG 决定(图1),VAVDD=VBG(R1+R2)/R2。应选择该输出电压比稳压电源的输入电压(VSUP)低至少100mV。
如果不使用芯片内的稳压电路,管脚VSUP应连接到DVDD 或AVDD 中电压较高的一个管脚上。管脚VBG 上不需要外接电容,管脚VFB 应接地,管脚BASE 为无连接。时钟选择如果将管脚 XI 接地,HX711 将自动选择使用内部时钟振荡器,并自动关闭外部时钟输入和晶振的相关电路。这种情况下,典型输出数据速率为10Hz 或80Hz。如果需要准确的输出数据速率,可将外部输入时钟通过一个20pF 的隔直电容连接到XI管脚上,或将晶振连接到XI 和XO 管脚上。这种情况下,芯片内的时钟振荡器电路会自动关
闭,晶振时钟或外部输入时钟电路被采用。此时,若晶振频率为11.0592MHz, 输出数据速率为准确的10Hz 或80Hz。输出数据速率与晶振频率以上述关系按比例增加或减少。使用外部输入时钟时,外部时钟信号不一定需要为方波。可将MCU 芯片的晶振输出管脚上的时钟信号通过20pF 的隔直电容连接到XI管脚上,作为外部时钟输入。外部时钟输入信号的幅值可低至150mV。
串口通讯
串口通讯线由管脚PD_SCK 和DOUT 组成,用来输出数据,选择输入通道和增益。当数据输出管脚DOUT 为高电平时,表明
A/D 转换器还未准备好输出数据,此时串口时钟输入信号PD_SCK 应为低电平。当DOUT 从高电平变低电平后,PD_SCK 应输入25 至27 个不等的时钟脉冲(图二)。其中第一个时钟脉冲的上升沿将读出输出24 位数据的最高位(MSB),直至第24 个时钟脉冲完成,24 位输出数据从最高位至最低位逐位输出完成。第25至27 个时钟脉冲用来选择下一次A/D 转换的输入通道和增益,参见表三。
PD_SCK 脉冲数输入通道 增益
时序图
PD_SCK 的输入时钟脉冲数不应少于25 或多于27,否则会造成串口通讯错误。当A/D 转换器的输入通道或增益改变时,A/D 转换器需要4 个数据输出周期才能稳定。DOUT 在4 个数据输出周期后才会从高电平变低电平,输出有效数据。
树莓派代码:
1 # include <stdio.h> 2 # include <unistd.h> 3 # include <wiringPi.h> 4 # include <hiredis/hiredis.h> 5 6 /*-----------------结构体-----------------*/ 7 struct hx711_pin{ 8 int SCK; 9 int SDA; 10 int EN; //校准使能 11 int calibration; //校准 12 int coefficient; //比例系数 13 int weight; //重量 14 unsigned long value; //记录数值 15 }; 16 17 void set_pin(struct hx711_pin *value){ 18 value->SCK = 4; 19 value->SDA = 5; 20 value->EN = 1; 21 value->coefficient = 415; 22 } 23 24 void init_pin(struct hx711_pin *value){ 25 pinMode(value->SCK,OUTPUT); 26 pinMode(value->SDA,INPUT); 27 pullUpDnControl(value->SDA,PUD_UP); 28 } 29 30 void start(struct hx711_pin *value){ 31 int i; 32 digitalWrite(value->SCK,LOW); //使能AD 33 while(digitalRead(value->SCK)); 34 value->value = 0; //数值 35 while(digitalRead(value->SDA)); //AD转换未结束则等待。 36 usleep(1); 37 for(i=0;i<24;i++){ 38 digitalWrite(value->SCK,HIGH); 39 while(0 == digitalRead(value->SCK))usleep(1); 40 value->value = value->value*2; 41 digitalWrite(value->SCK,LOW); 42 while(digitalRead(value->SCK)); 43 if(digitalRead(value->SDA)) 44 value->value = value->value + 1; 45 } 46 digitalWrite(value->SCK,HIGH); 47 digitalWrite(value->SCK,LOW); 48 if((value->EN == 1)&&(value->value<25000)){ 49 value->EN = 0; 50 value->calibration = value->value; 51 }else { 52 i = (value->value-value->calibration+50)/value->coefficient; 53 } 54 if(i<5000)value->weight = i; 55 printf("重量为:%d g\n",value->weight); 56 } 57 58 /*-----------------主体-----------------*/ 59 int setup(struct hx711_pin *value){ 60 if(wiringPiSetup()==-1)return 1; 61 set_pin(value); 62 init_pin(value); 63 return 0; 64 } 65 66 void loop(struct hx711_pin *value){ 67 while(1) 68 start(value); 69 } 70 71 int main(void){ 72 struct hx711_pin value; 73 if(0 == setup(&value)) 74 loop(&value); 75 return 0; 76 }
截图:
经过测试,数据还挺稳的。