【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采集模块。
【作品功能】
在产品出厂前,都需要对产品的各项指标进行测试测量,以往都是手工进行测量,往往人工成本高,人为的误差比较大。所以我们在提供测试架的同时,结合开发了此款与测试架配套的产品,旨在提高检测精度,节省时间与人工成本。
本产品可以精确的测量到纳安级别的待机电流,也可以模拟吸唤气等动作,来模拟现实中的使用场景,从而实现应用环境的精准测量。并且设计了参数可调,让用户可以根据不同时的产品来设定工作、休眠、吸换气等参数,来达到多个产品应用同一个测试架。
二、系统框图(图文结合)
本产品的设计思路是结合日常工作中测试测量的经验,来设计充放电、吸唤气等来设计出流水线,实现对各个场景的电流、电压的采集,根据用户设置的限值范围,结合测试结果,智能的实现产品的测试结果判定。
其流程图如下:
原理图:
【软件】
- stm32CubeIDE
- TouchGFX Designer-4.23
- FreeRTOS
Stm32提供了免费的stm32cubeIDE以及图形设计软件TouchGFX。设计采用GUI界面与后台分离设计。通过Model-Presenter-View的设计模式来对产品进行设计,这样的好处是通过接口进行对接,在设计过程中各个模块可以实现独立的测试等优点。
【作品实物】
内部原始的结构图:
最终内倍结构图:
【注】由于是工程样品,所以接线有点乱,当然生产环节会打板,要不接线成本太高呀,我接了一天。
三、各部分功能说明
- 主界面为参数设置、测试、帮助进行了导航。
- 参数设置部分,主是要对电流、电压的限值进行设置,软件中结合大量的测试经验,提供了高低限值,方便用户根据本身的产品进行设置:
主要代码如下:
/* 静态电流下限减 */
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中以备下次重启里恢复参数。
- 测试界面,用户按下按键后开始测试,测试的结果会同步显示在界面。
代码实现思路:
当按下为开始测试按键时,通过信号量触发,阻塞的任务开始执行,通过规定的开关、电机的规定程序进行测量,测量完一个项日更新到下一个状态。
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;
//更新测试数
}
}
- 作品源码
五、作品功能演示视频
六、项目总结
本次项目是基于TouchGFX来做为GUI界面设计,用于用户的交互,主要功能是对测试产品的参数进行设定,测试结果进行展示,编程语言采用MPV模式的C++进行设计。后台的控制部分用C进行编程,实现了对电流电压进行实时采集,测试结果的判定,输出到GUI。工程采用了freeRTOS实时操作系统,实现GUI的以及后台控制、数据实时采集等多任务调度,前后台采用任务间通信,能实时、高效的完成前后端的协调一致。
通过本次参赛我将TouchGFX替换了原来用串口屏来实现用户界面交互,相比原来的设计方案,开发周期比原来缩短,不用定制复制的通迅协议来协调前后端的交互。同时也减少了开发人员之间的复杂沟通成本。
本次采用的开发软件为STM32CubeIDE、TouchGFX、FreeRTOS,均为免费的开发软件,对于小微企业来说也是成本的降低。
通过这次比赛,我进一步的提高了对touchGFX的熟练度,在今后的开发中可以减少开发成本,减少通信协议的设计,缩短开发周期,特别适合开发人员少的小微企业、对开发周期要求高的产品开发。
当然这次作品在UI设计方面没有专业的美工设计,作品的界面不是很美观,数据采集也没有做滤波。在实际的生产环境还需要继续完善。
七、其他
此次项目我原来是考虑使用lvgl做为GUI开发来设计一款冷链监控产品的,因为临时接到需要做一款多路电流电压测试架的项目,所以在原来的比赛作品进行到一半时,临时改变为本次作品,并且开源出来了单路的产品设计,希望对一些小微企业有这方面需求的有所帮助。
此致要感谢深圳市嘉欣钰电子科技的许总,经过他的同意,我们开源了共同设计的单独测试架的作品创意、原理图、源代码,这对于做企业的人来说,是一种无私奉献的开源精神。
也要感谢EEWORLD论坛与得捷电子,提供了这么好的平台,能让我在比赛中夯实自己的业务知识,同时也学习到其他参赛人员的许多优秀开源作品。
通过本次比赛后,进一步将比赛的作品快速的落地,将单路设计拓展为10路的测试产品交付用户使用,进一步提高工厂的测试精度,缩短产品交付时间,节约生产成本。
附开发中的一些分享:
|