岁月如歌 发表于 2023-10-11 14:15:18

本帖最后由 岁月如歌 于 2023-12-2 11:16 编辑

哈尔滨理工大学===运动目标控制与自动追软件环节:我们在软件上面遇到了各种难题,准确说是视觉上,因为舵机的驱动代码是提前准备好的,几乎没有花费过多时间调试,这里也得强调我们的策略,我们并没有在单片机中写入特别多复杂的程序,和任务切换,而是把这些东西放到K210里面,单片机中只有串口接收,接收数据处理和舵机PWM的更新。因为在调试过程中,单片机是很难调试的,而且出现了问题追查问题很麻烦,所以最好不要去修改单片机里面的代码,只要它没问题,就放着它不动!相比之下K210的在线编程和PYTHON轻松的语法,让我们能对现状有个实时的了解,帮助我们快速修改。视觉上,我们采用的K210几乎是不可能扫到铅笔线的,所以我们采用的打点的方式来确定四个角坐标,然后通过插补和PID,让舵机扫框。调PID的艰辛相信各位参赛的选手都明白,这一阶段只能熬夜苦战的调,不睡觉才是常态。识别A4纸上的黑框,我们采集到的四个点坐标,不是按照题目要求的逆时针。所以我们还要对四个点坐标重新排序。我们注意到,不论A4纸怎么摆放,四个点坐标中,我们先找出X轴最小、最大,Y轴最小、最大。X轴最小的那个点向Y轴最大的那个点移动是逆时针的,Y轴最大的那个点到X轴最大的那个点也是逆时针的,X轴最大的那个点到Y轴最小的那个点也是逆时针的。不理解的话,拿出一个方框摆一摆就知道了,为了方便确定最大最小的坐标,所以我们的A4纸自己摆放时也没有完全摆的水平(也就是看上去扫框最简单的那种)而是微微倾斜。

舵机控制角度范围计算舵机的角度范围为0°到180°,要根据激光笔的位置信息来计算舵机应该转动的角度,使其能够对准目标物体。由于舵机需要能够将光斑移动到屏幕的任意位置,所以在此我们作简单计算。如图3-1所示,图中,舵机的航向角为file:///C:/Users/CXY/AppData/Local/Temp/msohtmlclip1/01/clip_image006.png,俯仰角为file:///C:/Users/CXY/AppData/Local/Temp/msohtmlclip1/01/clip_image008.png,舵机水平时的高度为h。依据题目要求,云台距离0.5m*0.5m的屏幕为1m,那么在此为了简便计算,按照舵机高度h为0.5m,同时放置在屏幕中线上。那么,即舵机水平和竖直最大转角为28°。
图 3-1 结构说明图
舵机转动精度计算舵机的转动精度需要达到小于1°的误差,取决于控制信号的分辨率。舵机的控制信号是通过脉冲宽度调制(PWM)来实现的。舵机控制信号周期为20ms,高电平周期为0.5ms~2.5ms,其中0.5ms对应最小角度,2.5ms对应最大角度。由上述的计算确定转角的大致范围为28°,我们以90°为水平时的状态,因此,舵机角度范围为76°~114°。以此计算出高电平周期为1.33ms~1.67ms,将舵机的角度范围等分为控制信号的脉冲宽度区间,通过调整脉冲宽度来控制舵机转动到特定角度,即每个脉冲宽度所对应的角度差。以实现舵机转动到目标位置的精确控制。


芯启程 发表于 2023-10-11 14:39:52

本帖最后由 小太阳 于 2023-12-14 15:35 编辑

华北理工大学===获得全国大学生电子设计竞赛2023,本科组一等奖
E题:运动目标控制与自动追踪系统, STC32G12K128作为唯一主控MCU实现
按规定一等奖奖金人民币2万元@STC32G12K128
===2023/12/14,审核通过

2023年全国大学生电子设计竞赛使用STC32G12K128为主控芯片-本科组

为确保奖金发放评审的公平公正,经广大老师推荐,委托第三方资深团队组织评审,点评如下:
没有看到实际硬件照片,但从其单片机程序框图和识别模块程序框图来看,识别模块仅输出识别完成的坐标信息,由STC32G完成后续所有计算,查看程序源码可以看到完整程序逻辑并且可以成功编译,程序逻辑合理,基本符合赛题任务需求。总结:整个系统中STC32G12K128确实是唯一主控并且完成了作为唯一主控的任务。结论:建议颁发一等奖全额奖金,人民币二万元,以资鼓励!发奖前必须补充相关硬件照片,最好有视频。
后记:已补充相关照片和相关视频。
获奖证书:

硬件照片:

图像显示:

运行2023年全国大学生电子设计竞赛使用STC32G12K128为主控芯片-本科组E题国一 -华北理工大学-人工智能学院
       华北理工大学-人工智能学院 三位参赛选手在三天四夜的参赛过程中虽一波三折,但万幸结果是好的,摘得国一桂冠。
运动目标控制系统和自动追踪系统均采用双自由度的二维云台实现对激光笔的方向和角度的调整且各自独立供电,并通过单自由度的云台调整追踪系统的摄像头角度。均以微处理器STC32G12K128作为系统的控制中心,采用BC6301串口键盘调参实现复位、循迹、追踪功能,通过V831自动搜寻识别靶纸,实时捕捉图像形状和色块,来实现对目标控制系统和自动追踪系统的控制,并连续发出声光提示,可随时暂停以便测量。

国一,2023电赛E题华北理工大学队伍开源 - 2025全国大学生电子设计竞赛技术支持版块,最高奖100万,一等奖2万,选型 - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)







芯启程 发表于 2023-10-11 14:44:59

本帖最后由 小太阳 于 2023-10-11 14:56 编辑

系统均以STC32G12K128作为控制系统;用宽电压输入、宽电压输出、高效率的开关电源作供电电源来控制输出电压。该设计为:二维云台调节系统的激光方向和角度来实现红色激光的复位、沿边线、靶纸移动和绿色激光的追踪。同时在IPS显示屏显示相关参数。

芯启程 发表于 2023-10-11 14:46:33

本帖最后由 小太阳 于 2023-10-11 14:53 编辑

电路的设计

大刀阔斧 发表于 2023-10-11 14:54:35

本帖最后由 大刀阔斧 于 2023-12-14 14:30 编辑

北方民族大学--获得2023年全国大学生电子设计竞赛,本科组一等奖
【G】题:空地协同智能消防系统@STC32位8051, STC32G12K128完成了三分之一的控制功能
因不是唯一主控,只占三分之一的工作量,RMB【20000元*1/3】=6666元
专家建议为鼓励大家广泛使用STC32位8051参加竞赛,奖金提升到RMB8000元。
2023/12/14,审核结果如上,虽非唯一主控,但照样有鼓励!
   
为确保奖金发放评审的公平公正,经广大老师推荐,委托第三方资深团队组织评审,点评如下:
   消防车中的STC单片机用作辅助控制功能,作串口通讯部分,火源的STC单片机也使用了I/O功能,整个模型STC单片机的性能发挥不多, 非唯一主控,大概工作量只占三分之一,消防小车还有JESTON NANO板子作为整体车模运动控制。结论:STC32G12K128完成了三分之一的角色, 建议颁发部分奖金,以资鼓励!如【20000*1/3】=6666元 。


================================以下是获奖团队文件描述和相关资料================================

视频演示:
https://www.stcaimcu.com/static/image/filetype/av.gif

赛题:2023电赛【G】空地协同智能消防系统
北方民族大学的三位参赛选手历经四天三夜中不分昼夜黑白颠倒, 荣获国一殊荣,实至名归!恭喜北方民族大学的小伙子们!我带领大家一起来了解一下他们在本次比赛中的精彩花絮,如下:

简述:作品由飞机,火源,无人车三部分构成,在火源和无人车两部分上使用了STC32G12K128,火源上的作为主控控制模拟火灾;无人车上的作为扩展版来方便各个系统通信。
一、 总体介绍
   代码上使用了一些逐飞写的库STC32G12K128 作为主控芯片作为“火源”的主控模块,在采用了单片机控制光明电阻控制led灯的亮灭,在接收到激光照射的信号后实现灯的开启,当飞机经过灯发现光源后向小车发送灭火信息,小车按照规定线路接近“火源”,在到达预定位置后使用激光照射“火源”模块实现灭火,当检测到火源熄灭后,由STC32G12K128向消防小车发送信息,小车接收到返回信号后按规定线路返回原点

    作者自述:题目大致分为三部分:无人机,小车(模拟消防车),模拟火源(模拟真实的火灾场景)。无人机几乎已经是不用调试的情况,仓促间找到了一台ROS小车,然后为了能在小车上实现和无人机的通信和“灭火”模块,为了尽快完成任务,各部分都是东拼西凑。选择了在ROS车上放置一块STC32G12K128作为数据交换中枢,来解决在ROS方面的短板,同时51内核带来的代码便利也能大大节省时间(and速度快很多),在这个系统中选择以STC32G12K128作为主控芯片,使其能够将ROS主控的信息通过2.4G数传模块发送给无人机,并且控制灭火云台实现“灭火”功能;同时在火源部分完全采用STC32G12K128控制,在检测到一定时间激光后可以实现“点火”和“灭火”的功能。    地处宁夏,甚至在淘宝买东西都是不包邮那一档,买了东西要等几天,所以过程中我们采用了很多土方法,甚至在决赛现场其他G题的小伙伴都能看见我们的NUC是用纱布(实验室急救箱的)固定的,使用了非常多的电工胶布+热熔胶+3D打印等等,遇到很多困难,一路兵来将挡,水来土掩,总算是撑到了最后拿到了满意的成绩。作品图片展示:                                                                           https://www.stcaimcu.com/forum.php?mod=viewthread&tid=4570&extra=


视频演示: 视频 .mp4 ...














大刀阔斧 发表于 2023-10-11 14:55:04

本帖最后由 大刀阔斧 于 2023-10-25 11:04 编辑

北方民族大学-2023电赛【G】题--空地协同智能消防系统-国一,软件开源
一、 软件开源
1. 无人机部分
NUC,这一部分用来处理MID-360雷达的数据,四线360°激光雷达的数据量和算力要求是任何单片机都不能满足的,所以采用了X86平台,总的来说使用了开源的:hku-mars/FAST_LIO: A computationally efficient and robust LiDAR-inertial odometry (LIO) package (github.com)在FAST_LIO算法部署时需要注意的是你必须同时安装ROS1和ROS2环境,MID360的ROS驱动需要在ros2下编译,但是调用是在ros1,以及在配置过程中更改IP(使用tcp协议在网口接受数据,多亏了nuc12的2.5G网口),在roslaunch文件中读取当前位置,通过串口(为此不得不在usb接口插上了一个ch340)发送至飞控,由于使用串口涉及到对/dev/USBtty0的操作,必须有root权限,为了配置自启动时能够正常运行,需要将用户加入到dialout用户组,于是再利用systemctl服务配置该luanch开机自启动,nuc部分就结束了。
激光雷达定位使用激光雷达获取点云数据,传输到NUC12进行处理。NUC12使用对初始点云数据数据进行滤波、配准并使用SLAM技术进行同步定位与地图构建。SLAM技术允许我们在未知环境中实时构建地图,并同时估计机器人的位置信息(odom)。通过与之前的地图进行比对,我们可以推断出机器人相对于初始位置的运动轨迹。无线通信小车与飞行器之间采用2.4G无线信号发射接收传感器来进行通讯连接,位于小车上的接收端可以接收到来自无人机上发射端的信号来进行平面定位操作,再由小车主控芯片解析位置信息并绘制巡航轨迹图和总里程。图像识别无人机,我们主要使用openmv4识别判断出图像中最大的红色色块,但是因为openmv容易误识别, 我们通过精确阈值以及对红色色块的长度、 宽度、 像素密度加以限制,来将其于其他背景物体区分开来,误识别率显著降低。识别到黑色色块之后通过计算该物体的的中心,坐标和飞机之间的相对坐标来进行定位。对于小车,我们在小车上搭载了深度相机,使用Jetson Nano作为处理器,使其识别“街道”两边的黑线辅助小车规划路径,并且为了防止小车驶入街区内,我们设计让小车始终与黑线保持一定距离,若太接近黑线则采取制动措施并重新规划路径。
(1) 飞控部分代码:无人机位置环pid:Mypid.c#include "my_PID.h"
PID_DATA centre_xy;void my_PID_Init(void){centre_xy.Kp = 0.22f;centre_xy.Ki = 0.001f;centre_xy.Kd_expect = 0;centre_xy.Kd_feedback = 0;centre_xy.K_ff = 0;      centre_xy=centre_xy;            centre_xy.Kp = 0.3f;centre_xy.Ki = 0.001f;centre_xy.Kd_expect = 0;centre_xy.Kd_feedback = 0;centre_xy.K_ff = 0;            centre_xy.Kp = 0.35f;centre_xy.Ki = 0.001f;centre_xy.Kd_expect = 0;centre_xy.Kd_feedback = 0;centre_xy.K_ff = 0;}
void PID_Calculate(float expect,float feedback,float feedforward,float dT,PID_DATA *PID,float ierr_Limit,float i_Limit){static float hz,derros;hz = Safe_div(1.0f,dT,0);PID->feedback_old = feedback;PID->expect_old   = expect;PID->err = expect - feedback; //误差PID->expect_d = PID->Kd_expect *(expect - PID->expect_old) *hz; //期望值微分PID->feedback_d = PID->Kd_feedback *(feedback - PID->feedback_old) *hz;//实际值微分derros = PID->expect_d - PID->feedback_d; //微分KD*PID->err_i += PID->Ki * Limit(PID->err,-ierr_Limit,ierr_Limit) *dT;PID->err_i = Limit(PID->err_i,-i_Limit,i_Limit);            /*P                  I               D          前馈 */PID->out = PID->Kp * PID->err + PID->err_i + derros + PID->K_ff *feedforward;}
Mypid.h#ifndef __MY_PID_H_#define __MY_PID_H_
#include "SysConfig.h"#define Safe_div(numerator, denominator, zero) ((denominator == 0) ? (zero) : ((numerator) / (denominator)))//分母不为0#define Limit( x,min,max ) ( ((x) <= (min)) ? (min) : ( ((x) > (max))? (max) : (x) ) ) //限幅
typedef struct{float Kp;   //比例系数float Ki;   //积分系数float Kd_expect;//微分系数float Kd_feedback;//微分先行float K_ff; //前馈float err;      float expect_old;          float feedback_old; float expect_d;      //目标微分float feedback_d;    //实际微分    float err_i;   //积分float out;   //PID输出}PID_DATA;void PID_Calculate(float expect,float feedback,float feedforward,float dT,PID_DATA *PID,float ierr_Limit,float i_Limit);
void my_PID_Init(void);extern PID_DATA centre_xy;
#endif
通信卡尔曼滤波:#include "KAERMAN.h"
extern KFP KFP_height={0.02,0,0,0,0.001,0.543};

float kalmanFilter(KFP *kfp,float input) {   //预测协方差方程:k时刻系统估算协方差 = k-1时刻的系统协方差 + 过程噪声协方差   kfp->Now_P = kfp->LastP + kfp->Q;   //卡尔曼增益方程:卡尔曼增益 = k时刻系统估算协方差 / (k时刻系统估算协方差 + 观测噪声协方差)   kfp->Kg = kfp->Now_P / (kfp->Now_P + kfp->R);   //更新最优值方程:k时刻状态变量的最优值 = 状态变量的预测值 + 卡尔曼增益 * (测量值 - 状态变量的预测值)   kfp->out = kfp->out + kfp->Kg * (input -kfp->out);//因为这一次的预测值就是上一次的输出值   //更新协方差方程: 本次的系统协方差付给 kfp->LastP 威下一次运算准备。   kfp->LastP = (1-kfp->Kg) * kfp->Now_P;   return kfp->out; }
#ifndef __KAERMAN_H_#define __KAERMAN_H_
#include "SysConfig.h"
typedef struct {    float LastP;//上次估算协方差 初始化值为0.02    float Now_P;//当前估算协方差 初始化值为0    float out;//卡尔曼滤波器输出 初始化值为0    float Kg;//卡尔曼增益 初始化值为0    float Q;//过程噪声协方差 初始化值为0.001    float R;//观测噪声协方差 初始化值为0.543}KFP;//Kalman
float kalmanFilter(KFP *kfp,float input);

#endif
丢灭火包时的中断:#include "Drv_RcIn.h"#include "LX_FC_Fun.h"#include "my_PID.h"#include "my_Data.h"#include "Drv_PwmOut.h"#include "Drv_Uart.h"#include "Ano_math.h"#include "throw.h"
u8 task_mod1 ={0x00}; u8 task_mod2 ={0x01}; u8 task_mod3 ={0x02};


void throw_flag(){                                PID_Calculate(100,my_data.z_cm,0,20*1e-3f,¢re_xy,5,5); //pid控制定点高度                rt_tar.st_data.vel_z = centre_xy.out;                 static float L_x_cm,L_y_cm,ms=20;                static u16 time_dly_cnt_ms;                L_x_cm += 0.25f*(my_data.x_cm - L_x_cm);   //a*f(t)-b*f(t-1)                L_y_cm += 0.25f*(my_data.y_cm - L_y_cm); //低通滤波 使得openmv的数据更加平滑                if(time_dly_cnt_ms<12000) //对准投放点                {                  time_dly_cnt_ms+=ms;                        PID_Calculate(L_x_cm,0,0,20*1e-3f,¢re_xy,5,5);                           PID_Calculate(L_y_cm,0,0,20*1e-3f,¢re_xy,5,5);                        centre_xy.out=LIMIT( centre_xy.out,-15,15);                        centre_xy.out=LIMIT( -centre_xy.out,-15,15);                        rt_tar.st_data.vel_x = centre_xy.out;                         rt_tar.st_data.vel_y = centre_xy.out;                         if(time_dly_cnt_ms>11000)                        {                              DrvUart3SendBuf(task_mod3,1);                              my_data.xyz=1;                        }                }                else                {                                              DrvUart3SendBuf(task_mod1,1);                              time_dly_cnt_ms=0;                              my_data.flag=0;                              centre_xy.err_i=                              centre_xy.err_i=0;//积分误差清零                              L_x_cm = L_y_cm = 0; //坐标误差清零                }}
#ifndef __THROW_H#define __THROW_H
#include "SysConfig.h"
void throw_flag(void);
#endif
Openmv程序:import sensor, image, timeimport ustructfrom image import SEARCH_EX, SEARCH_DSfrom pyb import UARTsensor.reset()sensor.set_pixformat(sensor.RGB565)sensor.set_framesize(sensor.QQVGA)sensor.skip_frames(time = 2000)thresholds = [(37, 100, 6, 83, 2, 90)]modle = 2clock = time.clock()from servo import Servosfrom machine import I2C, Pin
i2c = I2C(sda=Pin('P5'), scl=Pin('P4'))servo = Servos(i2c, address=0x40, freq=50, min_us=650, max_us=2800, degrees=180)uart = UART(1, 115200)uart.init(115200, bits=8, parity=None, stop=1)servo.position(0, 150)r=(30,20,100,80)def find_max(blobs):    max_size=0    for blob in blobs:      if blob*blob > max_size:            max_blob=blob            max_size = blob*blob    return max_blobwhile(True):    clock.tick()    read = uart.read(1)    if read == b'\x00':#模式2 识别降落点      modle = 1    elif read == b'\x01':      modle = 2    elif read == b'\x02':      modle = 3
    img = sensor.snapshot()    if modle == 1:      data1_1 = ustruct.pack(                  "<bbhhhbb",                  0xaa,                  0xff,                  int(0),                  int(0),                  int(0),                  0x01,                  0xee                  )      uart.write(data1_1)    elif modle == 2:      blobs = img.find_blobs(],roi=r)      for b in blobs:            max_blob = find_max(blobs)            img.draw_rectangle(max_blob.rect(), color = (0, 0, 255))            img.draw_cross(max_blob.cx(), max_blob.cy())            x = max_blob.cx()-80            y = 60-max_blob.cy()            if x == -80 or y == 60:                data1_2 = ustruct.pack(                        "<bbhhhbb",                        0xaa,                        0xff,                        int(0),                        int(0),                        int(0),                        0x01,                        0xee                        )                print(x,y)                uart.write(data1_2)            else:                data1_3 = ustruct.pack(                        "<bbhhhbb",                        0xaa,                        0xff,                        int(x),                        int(y),                        int(1),                        0x01,                        0xee                        )                print(x,y)                uart.write(data1_3)    elif modle == 3:      servo.position(0, 60)
    print(modle)


关于数传,因为使用了匿名数传,已经封装好了使用功能,只需用串口方式收发,这里需要注意的是因为我们过多的使用了杜邦线+热熔胶加固的原因,在匿名官方建议的波特率下无法正常通信,随即将波特率设置为115200才正常,代码使用逐飞的stc32串口收发就可以。灭火云台是与openmv配合,同时使用串口控制来为openmv指明左右(此时抽象为二维坐标系)。在火源部分,使用了简单的按键例程,加入了延时,满足题目要求的两秒左右,这里会遇到的难点在于时钟配置,与经典8051有些许的区别。

大刀阔斧 发表于 2023-10-11 14:55:38

本帖最后由 大刀阔斧 于 2023-10-25 11:05 编辑

北方民族大学-2023电赛【G】题--空地协同智能消防系统-国一,硬件开源

无人机采用450的机架,使用了大功率的电机和电调,动力方面采用4S,45C,5300mAh的大容量动力电池,让飞机的能够支撑起自身搭载的器件。定位方面在无人机选择NUC12搭载MID-360激光雷达,在小车上使用了JESTON NANO搭载T265深度相机。定点方面使用激光定高作为定高方案,图形处理方面使用了OPENMV4P作为图形识别模块做火源的识别。消防小车使用ROS小车搭载JESTON NANO作为主控,解算小车位置信息并自主规划路径。采用STC32G12K128作为主控来向无人机发送交换数据并与OPENMV通信,实现火源的识别。采用STC32G12K128作为“火源“的主控芯片,可以实现LED灯的”点亮“和”熄灭“。需要注意雷达的供电在9-27V,NUC的供电在12-24V,因为使用4S电池,所以直接从分电压板取电。NUC如果有一个HDMI欺骗器调试会方便很多。值得一提的是,为了增大光源面积,使用了导光膜,原本的作用是屏幕后面的匀光板,用它增加了灯源的显示面积和光敏电阻的检测面积。

32位8051-AI 发表于 2023-10-12 09:39:28

本帖最后由 32位8051-STCAI 于 2023-12-14 13:11 编辑

杭州科技职业技术学院===获得2023年全国大学生电子设计竞赛,大专组一等奖
J题:线路故障自动检测系统@STC32G12K128实现,STC是唯一主控MCU,奖金人民币2万
J题要求:设计一套线路故障自动检测装置,能判定并显示线路中故障位置和类型
杭州科技职业技术学院2023年全国大学生电子设计竞赛使用STC32位8051为主控芯片
===2023/12/14,已审核通过
按规定一等奖奖金人民币2万@STC32G12K128,32位8051


为确保奖金发放评审的公平公正,经广大老师推荐,委托第三方资深团队组织评审,点评如下:
该题目为线路故障自动检测系统,其工作逻辑比较清晰,一颗STC32G12K128/32位8051即完成了所有功能,根据其实物图片、程序框图以及开源代码分析可确认STC32G12K128为唯一主控且为唯一可编程器件。结论:建议颁发一等奖全额奖金人民币2万元,以资鼓励!
获奖证书:

视频介绍:

摘要
本装置以 STC32G 单片机为核心控制器件,结合 LM311 振荡电路等电路组成。LC 振荡电路作为装置的核心,通过监测 LM311 输出频率的变化来检测电感和电容元件的故障,并通过检测二极管两边 IO 口信号的 变化来判断二极管的故障问题。这种方案具有结构简单、调节便捷的特点。为了实现只允许按一次启动键的功能,我们采用了单片机主控模块发送控制信号,并通过继电器控制电路中各个部分的开关,从而实现对元件故障位置和类型的准确定位和识别。同时,通过精心设计的程序,单片机可将检测结果传输到液晶屏上显示,使 操作人员能够直观地了解电路中的故障情况。

题目分析方案一:NE555 无稳态 RC 谐振电路。NE555 集成电路是一种常见且价格低廉的集成电路,其可以被用来产生方波信号的无稳态RC谐振 电路。NE555 集成电路具有简单的引脚布局和操作方式,使得使用起来非常方便。但是 NE555 的无稳态RC 谐振电路精度较低:相对于一些专用的振荡器电路,NE555 无稳态电路的频率和幅值稳定性较差,容易受到外部条件的影响。
方案二:LC 振荡电路。
LC 振荡电路可以产生非常稳定的振荡信号,频率稳定度较高;通过调整电感和电容的数值,可以实现广泛的频率范围,适应不同的应用需求。通过调整电容和电感元件的数值,LC 振荡电路可以实现对电容和电感值的精确测量,满足高精度测量的要求。在实验中,我们对 NE555 无稳态 RC 谐振电路进行了测试,发现它并不能有效地检测线路网络中的电容短路问题。然而,在实验 LC 振荡电路时,我们观察到它能够准确地检测到线路网络中出现的任何元件的单一问题。故我们选择了方案二。总体设计框图

理论分析与设计1 检测原理分析
通过单片机采集检测系统输出的频率变化,我们可以判断线路网络中电感或电容是否正常;同时,通
过单片机采集的电压信号,我们可以判断二极管是否存在故障。
1.1 检测电感电容故障原理分析
测量的原理是由单片机通过对 LM311 输出端进行频率的采集。我们将线路网络视为一个整体,将其
作为 LC 振荡电路中的电感 L 和电容 C。当线路网络中的电感或电容出现故障时,LC 振荡网络就会发生
改变,进而导致 LM311 的输出频率发生变化。
1.2 检测二极管故障原理分析
二极管开路故障检测的原理是将二极管的 B-或 A-引脚与单片机的 IO 口相连。当将输入端的 IO 口
设置为高电平时,另外一边的 IO 口也会接收到高电平信号。通过这种连接方式,我们可以利用单片机的
IO 口来检测二极管是否正常工作。然而,如果二极管存在开路故障,输入端 IO 口的高电平信号将无法传
递到另一端的 IO 口,导致另一端无法接收到高电平。这种现象表明二极管存在开路故障。
2 故障定位原理分析
通过单片机采集 LM311 输出端的频率,并与预设的正常频率进行比较,我们可以准确地判断是哪个
电感或电容元件出现故障。另一方面,根据输入高电平,通过对接收信号的观察,我们可以确定二极管是
否正常工作。
2.1 电感电容故障定位原理分析**
当线路网络中的电感或电容出现故障时,这会导致 LM311 振荡电路的输出频率发生变化。不同的电
感或电容元件故障会引起不同的输出频率变化。在电路正常工作的情况下,我们可以根据 LC 振荡公式得
到一个预设的频率。当电感或电容元件出现故障时,振荡电路的参数发生改变,从而导致振荡频率的变化。
当电路正常工作时,根据 LC 振荡公式可得
2.2 二极管故障定位原理分析
二极管开路故障定位的原理是将二极管的 B-或 A-引脚与单片机的 IO 口相连。左右两个 IO 口分别
设置为高电平,通过检测接收到的信号可以判断二极管的工作状态。如果接收到高电平信号,表示对应方
向的二极管正常;而如果接收到低电平信号,则说明对应方向的二极管损坏。通过对左右两边的检测结果
进行判断,可以确定二极管的故障位置或者判断二极管是否正常工作。检测图如图 2,电路图如图 3


国一,2023年电赛J题 杭科院故障检测 - 2025全国大学生电子设计竞赛技术支持版块,最高奖100万,一等奖2万,选型 - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区https://www.stcaimcu.com/forum.p ... 4564&extra=page%3D1












32位8051-AI 发表于 2023-10-12 09:39:54

本帖最后由 32位8051-STCAI 于 2023-11-21 08:53 编辑

硬件介绍
主控电路:

1降压模块设计
本模块采用 78M05 芯片进行降压操作。78M05 是一款稳压器芯片,它可以将输入的高电压稳定地降压到 5V 输出。与其他降压芯片相比,78M05 在降压过程中消耗的电压较少,能够有效地提供稳定的电压输出。因此,使用 78M05 芯片进行降压操作可以确保系统获得稳定可靠的电源供应。模块如下图



2检测模块设计
通过对 LM311 输出端进行频率的采样,然后依据采集的频率不同再计算出是哪个电容或电感出现故障。检测二极管的好坏时,用继电器控制线路的通断,保证互不干涉。模块大致如下图



3 电路框架设计
电路框图如图 5所示。该系统采用了单电源供电的设计,经过降压处理后,为整套系统供电。在系统中,线路间的连接和切换是由单片机控制的继电器来实现的。通过单片机的精确控制,我们能够实现对各个部分的连接和切换,以便进行准确的故障检测操作。当系统工作时,单片机根据预设的程序和逻辑,控制继电器的开关状态,从而实现对线路的连接和切换。通过合理的连接和切换,以便单片机进行频率的采集和分析。通过单片机的控制,我们可以根据采集到的频率信息,与预设的正常频率进行比较和分析,从而准确地判断是哪个电感或电容元件出现故障。



实物及PCB原理图展示通过利用 LM311 比较器和 LC 振荡电路搭建基本的线路故障检测系统。让单片机接受 LM311 输出端频率并经过处理结合继电器实现自动检测,我们成功满足了设计要求。这个系统能够自动检测线路中的故障,并能够准确地判定和显示故障的位置和类型。
PCB及原理图采用嘉立创EDA专业版设计




32位8051-AI 发表于 2023-10-12 09:40:34

本帖最后由 32位8051-STCAI 于 2023-11-22 11:30 编辑

软件介绍
程序流程图如图 该系统以 STC32G 单片机为控制核心,利用其强大的处理能力和丰富的接口资源,实现对故障频率的信号采集和处理。在系统中,首先对每种故障产生的不同频率进行信号采集,通过单片机的输入引脚将信号输入到系统中。接下来,系统将采集到的信号和原始程序进行校准。通过比较采集到的信号和预设的正常频率范围,系统可以判断是否存在故障,并进一步确定是哪种元件故障。在测试过程中,系统将根据不同频率的输入信号,实时在屏幕上反应相应的问题。以便操作者直观地了解故障情况。

程序如下:#include "config.h"sfr   IE2         =   0xaf;sfr   AUXINTIF    =   0xef;#define ET3             0x20#define T3IF            0x02u8 dis_buf;u8 state = 0;bit EEP_Write_flag = 0;bit EEP_Read_flag = 0;void eeprom_write_fun();void eeprom_read_power_on();void Open_cir_fun();bit open_short_cir_job = 0;bit eep_w_job = 0;bit eep_r_job = 0;bit dis_job = 0;void Timer0Init(void)                {        AUXR |= 0x80;                //定时器时钟1T模式        TMOD &= 0xF0;                //设置定时器模式        TMOD |= 0x01;                //设置定时器模式        TL0 = 0x00;                //设置定时初始值        TH0 = 0x00;                //设置定时初始值        TF0 = 0;                //清除TF0标志        TR0 = 1;                //定时器0开始计时        ET0 = 1;}void Timer1Init(void)                //01微秒@33.000MHz{        TMOD |= 0x40;                              //外部计数模式    TL1 = 0xff;    TH1 = 0xff;    TR1 = 1;                                    //启动定时器    ET1 = 1;                                    //使能定时器中断}void Timer3Init(void)                //10毫秒@33.1776MHz{        T4T3M &= 0xFD;                //定时器时钟12T模式        T3L = 0x00;                //设置定时初始值        T3H = 0x94;                //设置定时初始值        T4T3M |= 0x08;                //定时器3开始计时        IE2 = ET3;                                  //使能定时器中断}
unsigned long WB_num = 0;u16 DS_NUM = 0;u16 WB_NUM_SAVE = 0;u16 TH0_NUM_SAVE = 0;u16 TL0_NUM_SAVE = 0;u16 TH1_NUM_SAVE = 0;u16 TL1_NUM_SAVE = 0;u16 DS_NUM_SAVE = 0;u16 JS_NUM = 0;u16 JS_NUM_SAVE = 0;float PL = 0;float Freq = 0;float DS = 0;float JS = 0;
bit OK = 0;float Freq_state_open={0};float Freq_save = {0};u8 Freq_index_save={0};float Most_MAX = {0};float Most_MIN = {0};float Freq_state_index_open = 0;
float _Ref = 0;u8 Sub = 1;
bit Save_start = 1;void TIME1() interrupt 3 //计数器{         JS_NUM++;}void TIME0() interrupt 1{        DS_NUM++;        if(DS_NUM>=331)//≈655.35ms        {                TR0 = 0;                TR1 = 0;                JS_NUM_SAVE = JS_NUM;                JS_NUM = 0;                TH0_NUM_SAVE = TH0;                TH0 = 0;                TL0_NUM_SAVE = TL0;                TL0 = 0;                TH1_NUM_SAVE = TH1;                TH1 = 0;                TL1_NUM_SAVE = TL1;                TL1 = 0;                DS_NUM_SAVE = DS_NUM;                DS_NUM = 0;                DS = 65535*DS_NUM_SAVE+TH0_NUM_SAVE*256+TL0_NUM_SAVE;                JS = 65535*JS_NUM_SAVE+TH1_NUM_SAVE*256+TL1_NUM_SAVE;                Freq = (JS*33177600/DS)/1.036892929292929;                Freq = Freq/1000;                TR0 = 1;                TR1 = 1;        }}bit Sub1_start_flag = 0;bit Sub2_start_flag = 0;bit Sub3_start_flag = 0;bit bit_cls = 0;bit Vocie_fun_flag = 0;bit _1s_voice_time_flag = 0;u16 _1s_voice_time = 0;void TM3_Isr() interrupt 19{        u8 i = 0;        static u8 key_value = 0;        static u8 _5ms_time = 0;        (_5ms_time>199)?(_5ms_time = 0):_5ms_time++;        if(_5ms_time%2==0)open_short_cir_job = 1;        if(_5ms_time%20==0)eep_w_job = 1;        if(_5ms_time%40==0)dis_job = 1;        if(_1s_voice_time_flag)        {                _1s_voice_time++;        }//        if(Sub==1)//        {//                if(_5ms_time%199==0)LCD_CLS();        //        }//        if(Sub==2)//        {//                if(_5ms_time%199==0)Sub3_start_flag = 1;        //        }//        if(Sub==3)//        {//                if(_5ms_time%199==0)Sub3_start_flag = 1;        //        }        key_value = key_get();        switch(key_value)        {                case 1:                        Sub=1;Sub1_start_flag = 1;_1s_voice_time_flag = 1;                break;                case 2:                        Sub=2;Sub3_start_flag = 1;_1s_voice_time_flag = 1;                break;                case 3:                        Sub=3;Sub3_start_flag = 1; _1s_voice_time_flag = 1;                break;                case 4:                        Sub=4;                break;                case 5:                        Freq_state_open = Freq;//存频率                        Freq_state_index_open++;                        if(Freq_state_index_open==15)                        {                                Save_start = 1;                                Freq_state_index_open = 0;                        }                        EEP_Write_flag = 1;                break;                case 14:                        Vocie_fun_flag = 1;                break;                case 15:                        Vocie_fun_flag = 0;                break;                case 16:                        Sub=0;                break;        }        }void Find_max_min(){        static u8 a = 0xff;        static u8 index = 0;        static u8 step = 0;        static u8 index_1 = 0;        float temp = 0;        int i, j;        if(Save_start)        {                Save_start = 0;                _Ref = Freq_state_open;                for(i=0;i<15;i++)                {                        Freq_save = _Ref/Freq_state_open;                }                for (i = 1; i < 15; i++)//外层循环是比较的轮数,数组内有10个数,那么就应该比较10-1=9轮                {                        for (j = 0; j < 15 - i; j++)//内层循环比较的是当前一轮的比较次数,例如:第一轮比较9-1=8次,第二轮比较9-2=7次                        {                                if (Freq_save > Freq_save)//相邻两个数如果逆序,则交换位置                                {                                        temp = Freq_save;                                        Freq_save = Freq_save;                                        Freq_save = temp;                                }                        }                }                for(i=0;i<15;i++)                {                        for(j=0;j<15;j++)                        {                                if(a==j)continue;                                if(Freq_save==(_Ref/Freq_state_open))                                {//                                        a = j;                                        Freq_index_save = j;                                }                        }                }                Most_MAX] = (Freq_save+Freq_save)/2;                Most_MIN] = 0;                Most_MAX] = 999999;                Most_MIN] = (Freq_save+Freq_save)/2;                for(i=1;i<14;i++)                {                        Most_MAX] = (Freq_save+Freq_save)/2;                        Most_MIN] = (Freq_save+Freq_save)/2;                }        }                }void Juge_LC();void check_d1(){        static u8 D1_D2_Nomarl = 0;        P5M0 = 0xff; P5M1 = 0X00;        P7M0 = 0xff; P7M1 = 0X00;        D_CHECK_B = 0;//AB io 置0        D_CHECK_A = 0;                Relay_close();//关闭继电器        P5M0 = 0X00; P5M1 = 0X00;//切换IO模式        P7M0 = 0X00; P7M1 = 0XFF;        D_CHECK_A = 1;//P5        Delay_ms(10);        if(D_CHECK_B==1)//正常        {                                D1_D2_Nomarl = 1;//                LCD_P8x16Str(0,2,"D1 ");//                LCD_P14x16Ch(32,2,24);//无//                LCD_P14x16Ch(48,2,20);//故//                LCD_P14x16Ch(64,2,21);//障        }        else         {                D1_D2_Nomarl = 0;                LCD_P8x16Str(0,2,"D2      ");//断路                LCD_P14x16Ch(48,2,28);//                LCD_P14x16Ch(64,2,27);//                Voice.diode = 16;        }        D_CHECK_A = 0;        D_CHECK_B = 0;                P5M0 = 0X00; P5M1 = 0Xff;        P7M0 = 0X00; P7M1 = 0X00;        D_CHECK_B = 1;//P7        Delay_ms(10);        if(D_CHECK_A==1)        {                if(D1_D2_Nomarl==1)                {                        Voice.diode = 18;                        LCD_P8x16Str(0,2,"D1 D2   ");                        LCD_P14x16Ch(64,2,24);//无                        LCD_P14x16Ch(80,2,20);//故                        LCD_P14x16Ch(96,2,21);//障                }        }        else         {                if(D1_D2_Nomarl==0)                {                        LCD_P8x16Str(0,2,"D1 D2");//断路                        LCD_P14x16Ch(48,2,28);//                        LCD_P14x16Ch(64,2,27);//                        Voice.diode = 15;                }                else                 {                        LCD_P8x16Str(0,2,"D1      ");//断路                        LCD_P14x16Ch(48,2,28);//                        LCD_P14x16Ch(64,2,27);//                        Voice.diode = 15;                }                        }        D_CHECK_A = 0;        D_CHECK_B = 0;        }void check_LC(){        Relay_open();//继电器吸合                P5M0 = 0X00; P5M1 = 0X00;        P7M0 = 0X00; P7M1 = 0X00;        D_CHECK_B = 0;//AB io 置0        D_CHECK_A = 0;        Delay_ms(200);        Find_max_min();//找边界        Juge_LC();//判断LC}
void Juge_LC(){        if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P14x16Ch(0,0,29);//电                LCD_P14x16Ch(16,0,30);//感                LCD_P14x16Ch(32,0,29);//电                LCD_P14x16Ch(48,0,32);//容                LCD_P14x16Ch(64,0,24);//无                LCD_P14x16Ch(80,0,20);//故                LCD_P14x16Ch(96,0,21);//障                Voice.LC = 17;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"C1      ");                LCD_P14x16Ch(32,0,28);//开                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 1;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"C2      ");                LCD_P14x16Ch(32,0,28);//开                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 2;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"C3      ");                LCD_P14x16Ch(32,0,28);//开                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 3;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"C4      ");                LCD_P14x16Ch(32,0,28);//开                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 4;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"L1      ");                LCD_P14x16Ch(32,0,28);//开                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 5;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"L2      ");                LCD_P14x16Ch(32,0,28);//开                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 6;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"L3      ");                LCD_P14x16Ch(32,0,28);//开                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 7;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"C1      ");                LCD_P14x16Ch(32,0,25);//短                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 8;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"C2      ");                LCD_P14x16Ch(32,0,25);//短                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 9;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"C3      ");                LCD_P14x16Ch(32,0,25);//短                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 10;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"C4      ");                LCD_P14x16Ch(32,0,25);//短                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 11;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"L1      ");                LCD_P14x16Ch(32,0,25);//短                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 12;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"L2      ");                LCD_P14x16Ch(32,0,25);//短                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 13;        }        else if(NOW_FREQ<Most_MAX&&NOW_FREQ>Most_MIN)        {                LCD_P8x16Str(0,0,"L3      ");                LCD_P14x16Ch(32,0,25);//短                LCD_P14x16Ch(48,0,27);//路                Voice.LC = 14;        }}void Sub_3(){        if(Sub3_start_flag)        {                check_LC();//先测电容                check_d1();//再测电感                if(_1s_voice_time_flag==0)_1s_voice_time_flag = 1;        }}
void Sub_1(){        if(Sub1_start_flag)        {                check_LC();                if(_1s_voice_time_flag==0)_1s_voice_time_flag = 1;        }}void main(){        u8 i = 0;        int j;        float T = 0;        sys_int();        Timer0Init();        Timer1Init();        Timer3Init();        UartInit();        LCD_Init();        LCD_CLS();        eeprom_read_power_on();        P_SW2 = 0x80;        XOSCCR = 0xc0; //启动外部晶振        while (!(XOSCCR & 1)); //等待时钟稳定        CLKDIV = 0x00; //时钟不分频        CLKSEL = 0x01; //选择外部晶振        P_SW2 = 0x00;        D_CHECK_A = 0;        D_CHECK_B = 0;        Relay_open();                EA = 1;        Usart_send("AF:31\r\n");        while(1)        {                if(open_short_cir_job)                {                        if(Sub==1)Sub_1();                        if(Sub==2)Sub_3();                        if(Sub==3)Sub_3();                        if(Vocie_fun_flag)                        {                                if(_1s_voice_time>=200)                                 {                                        Find_LC_voice();                                        _1s_voice_time = 0;                                        _1s_voice_time_flag = 0;                                 }                        }                        open_short_cir_job = 0;                }                if(eep_w_job)                {                        eeprom_write_fun();                        eep_w_job = 0;                }                if(dis_job)                {                        dis_play();                        dis_job = 0;                }        }}void eeprom_write_fun(){        u8 i = 0;        unsigned long addr = 0x0000;        static u8 write_check = 1;        if(EEP_Write_flag)        {                EEP_Write_flag = 0;                write_check = 0;                EEPROM_Erase(0x0000);Delay_ms(1);                EEPROM_Write(0x0000,(u8*)&write_check,4);Delay_ms(1);                for(i=0;i<15;i++)                {                        EEPROM_Write(addr,(u8*)&Most_MAX,4);Delay_ms(1);                        addr+=4;                }                for(i=0;i<15;i++)                {                        EEPROM_Write(addr,(u8*)&Most_MIN,4);Delay_ms(1);                        addr+=4;                }                for(i=0;i<15;i++)                {                        EEPROM_Write(addr,(u8*)&Freq_state_open,4);Delay_ms(1);                        addr+=4;                }        }}void eeprom_read_power_on(){        u8 i = 0;        long addr = 0x0000;        static u8 read_check = 0;        if(EEP_Read_flag==0)        {                EEP_Read_flag = 1;                EEPROM_Read(0x0000,(u8*)&read_check,4);Delay_ms(1);                if(read_check==0)                {                        for(i=0;i<15;i++)                        {                                EEPROM_Read(addr,(u8*)&Most_MAX,4);Delay_ms(1);                                addr+=4;                        }                        for(i=0;i<15;i++)                        {                                EEPROM_Read(addr,(u8*)&Most_MIN,4);Delay_ms(1);                                addr+=4;                        }                        for(i=0;i<15;i++)                        {                                EEPROM_Read(addr,(u8*)&Freq_state_open,4);Delay_ms(1);                                addr+=4;                        }                }        }}
页: 1 [2] 3 4 5 6 7 8
查看完整版本: 2023年电赛申领奖金,奖金已发放; 2025年,一等奖2万@AI8051U