项目介绍
此次项目主要使用的是纳芯微的温湿度传感NSHT30-QDNR 及压力传感器NSPAS3NIIRRAI 及角速度传感器 NSM3031A-Q1SPR 及12指神探控制器实现温度湿度、气压、磁场角度信息的采集,通过micropython 实现iic 控制读取温度湿度信息,然后通过adc 采集气压信息及磁场角度信息。通过kicad 绘制pcb 板,可以直接插到十二指神探中,并且预留了排针,后续也可进行单独使用。
项目设计思路(含设计框图)
1.温湿度传感器相对简单,通过IIC 总线控制就可获取相应的温度 湿度信息
2.气压传感器采用的是模拟输出,所有要使用RP2040 具有模拟接口的gpio 进行数据采集,由于输出最大是4.6v 大于3.3V 所以需要对输出的电压通过电阻分压,然后才能输入给mcu 中
3.地磁霍尔传感器器,是测量垂直磁场分布情况,进行感应输出模拟值,此处直接使用模拟信号进行采集,然后通过线性比例获取对应的角度信息,有于此次活动的版本不支持SPI ,曲线是默认 等比例的。
4.通过RP2040进行轮询获取所有传感器信息后,通过打印,上传给上位机中,可实时打印相关信息,便于查看
搜集素材的思路
1.十二指神探相关资料收集,扩展板pin定义指定,方便后续自己画扩展板,可以直接插到控制器上进行使用
2.查看wiki 上的 数据手册、编程手册、UG 等资料,设置电路图及代码编程
3.熟悉气压计、霍尔传感器、温湿度传感器相关工作原理
画原理图、PCB制板过程中遇到的问题,以及解决方法
1.三个元器件在kicad 中无现成的原理图库及封装库使用,需要自己进行绘制,或者去digekey 上找lib 导入到PCB 工程中
2.前期绘制原理图,考虑不充分,RP2040 只有指定的管脚有adc功能,后续调试通过跳线进行调试,然后再版打样测试实现的
3.早期的kicad 泪滴功能没有,后续使用KICAD 8.0 中,已经默认集成了泪滴功能,防止焊接把pin脚弄坏
实现结果展示(调试过程中遇到什么问题)
1.气压测量电压一直为3.3V,后来查看原理图默认输出范围会超过3.3V,最大会达到4.6V ,所以我通过输出进行1/2分压,然后输入给mcu 进行adc 采集计算电压
2.角度测量由于此次活动使用的NSM3031A-Q1SPR ,无法进行spi通讯设置,所以通过线性比例显示角度
关键代码及说明
1.温度湿度模块初始化及参数获取
i2c = I2C(0, scl=Pin(21), sda=Pin(20), freq=400_000)
nsht30 = NSHT30(i2c)
扩展板只有一组iic ,需要指定使用的PIN脚
def __init__(self, i2c=None,i2c_address=None,delta_temp=0,delta_hum=0):
self.delta_temp = delta_temp
self.delta_hum = delta_hum
if i2c is None:
raise ValueError('An I2C object is required.')
self.i2c = i2c
if(i2c_address==None):
self.i2c_addr=DEFAULT_I2C_ADDRESS
else:
self.i2c_addr = i2c_address
#print(self.i2c_addr)
def is_present(self):
"""
Return true if the sensor is correctly conneced, False otherwise
"""
return self.i2c_addr in self.i2c.scan()
模块初始化中,通过i2c扫描,确定是否能寻找到从设备
def send_cmd(self, cmd_request, response_size=6, read_delay_ms=100):
"""
Send a command to the sensor and read (optionally) the response
The responsed data is validated by CRC
"""
try:
self.i2c.writeto(self.i2c_addr, cmd_request)
if not response_size:
return
time.sleep_ms(read_delay_ms)
data = self.i2c.readfrom(self.i2c_addr, response_size)
## Byte1 Byte2 byte3 byte4 byte5 byte6
## tempMSB tempLSB CRC hum MSB hum LSB CRC
for i in range(response_size//3):
if not self._check_crc(data[i*3:(i+1)*3]): # pos 2 and 5 are CRC
raise SHT30Error(SHT30Error.CRC_ERROR)
if data == bytearray(response_size):
raise SHT30Error(SHT30Error.DATA_ERROR)
return data
except OSError:
raise SHT30Error(SHT30Error.BUS_ERROR)
except Exception as ex:
raise ex
通过I2C发送命令,然后收取I2C 回传的数据,通过校验确认数据的准确性,然后进行返回
def _check_crc(self, data):
# calculates 8-Bit checksum with given polynomial
crc = 0xFF
for b in data[:-1]:
crc ^= b
for _ in range(8, 0, -1):
if crc & 0x80:
crc = (crc << 1) ^ NSHT30.POLYNOMIAL
else:
crc <<= 1
crc_to_check = data[-1]
return crc_to_check == crc
crc8 计算方法
实际调用屏幕显示及回传给pc
data=nsht30.measure()
display.text(font2, "temp="+"%.1f c"%(data[0]), 10, 110)
print("temp=%.1f c\n",data[0])
display.text(font2, "hum="+"%.1f %%"%(data[1]), 10, 140)
print("hum=%.1f %%\n",data[1])
2.压力值获取
通过手册转换关系可知P= (Vout/5-B)/A = (Vout/5+0.00095)/0.008095
硬件采用1/2分压,所以P = (Vout/2.5+0.00095)/0.008095
所以实际采集及回传如下
vout = pressure_out.read_u16()*3.3/65535
per=(vout/2.5+0.00095)/0.008095
display.text(font2, "per="+"%.2fkPa"%(per), 10, 170)
print("per=%.1fkPa\n",per)
3.角度传感器
角度传感器读取和气压传感器类似,这里直接使用等比例转换如下:
vout1 = angle_out.read_u16()*3.3/65535
display.text(font2, "angle="+"%.1f c"%(vout1*360/3.3), 10, 200)
print("angle=%.1f c\n",per)
原理图/PCB图(放在项目附件)
可编译下载的代码(放在项目的附件,用于验证)
见附件
心得感受
1.建议答疑环节或者资料中提供厂商 demo板的原理图,方便进行移植验证
2.时间适当放宽些,年底相对比较忙,或者多个活动再同时参加