2. 移动式河流水质检测器
系统分主机(接收显示)和从机(检测发送)两部分,从机检测记录水相关参数(温度、浊度、TDS等),主机接收显示数据。
器材:
控制器:开元x2
模块:温度传感器;浊度传感器;TDS传感器;GPS卫星定位导航模块;无线串口通信模块x2
2.1. 程序(检测发送端)
from openaie import get_port_pin, bds, rf
import time, struct, _thread
from machine import ADC, Pin
import onewire, ds18x20
import lcd
lcd.rotation(0)
lcd.set_backlight(60)
'''
温度检测(DS18B20)
'''
sig = machine.Pin(get_port_pin(3, 2)) # 开元主控端口3,信号线2
ds = ds18x20.DS18X20(onewire.OneWire(sig))
roms = ds.scan()
print('found devices:', roms[0])
convert = False
temp_deadline = 0
temperature = 0
def read_temp():
global convert, temp_deadline, temperature
if not convert:
convert = True
ds.convert_temp() # 开始转换
temp_deadline = time.ticks_add(time.ticks_ms(), 750)
if time.ticks_diff(temp_deadline, time.ticks_ms()) < 0: # 等待
convert = False
temperature = ds.read_temp(roms[0]) # 读取测量结果
#print("temperature: %.1f℃\r\n"%temperature)
'''
TDS检测
'''
adc1 = ADC(Pin(get_port_pin(3, 1))) # 开元主控端口3,信号线1 ADC1
k = 1 # k为对照标准TDS溶液得到的计算值
tds = 0
def read_tds(temp=None):
global tds
r = adc1.read_u16()
#print("ADC value: ", r)
vol = r*3.3/65535.0 # 转换为电压
#print("Voltage: V", vol)
if temp is not None: # 温度补偿
temp_correct = 1+0.02*(temp-25) # 温度修正
vol = vol*temp_correct # 电压修正
tds_row = 66.71*pow(vol,3) - 127.93*vol*vol + 428.7*vol
tds = int(tds_row*k) # 矫正后的值
'''
浊度检测
'''
adc2 = ADC(Pin(get_port_pin(4, 1))) # 开元主控端口4,信号线1 ADC2
turbidity = 0
def read_turbidity():
global turbidity
r = adc2.read_u16()
#print("ADC value: ", r)
vol = r*3.3/65536.0 # 转换为电压
#print("Voltage: V", vol)
turbidity = vol
'''
无线串口通信模块初始化
'''
rf = rf(7)
if rf.set('tx', '11223'):
print("发送模式初始化成功")
else:
print("发送模式初始化失败")
'''
时区转换
@dt: 日期时间 格式[year, month, day, hour, minute, second]
@timezone: 时区 默认为东8区,即北京时间
'''
def datetime(dt, timezone=8):
year, month, day, hour, minute, second = dt[:]
month_day = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
if year%4 == 0: # 闰年判断
month_day[1] = 29
hour += timezone
if hour >= 24:
hour -= 24
day += 1
if day > month_day[month-1]:
day -= month_day[month-1]
month += 1
if month > 12:
month = 1
year += 1
date_string = "%04d/%02d/%02d"%(year, month, day)
time_string = "%02d:%02d:%02d "%(hour, minute, second)
#print(date_string, ' ', time_string)
return [year, month, day, hour, minute, second]
'''
GPS数据接收解析
'''
my_gps = bds(1)
def core1_main():
global my_gps
display_deadline = 0
gps_deadline = 0
while True:
if time.ticks_diff(gps_deadline, time.ticks_ms()) < 0:
gps_deadline = time.ticks_add(time.ticks_ms(), 200)
my_gps.update() # GPS更新数据
if time.ticks_diff(display_deadline, time.ticks_ms()) < 0:
display_deadline = time.ticks_add(time.ticks_ms(), 500) # 数据更新周期 500ms
read_turbidity()
time.sleep_ms(10)
read_temp()
read_tds(temperature)
lcd.clear(color=(0,0,0))
# 显示卫星信息
lcd.draw_string(10, 30, '可见卫星: %s 颗'%my_gps.satellites_in_view, fc=(0,0,255), bc=(0,0,0))
lcd.draw_string(10, 50, '使用卫星: %s 颗'%my_gps.satellites_in_use, fc=(0,0,255), bc=(0,0,0))
# 显示经纬度
lcd.draw_string(10, 70, '经度: %s'%(my_gps.longitude[0]), fc=(0,0,255), bc=(0,0,0))
lcd.draw_string(10, 90, '纬度: %s'%(my_gps.latitude[0]), fc=(0,0,255), bc=(0,0,0))
# 显示日期时间
day, month, year = my_gps.date[:] # 获取日期(UTC)
hour, minute, second = my_gps.timestamp[:] # 获取时间(UTC)
year, month, day, hour, minute, second = datetime([year+2000, month, day, hour, minute, second])[:] # 时区转换
date_string = "%04d/%02d/%02d"%(year, month, day)
lcd.draw_string(10, 5, date_string, fc=(0,0,255), bc=(0,0,0))
time_string = "%02d:%02d:%02d "%(hour, minute, second)
lcd.draw_string(100, 5, time_string, fc=(0,0,255), bc=(0,0,0))
# 显示测量信息
lcd.draw_string(10, 150, "温度: %.1f"%temperature, fc=(0,0,255), bc=0)
if tds>300:
tds_color = (255,0,0)
elif tds>200:
tds_color = (0,0,255)
else:
tds_color = (0,255,0)
lcd.draw_string(10, 170, "TDS: %d ppm"%tds, fc=tds_color, bc=0)
if turbidity > 2.96:
lcd.draw_string(10, 190, "浑浊度: 1 级", fc=(0,255,0), bc=0)
elif turbidity > 2.64:
lcd.draw_string(10, 190, "浑浊度: 2 级", fc=(0,0,255), bc=0)
elif turbidity> 1.84:
lcd.draw_string(10, 190, "浑浊度: 3 级", fc=(255,0,255), bc=0)
else:
lcd.draw_string(10, 190, "浑浊度: 4 级", fc=(255,0,0), bc=0)
#lcd.draw_string(10, 190, "浑浊度: %.2f"%turbidity, fc=(0,0,255), bc=0)
lcd.display()
_thread.start_new_thread(core1_main, ())
send_deadline = 0
send_buf = bytearray(20)
while True:
if time.ticks_diff(send_deadline, time.ticks_ms()) < 0:
send_deadline = time.ticks_add(time.ticks_ms(), 500) # 数据发送周期 1000ms
send_buf[:2] = 'TX'.encode() # 帧头
send_buf[2:6] = struct.pack('>f', temperature)
send_buf[6:10] = struct.pack('>f', turbidity)
send_buf[10:12] = struct.pack('>H', tds)
send_buf[12:16] = struct.pack('>f', my_gps.longitude[0])
send_buf[16:20] = struct.pack('>f', my_gps.latitude[0])
rf.send(send_buf)
2.2. 程序(接收显示端)
'''
注意:无线模块接线更改!!!
'''
import lcd, time, struct
from openaie import rf
# 无线串口通信模块初始化
rf = rf(1)
if rf.set('rx', '11223'):
print("发送模式初始化成功")
else:
print("发送模式初始化失败")
# 显示屏设置
lcd.rotation(1)
lcd.set_backlight(60)
rx_cnt = 0
update_deadline = 0
#
while True:
if time.ticks_diff(update_deadline, time.ticks_ms()) < 0:
update_deadline = time.ticks_add(time.ticks_ms(), 500)
# 读取接收数据
rx_buf = rf.read(32)
if rx_buf is not None:
#print('rx len: ',len(rx_buf))
if len(rx_buf) < 20:
continue
temperature = struct.unpack('>f', rx_buf[2:6])[0]
turbidity = struct.unpack('>f', rx_buf[6:10])[0]
tds = struct.unpack('>H', rx_buf[10:12])[0]
longitude = struct.unpack('>f', rx_buf[12:16])[0]
latitude = struct.unpack('>f', rx_buf[16:20])[0]
lcd.clear(color=(0,0,0))
#
lcd.draw_string(112, 5, '河流水质检测', fc=(0,0,255), bc=(0,0,0))
lcd.draw_line(0, 30, 319, 30, color=(0,0,255), thickness=2)
# 显示经纬度
lcd.draw_string(10, 50, '设备: %d'%1, fc=(0,0,255), bc=(0,0,0))
lcd.draw_string(10, 70, '经度: %s'%longitude, fc=(0,0,255), bc=(0,0,0))
lcd.draw_string(10, 90, '纬度: %s'%latitude, fc=(0,0,255), bc=(0,0,0))
# 显示测量信息
lcd.draw_string(10, 150, "温度: %.1f"%temperature, fc=(0,0,255), bc=0)
if tds>300:
tds_color = (255,0,0)
elif tds>200:
tds_color = (0,0,255)
else:
tds_color = (0,255,0)
lcd.draw_string(10, 170, "TDS: %d ppm"%tds, fc=tds_color, bc=0)
if turbidity > 2.96:
lcd.draw_string(10, 190, "浑浊度: 1 级", fc=(0,255,0), bc=0)
elif turbidity > 2.64:
lcd.draw_string(10, 190, "浑浊度: 2 级", fc=(0,0,255), bc=0)
elif turbidity> 1.84:
lcd.draw_string(10, 190, "浑浊度: 3 级", fc=(255,0,255), bc=0)
else:
lcd.draw_string(10, 190, "浑浊度: 4 级", fc=(255,0,0), bc=0)
#lcd.draw_string(10, 190, "浑浊度: %.2f"%turbidity, fc=(0,255,0), bc=0)
lcd.display()
print("receive count: ", rx_cnt)
rx_cnt += 1
time.sleep_ms(50)