0%

大学回忆录

大一上学期

回忆从开学前几日的寝室生活开始,室友都非常的好相处,大家在一起能玩的很嗨。再到大一我参加了两个学生会的部门(学生会办公室&党员之家实践部)和一个社团(单车俱乐部),自己在部门里认识了些不同班级不同专业的朋友,也交到了一位知心,大一上学期我天天晚上会和他去健身房,或是去钱塘江边散步,或是在寝室喝酒,元旦跨年我去了他家里,人生中第一次和别人跨年。参与了学生会的活动演出和演讲还有优秀干部的竞选;

大一寒假

寒假里我一个人坐飞机去了山东蓬莱,找我高考结束后在华为上班认识的同事,蓬莱待了7天,青岛待了2天。独自旅行,去一个陌生的地方,享受孤独,思考人生,一个人狂欢。旅行结束回家后,我学习了郭天祥的十天学会51单片机,但并没有完全学会;

大一下学期

大一下学期有我喜欢的课程模电,我通过教同学们解题来学习这门课程,因此也交到了陪伴我至今的女朋友。除了模电课我还选了一门电子课程设计也非常喜欢,老师授课讲了51单片机的知识,课程做了51数字钟(我在5月19日晚上写完,拍了个51开发版显示520倒计时的视频),最后的作业是51小车。这学期学生会部门成员积极性变差了,我最后没有选择留任执委,选择了留在电子创新实验室(一待就是三年);

大一暑假

暑假我留在实验室准备19年的全国大学生电子设计竞赛,暑假做了历年的题目(声音存储录放、风力摆、旋转倒立摆),那时候的我不知道熬夜会伤身体,每天白天调试,晚上在寝室看文档到凌晨2点。暑假里由于比较专注比赛,忘记关心女朋友,两人有过多次争执,女朋友不回消息,我直接去她家里了,就这样被她家人认识,至今我还常去她家蹭饭。这个暑假差一点点就分手了;

大二上学期

大二上学期,一开学和徐高东学长参加了工程训练大赛,那次比赛后感觉之前所有学过的东西都能联会贯通了。比赛的时候出现了意外,没有取得好成绩,东哥说了句:比赛不就是这样。随后我参加了飞思卡尔智能车竞赛,在校内训练的时候感觉都良好,本来计划我和洪晨益写程序,由于硬件画的板子实在惨不忍睹,就自己动手把硬件做完了,我那写代码的队友也很强,一人能维护好代码,那年寒假前我们俩调车调到学校关门。这学期,我和我的女朋友分手了,但几个星期又复合了,我们相互都很缺时间在一起交流;

大二寒假

那年是全世界肺炎流行的一年,寒假在家3个月,当然我也没闲着,趁家里无聊,打开电脑学了些东西,有python,tensorflow,sklearn,百度飞桨,git等,有潘利斌陪我一起学。疫情原因只能在家调飞卡,在家里把Altium Designer了一遍,画板子是没有问题了。3月在家网课,网课非常适合我,我可以不仅可以回放自己学校老师上课讲的,还能去B站慕课上找名校老师上课的视频;

大二下学期

中国疫情控制的很厉害,4月中就能返校了。这学期在学校主要是准备电赛,准备飞卡,飞卡参加的是AI组别,通过机器学习,训练后部署到单片机,实现自主规划路线;

大二暑假

暑假培训大一电赛新生,不过今年比赛延期了,暑假没有比赛。飞卡如期举行,离国赛就差0.02秒,怎么就这么可惜呀。电赛准备了很多模块,把模块间通信学的明明白白的,还有很多PCB上的设计规范也学了一遍,那年我们实验室都在看长江大学唐老师的教学视频。

大三上学期

大三上学期开始在黄道麒公司实习,老板非常厉害,抓住了疫情这个风口,做红外热像仪体温枪这些生意。公司离学校很近,我每天上完课就去公司,那段时间进步非常快,学的东西也非常多非常杂。用了好多品牌的国产mcu,用QT写了上位机,学习了二元光学。十月份浙江省电子大赛,作品实物验收满分取得了省二等奖,队友配合的非常棒!这学期上了算法与数据结构和数字逻辑设计、51汇编,非常感兴趣,买了块FPGA开发板练手;

大三寒假

寒假里我还在公司上班,老板让我住宾馆可以报销。寒假里我学习了linux应用开发,opencv,makefile,cmake,用树莓派做了个红外热像仪的demo。这个寒假我在公司借了很多书看,有linux的,opencv的,无线传感器网络的,感测技术的。在公司里和老板经常聊到很晚,我们谈未来的方向,谈生活时政等等,无所不谈,是一家有温度的公司

大三下学期

这学期了解了一些网络安全,开关电源设计,搭建了blog,仍然在公司实习。搞的东西太杂了容易忘记自己学过什么,写写博客记录下的话翻到还能有印象。公司里主要是把之前用树莓派跑的demo移到了m4的mcu,另一个项目是用高云fpga做了ov2640的串并转换到mcu处理,练习了fpga。5月份之前飞卡的软件队友提出来要再参加一次,让我做一下硬件,这次我非常熟练,PCB最多就设计了两版就完成了硬件设计;

大三暑假

暑假去了一家做半导体芯片的公司实习,是属于系统集成部,公司平均年龄比较大,部门里同事都不怎么说话,公司氛围不太好,领导经常会骂别人很凶,我一看不对劲就溜溜球了。暑假在做wifi图传的项目,尝试用m4自己看数据手册写WiFi驱动,不过后来这事没成,换了esp32用idf开发。很早开始我就对网络感兴趣,可能未来也会多往这个方向发展;

大四上学期

大四第一学期在世界五百强博世上班,公司的氛围特别好,领导都很有管理的能力,同事之间办公都非常的舒心,博世是个不加班的外企,但是工作效率挺高的,流程虽多,但处理速度很快。我在博世工作了4个月,学习了高压交流的PCB设计,直流无刷电机,永磁同步电机,把电力这一块学了一遍,也了解了电机的控制算法,最简单的六步换向,还有FOC。可以说这次实习经历相当难忘,每个牛的公司,都有一群好的团队管理者。这学期,还报名考研了,算是把大学的知识复习了一下,没考好,以后也不会再有考研的想法了;

还有最后一个假期

最后一个假期也没选择安逸,找了家做安防的公司实习,在这里我学到了linux驱动开发的知识,我的主管年龄挺大的技术很好,整个框架是他从头写出来的,我看git log一步步看他怎么写出来,太强了!面试的时候就被他的技术所吸引,这么强的人为人还非常谦虚,值得我去学习!在这里我重学了一年前了解过的makefile编写,shell脚本编程,C代码规范等等。看了主管写的几万行脚本代码,我再感叹到太强了!过年在家里自己系统的学了一遍计算机网络,本来还想学计算机组成原理和操作系统的,学操作系统的时候卡住了,看早期的linux源码也非常的费劲,只能推到我2月实习完回学校再学了;

致青春:如果没有源自内心的冲动,怎么可能登峰造极呢?

学习视频

以太网的介绍

网络体系结构

220113-fpga之eth-1.jpg

  • 物理层:在物理层上所传数据的单位是比特。发送方发送1(或0)时,接收方应当收到1(或0)而不是0 (或1),因此物理层要考虑用多大的电压代表”1”或”0”,以及接收方如何识别出发送方所发送的比特。物理层还要确定连接电缆的插头应当有多少根引脚以及各引脚应如何连接。当然,解释比特代表的意思,就不是物理层的任务。请注意,传递信息所利用的-些物理媒体,如双绞线、同轴电缆、光缆、无线信道等,并不在物理层协议之内而是在物理层协议的下面。
  • 数据链路层:数据链路层常简称为链路层。我们知道,两台主机之间的数据传输,总是在一段一段的链路上传送的,这就需要使用专门的链路层的协议。在两个相邻结点之间传送数据时,数据链路层将网络层交下来的IP数据报组装成帧(framing),在两个相邻结点间的链路上传送帧(frame),每一帧包括数据和必要的控制信息(如同步信息、地址信息、差错控制等)。在接收数据时,控制信息使接收端能够知道一个帧从哪个比特开始和到哪个比特结·束。这样,数据链路层在收到一个帧后,就可从中提取出数据部分,上交给网络层。控制信息还使接收端能够检测到所收到的帧中有无差错。如发现有差错,数据链路层就简单地丢弃这个出了差错的帧,以免继续在网络中传送下去白白浪费网络资源。如果需要改正数据在数据链路层传输时出现的差错(这就是说,数据链路层不仅要检错,而且要纠错),那么就要采用可靠传输协议来纠正出现的差错。这种方法会使数据链路层的协议复杂些。
  • 网络层、运输层、应用层见《计算机网络》书籍;fpga跑eth主要用到了phy层、数据链路mac层、网络层、udp传输层;

FPGA数据包内容

下面放出fpga发送的以太网数据包的组层图,图片来自《开拓者FPGA 开发指南V1.3》,相关介绍也可以查看PDF。

以太网数据包格式

220113-fpga之eth-2.jpg

以太网帧格式

220113-fpga之eth-3.jpg

IP数据包格式

220113-fpga之eth-4.jpg

UDP数据格式

220113-fpga之eth-5.jpg

千兆以太网物理层

  • 下面这个是我开发板图和板上的千兆以太网原理图,设计的非常好,板子上的IO基本上都是等长线。

220113-fpga之eth-6.jpg

220113-fpga之eth-7.jpg

  • 物理层的设计和学习还有个非常重要的学习资料就是《RTL8211数据手册》,这个手册上竟然写着不对外公布。

调试过程

例程修改

  • 简易的修改了下例程,让udp每次数据包发送1472个字节数据,其中前4字节是包序列号,用于接收端检测是否掉包,其他的1468个字节数据为0x00-0xFF循环,从而更为精确的模仿正常传输时的内容。再通过每次发完控制idle时间来控制传输速率。

上位机编写

  • 上位机才用Python编写,在JupyterNotebook里实现。实现原理主要就是一直读udp,再去比较这次的包序列号是不是上一次+1,如果不是的话打印出来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import socket
BUFSIZE = 1472 * 100
ip_port = ('192.168.0.3', 8080)
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # udp协议
server.bind(ip_port)
error = 0
recv_data_a = server.recvfrom(BUFSIZE)[0][:4]
while True:
recv_data_b = server.recvfrom(BUFSIZE)[0][:4]
if(int.from_bytes(recv_data_b,byteorder='big',signed=False) != \
int.from_bytes(recv_data_a,byteorder='big',signed=False) + 1):
error += 1
print("error:%u, recv_data_a = %u, recv_data_b = %u" \
%(error, int.from_bytes(recv_data_a,byteorder='big',signed=False), \
int.from_bytes(recv_data_b,byteorder='big',signed=False)))
recv_data_a = server.recvfrom(BUFSIZE)[0][:4]
if(int.from_bytes(recv_data_a,byteorder='big',signed=False) != \
int.from_bytes(recv_data_b,byteorder='big',signed=False) + 1):
error += 1
print("error:%u, recv_data_b = %u, recv_data_a = %u" \
%(error, int.from_bytes(recv_data_b,byteorder='big',signed=False), \
int.from_bytes(recv_data_a,byteorder='big',signed=False)))
server.close()

掉包处理

  • 在100Mbps速率传输的时候,每65536帧传输后都会出现2帧的掉包,通过WireShark查看,能找到那2帧包,也就是说数据包被网卡接收但是在上位机处没有接收。通过WireShark查看整个以太网数据包内容后发现规律:只有在IP数据包的首部校验和为0xFFFF的时候才会出现掉包,百度上也有这样的案例,于是修改FPGA代码,让IP包首部标识位不每次+1,这样校验和就不会出现0XFFFF。

调试结果

  • 经过简易测试,当传输速率为200Mbps的时候,不掉包;当传输速率为300Mbps的时候,出现掉包。

总结

  • 本次调试,学习了网络5层模型的物理层和MAC层,通过亲自实践解决出现的问题,对网络的底层实现有了更清楚的认识,对日后学习Linux驱动开发的网络部分会有极大的帮助,以及我的毕设,udp传输图像只是其中的一小部分,如果有时间,我会做个更复杂题目,学习更多的网络知识(大学只学了物联网和网络相关,计网没学)。

Linux-File(文件写入)

​ 对于write函数,我们认为该函数一旦返回,数据便已经写到了文件中。但是这种概念只是宏观上的,一般情况下,对硬盘(或者其他持久存储设备)文件的write操作,更新的只是内存中的页缓存(page cache),而脏页不会立即更新到硬盘中,而是由操作系统统一调度,如flusher内核线程在满足一定条件时(一定时间间隔、内存中的脏页达到一定比例)将脏页面同步到硬盘上(放入设备的IO请求队列)。因为write调用不会等到硬盘IO完成之后才返回,设想如果操作系统在write调用之后、硬盘同步之前崩溃,则数据可能丢失。虽然这样的时间窗口很小,但是对于需要保证事务的持久化(durability)和一致性(consistency)的数据库程序来说,write()所提供的“松散的异步语义”是不够的,通常需要操作系统提供的同步IO(synchronized-IO)原语来保证:

​ Linux、unix在内核中设有缓冲区、高速缓冲或页面高速缓冲,大多数磁盘I/O都通过缓冲进行,采用延迟写技术。
sync:将所有修改过的快缓存区排入写队列,然后返回,并不等待实际写磁盘操作结束;
fsync:只对有文件描述符制定的单一文件起作用,并且等待些磁盘操作结束,然后返回;
fdatasync:类似fsync,但它只影响文件的数据部分。fsync还会同步更新文件的属性;
fflush:标准I/O函数(如:fread,fwrite)会在内存建立缓冲,该函数刷新内存缓冲,将内容写入内核缓冲,要想将其写入磁盘,还需要调用fsync。(先调用fflush后调用fsync,否则不起作用)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
pFile = fopen(pFilePath, "wb");
if (NULL == pFile)
{
return FAILURE;
}
res = fwrite(aValStr, 1, strlen(aValStr), pFile);
if(res != strlen(aValStr))
{
return FAILURE;
}
fflush(pFile); //刷新缓冲区,强制缓冲区文件内容写入内核缓冲
fsync(fileno(pFile)); //同步内存中已修改的对应fd的文件数据到设备存储
//fileno()用于返回文件流对应的文件描述符fd
fclose(pFile);

Linux-Net(五种IO模型)

阻塞IO模型

  • 当用户线程发出IO请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出CPU。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除block状态。

非阻塞IO模型

  • 当用户线程发起一个read操作后,并不需要等待,而是马上就得到了一个结果。如果结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦内核中的数据准备好了,并且又再次收到了用户线程的请求,那么它马上就将数据拷贝到了用户线程,然后返回。
  • 所以事实上,在非阻塞IO模型中,用户线程需要不断地询问内核数据是否就绪,也就说非阻塞IO不会交出CPU,而会一直占用CPU,如果在while循环体中一直去询问内核数据是否就绪,就会导致CPU占用率非常高。

多路复用IO模型

  • 在多路复用IO模型中,会有一个线程不断去轮询多个socket的状态,只有当socket真正有读写事件时,才真正调用实际的IO读写操作。因为在多路复用IO模型中,只需要使用一个线程就可以管理多个socket,系统不需要建立新的进程或者线程,也不必维护这些线程和进程,并且只有在真正有socket读写事件进行时,才会使用IO资源,所以它大大减少了资源占用。
  • 也许有朋友会说,我可以采用 多线程+ 阻塞IO 达到类似的效果,但是由于在多线程 + 阻塞IO 中,每个socket对应一个线程,这样会造成很大的资源占用,并且尤其是对于长连接来说,线程的资源一直不会释放,如果后面陆续有很多连接的话,就会造成性能上的瓶颈。
  • 不过要注意的是,多路复用IO模型是通过轮询的方式来检测是否有事件到达,并且对到达的事件逐一进行响应。因此对于多路复用IO模型来说,一旦事件响应体很大,那么就会导致后续的事件迟迟得不到处理,并且会影响新的事件轮询。(才用多线程或线程池的方式来轮询和处理时间可解决)

信号驱动IO模型

  • 在信号驱动IO模型中,当用户线程发起一个IO请求操作,会给对应的socket注册一个信号函数,然后用户线程会继续执行,当内核数据就绪时会发送一个信号给用户线程,用户线程接收到信号之后,便在信号函数中调用IO读写操作来进行实际的IO请求操作。

异步IO模型

  • 异步IO模型才是最理想的IO模型,在异步IO模型中,当用户线程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从内核的角度,当它收到一个asynchronous read之后,它会立刻返回,说明read请求已经成功发起了,因此不会对用户线程产生任何block。然后,内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它read操作完成了。也就说用户线程完全不需要知道实际的整个IO操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示IO操作已经完成,可以直接去使用数据了
  • 也就说在异步IO模型中,IO操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完成,然后发送一个信号告知用户线程操作已完成。用户线程中不需要再次调用IO函数进行具体的读写。这点是和信号驱动模型有所不同的,在信号驱动模型中,当用户线程接收到信号表示数据已经就绪,然后需要用户线程调用IO函数进行实际的读写操作;而在异步IO模型中,收到信号表示IO操作已经完成,不需要再在用户线程中调用iO函数进行实际的读写操作。
  • 前面四种IO模型实际上都属于同步IO,只有最后一种是真正的异步IO,因为无论是多路复用IO还是信号驱动模型,IO操作的第2个阶段都会引起用户线程阻塞,也就是内核进行数据拷贝的过程都会让用户线程阻塞。

学习视频

SDRAM介绍

  • 同步动态随机存取内存(synchronous dynamic random-access memory,简称SDRAM)是有一个同步接口动态随机存取内存DRAM)。通常DRAM是有一个异步接口的,这样它可以随时响应控制输入的变化。而SDRAM有一个同步接口,在响应控制输入前会等待一个时钟信号,这样就能和计算机的系统总线同步。时钟被用来驱动一个有限状态机,对进入的指令进行管线(Pipeline)操作。这使得SDRAM与没有同步接口的异步DRAM(asynchronous DRAM)相比,可以有一个更复杂的操作模式。

  • SDRAM从发展到现在已经经历了五代,分别是:第一代SDR SDRAM,第二代DDR SDRAM,第三代DDR2 SDRAM,第四代DDR3 SDRAM,第五代,DDR4 SDRAM。

SDRAM操作时序

  • 在对 SDRAM进行读写操作之前需要先对芯片进行初始化;SDRAM读写是一个较为复杂的控制流 程,其中包括行激活、列读写、预充电、刷新等一系列操作。

初始化

  • 初始化流程如下
    211219-fpga之sdram-1.jpg
    SDRAM上电后要有200us的输入稳定期,在这个时间内不可以对SDRAM的接口做任何操作; 200us结束以后给所有L-Bank预充电,然后是连续8次刷新操作;最后设置模式寄存器。初始化 最关键的阶段就在于模式寄存器(MR,Mode Register)的设置,简称MRS(MR Set)。

  • 模式寄存器如下
    211219-fpga之sdram-2.jpg
    如上图所示,用于配置模式寄存器的参数由地址线提供,地址线不同的位分别用于表示不 同的参数。SDRAM通过配置模式寄存器来确定芯片的工作方式,包括突发长度(Burst Length)、 潜伏期(CAS Latency)以及操作模式等。
    需要注意的是,在模式寄存器设置指令发出之后,需要等待一段时间才能够向SDRAM发送 新的指令,这个时间我们称之为模式寄存器设置周期tRSC(Register Set Cycle)。

行激活

  • 行激活时序图
    211219-fpga之sdram-3.jpg
    初始化完成后,无论是读操作还是写操作,都要先激活(Active)SDRAM中的一行,使之 处于活动状态(又称行有效)。在此之前还要进行SDRAM芯片的片选和L-Bank的定址,不过它 们与行激活可以同时进行。
    在片选CS#(#表示低电平有效)、L-Bank定址的同时,RAS(Row Address Strobe,行地址选通脉冲)也处于有效状态。此时An地址线则发送具体的行地址。如图中是A0-A11,共有12个地址线,由于是二进制表示法,所以共有4096个行(2^12=4096),A0-A11的不同数值就确定了具体的行地址。由于行激活的同时也是相应L-Bank有效,所以行激活也可称为L-Bank有效。

列读写

  • 列选通与读操作时序图
    211219-fpga之sdram-4.jpg
    由于在SDRAM中,地址线是行列共用的,因此列寻址时地址线仍然是A0-A11。在寻址时,利用RAS(Row Address Strobe,行地址选通脉冲)与CAS(Column Address Strobe,列地址选通脉冲)来区分行寻址与列寻址。
  • 在发送列读写命令时必须要与行激活命令有一个时间间隔,这个间隔被定义为tRCD, 即RAS to CAS Delay(RAS至CAS延迟)。这是因为在行激活命令发出之后,芯片存储阵列电子 元件响应需要一定的时间。tRCD是SDRAM的一个重要时序参数,广义的tRCD以时钟周期(tCK, Clock Time)数为单位,比如tRCD=3,就代表RAS至CAS延迟为三个时钟周期,如图 33.1.8所 示。具体到确切的时间,则要根据时钟频率而定。

数据输出(读)

  • 在选定列地址后,就已经确定了具体的存储单元,剩下的事情就是数据通过数据I/O通道(DQ)输出到内存总线上了。但是在CAS发出之后,仍要经过一定的时间才能有数据输出,从CAS与读取命令发出到第一笔数据输出的这段时间,被定义为CL(CAS Latency,CAS潜伏期)。CL时间越短,读数据时SDRAM响应就越快。由于CL只在读取时出现,所以CL又被称为读取潜伏期(RL,Read Latency)。CL的单位与tRCD一样,为时钟周期数,具体耗时由时钟频率决定。

数据输出(写)

  • 数据写入时序图
    211219-fpga之sdram-5.jpg
    数据写入的操作也是在tRCD之后进行,但此时没有了CL(记住,CL只出现在读取操作中), 行寻址与列寻址的时序图和上文一样,只是在列寻址时,WE#为有效状态。
    数据与写指令同时发送。不过,数据并不是即时地写入存储单元,数据的 真正写入需要一定的周期。为了保证数据的可靠写入,都会留出足够的写入/校正时间(tWR, Write Recovery Time),这个操作也被称作写回(Write Back)。tWR至少占用一个时钟周期 或再多一点(时钟频率越高,tWR占用周期越多)。

此外

  • 除上述操作之外,还有突发长度、预充电、刷新、数据掩码常用操作,具体可以查阅《开拓者FPGA开发指南》SDRAM读写测试实验。

实验仿真

211219-fpga之sdram-6.jpg
211219-fpga之sdram-7.jpg
211219-fpga之sdram-8.jpg
211219-fpga之sdram-9.jpg

学习资料

需求

  • 在博世实习,同事想要远程调试,打印log到终端功能(代替出差去现场调试),于是我就决定用LTE Cat.1模块,配合阿里云物联网平台,使用MQTT传输日志文件。

阿里云物联网平台使用

  1. 打开阿里云物联网平台,使用公共实例,创建产品,数据格式选择(透传/自定义),以便将上行的自定义格式的数据转换为Alink JSON格式,连网方式这里选择蜂窝(2G/3G/4G/5G),所属品类选择自定义品类,其它配置默认即可。配置完在产品详情界面图如下:211217-ltecat1-1.jpg
  2. 创建设备,创建设备成功后,将自动弹出添加完成对话框。您可以查看、复制设备证书信息。设备证书由设备的ProductKey、DeviceName和DeviceSecret组成,是设备与物联网平台进行通信的重要身份认证,建议您妥善保管。配置完在设备详情界面图如下:211217-ltecat1-2.jpg

  3. 接下来就是在产品详情界面中的功能定义,可以查看物模型概述,设置MQTT需要上传的变量。我设置了一些调试时用到的变量,如下图:211217-ltecat1-3.jpg

  4. 在产品详情界面中的数据解析可以设置物模型数据解析,通过物模型数据解析我们可以将自定义帧结构的数据解析成Alink JSON格式,注意:产品的数据格式选择为透传/自定义(这个坑我一天,最后找阿里云客服解决)。写完数据解析后,选择模拟类型为设备上报数据,执行与提交。

  5. 接下来就是mcu使用LTE Cat.1模块给阿里云平台发数据了!在设备详情的物模型数据中可以看见,通过物模型数据上报的topic发送来的调试变量。我们也可以通过设备详情中的日志服务看见,阿里云上的数据收发记录和解析记录。
  6. 阿里云平台上还有很多其他功能,比如说把平台收到的数据再MQTT发给自己服务器做个数据处理与显示等,本次我没有用到,可以查看阿里云物联网平台-产品文档了解更多功能。

LTE Cat.1模块介绍

  1. Luat Air724UG LTE Cat.1 模块,淘宝链接:Air724UG DTU透传4G模块Cat.1全网通TTL转LTE FS704UM阿里云MQTT

  2. 模块是串口输入,走4G网发送数据。模块可以一键配置阿里云MQTT服务,然后就能实现透传的功能。MCU也可以使用AT指令控制模块,可以有更丰富的操作。

  3. 连接阿里云流程可以看模块资料《Air724UG_软件设计手册V1.5》,连阿里云首先HTTP获取MQTT密码,然后连接MQTT,阿里云物联网会比较安全。

安装运行clash

  1. clash发布网站下载对应的版本,我下载的是clash-linux-amd64-v1.7.1.gz

  2. 将压缩包里的文件解压至/opt/clash,改名为clash,下载订阅链接文件到同个目录

    1
    sudo wget -O config.yaml [订阅链接]
  3. Country.mmdb为全球IP库,可以实现各个国家的IP信息解析和地理定位,没有这个文件clash是无法运行的

    1
    sudo wget -O Country.mmdb https://www.sub-speeder.com/client-download/Country.mmdb
  4. 把clash权限改为可执行应用

    1
    chmod +x clash
  5. 执行clash,

    1
    ./clash -d .

修改系统代理

  1. 我使用的是ubuntu18.4,在设置里面修改。打开系统设置,点击网络代理右边的 ⚙ 按钮,选择手动,填写 HTTP 和 HTTPS 代理为 127.0.0.1:7890,填写 Socks 主机为 127.0.0.1:7891,即可启用系统代理

配置clash

  1. 在运行了clash后可以打开clash配置页面进行配置,基本上就和windows中的clash图形化差不多了

设置为开机启动

  1. 创建service文件

    1
    touch /etc/systemd/system/clash.service
  2. 编辑service文件,填入以下内容(注意修改clash文件夹路径)

    [Unit]
    Description=clash daemon

    [Service]
    Type=simple
    User=root
    ExecStart=/opt/clash/clash -d /opt/clash/
    Restart=on-failure

    [Install]
    WantedBy=multi-user.target

  3. 重新加载systemctl daemon,systemctl daemon-reload

  4. 启动Clash,systemctl start clash.service

  5. 设置Clash开机自启动,systemctl enable clash.service

  6. systemctl的其他命令参考linux中systemctl详细理解及常用命令

配置定时更新订阅

  1. 可以设置个定时执行的任务,去下载新的配置文件,并重启clash服务

电机位置反馈

霍尔传感器

  • 马达轴上连有磁体,传感器为三个间隔60°的开关霍尔,霍尔会按照【001 - 101 - 100 - 110 - 010 - 011】六个状态变换,根据三相霍尔信号可以检测出电机转子位置所处的扇区,然后控制MOS或IGBT实现六步换向控制。
  • 三路霍尔信号图
    210924-电机控制部分-1.JPG
  • 120°霍尔换相真值表
    210924-电机控制部分-2.JPG

无霍尔传感器

  • 传感器很有用,但会增加成本,增加复杂性(由于需要附加绕组),并降低了可靠性(部分原因是传感器连接更容易受到灰尘和潮湿环境的污染),无传感器控制方式解决了这些不足。
  • 无传感器利用电机反电动势确定转子角度,下图为三相反电动势波形和霍尔波形比较图
    210924-电机控制部分-3.JPG
    可见,传统BLDC电机中单个霍尔传感器变化输出,与无传感器电机中单个线圈的反电动势零交叉点之间有一个30度的相位差。因此,在检测到零交叉点之后,我们会在无传感器电机电路的固件中内置一个30度相位延迟,然后再激活激励序列中的下一个动作。

检测反电动势方法

  1. 最简单的方法就是用比较器将反电动势与一半的直流总线电压比较
    210924-电机控制部分-4.JPG
    在此图中,线圈A正向激励,线圈C反向激励,而线圈B则开路。当实现此相位的激励序列时,反电动势就会上升和下降。这一简单比较器方法主要缺点就是三个绕组可能没有相同的特征,造成实际零交叉点的正负相移。电机仍可能在运转,但可能消耗过多电流。
    1. 上面问题解决方法就是通过使用与电机绕组并接的三个电阻网络来产生一个虚拟中性点,反电动势然后就会与虚拟中性点进行比较。
      210924-电机控制部分-5.JPG
    2. 第三种方法是采用模数转换器 (ADC)。为BLDC电机控制提供的许多MCU包括适合作此用途的高速ADC。采用这种方法后,反电动势就会衰减,以便可以直接馈送给MCU。信号被ADC采样后就会同与零点对应的数字值比较。当这两个值匹配时,线圈激励序列就会变址到下一步。这种技术具有一定优势,如允许使用数字滤波器来清除反电动势信号中的高频切换成份。
      210924-电机控制部分-6.JPG

无感缺点

无传感器BLDC电机控制有一大不足,就是当电机静止时,不会产生反电动势,这样MCU就无法知道定子和转子位置信息。  
解决方法就是通过以预定序列激励线圈来启动处于开环配置的电机。当电机看似运转效率不高时,就会开始循环该序列。最终,速度将足以产生足够的反电动势,供控制系统切换到正常闭环运行状态(有效状态)。  
由于反电机势与旋转速度成正比,因此在需要较低速度的应用中,无传感器BLDC电机可能不是一个好的选择。此时带有霍尔效应传感器的BLDC电机可能是更好的选择。  

示波器测霍尔角

210924-电机控制部分-7.JPG

FOC

【自制FOC驱动器】深入浅出讲解FOC算法与SVPWM技术

MCU外围电路设计

复位电路二极管

复位电路为什么要加二极管,断电后瞬间放掉电容的电荷,复位,使断电瞬间RC充分放电。

逆变

单相逆变

  1. 需要4个NMOS或者IGBT控制
  2. 正弦脉宽调制SPWM,在输出加电感电容滤波,电感电容值需要足够大(6mH 20uF)
  3. 在mos桥驱动中,用PNP三极管挂在MOS的GS上,作用是用三极管形成放电回路,否则GS电容的电过二极管往驱动芯片内部下管释放
    210917-驱动部分设计-1.JPG
  4. 在PCB布线时要注意让MOS开关部分的高频回流面积最小;功率地需要单点接地,高频开关环流路径不要铺地,以减小地干扰
    210917-驱动部分设计-2.JPG
  5. 反馈到单片机的信号需要隔离(电流电压互感器),低通或带通滤波
  6. 先直流升压再逆变的效率比先逆变再工频变压器升压的效率高很多

三相逆变

  1. 需要6个NMOS或者IGBT控制
  2. 负载有星形负载和三角形负载
    210917-驱动部分设计-3.JPG
  3. 三相桥式逆变器可控器件导通顺序
    210917-驱动部分设计-4.JPG

驱动系统

高铁

  1. 接触网上传输高压交流电(25kV),通过变压器降压和四象限整流器转换成直流电,在经过逆变器降至六点转换成可调压调频的交流电,输入三相异步、同步牵引电动机,通过传动系统带动车轮运行
  2. 牵引变电所输入220kV三相交流电,通过三相变压器,低侧输出25kV三相交流电,一相往前方接触网,一相往后方接触网,另一项接铁轨
  3. 高铁趋势:整流 -> 图腾柱PFC(无桥PFC);IPM(IGBT) -> SIC mostet(6个IGBT封装在一起);三相异步电动机 -> 永磁同步电动机(省电30%)
  4. MOS管、IGBT、BJT的区别

PFC功率因数校正

什么是PFC

PFC的英文全称为”Power Factor Correction” ,意思是“功率因数校正”,功率因数指的是有效功率与总耗电量(视在功率)之间的关系,也就是有效功率除以总耗电量(视在功率)的比值。基本上功率因数可以衡量电力被有效利用的程度,当功率因数值越大,代表其电力利用率越高。功率因数是用来衡量用电设备用电效率的参数,低功率因数代表低电力效能。为了提高用电设备功率因数的技术就称为功率因数校正。(大于70瓦就必须使用功率因数校正PFC)

被动式PFC

被动式PFC一般分“电感补偿式”和“填谷电路式(Valley Fill Circuit)”
“电感补偿式”是使交流输入的基波电流与电压之间相位差减小来提高功率因数,“电感补偿式”包括静音式和非静音式。“电感补偿式”的功率因数只能达到0.7~0.8,它一般在高压滤波电容附近。
“填谷电路式”属于一种新型无源功率因数校正电路,其特点是利用整流桥后面的填谷电路来大幅度增加整流管的导通角,通过填平谷点,使输入电流从尖峰脉冲变为接近于正弦波的波形,将功率因数提高到0.9左右,显著降低总谐波失真。与传统的电感式无源功率因数校正电路相比,其优点是电路简单,功率因数补偿效果显著,并且在输入电路中不需要使用体积大重量沉的大电感器。

主动式PFC

主动式PFC则由电感电容及电子元器件组成,体积小、通过专用IC去调整电流的波形,对电流电压间的相位差进行补偿。主动式PFC可以达到较高的功率因数──通常可达98%以上,但成本也相对较高。此外,主动式PFC还可用作辅助电源,因此在使用主动式PFC电路中,往往不需要待机变压器,而且主动式PFC输出直流电压的纹波很小,这种电源不必采用很大容量的滤波电容。

Boost PFC变换器

210917-驱动部分设计-5.JPG

PFC参考

  1. 一文搞懂PFC(功率因数校正)
  2. 电赛必备之PFC电路,2006年B题功率因数监测与补偿系统

电源部分

AC/DC

210913-电源部分设计-1.JPG

  1. 共模干扰和差模干扰
  2. 共模电感上流过共模电流时磁环中的磁通相互叠加,从而具有相当大的电感量,对共模电流起到抑制作用
  3. X电容滤除差模干扰,利用其在高频时低阻抗的特性,短路掉差模干扰
  4. 压敏电阻是一种限压型保护器件,利用压敏电阻的非线性特性,当过电压出现在压敏电阻的两极间,压敏电阻可以将电压钳位到一个相对固定的电压值,从而实现对后级电路的保护
  5. 聚丙烯膜电容(CBB电容 MKP电容)做直流母线电容效果更好

Buck

210913-电源部分设计-2.JPG

  1. AC-DC芯片采用MP174,SOURCE引脚是VCC和FB引脚的参考地
  2. VCC供电电压是哪里来的?根据DataSheet,当Vout<7V的时候,芯片空载功率较小,内部供电足够,当Vout>7V时,需要添加外部辅助电源
    210913-电源部分设计-6.JPG
  3. 电源大师6——BUCK 降压电路降低EMI与EMC设计,开关电源PCB layout宝典
  4. 小信号地连一起(FB分压电阻,comp,ss)然后再与PGND单点相连,或者通过过孔连到背面
  5. 电感两个引脚间距京可能大,非一体成型电感底部不铺铜,让敏感电路(FB)和回路远离电感

LDO

210913-电源部分设计-3.JPG

  1. LDO输入串阻,限流作用
  2. LDO输出加TVS保护

采样部分

电压采样

210913-电源部分设计-4.JPG

  1. 整流桥前和后的采样区别:整流桥前电压更稳定,一般采样用来测各种功率参数;整流桥后面的电压不稳定,会受到马达反冲等影响,整流桥后电压采样应用于过压和欠压保护

电流采样与过压保护

210913-电源部分设计-5.JPG

  1. 差分放大,迟滞比较器,电平反转,三极管自锁
  2. 在差分运放中电容并电阻微分作用,电容串电阻积分作用
  3. 对于电子电路:电阻的两端并联一个电容,为了减小对高频信号的阻抗,相当于微分,这样信号上升速度加快,用于提高响应速度;电容一端接电阻,一端接地,则相反,滤去高频,相当于积分,用于滤波。最典型的应用就是放大电路中的高低音频控制。
    对于电力电路:不管RC串联还是并联,电容的作用都是一样的,电容的作用就是防止电压突变,吸收尖峰状态的过电压,串联的电阻起阻尼作用,电阻消耗过电压的能量,从而抑制电路的振荡。并联的电阻吸收电容的电能,防止电容的放电电流过大,避免对与之并联的器件(如晶闸管)造成损坏。最典型的应用就是防止操作过电压。

程序框架和环境

  • esp32的程序是通过esp-idf框架开发
  • esp32做Server,电脑做Client,手机热点AP
  • esp32使用外置天线更加稳定,但速率没有明显提升

TCP-Server

  • 编译优化-O2,速率可从最高500KB/s提升到800KB/s
  • TCP传输错误会重传,有问题的时候速率会下降到100KB/s以下
  • 应用在640*320分辨率的25帧JPEG图传不稳定

UDP-Server

  • 速度可以达到1MB/s~2MB/s

  • UDP是个不稳定的传输,会有传输错误

  • 不适合应用在JPEG图传

说明

210831-esp32传输测试-1.jpg

  • 由于本人技术原因,无法达到官方测试的速率,大家使用需要亲自测试后才能做结论,可以参考iperf例程后再进行测试

  • 参考:ESP-IDF编程指南