1. 项目背景与硬件选型
大家好,今天我想和大家分享一个实用的智能体重秤项目,使用STC8G1K08A单片机和HX711模块来实现低功耗设计。这个项目特别适合想要自己动手做智能家居设备的朋友,不需要太多专业知识就能上手。
先说说为什么选择STC8G1K08A这款单片机。我在实际项目中测试过多款MCU,最终选择它主要是因为它的低功耗特性非常出色。这款芯片基于8051架构,最高运行频率可以达到30MHz,内置8KB的Flash存储器和1.2KB的SRAM,对于体重秤这种应用来说完全够用。更重要的是,它支持多种低功耗模式,在待机状态下功耗可以低至0.1微安,这对电池供电的设备来说非常关键。
HX711是一款24位高精度模数转换芯片,专门为称重传感器设计。我之前用过其他ADC芯片,但HX711的集成度更高,它内置了放大器,可以直接连接称重传感器,大大简化了电路设计。在实际测试中,它的精度可以做到10克以内的误差,完全满足家用体重秤的需求。
显示部分我选择了TM1637驱动芯片配合四位共阳极数码管。这种组合的好处是接线简单,只需要两根数据线就能驱动数码管显示,而且TM1637本身也支持亮度调节,可以帮助进一步降低整体功耗。
2. 硬件电路设计
电路设计是整个项目的基础,好的电路设计不仅能保证测量精度,还能有效降低功耗。我的设计思路是尽量简化电路,减少外部元件数量。
电源部分使用两节AA电池供电,通过一个低压差稳压器提供3.3V工作电压。这里有个小技巧:我在稳压器的使能端接了一个单片机IO口,当系统进入休眠模式时,可以通过这个引脚关闭稳压器,进一步降低静态功耗。
称重传感器采用常见的悬臂梁式传感器,量程150kg,灵敏度2.0mV/V。传感器输出信号直接连接到HX711的A+和A-输入端。这里要注意接线顺序,如果发现读数异常,可以尝试调换A+和A-的接线,或者调换E+和E-的接线。
我在实际制作时发现采样电阻的选择很重要。最初使用100K欧姆的采样电阻,发现读数不太稳定,后来换成200K欧姆后效果明显改善。这是因为较大的采样电阻可以减小输入电流,提高测量稳定性,但同时也会降低灵敏度,需要根据实际需求权衡。
显示部分使用TM1637驱动数码管,只需要四根连接线:VCC、GND、DIO和CLK。为了降低功耗,我通过程序控制数码管的亮度,在不需要显示时将亮度调到最低,甚至完全关闭显示。
3. 软件程序设计
软件设计是项目的核心,好的程序不仅能实现功能,还能最大化降低功耗。我的程序结构主要分为三个部分:系统初始化、数据采集处理和显示控制。
系统初始化包括设置IO口模式、初始化定时器、配置低功耗模式等。这里要特别注意IO口的配置,未使用的IO口最好设置为高阻输入模式,这样可以减少不必要的功耗。
void System_Init(void)
{
P1M0 = 0x00; //设置所有IO口为准双向模式
P1M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
// 设置HX711相关IO口
HX711_CLK = 0;
HX711_DATA = 1; //设置为输入模式
// 初始化TM1637
TM1637_Init();
// 启用低功耗模式
PCON |= 0x01; //启用空闲模式
}
数据采集是关键部分,HX711的读数需要严格按照时序进行。每次读数前需要等待DOUT引脚变低,表示数据就绪,然后发送25-27个时钟脉冲来读取24位数据。
unsigned long Read_HX711(void)
{
unsigned long count = 0;
unsigned char i;
HX711_CLK = 0;
while(HX711_DATA); // 等待数据就绪
for(i = 0; i < 24; i++)
{
HX711_CLK = 1;
Delay_us(1);
count = count << 1;
HX711_CLK = 0;
Delay_us(1);
if(HX711_DATA)
count++;
}
// 发送第25个脉冲设置下次采样的增益
HX711_CLK = 1;
Delay_us(1);
HX711_CLK = 0;
return count;
}
数据处理部分包括重量计算和滤波算法。我采用了一个简单的滑动平均滤波来平滑数据,同时设置了重量阈值,只有当重量变化超过一定值时才更新显示,这样可以避免数码管数字频繁跳动。
4. 低功耗优化策略
低功耗设计是这个项目的重点,我通过硬件和软件两方面进行了优化。在实际测试中,整个系统在待机状态下的功耗可以做到低于5微安,这意味着两节AA电池可以使用一年以上。
硬件方面的优化主要包括:选择低功耗器件、优化电源电路、合理配置未使用IO口。我特别推荐使用低功耗LDO稳压器,它的静态电流可以做到1微安以下。另外,所有外部上拉或下拉电阻都选择较大的阻值,比如100K欧姆以上,以减少电流消耗。
软件方面的优化更加重要。我的做法是让单片机大部分时间处于休眠模式,只有需要采样时才唤醒。具体实现是通过定时器中断,每秒钟唤醒一次进行采样,采样完成后立即返回休眠模式。
void Timer0_Init(void)
{
AUXR |= 0x80; //定时器0为1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1; //开启总中断
}
void Timer0_ISR() interrupt 1
{
static unsigned int counter = 0;
if(++counter >= 1000) //1秒
{
counter = 0;
wakeup_flag = 1; //设置唤醒标志
}
}
显示部分的功耗优化也很重要。TM1637支持多级亮度调节,在正常使用时设置亮度为中级,在待机时设置为最低亮度甚至关闭显示。我还设置了显示超时功能,如果10秒内没有重量变化,就自动关闭显示。
5. 数据处理与校准算法
重量数据的处理和校准直接影响到测量精度。我采用了一套完整的校准流程,包括去皮、线性校准和温度补偿。
首先是最重要的去皮功能。每次上电后,系统会自动采集10次空载读数并取平均值作为零点值。在实际使用中,用户也可以长按按键手动去皮。
void Tare_Weight(void)
{
unsigned char i;
unsigned long sum = 0;
for(i = 0; i < 10; i++)
{
sum += Read_HX711();
Delay_ms(100);
}
zero_offset = sum / 10; //计算零点偏移值
}
线性校准使用两点校准法。需要准备两个已知重量的标准砝码,通常选择量程的20%和80%两个点。通过这两个点可以计算出校准系数:
void Calibration(void)
{
float weight1 = 10.0; //10kg标准砝码
float weight2 = 80.0; //80kg标准砝码
unsigned long adc1, adc2;
// 采集轻重量读数
adc1 = Read_HX711() - zero_offset;
// 采集重重量读数
adc2 = Read_HX711() - zero_offset;
// 计算校准系数
scale_factor = (weight2 - weight1) / (adc2 - adc1);
linear_offset = weight1 - adc1 * scale_factor;
}
在实际测量中,我还加入了数字滤波算法。使用一阶低通滤波来平滑数据,同时设置了重量变化阈值,只有当重量变化超过0.2kg时才更新显示,这样可以避免数码管数字跳动。
6. 实际调试与问题解决
在实际调试过程中,我遇到了几个典型问题,这里分享给大家避免踩坑。
第一个问题是读数不稳定。最初发现读数总是跳变,后来发现是电源噪声导致的。解决方法是在HX711的电源引脚加了10uF和0.1uF的退耦电容,同时给模拟部分单独供电,与数字部分隔离。
第二个问题是重量显示异常。有时候会出现负数或者超量程的数值。经过分析发现是24位ADC的数据处理问题。STC8G是16位单片机,直接使用int类型会溢出,必须使用long类型。
long int Process_Data(unsigned long raw_data)
{
long int processed_data;
// 转换为有符号数
if(raw_data & 0x800000)
processed_data = -(long int)((raw_data ^ 0xFFFFFF) + 1);
else
processed_data = (long int)raw_data;
// 减去零点偏移
processed_data -= zero_offset;
// 应用校准系数
return (long int)(processed_data * scale_factor + linear_offset);
}
第三个问题是低功耗模式下的唤醒问题。最初发现单片机有时无法正常唤醒,后来发现是中断配置问题。解决方法是在进入休眠前清除所有中断标志,并确保唤醒中断正确配置。
第四个问题是温度漂移。称重传感器的输出会随温度变化,我采用了简单的温度补偿算法。通过测量环境温度,对读数进行补偿:
float Temperature_Compensation(long int raw_weight, float temperature)
{
float compensated_weight;
float temp_coeff = 0.001; //温度补偿系数
// 简单的线性温度补偿
compensated_weight = raw_weight * (1 + temp_coeff * (temperature - 25.0));
return compensated_weight;
}
7. 性能测试与优化
完成初步开发后,我进行了一系列性能测试,包括精度测试、功耗测试和稳定性测试。
精度测试使用标准砝码,从5kg到150kg每隔5kg测试一个点。测试结果显示,在全部量程范围内,误差小于0.1%,完全满足家用体重秤的精度要求。特别是在50-100kg常用范围内,误差可以控制在0.05%以内。
功耗测试结果令人满意。正常工作状态下,平均电流为1.2mA;显示状态下电流为3.5mA;休眠状态下电流仅4.8微安。按照每天使用10次,每次使用10秒计算,两节AA电池可以使用超过2年。
稳定性测试包括长时间运行测试和温度变化测试。连续运行72小时,读数漂移小于10克;在10-40摄氏度温度范围内,温度系数小于0.01%/℃。
基于测试结果,我进一步优化了程序:调整了采样频率,在稳定状态下降低采样率以减少功耗;优化了显示刷新算法,减少不必要的显示更新;改进了滤波算法,在保证响应速度的前提下提高了稳定性。
8. 实用技巧与注意事项
在实际制作过程中,我总结了一些实用技巧。焊接时要特别注意HX711模块的焊接温度,建议使用350度以下的温度,焊接时间不要超过3秒,否则容易损坏芯片。称重传感器的安装很重要,要确保四个传感器均匀受力,最好使用专用的安装支架。
程序调试时,建议先调试HX711的读数功能,确保能读到稳定的原始数据后再进行后续处理。可以使用串口输出原始读数,方便调试。显示部分可以先测试TM1637的基本功能,确保能正常显示数字后再集成到主程序中。
在使用过程中,要定期校准,建议每半年校准一次。校准时要使用准确的砝码,最好选择两个不同重量的砝码进行两点校准。放置秤的位置要水平稳固,避免在柔软的地毯或不平整的地面上使用。
对于想要进一步改进的朋友,可以考虑增加蓝牙功能,将数据发送到手机APP记录;或者增加用户识别功能,支持多用户使用;还可以增加体脂测量功能,不过这就需要使用四电极测量法,复杂度会提高很多。
最后提醒大家,静电防护很重要,特别是在干燥季节。焊接和使用时最好佩戴防静电手环,避免芯片被静电击穿。
8976



被折叠的 条评论
为什么被折叠?



