1410|7

6995

帖子

11

TA的资源

版主

楼主
 

【DigiKey“智造万物,快乐不停”创意大赛】《电流电压综合测试系统》作品提交 [复制链接]

  本帖最后由 lugl4313820 于 2024-1-9 18:05 编辑
一、作品简介
《电流电压综合测试系统》作者:lugl4313820
所用到的板卡为:
1、32F746GDISCOVERY
STM32F746NGH6微控制器具有1MB的闪存和340KB的RAM,BGA216封装
◆板载ST-LINK支持USB重新枚举能力
◆USB功能可可实现虚拟COM端口、海量存储、调试端口三大功能
◆4.3英寸480×272彩色LCD-TFT电容式触摸屏 (触摸芯片RK043FN48H-CT672B)
◆摄像头连接口(新提供)
◆音频输入、输出插孔
◆两个MEMS麦克风
◆SPDIF音频输入接口
◆用户和复位按键
◆128-Mbit四通道SPI闪存 (芯片 N25Q128A)
◆128-Mbit SDRAM(64Mbits 可访问) (芯片 MT48LC4M32B2)
◆提供microSD 卡
◆提供外部RF\EEPROM的IIC连接口
◆两个Micro-AB,类型为USB OTG HS 和USB OTG FS
◆以太网接口
◆Arduino 接口

2、电压采集芯片为ADS1115。16位ADC采集模块。

【作品功能】
在产品出厂前,都需要对产品的各项指标进行测试测量,以往都是手工进行测量,往往人工成本高,人为的误差比较大。所以我们在提供测试架的同时,结合开发了此款与测试架配套的产品,旨在提高检测精度,节省时间与人工成本。
本产品可以精确的测量到纳安级别的待机电流,也可以模拟吸唤气等动作,来模拟现实中的使用场景,从而实现应用环境的精准测量。并且设计了参数可调,让用户可以根据不同时的产品来设定工作、休眠、吸换气等参数,来达到多个产品应用同一个测试架。
二、系统框图(图文结合)
本产品的设计思路是结合日常工作中测试测量的经验,来设计充放电、吸唤气等来设计出流水线,实现对各个场景的电流、电压的采集,根据用户设置的限值范围,结合测试结果,智能的实现产品的测试结果判定。
其流程图如下:
原理图:
【软件】
  1. stm32CubeIDE
  2. TouchGFX Designer-4.23
  3. FreeRTOS
Stm32提供了免费的stm32cubeIDE以及图形设计软件TouchGFX。设计采用GUI界面与后台分离设计。通过Model-Presenter-View的设计模式来对产品进行设计,这样的好处是通过接口进行对接,在设计过程中各个模块可以实现独立的测试等优点。
【作品实物】
内部原始的结构图:
最终内倍结构图:
【注】由于是工程样品,所以接线有点乱,当然生产环节会打板,要不接线成本太高呀,我接了一天。
三、各部分功能说明
  1. 主界面为参数设置、测试、帮助进行了导航。
  2. 参数设置部分,主是要对电流、电压的限值进行设置,软件中结合大量的测试经验,提供了高低限值,方便用户根据本身的产品进行设置:

    主要代码如下:
    /* 静态电流下限减 */
    void testSetView::FunLowerOperatingCurrentISubstract()
    {
    Test_dian1.Lower_limit_operating_current_vlaue = Test_dian1.Lower_limit_operating_current_vlaue - 1 ;
    //如果超出了默认的下限就设置为下限
    if(Test_dian1.Lower_limit_operating_current_vlaue <= LOWER_LIMIT_OPERATING_CURRENT_VALUE)
    {
    Test_dian1.Lower_limit_operating_current_vlaue = LOWER_LIMIT_OPERATING_CURRENT_VALUE;
    }
    Unicode::snprintf(textAreaLowerLimitOperatingCurrentValueBuffer, TEXTAREALOWERLIMITOPERATINGVOLTAGE2VALUE_SIZE, "%d",Test_dian1.Lower_limit_operating_current_vlaue);
    textAreaLowerLimitOperatingCurrentValue.invalidate();
    }
    /* 静态电流下限加 */
    void testSetView::FunLowerOperatingCurrentAdd()
    {
    Test_dian1.Lower_limit_operating_current_vlaue +=1 ;
    /* 判断是否到达上限 */
    if(Test_dian1.Lower_limit_operating_current_vlaue >= UPPER_LIMIT_OPERATING_CURRENT_VALUE)
    {
    Test_dian1.Lower_limit_operating_current_vlaue = UPPER_LIMIT_OPERATING_CURRENT_VALUE;
    }
    /* 判断是否比上限高 */
    if(Test_dian1.Lower_limit_operating_current_vlaue >= Test_dian1.Upper_limit_operating_current_vlaue)
    {
    Test_dian1.Lower_limit_operating_current_vlaue = Test_dian1.Upper_limit_operating_current_vlaue -1;
    }
    Unicode::snprintf(textAreaLowerLimitOperatingCurrentValueBuffer, TEXTAREALOWERLIMITOPERATINGVOLTAGE2VALUE_SIZE, "%d",Test_dian1.Lower_limit_operating_current_vlaue);
    textAreaLowerLimitOperatingCurrentValue.invalidate();
    }

    其余的按键代码以此类推,详细见源码
    同时结合不同的产品,设置了不同测试时间段的测试时间

    代码的构思为每按下减进行递减,如果小于规定的下限值,则无效。上限也如此,四组按键均如此。
    void DelaySetView::Fun_but_C_T_Down()
    {
    Test_dian1.charging_current_times -= 100;
    //如果小于规定的下限,则无效
    if(Test_dian1.charging_current_times <= MIN_CHARGING_CURRENT_TIMES)
    {
    Test_dian1.charging_current_times = MIN_CHARGING_CURRENT_TIMES;
    }
    Unicode::snprintf(textAreaChargeCurrentTestTimeBuffer, TEXTAREACHARGECURRENTTESTTIME_SIZE, "%d", Test_dian1.charging_current_times);
    textAreaChargeCurrentTestTime.invalidate();
    }
    void DelaySetView::Fun_but_C_T_Up()
    {
    Test_dian1.charging_current_times += 100;
    //如果超出规定的上限,测无效
    if(Test_dian1.charging_current_times >= MAX_CHARGING_CURRENT_TIMES)
    {
    Test_dian1.charging_current_times = MAX_CHARGING_CURRENT_TIMES;
    }
    Unicode::snprintf(textAreaChargeCurrentTestTimeBuffer, TEXTAREACHARGECURRENTTESTTIME_SIZE, "%d", Test_dian1.charging_current_times);
    textAreaChargeCurrentTestTime.invalidate();
    }

    也可以根据不同的产品特点设置不同的工作模式:

    这里的代码主要是用按键组来选择工作模式:
    void worksequenceView::setupScreen()
    {
    if(Test_dian1.work_mode == 0)
    {
    radioBnt_0.setSelected(true);
    }
    else
    {
    radioBnt_1.setSelected(true);
    }
    worksequenceViewBase::setupScreen();
    }
    void worksequenceView::tearDownScreen()
    {
    worksequenceViewBase::tearDownScreen();
    }
    void worksequenceView::FunSetMode0()
    {
    Test_dian1.work_mode = 0;
    }
    void worksequenceView::FunSetMode1()
    {
    Test_dian1.work_mode = 1;
    }

    参数设置最后是给用户提供总结设置的确实界面,用户设置好后可以保存参数,方便重新开机后自动读取参数。

    实现的代码为将设置好的参数进行展示,让用户再次确认,如果按保存则更新到flash中以备下次重启里恢复参数。
  3. 测试界面,用户按下按键后开始测试,测试的结果会同步显示在界面。

    代码实现思路:
    当按下为开始测试按键时,通过信号量触发,阻塞的任务开始执行,通过规定的开关、电机的规定程序进行测量,测量完一个项日更新到下一个状态。
    void TaskChargeI(void *argument)
    {
    /* USER CODE BEGIN TaskChargeI */
    /* Infinite loop */
    for(;;)
    {
    if (xSemaphoreTake( xSemaChargeIHandle, portMAX_DELAY) == pdTRUE )
    {
    HAL_GPIO_WritePin(K3_GPIO_Port, K3_Pin, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(K6_GPIO_Port, K6_Pin, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(K5_GPIO_Port, K5_Pin, GPIO_PIN_RESET);
    osDelay(Test_dian1.start_wait_times);
    Test_dian1.charging_current_vlaue = (uint16_t)(ADS1115_ADDR_VDD.ADS1115_Vol[ADS1115_CHANNEL0_1]*10);
    //printf("ADS1115 VDD CH vol = %d \n\n",Test_dian1.charging_current_vlaue);
    if((Test_dian1.charging_current_vlaue > Test_dian1.Upper_limit_charging_current_vlaue) ||( Test_dian1.charging_current_vlaue < Test_dian1.Lower_limit_charging_current_vlaue) )
    {
    Test_dian1.charging_current_result = 1;
    }
    else
    {
    Test_dian1.charging_current_result = 0;
    }
    my_dianzhi_test_state = CHARGING_CURRENT_OK;
    osDelay(1000);
    HAL_GPIO_WritePin(K3_GPIO_Port, K3_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(K6_GPIO_Port, K6_Pin, GPIO_PIN_SET);
    //打开气泵
    //打开3.7V开关
    HAL_GPIO_WritePin(K5_GPIO_Port, K5_Pin, GPIO_PIN_RESET);
    //打开负载开关
    HAL_GPIO_WritePin(K2_GPIO_Port, K2_Pin, GPIO_PIN_RESET);
    //延时100ms
    //开气泵
    HAL_GPIO_WritePin(K1_GPIO_Port, K1_Pin, GPIO_PIN_RESET);
    //检测电压
    Get_adc();
    Test_dian1.operating_voltage1_vlaue = ((Get_adc() & 0x0FFF)*3.3f*5.2/4096)*1000;
    osDelay(1000);
    //关气泵
    HAL_GPIO_WritePin(K1_GPIO_Port, K1_Pin, GPIO_PIN_SET);
    osDelay(1000);
    HAL_GPIO_WritePin(K1_GPIO_Port, K1_Pin, GPIO_PIN_RESET);
    //开气泵
    osDelay(Test_dian1.smokeing_times);
    Get_adc();
    Test_dian1.operating_voltage1_vlaue = ((Get_adc() & 0x0FFF)*3.3f*2.3/4096)*1000;
    //发送检测完毕的信号
    //判断检测结果
    if((Test_dian1.operating_voltage1_result > Test_dian1.Upper_limit_operating_voltage1_vlaue) || (Test_dian1.operating_voltage1_vlaue < Test_dian1.Lower_limit_operating_voltage1_vlaue))
    {
    Test_dian1.operating_voltage1_result = 1;
    }
    else
    {
    Test_dian1.operating_voltage1_result = 0;
    }
    my_dianzhi_test_state = OPERATING_VOLATGE_1_OK;
    //关闭负载开关
    HAL_GPIO_WritePin(K2_GPIO_Port, K2_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(K1_GPIO_Port, K1_Pin, GPIO_PIN_SET);
    //延时到休眠状态
    osDelay(Test_dian1.wait_sleep_time);
    //打开检测电阻开关
    Test_dian1.operating_current_vlaue = (uint16_t)(ADS1115_ADDR_VDD.ADS1115_Vol[ADS1115_CHANNEL2_3]/100);
    my_dianzhi_test_state = OPERATING_CURRENT_OK;
    if((Test_dian1.operating_current_vlaue > Test_dian1.Upper_limit_operating_current_vlaue) || (Test_dian1.operating_current_vlaue < Test_dian1.Lower_limit_operating_current_vlaue) )
    {
    Test_dian1.operating_current_result = 1;
    }
    else
    {
    Test_dian1.operating_current_result = 0;
    }
    //测试结束
    osDelay(100);
    if( (Test_dian1.operating_current_result + Test_dian1.operating_voltage1_result + Test_dian1.charging_current_result) >0)
    {
    Test_dian1.test_result = 1;
    }
    else
    {
    Test_dian1.test_result = 0;
    }
    my_dianzhi_test_state = DIANZHI_TEST_FINISH;
    HAL_GPIO_WritePin(K4_GPIO_Port, K4_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(K5_GPIO_Port, K5_Pin, GPIO_PIN_SET);
    }
    osDelay(1);
    }
    /* USER CODE END TaskChargeI */
    }
    在model.cpp中,tick函数监检测的任务状态,更根据状态的不同,通过Persenter向View发送相应的数据,并在test_main中实时更新状态:
    void Model::tick()
    {
    if(my_dianzhi_test_state == CHARGING_CURRENT_OK)
    {
    //更新显示
    modelListener->notify_chargI_set(Test_dian1.charging_current_vlaue,Test_dian1.charging_current_result);
    }
    else if(my_dianzhi_test_state ==OPERATING_CURRENT_OK)
    {
    modelListener->notify_operatI_set(Test_dian1.operating_current_vlaue, Test_dian1.operating_current_result);
    }
    else if(my_dianzhi_test_state ==OPERATING_VOLATGE_1_OK)
    {
    modelListener->notify_volate1_set(Test_dian1.operating_voltage1_vlaue, Test_dian1.operating_voltage1_result);
    }
    else if(my_dianzhi_test_state == DIANZHI_TEST_FINISH)
    {
    //更新总测试结果
    modelListener->notify_test_result_set(Test_dian1.test_result);
    my_dianzhi_test_state = DIANZHI_TEST_START;
    //更新测试数
    }
    }

     

  4. 作品源码
五、作品功能演示视频
六、项目总结
本次项目是基于TouchGFX来做为GUI界面设计,用于用户的交互,主要功能是对测试产品的参数进行设定,测试结果进行展示,编程语言采用MPV模式的C++进行设计。后台的控制部分用C进行编程,实现了对电流电压进行实时采集,测试结果的判定,输出到GUI。工程采用了freeRTOS实时操作系统,实现GUI的以及后台控制、数据实时采集等多任务调度,前后台采用任务间通信,能实时、高效的完成前后端的协调一致。
通过本次参赛我将TouchGFX替换了原来用串口屏来实现用户界面交互,相比原来的设计方案,开发周期比原来缩短,不用定制复制的通迅协议来协调前后端的交互。同时也减少了开发人员之间的复杂沟通成本。
本次采用的开发软件为STM32CubeIDE、TouchGFX、FreeRTOS,均为免费的开发软件,对于小微企业来说也是成本的降低。
通过这次比赛,我进一步的提高了对touchGFX的熟练度,在今后的开发中可以减少开发成本,减少通信协议的设计,缩短开发周期,特别适合开发人员少的小微企业、对开发周期要求高的产品开发。
当然这次作品在UI设计方面没有专业的美工设计,作品的界面不是很美观,数据采集也没有做滤波。在实际的生产环境还需要继续完善。
七、其他
此次项目我原来是考虑使用lvgl做为GUI开发来设计一款冷链监控产品的,因为临时接到需要做一款多路电流电压测试架的项目,所以在原来的比赛作品进行到一半时,临时改变为本次作品,并且开源出来了单路的产品设计,希望对一些小微企业有这方面需求的有所帮助。
此致要感谢深圳市嘉欣钰电子科技的许总,经过他的同意,我们开源了共同设计的单独测试架的作品创意、原理图、源代码,这对于做企业的人来说,是一种无私奉献的开源精神。
也要感谢EEWORLD论坛与得捷电子,提供了这么好的平台,能让我在比赛中夯实自己的业务知识,同时也学习到其他参赛人员的许多优秀开源作品。
通过本次比赛后,进一步将比赛的作品快速的落地,将单路设计拓展为10路的测试产品交付用户使用,进一步提高工厂的测试精度,缩短产品交付时间,节约生产成本。
附开发中的一些分享:
附件:world文档 综合电流电压监测系统.doc (1.52 MB, 下载次数: 2)
         pdf格式: 综合电流电压监测系统_20240109174124.pdf (1.27 MB, 下载次数: 1)

最新回复

lugl老师,这个系统的木板是电工胶木板,感觉有些年头了。 开关电源那边应该开个孔散热吧。 要不环境温度上来了,会不会影响采样电阻的精度呀   详情 回复 发表于 2024-4-24 13:48
点赞(1) 关注(1)
 
 

回复
举报

6500

帖子

10

TA的资源

版主

沙发
 

模拟吸气换气是干嘛用的?  

点评

是在一款日用品上的,吸一下激活设备,再吸一下,里面就有电压输出到加热设备上。  详情 回复 发表于 2024-1-10 11:08
个人签名

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

 
 
 

回复

6995

帖子

11

TA的资源

版主

板凳
 
秦天qintian0303 发表于 2024-1-10 11:00 模拟吸气换气是干嘛用的?  

是在一款日用品上的,吸一下激活设备,再吸一下,里面就有电压输出到加热设备上。

点评

方便透露是什么吗?感觉挺有创意的,没见过这种方式,放到开关上是不是也可以  详情 回复 发表于 2024-1-10 15:25
 
 
 

回复

6500

帖子

10

TA的资源

版主

4
 
lugl4313820 发表于 2024-1-10 11:08 是在一款日用品上的,吸一下激活设备,再吸一下,里面就有电压输出到加热设备上。

方便透露是什么吗?感觉挺有创意的,没见过这种方式,放到开关上是不是也可以

点评

可以私下告诉您,现在国内销售非常少,都是出口的产品。  详情 回复 发表于 2024-1-10 15:36
个人签名

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

 
 
 

回复

6995

帖子

11

TA的资源

版主

5
 
秦天qintian0303 发表于 2024-1-10 15:25 方便透露是什么吗?感觉挺有创意的,没见过这种方式,放到开关上是不是也可以

可以私下告诉您,现在国内销售非常少,都是出口的产品。

 
 
 

回复

328

帖子

5

TA的资源

纯净的硅(中级)

6
 

大佬的作品,一向都是用心设计,用心研究,用心分享,结合实际,落到实处!

仔细拜读,不仅把开发板自身功能用得好,外部设备结合得好,还把TouchGFX也用得非常非常的好!

值得好好学习了!

 
 
 

回复

4934

帖子

12

TA的资源

版主

7
 

lugl老师,这个系统的木板是电工胶木板,感觉有些年头了。

开关电源那边应该开个孔散热吧。

要不环境温度上来了,会不会影响采样电阻的精度呀

点评

这是工程板,升温是会影响的,测试环境会有空调。  详情 回复 发表于 2024-4-24 13:56
 
 
 

回复

6995

帖子

11

TA的资源

版主

8
 
吾妻思萌 发表于 2024-4-24 13:48 lugl老师,这个系统的木板是电工胶木板,感觉有些年头了。 开关电源那边应该开个孔散热吧。 要不环境 ...

这是工程板,升温是会影响的,测试环境会有空调。

 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
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
快速回复 返回顶部 返回列表