数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 3886|回复: 42

[ARM] 基于“HC32L136J8TA+SHT35+BMP280”的温度/湿度/大气压测量记录器

[复制链接]
发表于 2023-1-27 12:18:59 | 显示全部楼层 |阅读模式
本帖最后由 mmxx2015 于 2023-1-30 01:12 编辑

早就想做一个记录温度、湿度、大气压的装置,以前来找不到合适的外壳,也找不到合适的主控芯片,多方了解后决定用顶盖透明的ABS塑料盒做外壳,用宽电压、带段码LCD驱动的华大(小华)M0+芯片HC32L136J8TA做主控,显示使用6个8段码LCD,存储使用SPI接口写SD卡。

实物图:




为了低功耗,主控直接使用18650电池供电,外设电源用PMOS管控制后稳压再使用。为了高精度,传感器尽量选标称精度高的,大气压测量本来想使用BMP581,买了2颗芯片,发现手工焊接难度太大,暂时使用中端规格的BMP280成品模块。

数据按日期、时间以文本方式以csv格式保存到SD卡,可以直接用excel做出曲线。




主控平时工作于深度休眠模式,每秒通过RTC唤醒一次更新显示,电流约35μA,每分钟测量一次温度、湿度、大气压,工作时长约1秒,电流约8mA,一小时保存一次测量数据到SD卡,工作时长约10秒(预先5秒通电,写完成后延时5秒关电),电流约12mA(顺时针可能远大于这个值,工作时间太短,万用表测不到)。

  • 原理图


    原设计通过Micro USB座对18650电池充电,充电控制使用TP4065X(设计使用太阳能电池板为电池充电),顺便通过CH340N USB-串口芯片连接电脑作后续功能扩展用,如读取数据,后来觉得既然已经近距离操作了,还不如直接拔SD卡读卡方便,改为预留一个433MHz无线串口模块接口,需要时可以远距离查询数据。

    手上还有测量VCO、CH2O的模块,本来想有用没有全挂上,可是,这些模块都是电化学原理的,需要预热,而且测量时间长,工作电流大,放弃。
  • RTC校准
    为保证测量数据尽量和实际时间对应,需要高精度计时,一般做法是使用带温度补偿的时钟芯片或加网络授时模块,以DS3231SN为例,其标称精度是2ppm,也就是每月偏差5秒左右,一年大概偏差1分钟,实测也大概是这个精度,,精度也不是太高,网络授时一必须有网络二这种模块功耗太大,不符合低功耗要求。之前用调整补偿电容方法校准走时不准的石英钟可以做到每年误差不超过1分钟,HC32L136J8TA内部RTC可以校准,虽然不是每秒校准,但是可以满足要求。通常的校准方法是:先关闭校准功能,然后走时一段时间,如1天,根据时间差计算偏差ppm,这种做法首次校准耗时太长(可能需要数次校准才能达到预期的精度),可以换一种方法实现首次校准:用32768晶振作为主振荡器,通过芯片的HCLK输出功能将32768晶振实际频率从特定引脚输出,通过测量一段时间的脉冲数计算频偏ppm。

    实测:

    6554038个周期=199.99993904秒

    标称:
    (6554038*(1/32768))=200.01336669921875秒

    ppm=((200.01336669921875-199.99993904)/200.01336669921875)*1000000=67.133809306567950933455069988914

    实测时间比标称时间短,时间正偏,根据计算得到的误差ppm计算校准值写入RTC校准寄存器,实际运行几天,再根据实测偏差在上次校准值基础上微调就可以达到较高的计时精度。
  • 温度、湿度、大气压测量
    SHT35、BMP280都可以使用I2C接口控制,且它们预留的地址引脚无论怎么接,地址都不冲突,可以使用同一个I2C通讯口控制,主机、两个从机都支持标准的I2C协议,优选硬件I2C通讯。HC32L136J8TA的硬件I2C使用方法很简单,只需要设置好寄存器并开启I2C中断,在I2C中断服务程序中根据I2C状态码和参考手册中的状态图操作即可。相比SHT21,SHT35只需启动一次测量即可完成温度和湿度测量,相比BMP180,BMP280只需启动一次测量即可完成温度和大气压测量(BMP280测得温度与SHT35测得温度差0.5℃左右,个人认为SHT35测量结果更可靠)。每次测量,只需分时控制SHT35、BMP280测量一次即可。根据数据手册,这两颗芯片启动单次测量后都可以查询测量完成状态后读取测量结果,为简化程序,使用启动测量后延时比标称最长测量时间长10mS左右再读取测量结果。
  • 数据保存到SD卡
    为长时间存储且方便通过电脑读取保存的数据,使用SPI接口写SD卡、使用FATFS管理文件。读写SD卡程序随便找一个ARM开发板的例子中都有,读写使用的是延时等待逐个字节读写方式,移植是只需移植SPI收发和CS信号控制即可。FATFS模块移植只需按需修改ffconf.h中的配置,然后修改disk_read()、disk_write()调用扇区读写函数,其它初始化、状态查询函数直接返回正常状态即可。网上的FATFS模块移植例子使用的FATFS模块版本都比较老,最新的版本是FatFs R0.15+2022.12.4补丁,建议使用最新版打最新补丁后再使用,使用方法与旧版差异不大。
  • 日期和时间设置
    虽然设计上电后就不再断电,但为了更新程序或意外断电后方便调整日期、时间,增加按键设置接口,为更精准校时,预留中国码电波钟模块接口。
  • 软硬件文件
    硬件V2(立创EDA专业版工程):


    软件V1(Keil MDK工程,需稍加修改才能匹配V2硬件):



2023.1.30:
修正电源切换MOS管Q1电路错误(SD接反),感谢40560335指正。附件已更新。



补充内容 (2023-2-1 13:03):
附件程序生成保存数据的文件夹和文件名时存在重复用malloc()分配内存问题,堆空间满后程序运行不正常,下载过附件程序的请更新程序,见帖子最新。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x

打赏

参与人数 2家元 +40 收起 理由
cushion + 20 優秀文章
newnet1234 + 20 優秀文章

查看全部打赏

 楼主| 发表于 2023-1-27 17:16:35 | 显示全部楼层
kpj001 发表于 2023-1-27 12:57
还守着8字数码显示和SD卡,一个ESP32/ESP8266不就都解决了。https://blog.csdn.net/jiangge12/article/deta ...

定位不一样,我做这个是电池供电,必需省电,网络传输这种电老虎实在耗不起,还有,ESP32/ESP8266这种无法仿真的芯片不在考虑之内。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-27 17:24:35 | 显示全部楼层
触景情伤 发表于 2023-1-27 16:48
厉害了………单片机有点小众了…

宽电压、低功耗、RAM多、带段码LCD驱动、可仿真……这样一筛选,可选的不多。如果LDO稳压后再给MCU供电,可选的就比较多,不过,我查了好多LDO芯片的静态电流都在10μA以上,不划算,选的这颗芯片除了贵一点外,性能还是不错的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-29 10:54:30 | 显示全部楼层
kkstun 发表于 2023-1-29 08:51
我也认为esp8266不错。可以传输到服务器保存数据,手机实时查看服务器数据。 ...

这是个电老虎,而且无法仿真,出问题不好查,不适合我用,我也没用联网查询的需求,我的目标是做好后丢个角落过几个月、一年再去回收数据。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-29 23:07:18 | 显示全部楼层
本帖最后由 mmxx2015 于 2023-1-30 09:01 编辑
40560335 发表于 2023-1-29 22:20
外接电源供电/充电与电池供电电路会不会设计的有点问题,当外接电源时,VCC通过D1、MOS内部的二极管向锂电 ...

这是网上抄的电路,再搜一下这个电路,是MOS管SD极抄反了,我用的电池有保护板,没过冲,所以,没发现这个问题。



回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-30 15:59:02 | 显示全部楼层
sxwt1 发表于 2023-1-29 20:11
小米蓝牙温湿度计了解一下,温湿度正负百分之一误差,一节纽扣电池用一年 ...

网上拆解资料显示,这个用的传感器是是SHT30,相对湿度精度是±2、温度精度是±0.2。
我用的是SHT35,相对湿度精度是±1.5、温度精度是±0.1。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-30 16:15:17 | 显示全部楼层
lemontreenm 发表于 2023-1-30 13:58
我也一直想弄个测量并记录温湿度的模块。由于各种困难和自己的能力有限一直没弄好。看到楼主这个感觉可以参 ...

1.温湿度模块摆那里一是盒子布局决定的,二是本来设计用太阳能电池板对电池充电,希望测温位置离电池远些,如果有影响,可以在侧面钻孔(不影响美观)。
2.设计是1分钟测量一次,只是测量前提前1秒为传感器供电。
3.时间校准是另外做的,并不是每次校准,获得精度较好的校准值后直接使用。
4.我使用的很多地方都没有网络,网络校时不好实现,BPC校时就算是城市密集楼房,晚上1/4左右时间都可以校时。


回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-1 13:25:24 | 显示全部楼层
本帖最后由 mmxx2015 于 2023-2-1 13:27 编辑

2023.2.1程序更新:
保存数据的文件夹、文件名的RAM改为静态分配,解决多次重复动态分配内存问题导致堆空间溢出问题。


下载过附件程序的可以重新下载这一楼的附件,也可以按下面修改点修改:
SD_Card_Read_Write.h
  1. //FATFS结构体
  2. typedef struct
  3. {
  4.     FATFS    fs;                //文件系统对象
  5.     FIL    file;                //指向文件对象结构的指针
  6.     char    Directory[6+1];            //保存csv文件的文件夹
  7.     char    File_Path[19+1];        //csv文件完整路径
  8.     //char    *pDirectory;            //保存csv文件的文件夹指针
  9.     //char    *pFile_Path;            //csv文件完整路径指针
  10. }TypeDef_SD_Card_FATFS;
复制代码


SD_Card_Read_Write.c
  1. void SD_Card_Creat_File(void)
  2. {
  3.     //文件夹格式:年月,如:202301
  4.     SD_Card_FATFS.Directory[0]='2';    //20xx
  5.     SD_Card_FATFS.Directory[1]='0';
  6.     SD_Card_FATFS.Directory[2]=Digit_Character_Table[((User_RTC.Year>>4)&0x0f)];
  7.     SD_Card_FATFS.Directory[3]=Digit_Character_Table[(User_RTC.Year&0x0f)];
  8.     SD_Card_FATFS.Directory[4]=Digit_Character_Table[((User_RTC.Month>>4)&0x0f)];
  9.     SD_Card_FATFS.Directory[5]=Digit_Character_Table[(User_RTC.Month&0x0f)];
  10.     SD_Card_FATFS.Directory[6]=0;    //字符串结束符
  11.    
  12.     //SD_Card_FATFS.pDirectory=(char *)&SD_Card_FATFS.Directory;
  13.    
  14.    
  15.     //文件夹格式:年月,如:202301
  16.     SD_Card_FATFS.File_Path[0]='2';    //20xx
  17.     SD_Card_FATFS.File_Path[1]='0';
  18.     SD_Card_FATFS.File_Path[2]=Digit_Character_Table[((User_RTC.Year>>4)&0x0f)];
  19.     SD_Card_FATFS.File_Path[3]=Digit_Character_Table[(User_RTC.Year&0x0f)];
  20.     SD_Card_FATFS.File_Path[4]=Digit_Character_Table[((User_RTC.Month>>4)&0x0f)];
  21.     SD_Card_FATFS.File_Path[5]=Digit_Character_Table[(User_RTC.Month&0x0f)];
  22.     SD_Card_FATFS.File_Path[6]='/';

  23.     //文件名格式:年月日.csv,如:20221201.csv
  24.     SD_Card_FATFS.File_Path[7]='2';    //20xx
  25.     SD_Card_FATFS.File_Path[8]='0';
  26.     SD_Card_FATFS.File_Path[9]=Digit_Character_Table[((User_RTC.Year>>4)&0x0f)];
  27.     SD_Card_FATFS.File_Path[10]=Digit_Character_Table[(User_RTC.Year&0x0f)];
  28.     SD_Card_FATFS.File_Path[11]=Digit_Character_Table[((User_RTC.Month>>4)&0x0f)];
  29.     SD_Card_FATFS.File_Path[12]=Digit_Character_Table[(User_RTC.Month&0x0f)];
  30.     SD_Card_FATFS.File_Path[13]=Digit_Character_Table[((User_RTC.Date>>4)&0x0f)];
  31.     SD_Card_FATFS.File_Path[14]=Digit_Character_Table[(User_RTC.Date&0x0f)];
  32.     SD_Card_FATFS.File_Path[15]='.';
  33.     SD_Card_FATFS.File_Path[16]='c';
  34.     SD_Card_FATFS.File_Path[17]='s';
  35.     SD_Card_FATFS.File_Path[18]='v';
  36.     SD_Card_FATFS.File_Path[19]=0;    //字符串结束符
  37.    
  38.     //SD_Card_FATFS.pFile_Path=(char *)&SD_Card_FATFS.File_Path;
  39. }
复制代码


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-3 12:40:11 来自手机浏览器 | 显示全部楼层
revery 发表于 2023-2-3 11:56
感觉优化一下可以加装一块小太阳能电池板,续航就就更久了

设计了充电电路就是为了用太阳能电池板充电的,文中也提到了,为了避免充电时电池温度高影响测温,特意把电池装在外面,最初的设计时用插针焊接的电池盒装里面的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-8 01:00:41 | 显示全部楼层
一天温度、湿度、大气压变化(阴天)


大气压变化与网上描述接近:
气压的日变化
  一般来讲,在气压的日变化中,一天中有两个高值和两个低值时段。最高值和最低值分别出现在当地((地方时,下同)9〜10时和15~16时;次高值和次低值分别出现在21~22时和3〜4时。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2023-3-24 00:19:50 | 显示全部楼层
alloystorm 发表于 2023-3-23 14:28
小华的11x系列是不是更便宜?硬件要求不高的话,好像有直接Pinpin兼容的更低端系列。 ...

HC32L110系列最多只有20Pin封装的,ROM够用,按照现在缓存一小时再保存的做法RAM就不够,虽然可以缓存少一些数据,但这个系列没有段码LCD,没有合适的低功耗显示方案。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-7-23 10:22 , Processed in 0.327601 second(s), 14 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表