imuncle.github.io
imuncle.github.io copied to clipboard
大叔的个人小站
好几周没写文章了,主要是因为保研了嘛,又被学弟叫回战队去了,前段时间在忙着搞培训,制定规章制度之类的,当然最主要的还是因为我想搞一个大的。 今年的RoboMaster多了很多元素,据说今天出规则,不过现在我写文章的这个时刻还没出,估计再过几个小时就出了吧。今年主要多了导弹和雷达站元素,其中导弹需要嵌入式视觉的参与,于是我就参与了嵌入式视觉的研发。而我最熟悉的还是MCU的开发,所以希望能直接在MCU上运行视觉代码。 # openmv 目前市面上最火爆的,运行在MCU上的视觉识别产品是[openmv](https://openmv.io/),它是完全开源的,github地址在[这里](https://github.com/openmv/openmv),目前国内的官方代理商是[星瞳科技](https://singtown.com/openmv/)。 星瞳科技做的比较好的一点是把官方的openmv英文文档翻译成了中文,不过有些地方翻译的还不是太好。英文文档点[这里](http://docs.openmv.io/),翻译的中文文档点[这里](https://docs.singtown.com/micropython/zh/latest/openmvcam/index.html)。 openmv内嵌了[micropython](https://github.com/micropython/micropython),实现了在单片机上运行python,支持最新的python 3.X,还是非常不错的。回想起来前几年在MakerFair上看到的可以用python编程的单片机,估计就是内嵌了micropython,亏我当时还以为是那些公司自己写的中间层,没想到是直接用的开源的东西。 正是因为有了micropython,openmv留给用户的接口是python的接口,且基于Qt开发了一个挺舒服的IDE,用户直接在里面用python调用API就行了,上手非常快,效果看得见。目前主要是各种电子设计大赛中会见到它的身影。 那么既然已经有了openmv为什么还要自己另外做嵌入式视觉呢?原因主要有以下几点: * openmv留出来的接口都是固定的,虽说已经很多了,但是可能在一些很特殊的环境下无法很好完成工作 * openmv内部是封装好的,优化是没法优化的 * 用户代码用python写,写好之后是以字符串的形式传给单片机的,单片机还得挨个解析,然后调用相应的函数,资源再怎么也耗费了一些,感觉不爽 * 要不是openmv用的 F7和H7系列,性能绝对不行 * 最重要的一点,直接用openmv多无趣啊,RM比赛本就是挑战自我的,正好趁这次机会学点新东西 综上,我选择了自己研发。 # OpenOV 先给自己的东西取个名字。其他两搞视觉的一个是`opencv`,一个是`openmv`,而我的打算用OmniVision公司的OV系列摄像头(其实openmv用的也是这个),所以我的就叫做`OpenOV`吧。 先列一下我所计划有的资源: * 摄像头×1 * LCD×1...
记得高一的时候第一次接触三维立体图,非常震惊,热情地推荐给身边的同学,结果到目前为止,没有一个同学和我一样能看出其中的三维信息,十分沮丧。 最开始接触的三维立体图是刘红石大大制作的,他的官网点[这里](http://www.liuhs.com/),里面有他的三维立体图,有立体摄影,有文本立体图,还有图片程序下载以及实现的代码,我把他的代码用JavaScript重写了一遍,将文本立体图和三维立体图整合起来,可以使用浏览器直接生成。 代码放在最后说。以下是转载刘红石老师的**三维立体画原理和观看方法**。 --- 三维立体画是利用人眼立体视觉现象制作的绘画作品。普通绘画和摄影作品,包括电脑制作的三维动画,只是运用了人眼对光影、明暗、虚实的感觉得到立体的感觉,而没有利用双眼的立体视觉,一只眼看和两只眼看都是一样的。充分利用双眼立体视觉的立体画,将使你看到一个精彩的世界。 # 一、立体视觉和立体画原理 人有两只眼,两只眼有一定距离,这就造成物体的影象在两眼中有一些差异,见右图,由图可见,由于物体与眼的距离不同,两眼的视角会有所不同,由于视角的不同所看到是影象也会有一些差异,大脑会根据这种差异感觉到立体的景象。  三维立体画就是利用这个原理,在水平方向生成一系列重复的图案,当这些图案在两只眼中重合时,就看到了立体的影象。参见下图,这是一幅不能再简单的立体画了。图中最上一行圆最远,最下一行圆最近,请注意:最上一行圆之间距离最大,最下一行圆之间距离最小。  这是怎么发生是呢?让我们再看下图,从图中我们可以看到,重复图案的距离决定了立体影象的远近,生成三维立体画的程序就是根据这个原理,依据三维影象的远近,生成不同距离的重复图案。  # 二、立体画的观看 如果你现在还不会看立体画,是不是已经很着急了,下面我将介绍怎样看立体画。 立体画有两种形式:第一种是由相同的图案在水平方向以不同间隔排列而成,看起来是远近不同的物体,请看下图。这样的立体画可用任意一种图象处理软件制作,如Photoshop、Windows画笔等,你也可以一试。  另一种立体画较复杂,在这种立体画上你不能直接看到物体的形象,画面上只有杂乱的图案,制作这样的立体画只有使用程序了,我为此编写了一些程序,有C和QBASIC的源程序,请看自制立体画和程序下载。两种作品看法是一样的,原理都是使左眼看到左眼的影象,让右眼看到右眼的影象,(有人说了:你这不是废话吗?)听我说具体的方法:当你看立体画时,你要想象你在欣赏玻璃橱窗中的艺术品,也就是说你不要看屏幕上的立体画,而要把屏幕看成是玻璃橱窗的玻璃,你要看的是玻璃之内的影象。  # 三、两点练习法 请把下图上方的两点作为目标,先使眼睛休息片刻,然后象眺望远方那样,用稍模糊的视线瞄准两点,就会看从两点各自分离出另外两个点,然后调整视线,试图将里面两个点合成一点,当四点变为三点时,你便会看到立体图象。  # 四、另一种观看方法 从电脑上看费劲的话,可以这样,如果画面上标有两点(如没有,可以通过仔细观看,在横向上,相隔约3-5厘米,就有相同的图案,如两个相同颜色和大小的点等),那么可以用两个颜色深点的线垂直粘在显示器屏幕的上面(可以进入屏幕少许),使两条线垂直并分别与两点相连。然后,在显示器后面上方放个小东西做参照物,沿显示器上边沿来看参照物,前后移动眼睛的焦点,使左眼、左线、参照物成一直线,右眼、右线、参照物成一直线,可以挡上一只眼调整,然后两眼看参照物,此时两条线就变成了三条,让视线沿中间的线爬进立体画面就看到了立体效果。 --- 刘老师的主页里有示例代码,然而最关键的部分却没有注释: ```c...
目前市场上USB设备的种类繁多,但是这些设备会有一些共同的特性,根据这些特性可以把USB设备划分为不同的类,如显示设备、通信设备、音频设备、大容量存储设备、人机接口设备(HID)。这里介绍如何实现HID类设备,以及如何在应用程序中对HID类设备进行访问。从Windows98操作系统开始,为HID类设备提供了通用的驱动程序,所以只要按照HID设备类的规范编写设备的固件程序,就能够让Windows系统自动识别设备,省去了复杂的驱动程序编写过程。 # HID 协议简介 人机接口设备(HID)主要是指一些人与计算机进行交互的设备,如键盘、鼠标、游戏杆等;但是HID设备不一定非要是这些人机交互设备,只要符合HID设备级定义规范要求的都可以认为是HID设备。HID设备有以下主要特点: * 交换的数据存储在报告的结构内,设备必须支持HID报告格式。 * 每笔事务可以携带小量或中量的数据。低速设备每笔事务最大为8字节,全速设备每笔最大为64字节,高速设备最大为1 024字节; * 有最大传输速度的限制。低速设备最快10 ms一笔事务,最高速度为800 B/s;全速设备最快1 ms一笔事务,最高速度为64 KB/s;高速设备最快125 μs一笔事务,最高速度为24.576 MB/s。 * 没有传输速度的保证。 当插入USB设备后,主机会向设备请求各种描述符来识别设备。为了把一个设备识别为HID类别,设备在定义描述符的时候必须遵守HID规范。图1显示了HID各种描述符之间的关系。事实上,每个设备可以有多个接口描述符来实现多接口设备,而且每个接口描述符下应该有多个端点描述符 。  从图中可以看出,除了USB标准定义的一些描述符外,HID设备还必须定义HID描述符。另外设备和主机的通信是通过报告的形式来实现的,所以还必须定义报告描述符;而物理描述符不是必需的。还有就是HID描述符是关联于接口(而不是端点)的,所以设备不需要为每个端点都提供一个HID描述符。 USB设备有4种传输方式与主机进行通信:...
今天已经18号了,距离出车的deadline已经不远了,留给电控的时间不多了。 昨天和前天已经有好几波人轮流调了英雄车的云台,但都无功而返,眼看死期将至,决定自己还是亲自拼一把。 我想起了上一年比赛第一次接触PID的时候,连PID是啥都不知道,结果上手就是一个串级PID,六个参数直接玄学调参,调了一个月左右,最后发现反馈数据给错了!修正之后立马就调好了。 今天的情况其实也很类似,也算是反馈数据不准确吧。 今天我才知道串级PID的调试方法,之前我一直是六个参数同时变,然后波形也不看,就各种自闭,虽然我熬了很多次夜来调试,逃了好几节来调试,都无济于事,说白了就是没掌握方案,没有完全理解PID的含义。 串级PID先调内环的参数。我这里的串级PID分别是外环位置环和内环速度环,使用的是带输出上限和积分饱和上限的普通位置式PID函数。 首先只调速度环,我使用的是陀螺仪反馈的角速度信息,单位是`°/s`,输出的是电机的电流大小,也就是扭矩的大小。 但是自闭了一个早上之后一点进度都没有,调出来的yaw轴云台要么没有力,要么就是疯狂振荡,后来我使用J-Scope在线查看PID设定值和反馈值,以及电机的角度值的曲线才发现,陀螺仪的角速度反馈值存在两个问题。 1. 角速度数据反馈频率低,在J-Scope中显示的曲线呈很明显的阶梯状 2. 陀螺仪的角速度是根据加速度积分得到的,计算需要时间,所以反馈的数据在图像上显示存在相位差 上面两个特点就决定了陀螺仪的反馈数据不可用,因为角速度无法得到快速的反馈。速度环是属于内环的,内环是整个串级PID的基础,内环调不好,那整个系统就崩溃了。 在自闭了一会儿之后,我决定使用电机编码器的反馈的机械角度位置进行微分计算电机的转速。 在这里介绍一下电机的参数: > 机械角度反馈范围为0~8191 反馈频率为1000Hz 从上面的信息可以算出,如果只采集相邻两次的编码器数据,那么对应的角速度大约为  这显然是不行的,所以我连续采集了24次编码器数据计算平均速度,这样子精度可以在上面的精度基础上再二四分之。  实现的代码如下: ```c /** * @brief CAN通信电机的反馈数据具体解析函数 * @param...
先把读卡器功能实现,相对于真正核心的嵌入式视觉代码来说,这种如同外设一般的存在就应该尽早被攻克掉。 # SDIO协议及SD卡简介 这里推荐看正点原子的教程,讲的很详细。这里真心给正点原子点个赞!暑假的时候突然发现正点原子入驻B站了,可以直接在线观看高清的视频教程了!去他妈的限速百度云,保存到网盘在线看也没法高清,还时不时卡顿,入驻B站这一操作简直感动到哭! * [【正点原子】 手把手教你学STM32 系列视频之 STM32F4-基于探索者F407-SDIO简介](https://www.bilibili.com/video/av56936776/?p=72) * [【正点原子】 手把手教你学STM32 系列视频之 STM32F4-基于探索者F407-SD卡简介](https://www.bilibili.com/video/av56936776/?p=73) * [【正点原子】 手把手教你学STM32 系列视频之 STM32F4-基于探索者F407-SD卡实验源码讲解](https://www.bilibili.com/video/av56936776/?p=74) # SD卡驱动 不得不说,STM32CubeMX帮我们省去了很多很多外设的操作步骤。按照正点原子的教程,我们需要首先把SD卡的时钟降下来,发送指令初始化SD卡,初始化成功之后再把时钟升上去,每次发送命令操作寄存器,处理SD卡长短响应之类的,完全不用我们去管,只管调用函数就行。 STM32CubeMX里面的配置也非常简单,直接使能,一步到位:  之后读写SD卡什么的直接调用函数就行了。 # USB接口模拟大容量存储设备 USB接口真的有好多用处啊,基本上是可以模拟出所有USB接口的设备了,之前有写过一篇[USB实现虚拟串口CDC](https://imuncle.github.io/content.html?id=59)的文章,这次实现模拟大容量存储设备,前几天还模拟了一下HID人体学输入设备,后面把HID的文章补上。说一句,HID比CDC好用多了! 限于篇幅,这里直接贴上cubemx的配置过程,在后面HID的文章中再稍微讲讲USB是怎么让电脑识别为大容量存储设备的。 ...
> 版权声明:本文为CSDN博主「FEWY」的原创文章,遵循 [CC 4.0 BY-SA](http://creativecommons.org/licenses/by-sa/4.0/) 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/FE_dev/article/details/82586698 # 说明 > canvas元素标签强大之处在于可以直接在HTML上进行图形操作,具有极大的应用价值。 canvas 可以实现对图像的[像素操作](https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas),这就要说到 [getImageData()](https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/getImageData) 方法了。 # 解释 `CanvasRenderingContext2D.getImageData()` 返回一个 [ImageData](https://developer.mozilla.org/zh-CN/docs/Web/API/ImageData) 对象,用来描述 canvas 区域隐含的像素数据,这个区域通过矩形表示,起始点为(sx, sy)、宽为sw、高为sh。 ## 语法 `ctx.getImageData(sx, sy, sw, sh);`...
快预推免面试了,最近疯狂补专业知识(没办法,跨专业跨系),又遇到要外出比赛,便想着把B站上的教学视频下载下来离线观看,没想到连“缓存”按钮都没找到。经过简单查询之后发现了以下三个方法: 拿我正在学习的“复变函数与积分变换”为例:  链接为 ```txt https://www.bilibili.com/video/av11923599/?p=56 ``` # 方法一 在`bilibili`前面添加字母`i`,如下: ```txt https://www.ibilibili.com/video/av11923599/?p=56 ``` 这会打开一个名为“爱哔哩”的网站,右击鼠标即可选择下载视频。  # 方法二 在`bilibili`前面添加`kan`,如下: ```txt https://www.kanbilibili.com/video/av11923599/?p=56 ``` 这会打开一个名为“看哔哩哔哩”的网站,这里展示的信息数据更加丰富。  # 方法三 在`bilibili`后面添加`jj`,如下: ```txt https://www.bilibilijj.com/video/av11923599/?p=56 ``` 
学校立项用到了导电银墨水,在网上浏览的时候看到一个很有意思的产品:[Electric Paint Lamp Kit - paint, plug and play!](https://www.kickstarter.com/projects/863853574/electric-paint-lamp-kit-paint-plug-and-play) 这个小实例里通过检测是否被触碰来控制灯的亮灭,以实现开关的效果。经过进一步查阅,原来这其中使用到了MPR121这款触控传感器。 # 原理 MPR121通过检测电容的变化来判断是否被触控,可以手动设置touch和release的电容阈值。  MPR121一共有12个通道可以检测触控。根据上图,每个通道有一个10位的ADC检测电压。 MPR121检测电容的方法是,对每一个通道进行充放电,根据充放电的时间、电流和峰值电压来计算电容值,其中充放电的时间和电流都可以通过寄存器配置。  假设充电电流为$I$,充电电压峰值为$V$,充电时间为$T$,那么电容为: $$C=\frac{Q}{V}=\frac{I×T}{V}$$ MPR121可以根据用户设置的电容阈值独立判断是否被触控,判断的逻辑如下:  它判断的是电容的变化量,这变化量是基于baseline计算的,同时,MPR121还支持三重过滤器Filter配置,使电容测量更准确稳定。 # 相关寄存器  我们可以直接从`0x00`和`0x01`两个寄存器获取每个通道的状态,0代表未触控,1代表触碰。  同时我们还可以从`0x04`到`0x1B`读取到每一个通道的数值。  #...
HAL库自带的延时函数`HAL_Delay(uint32_t time_ms)`基于Systick定时器,只能实现毫秒级延时,但在很多外设通信中,通信时间是以微秒为单位的,自带的延时函数远远无法满足要求。 STM32有好几种定时器,既有高级的,也有低级的,何不使用低级定时器实现手动实现微秒延时呢? Systick定时器是HAL的默认时钟源,最好还是不要乱用,我这里使用TIM7,在STM32CubeMX中预分配为1MHz,对应1us,通过操作定时器的CNT寄存器实现延时,代码很简单: ```c void Delay_us(uint16_t time) { uint16_t differ = 0xffff-time-5; __HAL_TIM_SET_COUNTER(&htim7, differ); HAL_TIM_Base_Start(&htim7); while(__HAL_TIM_GET_COUNTER(&htim7) < 0xffff-6){} HAL_TIM_Base_Stop(&htim7); } ``` 实测真的非常准确!! --- 参考:[STM32 HAL库实现微秒级别延时](http://www.stm32cube.com/article/176)
前段时间给社团建官网(推销一波,https://hitszqmaker.github.io ),今天想起来打开看了一下,结果发现了问题。  关键它奇特在Chrome浏览器里屁事没有,一换到其他浏览器,不管有没有用Chrome内核,通通扑街。为此我还特意多下载了几个浏览器测试,包括手机,发发现果真如此。 但是flex布局是2009年被提出的,早就被各大浏览器全面支持的了。  # 一、flex-shrink: 0 经过查阅,发现是因为`flex-shrink`属性,`flex-shrink`属性默认为1,如果没有显示定义该属性,将会自动按照默认值1在所有因子相加之后计算比率来进行空间收缩。设置为0表示不收缩。 flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值。注意:如果元素不是弹性盒对象的元素,则 flex-shrink 属性不起作用。 所以第一种方法就是将`img`元素添加属性`flex-shrink: 0`。 # 二、height: 100% 在父元素没有设置高度的情况下,给图片设置`height: 100%;` # 三、外层div标签包裹 用div标签包裹图片,这种方案比较通用,缺点:产生无用标签。 # 参考 * [flex布局下img图片变形的解决方法](https://www.jianshu.com/p/d71f6e9d3236)...