基于纳芯微NSHT30,NSPAS3,NSM3013设计的环境检测桌搭
本项目采用树莓派十二指神探作为主控, 通过多种协议实现对纳芯微NSHT30,NSPAS3,NSM3013数据的读取,使其可以在主控上显示环境的相关参数信息。
标签
嵌入式系统
WeDesign活动
纳芯微电子
Wang Chong
更新2024-12-26
90

项目介绍

该项目采用树莓派RP2040作为主控芯片(十二指神探),通过ADC,I2C等外设完成对、NSHT30(湿温度传感器),NSPAS3(压力传感器),NSM3013(角速度传感器)的读取。 并且结合SPI驱动屏幕,使其对应的数据信息显示在屏幕上。 通过判断不同的按键的状态, 允许用户切换不同的界面来显示不同的数据信息等。

项目设计思路

由于项目本次的主控为树莓配的RP2040, 同时开发环境为Micro-python, 因此在项目的开发中需要首先熟悉Micro -python和相关库的使用, 比如说Uart , ADC, I2C 等等。

对于相关的传感器器件,我们首先要确定的是其通讯的方式, 比如说通过查看数据手册的方式来找到对应的通讯时序, 通讯协议等等。拿NSH30举例, 其通讯协议为I2C,因为我们只需要熟悉micro python的I2C库代码,并且结合通讯时序即可正确的读取湿温度数据。


对于每一个传感器等,我们可以创建不同的Py程序,使用不同的方式驱动。 在驱动成功之后(即有正确数据回显),我们再将当前程序的核心功能封装成Class的形式来供其外部进行调用。


当所有的功能模块都集成在一起并且可以正确显示之后,我们便可以进行进阶任务的完成,比如说编写GUI界面使其可以通过不同的IO状态来显示不同的UI界面等。


搜集素材的思路

对于素材的收集,纳芯微官方提供了非常好的资料, 比如说数据手册或者详细的使用说明。 因为选取资料的时候我们应该首选使用官方的资料进行参考,其次才是从网上寻找博客内容进行引用。对于部分的传感器比如NSHT30, 纳芯微官方还提供了基于STM32Hal函数的实现。 因为我们可以更好的理解并且转换这一部分知识。


而对于芯片的封装,纳芯微官方同样提供了不同的文件供我们下载使用,我们可以非常方便的将对应的封装信息导入到Kicad中,并且进行原理图和PCB绘制


画原理图、PCB制板过程中遇到的问题,以及解决方法


项目要求使用KIcad绘制PCB,但是碰巧的是硬禾课堂中正好有一份非常详细的Kicad的教程, 我花了一天的时间进行学习。基本上可以上手Kicad的使用,当我遇见问题的时候我会重新打开对应的视频章节中进行复习。


实现结果展示(调试过程中遇到什么问题)


在实际的实现过程中我主要遇见了两个问题, 第一个问题是湿温度传感器无响应的, 第二个则是压力传感器的引脚焊盘没有正确的焊接成功。


湿温度传感器无响应

对于NSHT30, 我是一步一步的根据数据手册上面的命令和通讯时序进行操作, 同时使用逻辑分析仪进行辅助数据分析。如下图所示

2253cbb98091646dc92e543144d4a83.png
我已经严格的按照的通讯的要求进行数据的发送,但是实际上在读Data的时候NSHT30完全没有数据的响应。
8befbc4a2c6ecde86fd8bdc0833ccda.png
下图为读命令
a647dc89a56ac1ffd6a74d78974a5df.png
之后也根据数据手册尝试过不同的读取模式, 皆没有得到过响应, 于是在群友的指导下,我尝试使用了一块ESP32, 结合Adafruit的SHT30库,来对NSHT30的数据在Arduino的环境下进行数据的读取。 结果也不能正常的通讯。如下图所示。

897f95a6d21f1a640ecf036dc69f009.png

其错误信息和我使用Mpy的错误信息一致(无数据返回)。

16c7a02c4ab4c5064db483b9e59aa6e.png

之后我更换了NSHT30, 然后重新使用Arduino的库进行测试, 发现通讯恢复,即是芯片的问题(可能是因为我使用洗板水清洗了电路板导致的)

99c06a499e375646fda3c4995d119cb.png

至此, NSHT30的测试完毕, 可以正常的移植到Mpy上了。


NSPAS3压力传感器虚焊


对于NSPAS3压力传感器,则是因为这个引脚虚焊了,导致每次读取出来的电压都是0.5v左右,而当我更换引脚的时候错把角度传感器的输出当作了压力传感器的输出, 因此每次读出来的数据还真的基本上正确。 但是到最后排查的时候发现,不知道为什么压力传感器会根据磁铁的变化而变化才之后是自己接错了线。 并且使用万用表进行通断检测的时候才发现这个压力传感器虚焊了。于是我简单的刮开了一些铜皮,再次焊接,便完成了这次的错误排查。


fc47aa9996f78bdd76412325a7a6c8d.jpg

关键代码及其说明


关键代码主要有NSHT30的读取, 压力传感器和角度传感器的读取。


NSHT30 驱动类

from machine import I2C, Pin
import utime

class SHT30:
def __init__(self, i2c, address=0x44):
self.i2c = i2c
self.address = address

@staticmethod
def check_crc(data):
"""Check CRC checksum"""
POLYNOMIAL = 0x31
crc = 0xFF
for byte in data:
crc ^= byte
for _ in range(8):
if crc & 0x80:
crc = (crc << 1) ^ POLYNOMIAL
else:
crc <<= 1
crc &= 0xFF
return crc

def read_temperature_humidity(self):
"""Read temperature and humidity from SHT30 sensor"""
try:
# Send read command and wait for data
self.i2c.writeto(self.address, bytes([0x24, 0x00]), False)
utime.sleep_ms(50) # Wait for SHT30 to prepare data
data = self.i2c.readfrom(self.address, 6)

# Check CRC
temp_raw = data[0:2]
temp_crc = data[2]
hum_raw = data[3:5]
hum_crc = data[5]

if self.check_crc(temp_raw) != temp_crc:
raise ValueError("Temperature CRC check failed!")

if self.check_crc(hum_raw) != hum_crc:
raise ValueError("Humidity CRC check failed!")

# Parse and calculate temperature and humidity
temp_val = (temp_raw[0] << 8) | temp_raw[1]
hum_val = (hum_raw[0] << 8) | hum_raw[1]

temperature = -45 + 175 * (temp_val / 65535.0)
humidity = 100 * (hum_val / 65535.0)

t_res = float("{:.2f}".format(temperature))
h_res = float("{:.2f}".format(humidity))


return t_res, h_res

except OSError as e:
print("Error reading from sensor:", e)
return None, None


压力传感器的两种转换方法

import machine
import utime

# 初始化ADC
potentiometer = machine.ADC(2)
# 转换因子
conversion_factor = 3.3 / (65536)
A = 0.008095
B = -0.00095
VDDHV = 3.3

while (1):
# 读取ADC值并转换成电压
voltage = potentiometer.read_u16() * conversion_factor

# 计算实际压力,假设为比率计量输出
pressure_ratio_metric = ((voltage / VDDHV) - B) / A

# 对于绝对输出,可以按照下面的方式计算(如果适用的话)
# 注意:这里直接使用3.3V作为参考电压,因为你的转换因子是基于3.3V。
pressure_absolute = ((voltage / 3.3) - B) / A

print("Voltage: {:.4f}V, Ratio Metric Pressure: {:.4f}kPa, Absolute Pressure: {:.4f}kPa".format(voltage, pressure_ratio_metric, pressure_absolute))

utime.sleep_ms(500)


角度传感器的读取


from machine import ADC
import utime

class AngleSensor:
def __init__(self, adc_pin):
"""初始化角度传感器"""
self.adc = ADC(adc_pin)

def get_angle(self):
"""读取传感器角度值"""
analog_value = self.adc.read_u16()
angle = 300 * float(analog_value) / 65535 # 将 ADC 值转换为角度
return round(angle, 2) # 保留两位小数


以及最终的GUI界面的核心代码和效果等


import test.st7789 as st7789
from test.fonts import vga2_8x8 as font1
from test.fonts import vga1_16x32 as font2
import framebuf
from machine import Pin, SPI, PWM, I2C,ADC,UART
from sht30 import SHT30
from angle_sensor import AngleSensor

# 按键初始化
button_right = Pin(9, Pin.IN, Pin.PULL_UP)
button_left = Pin(7, Pin.IN, Pin.PULL_UP)
# 初始化变量
index = 1

# PWM 初始化
pwm = PWM(Pin(19))
pwm.freq(50)

# 显示屏初始化
st7789_res = 0
st7789_dc = 1
disp_width = 240
disp_height = 240
spi_sck = Pin(2)
spi_tx = Pin(3)
spi0 = SPI(0, baudrate=4000000, phase=1, polarity=1, sck=spi_sck, mosi=spi_tx)
uart = UART(1, baudrate=115200, tx=Pin(20), rx=Pin(21))

display = st7789.ST7789(
spi0,
disp_width,
disp_width,
reset=Pin(st7789_res, Pin.OUT),
dc=Pin(st7789_dc, Pin.OUT),
xstart=0,
ystart=0,
rotation=0,
)
display.fill(st7789.BLACK)

# SHT30 初始化
i2c = I2C(1, scl=Pin(23), sda=Pin(22), freq=400000)
sensor = SHT30(i2c)

angle_sensor = AngleSensor(0)

potentiometer = machine.ADC(2)

#转换因子
conversion_factor = 3.3 / (65536)
A = 0.008095
B = -0.00095
VDDHV = 3.3

def readPressure():
# 读取ADC值并转换成电压
voltage = potentiometer.read_u16() * conversion_factor

# 计算实际压力,假设为比率计量输出
pressure_ratio_metric = ((voltage / VDDHV) - B) / A

# 对于绝对输出,可以按照下面的方式计算(如果适用的话)
# 注意:这里直接使用3.3V作为参考电压,因为你的转换因子是基于3.3V。
pressure_absolute = ((voltage / 3.3) - B) / A

#print("Voltage: {:.4f}V, Ratio Metric Pressure: {:.4f}kPa, Absolute Pressure: {:.4f}kPa".format(voltage, pressure_ratio_metric, pressure_absolute))
display.text(font2, str(pressure_ratio_metric) , 50, 110)
uart_data = "Voltage: {:.4f}V, Ratio Metric Pressure: {:.4f}kPa, Absolute Pressure: {:.4f}kPa\r\n".format(voltage, pressure_ratio_metric, pressure_absolute)
uart.write(uart_data)

# 界面绘制函数
def drawTH():
display.fill(st7789.BLACK)
display.fill_rect(0, 0, 240, 50, 0xFCA0)
display.text(font2, "HUM & TEMP", 50, 10)
display.text(font1, "Temperature:", 0, 70)
display.line(0, 130, 240, 130, 0xFCA0)
display.text(font1, "Humidity:", 0, 150)


def drawAngle():
display.fill_rect(0, 0, 240, 50, 0xFCA0)
display.text(font2, "Angle Sensor", 30, 10)
display.text(font1, "°" , 190, 100)


def drawPressure():
display.fill_rect(0, 0, 240, 50, 0xFCA0)
display.text(font2, "Pressure Sensor", 0, 10)
display.text(font1, "Kpa" , 190, 150)


needUpdate = True


# 主循环
while True:
# 按键右,切换到下一界面
if button_right.value() == 0:
if index < 3:
index += 1
needUpdate = True
display.fill(st7789.BLACK) # 清屏
# 按键左,切换到上一界面
if button_left.value() == 0:
if index > 1:
needUpdate = True
index -= 1
display.fill(st7789.BLACK) # 清屏

# 根据 index 显示不同的界面
if index == 1:
temperature, humidity = sensor.read_temperature_humidity()
if(needUpdate):
drawTH()
needUpdate = False
t_res = float("{:.2f}".format(temperature))
h_str = "{:4}".format("{:.2f}".format(humidity))
display.text(font2, str(t_res)+" C'", 90, 90)
display.text(font2, h_str +" %", 90, 170)
t_res = float("{:.2f}".format(temperature))
h_res = float("{:.2f}".format(humidity)) # 将湿度值转换为浮动数值

# 格式化数据为字符串
uart_data = "Temperature: {:.2f} C, Humidity: {:.2f}%\r\n".format(t_res, h_res)
uart.write(uart_data)
elif index == 2:
if(needUpdate):
drawAngle()
needUpdate = False
angle = angle_sensor.get_angle()
display.text(font2, str(angle) , 70, 110)
uart_data = "Angle: {:.2f} degrees\r\n".format(angle)
uart.write(uart_data)
elif index == 3:
if(needUpdate):
drawPressure()
needUpdate = False
readPressure();


效果展示


界面 1 : 温度和湿度


27349ef10ad5017afd82844a1fc783a.jpg


界面2 : 角度


ef640f08a5fafcf815042174c17cfc5.jpg


界面3 : 大气压强


4a179b3c2ee10b858f31c6b123b929c.jpg



心得感悟

非常感谢能够参加到本次的活动,这次活动中我最大的收获就是学习到了如何使用micro python 和其相关的库, 非常感谢EETree 和纳芯微电子举办的这次活动。增加了我在代码方面的能力。非常感谢!

物料清单
KiCad文件
使用说明
全屏
附件下载
电子森林.zip
project.zip
请运行screen.py
团队介绍
电子爱好者
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号