7752|6

330

帖子

5

TA的资源

纯净的硅(中级)

楼主
 

【行空板 Python编程学习主控板】基于行空板的便携式果汁光谱分析仪 [复制链接]

本帖最后由 HonestQiao 于 2022-11-21 10:53 编辑

目录:

  • 一、想法起源
  • 二、硬件材料
  • 三、准备工作
  • 四、原理图与实物连线
  • 五、逻辑设计与代码编写
  • 六、实测步骤
  • 七、总结
  • 八、花絮

 

一、想法起源

最近在行空板上,测试了使用AS&341可见光传感器,可以用于分析可见光的光谱,于是就想进一步寻找其实际用途。

最开始,想的是进行水质检测。不过进行污水检测,需要提取不同地区的污水,现在要到冬天了,气温较低,操作不方便。

最终,经过多种测试,决定进行果汁光谱分析。通过果汁的光谱分析,可以初步了解果汁中的果汁含量高低水平。

 

二、硬件材料

硬件材料分为两部分,一部分是制作便携式果汁光谱分析仪的电子设备硬件材料,一部分是果汁的材料。

电子设备硬件材料如下:

  • 主控板:行空板
  • 可见光传感器:AS7341
  • 供电设备:充电宝、电池、或者可对外充电的手机
  • 连接线:I2C连接线一根
  • 电源线:Tyep-C充电数据线一根

果汁的材料:

  • 橙子:新鲜橙子 * 2
  • 测量杯:奶酪瓶子 * 3
  • 果汁:沙棘果汁
  • 纯净水:一桶

三、准备工作

3.1. 准备测量杯:

准备好3个奶酪瓶,一定要带盖的,盖好盖可以预防果汁暴露在空气中氧化,导致光谱发生变化。

然后给个测量杯标号: 

  1. 纯果汁
  2. 50%果汁
  3. 25%果汁

使用不同纯度的果汁进行对比测试,方便观测到光谱的变化。

 

3.2 准备纯净水:

稀释果汁的时候,应使用纯净水,避免不同的水质对光谱产生影响。 

 

3.3. 橙子榨汁:

手头没有榨汁机,所以只能手工榨汁。

先将橙子剥皮,放碗里,用拳头挤压:

 

不过,看似橙子果肉水份十足,要挤出橙子,可不容易,用拳头,只能挤出一小部分;用手捏,也是如此;

 

再用两个碗对扣挤压,发现碗底到不了另外一个碗的内底;

再用果汁瓶挤压,忙乎了好一会,总算挤压出来半瓶:

 

没有榨汁机,手工榨汁太麻烦了,所以还有一个橙子,不榨汁了,半杯将就用吧。

因为只有半杯橙汁,所以后续测量的时候,先测量纯橙汁的光谱,然后再加满水,测量50%的橙汁;最后再倒出一半,再次加满水,测量25%的橙汁。

因为没有使用两杯,所以以上及后续的50%、25%,都只是大致比例。

 

3.4. 准备沙棘汁:

因为家里刚好有一瓶沙棘汁,所以就直接使用了,免了榨汁的步骤。

因为沙棘汁充足,所以直接就准备好纯沙棘汁、50%沙棘汁、25%沙棘汁好了。

 

3.4.1 将1号瓶装满沙棘汁:

 

3.4.2 勾兑25%沙棘汁:

将1号瓶倒出一半到2号瓶:

加水将2号瓶 补满:

 

将2号瓶倒入一半到3号瓶:

 

将3号瓶补满水:

然后将3号瓶封盖,2号瓶喝掉:

  

3.4.2 勾兑50%的沙棘汁:

将1号瓶剩下的半瓶沙棘汁,倒入到2号瓶:

 

将2号瓶补满水:

3.4.3 准备100%的沙棘汁:

将1号瓶加满沙棘汁,然后都封盖:

  

 

3.5 设计数据记录表格:

 
 

 

四、原理图与实物连线

行空板本身设计好了搭配的传感器接口,所以原理图和实际连接,都比较简单,具体如下:

 

 

 

将AS7341可监管传感器,使用I2C连接线,直接连到行空板的I2C0接口器即可。

 

五、逻辑设计与代码编写

具体的逻辑设计如下:

 

 

对应的代码编写如下:

# -*- coding:utf-8 -*-
import time
from pinpong.board import Board
from pinpong.libs.dfrobot_as7341 import AS7341
from PIL import Image, ImageDraw
from unihiker import GUI


# 设定颜色区块信息
x0 = 50
y0 = 220
wh = 90
lwh = 34

# 设定屏幕宽高
W = 240
H = 320

# 初始化板子
Board("UNIHIKER").begin()

# 实例化GUI对象
gui=GUI()

# 打开AS7341 FLICKER图片
flicker_image = Image.open("AS7341_Flicker.jpg")

# 设定F1-F8的顺序
colors_where = dict()
colors_where['F1'] = (0,0)
colors_where['F2'] = (2,1)
colors_where['F3'] = (1,0)
colors_where['F4'] = (3,1)
colors_where['F5'] = (2,0)
colors_where['F6'] = (0,1)
colors_where['F7'] = (3,0)
colors_where['F8'] = (1,1)

# 预设定颜色
colors = dict()

# 显示图片
flicker_image_obj = gui.draw_image(x=0, y=0, w=160, h=160, image=flicker_image)

# 获取背景颜色
bgc = flicker_image.getpixel((10, 100))

# 创建新的图像,用于显示获取的颜色值
tile_img = Image.new('RGB', flicker_image.size, bgc)

# 在新图像上,创建画板
tile_img1 = ImageDraw.Draw(tile_img)

# 按位置复刻颜色区块
if False:
    for i in range(0,4):
        for j in range(0,4):
            # 计算坐标
            x = x0 + i * (wh+lwh)
            y = y0 + j * (wh+lwh)

            # 获取颜色
            c = flicker_image.getpixel((x+10, y+10))

            # 设置要显示的区块大小
            shape = [(x, y), (x+wh, y+wh)]

            # 绘制区块
            tile_img1.rectangle(shape, fill =c, outline =c)

# 获取各颜色区块的颜色值,并复刻区块
if True:
    for f in colors_where:
        # 获取顺序值
        i = colors_where[f][0]
        j = colors_where[f][1]

        # 计算坐标
        x = x0 + i * (wh+lwh)
        y = y0 + j * (wh+lwh)

        # 获取颜色
        c = flicker_image.getpixel((x+10, y+10))

        # 设置要显示的区块大小
        shape = [(x, y), (x+wh, y+wh)]

        # 绘制区块
        tile_img1.rectangle(shape, fill =c, outline =c)

        # 记录F1-F8对应的颜色值
        colors[f] = c

# 显示绘制区块后的图片
tile_img_obj = gui.draw_image(x=0, y=160, w=160, h=160, image=tile_img)

# 演示
time.sleep(3)

# 清屏
gui.clear()

# 绘制黑色背景
result_img = Image.new('RGB', (W, H), bgc)
gui.draw_image(x=0, y=0, w=W, h=H, image=result_img)
gui.draw_text(x=40,y=0,text="便携果汁光谱分析仪",color=colors[f])

# 显示标签和初始值0
y = 15
bars_obj = dict()
nums_obj = dict()
for f in colors:
    y = y + 30
    c = colors[f]
    # f_img = Image.new('RGB', (180,20), c)
    gui.draw_text(x=2,y=y,text=f,color=colors[f], font_size=12)
    # bars_obj[f] = gui.draw_image(x=30, y=y+5, w=160, h=20, image=f_img)
    bars_obj[f] = gui.fill_round_rect(x=30, y=y+5, w=0, h=0, r=2, color=c)
    nums_obj[f] = gui.draw_text(x=195,y=y,text="%d" % 100,color=colors[f], font_size=12)

# 显示时间
time_obj = gui.draw_digit(x=2, y=300, color="red", font_size=12, text=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

# led数值
gui.draw_text(x=202,y=300,text="L",color="red", font_size=12)
led_obj = gui.draw_digit(x=210, y=300, color="red", font_size=12, text="L:%d" % 0)

# led处理
led_val = 0
let_done = True
def led_set(val):
    global as7341, led_val, let_done
    if let_done == False:
        return

    let_done = False
    led_val = led_val + val
    if led_val <= 0:
        led_val = 0
        as7341.enable_led(False)
    else:    
        led_val = led_val if led_val <= 250 else 250
        as7341.enable_led(True)

    as7341.control_led(led_val)
    led_obj.config(text="%d" % led_val)
    let_done = True

# 初始化化AS7341
as7341 = AS7341()
gui.on_key_click('a', lambda: led_set(10))
gui.on_key_click('b', lambda: led_set(-10))
led_set(0)

while(as7341.begin() != True):
    #  Detect if IIC can communicate properly 
    print("IIC init failed, please check if the wire connection is correct")
    time.sleep(1)

    #  Integration time = (ATIME + 1) x (ASTEP + 1) x 2.78μs
    #  Set the value of register ATIME, through which the value of Integration time can be calculated. The value represents the time that must be spent during data reading.
    #  as7341.set_a_time(29)
    #  Set the value of register ASTEP, through which the value of Integration time can be calculated. The value represents the time that must be spent during data reading.
    #  as7341.set_a_step(599)
    #  Set gain value(0~10 corresponds to X0.5,X1,X2,X4,X8,X16,X32,X64,X128,X256,X512)
    #  as7341.set_again(7)
    #  Enable LED
    #  as7341.enable_led(True)
    #  Set pin current to control brightness (1~20 corresponds to current 4mA,6mA,8mA,10mA,12mA,......,42mA)
    #  as7341.control_led(10)

while True:
    if let_done == False:
        continue

    #开启f1_f2__f3_f4_clear_nir的测量
    as7341.start_measure(0)
    data1 = as7341.read_spectral_data_one()
    data1 = type('dict', (object,), data1)
    print("F1(405-425nm):",data1.adf1)
    print("F2(435-455nm):",data1.adf2)
    print("F3(470-490nm):",data1.adf3)
    print("F4(505-525nm):",data1.adf4)   

    #开启f5_f6_f7_f8_clear_nir的测量
    as7341.start_measure(1)
    data2 = as7341.read_spectral_data_two()
    data2 = type('dict', (object,), data2)
    print("F5(545-565nm):",data2.adf5)
    print("F6(580-600nm):",data2.adf6)
    print("F7(620-640nm):",data2.adf7)
    print("F8(670-690nm):",data2.adf8)
    print("Clear:",data2.adclear)
    print("NIR:"  ,data2.adnir)

    time_obj.config(text=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

    nums = dict()
    for f in colors:
        key = "ad%s" % f.lower()
        num = 0
        if hasattr(data1, key):
            num = getattr(data1, key)
        elif hasattr(data2, key):
            num = getattr(data2, key)

        nums[f] = int(num)
        max_num = max(nums.values())

    for f in colors:
        key = "ad%s" % f.lower()
        num = nums[f]

        bar_width = 160 * nums[f]/max_num
        bar_height = bar_width * 20 / 160
        bars_obj[f].config(w = int(bar_width), h = int(bar_height))
        nums_obj[f].config(text="%d" % num)

    time.sleep(0.1)

 

上述代码中的AS7341色卡图片,来自 :SEN0364 Gravity:AS7341可见光传感器 (dfrobot.com.cn)

 

 

 

在上述代码中,使用了Python的图像处理库,从AS7341色卡图片中取得对应的颜色值,用于后续的光谱色条显示。

 

行空板上的Python预装类硬件操作库:pinpong,其中就带有AS7341驱动库:pinpong.libs.dfrobot_as7341,可以很方便的引入操控AS7341。

 

AS7341的使用分为3个步骤:

  1. 初始化:as7341.begin()
  2. 开启测量:as7341.start_measure(0)、as7341.start_measure(1)
  3. 读取数据:as7341.read_spectral_data_one()、as7341.read_spectral_data_two()读取到的数据中,包含:adf1~adf8,及对应上述色卡的8个通道F1~F8。

从AS7341读取到数据后,将8个数据的数值更新到屏幕上对应GUI文本控件,再计算得出各通道对应的颜色,并更新对应色条的GUI图像的大小。

 

六、实测步骤

6.1 启动便携式果汁光谱分析仪

将行空板接上电源,启动后,从操作界面中,启动上述 便携式果汁光谱分析仪 的Python脚本,系统会先显示AS7341色卡,并从中提取各通道的颜色:

 

然后,会进入光谱分析界面,显示当前环境下的光谱分析结果:

 
 

 

6.2 测量橙汁的光谱:

前面说了,手工榨汁太麻烦,所以橙汁的量不多,只有半杯,所以不能提前把三种比例的橙汁都准备后,只能一个个测量了,再准备下一个比例的。

 

6.2.1 测量纯橙汁光谱:

将纯的鲜橙汁导入1号测量杯,将AS7341的光纤传感器部分,贴近测量杯:

 待读数稳定后,记录数据:

 如有可能,可以多记录几组数据,然后取平均值,或者计算各标准差、方差之类的。

这里简单起见,就只记录一组数据了。

 

6.2.2 测量50%橙汁的光谱:

先将1号瓶的橙汁,导入2号瓶,并加满水,放到刚才测量纯果汁同样的位置,确保AS7341传感器与和刚才一样紧贴:

 待读数稳定后,记录数据:

 
  6.2.3 测量25%橙汁的光谱

将2号瓶50%的橙汁,倒入一半到3号瓶:

 

然后参考上一步,将3号瓶补满水,并放到测量位置测量:

 

待读数稳定后,记录数据:

 

6.2.4 测量完成后,总结分析测量数据:

 

从记录的数据中,进行分析,可以明显的看到,随着橙汁浓度的变化:

  • F6、F7、F8三项数据,随着浓度降低,明显跟随降低
  • F3、F4两线数据,随着浓度降低,显著上升

6.3 测量沙棘汁的光谱:

测量方法类似橙汁,依次测量3个瓶子的光谱即可,并做好数据记录:

 

6.3.1 测量100%沙棘汁的光谱

 

 

6.3.2 测量50%沙棘汁的光谱:

 

6.3.3 测量25%沙棘汁的光谱:

   

6.3.4 测量完成后,总结分析测量数据:

 从上述数据中,发现数据变化并不明显。

100%~50%的沙棘汁,浓度较高,光线通过效果不好,所以F8占比较高。

但浓度大幅降低后,F6通道的数据,有明显的上升,F8通道的数据则有明显的降低。

另外,实际品藏,100%的沙棘汁,并不好喝,味儿太重。50%的则挺好喝的,25%的味儿就太淡了。

 

七、总结

这个便携式果汁光谱分析仪,只是行空板+可监管传感器的一个基础使用作品,制作的还比较初级,功能也比较简单。

不过,通过这个作品,我们可以看到,结合行空板盒传感器,能够把我们很多好的想法,快捷方便的变为现实。

发挥想象力,好好研究开发,说不定你也能够开发出一个爆款的便携设备!!!

 

八、花絮

出演成员:

 
测试完成后,剩余的沙棘汁,挨个品藏了一番,确定50%的更好喝!

二前面测试的橙汁,不用说,100%的最好喝了!!!

最新回复

厉害了,可以省下几百万地光谱分析仪,在化工行业非常实用。   详情 回复 发表于 2023-2-22 15:35
点赞(1) 关注

回复
举报

6534

帖子

9

TA的资源

版主

沙发
 

可以保存为草稿

 
个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 

回复

4942

帖子

19

TA的资源

版主

板凳
 

柠檬汁测一下呗~

点评

橙,明天就去买柠檬好了  详情 回复 发表于 2022-11-21 17:49
 
 
 

回复

330

帖子

5

TA的资源

纯净的硅(中级)

4
 
吾妻思萌 发表于 2022-11-21 13:44 柠檬汁测一下呗~

成,明天就去买柠檬好了

 
 
 

回复

4942

帖子

19

TA的资源

版主

5
 

写的真不错,加精好评,

 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

6
 

厉害了,可以省下几百万地光谱分析仪,在化工行业非常实用。

 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

7
 

厉害了,可以省下几百万地光谱分析仪,在化工行业非常实用。

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表