传感器驱动系列之HX711称重模块

目录

一、HX711称重模块简介

1.1 HX711简介

1.2 称重传感器简介

1.3 称重模块

二、工作原理简介

三、STM32驱动源码

3.1 STM32源码

3.2 代码分析

END


一、HX711称重模块简介

1.1 HX711简介

        HX711是一种高精度、低噪声的模拟前端芯片,常用于称重传感器和负载细节测量应用中。它具有内置的放大器和ADC(模数转换器),可以将称重传感器的模拟信号转换为数字信号。其实物见下图1所示。

图1  HX711称重模块

        HX711模块通常与称重传感器(如压阻式称重传感器)配合使用,以便实现重量测量功能。在使用HX711时,通常需要将其与一个称重传感器连接,以便将传感器的模拟输出信号转换为数字信号。然后,这个数字信号可以被微控制器或其他数字系统处理和解读。

1.2 称重传感器简介

        称重传感器,也可称为负载单元,称重单元。称重传感器测量重量(或者更准确地说是方向力)通常是通过弹簧元件和应变片的组合,转换为电气输出。应变片称重传感器由固定应变片的固体金属体(或"弹簧元件")组成。应用负载时,称重传感器的主体轻微变形并偏转。见下图2示。

图2  称重传感器

        如上图2所示,单点式称重传感器是低量程高精度的称重传感器。外形如四方体形状,测量结果准确可靠,广泛运用于电子秤,厨房秤,珠宝秤等领域,是工业和农业自动化系统中不可缺少的核心部件。

1.3 称重模块

        称重模块实物图示意见下图3所示。

图3  HX711称重模块实物

二、工作原理简介

        HX711的串口通讯线由管脚PD_SCKSCK)和DOUTDT)组成,共同用来输出数据、选择输入通道和增益。下图4为数据手册贴出的工作时序图。

图4  HX711工作时序

        1. 当DOUT(数据输出引脚)为高电平时,表明A/D转换器还未准备好输出数据,此时串口时钟输入信号PD_SCK应为低电平;

        2. 当DOUT从高电平变低电平后,PD_SCK应输入2527个不等的时钟脉冲(其中前24各时钟脉冲输出的是传感器测得的ADC数据,第25-27个时钟脉冲与数据无关,仅用于选择下一次传感器的输出增益和输出通道)。

需要注意的是:这里说明的DOUT和PD_SCK是针对于传感器的数据手册来说明的,即在数据手册中,传感器的DOUT引脚是作为输出,那么我们在使用MCU控制器驱动该传感器时,需要将该引脚作为输入引脚进行配置;同理,PD_SCK引脚是需要MCU向传感器输出时钟脉冲的,因此MCU控制器需要将该引脚配置为输出模式向HX711输入时钟脉冲。

        3. 在第一个时钟脉冲的上升沿会读取出输出的24位数据的最高位(即最高有效位,MSB),然后在接下来的时钟脉冲中,逐位输出这24位数据,从最高位到最低位。这个过程会一直持续,直到24位数据全部输出完成。因此传感器的数据输出是从高位到低位的,驱动编写时需注意。

        4. 数据手册中还有一个可能会被忽略的细节,见下图5所示。

图5  时序时间分析

        由上图5可知,我们需要给定的时PD_SCK正脉冲的电平(高电平)最大时间不能超过50us,而负脉冲的电平(低电平)的时间不能小于0.2us,而由于我们一般是选择将脉冲的占空比设置为50%,因此我们可以给定高低电平的延时时间相等,后续的驱动程序中给定的是1us。

        5. PD_SCK 的输入时钟脉冲数不应少于 25 或多于 27,否则会造成串口通讯错误。 当 A/D 转换器的输入通道或增益改变时,A/D 转换器需要 4 个数据输出周期才能稳定。DOUT 在 4 个数据输出周期后才会从高电平变低电平,输出有效数据。见下图6所示。

图6  PD_SCK脉冲数选择

        上图中,第2527个时钟脉冲用来选择下一次A/D转换的输入通道和增益。关于整体HX711的介绍就到这里,感兴趣的读者可以参考HX711的数据手册,链接如下:HX711数据手册

三、STM32驱动源码

3.1 STM32源码

        其中hx711.c驱动源码如下:

/**********************************************************************
* 文件名称: hx711.c
* 作    者: JJ-KING
* 版 本 号: V1.0.0
* 创建日期: 2023-02-09
* 模块描述: 压力传感器配置
* 其他说明:  
* 修改记录: <作者>  <时间>  <版本号>  <描述>
**********************************************************************/
/*----------------------------------------------------------------------------
  更新日志:
  2023-02-09 V1.0.0: 修改引脚为宏定义声明
  2024-01-04 V1.0.0: 重新定义获取重量的外部接口函数
  ----------------------------------------------------------------------------*/
/* 包含的头文件 --------------------------------------------------------------*/
#include "hx711.h"
#include "delay.h"

#define     HX711_DOUT(x)          GPIO_WriteBit(HX711_DOUT_GPIO_PORT, HX711_DOUT_GPIO_PIN, (BitAction)x)
#define     HX711_SCK(x)           GPIO_WriteBit(HX711_SCK_GPIO_PORT, HX711_SCK_GPIO_PIN, (BitAction)x)
#define     HX711_SCK_STATE     GPIO_ReadOutputDataBit(HX711_SCK_GPIO_PORT, HX711_SCK_GPIO_PIN)
#define     HX711_DOUT_STATE    GPIO_ReadInputDataBit(HX711_DOUT_GPIO_PORT, HX711_DOUT_GPIO_PIN)

static STRUCT_HX711_TYPEDEF hx711;

/* 传感器 gpio引脚配置 */
static void hx711_gpio_config(void)
{
	RCC_APB2PeriphClockCmd(HX711_DOUT_GPIO_CLK | HX711_SCK_GPIO_CLK, ENABLE);

    GPIO_InitTypeDef  GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;    /* IO口速度为2MHz */
    
    GPIO_InitStructure.GPIO_Pin   = HX711_SCK_GPIO_PIN; /* 端口配置 */
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;   /* 推挽输出 */
    GPIO_Init(HX711_SCK_GPIO_PORT, &GPIO_InitStructure);/* 根据设定参数初始化 */
    
    GPIO_InitStructure.GPIO_Pin   = HX711_DOUT_GPIO_PIN; /* 端口配置 */
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;       /* 上拉输入 */
    GPIO_Init(HX711_DOUT_GPIO_PORT, &GPIO_InitStructure);/* 根据设定参数初始化 */
    HX711_SCK(0); HX711_DOUT(1);
}

/* 传感器结构体参数初始化 */
static void hx711_struct_config(void)
{
	hx711.gain = GAIN_128;	/* 当前增益 128 */
    hx711.isTare = true;	/* 默认第一次称重为皮重 */
    hx711.k = 0.004757f;	/* 传感器转换系数 */
    hx711.b = 0.f;			/* 传感器误差校正/补偿值 */
    hx711.tare = 0.f;		/* 保存皮重数据 */
    hx711.actual = 0.f;		/* 保存净重数据 */
}

/* 读取传感器返回的ADC数据值(数字量) 假定为一阶线性关系 y=kx+b */
static unsigned long hx711_readCount(void)
{
    unsigned long count = 0;		/* 需要读取25-27个0/1数据 */
    unsigned char timeOut_cnt = 0; 	/* 检测超时计数值 */
    
    HX711_SCK(0);
	/* 添加超时检测 防止一直未识别到传感器导致程序卡死在这里 */
    while(HX711_DOUT_STATE) { /* 等待DOUT从高电平到低电平跳变 */
        timeOut_cnt ++;
        delay_ms(1);
        if(timeOut_cnt > 100) return 0;
    }
    /* 读取24位的ADC数字量数据 */
    for(unsigned char i=0; i<24; i++) {
        HX711_SCK(1);
        delay_us(1);
        HX711_SCK(0);
        count |= (HX711_DOUT_STATE) << (24-i); /* 上升沿读取数据 */
        delay_us(1);
    }
    /* 用于设置输出增益和输出通道 */
    for(unsigned char j=0; j<hx711.gain; j++) {
        HX711_SCK(1);
        delay_us(1);
        HX711_SCK(0);
        delay_us(1);
    }
    return (count ^ 0x800000);
}

/* ----------------------------- 接口函数 ---------------------- */
/* 传感器 初始化 */
void hx711_init(void)
{
    hx711_gpio_config();
    hx711_struct_config();
}

/* 传感器断电 */
void hx711_power_off(void)
{
    HX711_SCK(0);
    delay_us(1);
    HX711_SCK(1);
    delay_us(100);
}

/* 传感器上电 */
void hx711_reset(void)
{
    if(HX711_SCK_STATE == 1) {
        HX711_SCK(0);
    }
}

/* 设置传感器转换系数 */
void hx711_set_convert_ratio(float ratio)
{
    hx711.k = ratio;
}

/* 设置传感器误差校正/补偿值 */
void hx711_set_offset_value(float offset)
{
    hx711.b = offset;
}

/* 设置传感器增益 */
void hx711_set_gain(ENUM_HX711_GAIN_TYPEDEF gain)
{
    hx711.gain = gain;
}

/* 获取传感器皮重数据 */
float hx711_get_tare_weight(void)
{
    hx711.isTare = true; /* 获取皮重的时候 将该标志位置位 */
    if(hx711.isTare == true) {
        hx711.isTare = false;
        hx711.tare = (float)hx711_readCount() * hx711.k + hx711.b; /* 此时获取到的重量为皮重 */
    }
    return (hx711.tare);
}

/* 获取传感器实际重量 */
float hx711_get_actual_weight(void)
{
    float weight = 0.f;
    
    if(hx711.isTare == false) { /* 当该标志位复位 代表此时应计算净重 */
        weight = (float)hx711_readCount() * hx711.k + hx711.b;
        hx711.actual = weight - hx711.tare;
    }
    return (hx711.actual);
}

      hx711.h文件如下:

/**********************************************************************
* 文件名称: hx711.h
* 作    者: JJ-KING
* 版 本 号: V1.0.0
* 创建日期: 2023-02-09
* 模块描述: 压力传感器配置
* 其他说明:  
* 修改记录: <作者>  <时间>  <版本号>  <描述>
**********************************************************************/
/*----------------------------------------------------------------------------
  更新日志:
  2023-02-09 V1.0.0: 修改引脚为宏定义声明
  2024-01-04 V1.0.0: 重新定义获取重量的外部接口函数
  ----------------------------------------------------------------------------*/
#ifndef __HX711_H
#define __HX711_H

#include "stm32f10x.h"
#include "stdbool.h"

/* 用于保存HX711的增益 */
typedef enum {
    GAIN_128 = 1,
    GAIN_32,
    GAIN_64,
} ENUM_HX711_GAIN_TYPEDEF;

/* 结构体 用于实现HX711本身的属性 */
typedef struct {
    ENUM_HX711_GAIN_TYPEDEF gain; /* 增益 */
    bool isTare;    /* 判断传感器数据是否是皮重 true-是 false-否 */
    float k;        /* 比例系数 */
    float b;        /* 补偿值 */
    float tare;     /* 皮重 */
    float actual;   /* 实重 */
} STRUCT_HX711_TYPEDEF;

/* HX711传感器引脚定义 */
#define     HX711_DOUT_GPIO_CLK    RCC_APB2Periph_GPIOC
#define     HX711_DOUT_GPIO_PORT   GPIOC
#define     HX711_DOUT_GPIO_PIN    GPIO_Pin_0

#define     HX711_SCK_GPIO_CLK     RCC_APB2Periph_GPIOC
#define     HX711_SCK_GPIO_PORT    GPIOC
#define     HX711_SCK_GPIO_PIN     GPIO_Pin_1

/* ---------------- 函数清单 --------------- */
void        hx711_init(void);       				/* HX711初始化 */
void        hx711_power_off(void);   				/* HX711断电 */
void        hx711_reset(void);      				/* HX711断电后复位 */
void        hx711_set_convert_ratio(float ratio); 	/* 设置HX711重量比例系数 */
void        hx711_set_offset_value(float offset); 	/* 设置HX711重量补偿值 */
void        hx711_set_gain(ENUM_HX711_GAIN_TYPEDEF gain); /* 设置HX711增益系数 */
float       hx711_get_tare_weight(void); 			/* 获取皮重 */
float       hx711_get_actual_weight(void); 			/* 获取实重 */

#endif

3.2 代码分析

        上述代码中设置了结构体STRUCT_HX711_TYPEDEF用于配置传感器的自有属性:

/* 结构体 用于实现HX711本身的属性 */
typedef struct {
    ENUM_HX711_GAIN_TYPEDEF gain; /* 增益 */
    bool isTare;    /* 判断传感器数据是否是皮重 true-是 false-否 */
    float k;        /* 比例系数 */
    float b;        /* 补偿值 */
    float tare;     /* 皮重 */
    float actual;   /* 实重 */
} STRUCT_HX711_TYPEDEF;

        其中结构体成员变量k,用于配置传感器与实际重量之间的比例关系,即传感器系数。根据传感器数据手册的时序图得到的传感器数据,其实质上是一个24位的ADC数据值,与实际的物体重量其本质上并没有关联,我们可以认为的让他们之间存在一个一阶线性相关,即:

y = kx + b

        因此我们可以得到如下的公式:

实际重量(w)= 比例系数(k)* 读取的传感器adc数据 + 补偿值(b)

        那么如何计算这个参数k呢?

        1. 首先我们可以在hx711.c中将结构体初始化中的成员变量(k)初始化为1,然后我们不在称重传感器上放置任何物体,那么我们通过hx711_get_tare_weight()函数得到的皮重数据其本质上为传感器本身的adc值。

        2. 然后找到一个可以确定重量的物体,比如我们的手机(在官网上可以查到手机的参考重量),然后放置在称重传感器上,此时通过hx711_get_actual_weight()函数得到的实际重量数据为传感器本身的adc值(k值为1,即此时调用该函数得到的重量数据为ADC模数转换值,并不是具体重量)。

        3. 我们可以通过如下公式将得到的两个传感器数据值相减,算出参数k的值。公式如下:

比例系数(k)=(手机实际重量(w1) - 电子秤皮重(w0)) / (手机传感器adc数值 - 皮重adc值)

        4. 这样得到的比例系数(k)值就是适配与当前传感器模块的参数了,我们叫它传感器系数。

        5. 补偿值(b)的确定可以由物体在测量过程中的实际表现酌情设置。

        注意:测重的adc数据值可能会跳变的比较快,这是由于读取的传感器精度决定的,由于传感器是24位高精度,因此细小的变动都会导致传感器数据值发生改变。所以我们只需要取跳变中的任意一个时刻的数据值即可。

四、测试实例

        1. 首先需要调用hx711_init()函数用于初始化引脚及结构体;

        2. 然后需要先调用获取皮重函数hx711_get_tare_weight()获取一次物体的皮重

        3. 接着就可以使用hx711_get_actual_weight函数获取物体的实时重量了

END

  • 52
    点赞
  • 211
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
### 回答1: HX711称重模块是一种高精度、高稳定性的AD转换器,主要用于测量物体的重量。在使用过程中,如果需要对称重模块进行调试打印,则需要采取如下步骤: 1. 确认硬件连接是否正确:首先需要将HX711称重模块与电路板连接好,并接上电源,确认模块正常工作; 2. 配置软件环境:在连接成功后,需要进行软件环境的配置。比如需要安装Arduino IDE编辑器,在Arduino IDE中安装HX711称重模块的相关库文件; 3. 编写代码:根据自己的需求编写对应的代码,实现称重模块读取数据并将其打印出来的功能。为了保证数据的准确性,需要对校准参数进行设置; 4. 运行代码:将编写好的代码上传到Arduino控制板中,进行运行。在运行过程中,需要注意模块的读数是否合理,如果出现读数异常,则需要检查连接和代码的正确性。 总体来说,HX711称重模块的调试打印较为简单,只需要注意硬件连接和软件环境的设置,以及代码的编写和运行即可。此外,在使用过程中需要注意保持环境的稳定性,避免外部因素对称重模块的测量产生干扰。 ### 回答2: HX711称重模块是一种高精度的ADC(模数转换器)芯片,它常用于测量和记录重量或其他力的大小。它的工作原理是将压力传感器的输出信号转换成数字信号,以便于扫描和处理,同时可以输出2个电平(高电平或低电平)信号来驱动外部装置。 首先,用户需要确保已经正确地连接了HX711称重模块和压力传感器,并按照正确的接线方式进行接口连接。接口连接后,可以通过Arduino或其他微控制器编写程序,将程序上传至板子中,并进行调试。调试包括断点调试和串口打印。 在断点调试中,用户可以设置断点,跟踪程序运行,查看代码运行到哪里会出现问题。这可以帮助用户轻松地定位代码错误并进行修复。 在串口打印中,用户可以通过设置串口波特率、串口发送和接收功能等参数来输出相关信息。这可以帮助用户更好地理解和处理设备的工作情况,更有效地进行数据分析和处理。 调试过程中,用户还可以通过实际测量物体的重量,并将其输出到串口监视器上来验证程序是否正确。如果程序正确,那么输出的重量应该与实际测量值基本相同。 总之,HX711称重模块的调试打印需要用户将程序上传到设备中,进行断点调试和串口打印,并进行实际测量来验证程序是否正确。通过这些步骤,用户可以快速调试和排除设备问题,从而有效地使用HX711称重模块。 ### 回答3: HX711称重模块是一种常用的传感器,可以广泛应用于称重、较高精度重量测量等领域。在使用过程中,常常需要对模块进行调试,以确保测量数据的准确性。调试打印是一种常用的调试方法,下面我们来介绍一下这种方法的具体实施过程。 首先需要准备好Arduino开发板、HX711称重模块和用于存储数据的计算机。然后将HX711模块与Arduino开发板相连,并将计算机与开发板通过USB线连接。接下来,在Arduino IDE中编写一个简单的程序,调用HX711的库函数,并将测量数据用串口输出到计算机上。具体代码如下: #include <HX711.h> HX711 scale; void setup() { Serial.begin(9600); scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN); } void loop() { float weight = scale.get_units(1); Serial.println(weight); delay(100); } 其中LOADCELL_DOUT_PIN和LOADCELL_SCK_PIN为HX711模块的数据和时钟引脚,根据实际连接情况进行修改。然后在串口监视器中打开打印窗口,即可实时看到模块测量到的数据。如果需要记录数据,可以将调用get_units()函数的次数增加或者添加数据存储功能,保存数据到计算机硬盘中。 当然,调试打印只是调试工具的一种,如果需要更加高效和准确地调试HX711模块,可以使用示波器、逻辑分析仪等专业的调试设备。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值