移植u8g2库到stm32
抑制u8g2库到stm32(标准库)
移植u8g2库到stm32(标准库)
实验硬件:
STM32F103ZE
OLED:0.96寸OLED,IIC接口
U8g2 是一个用于嵌入式设备的单色图形库。U8g2支持单色OLED和LCD,并支持如SSD1306等多种类型的OLED驱动。
U8g2源码的开源库地址:https://github.com/olikraus/u8g2
移植步骤
从官网下载 u8g2 的源码;
只移植c语言版本,因而只需要将用到 csrc文件夹内的文件;
找到需要对应的驱动文件(u8x8_d_xxx.c),只需要添加一个型号即可,这里我用到的是 u8x8_d_ssd1306_128x64_noname.c 文件,然后其余的型号可以删除掉(格式一般都为 u8x8_d_xxx.c)
修改 u8g2_d_setup.c 文件,找到对应 OLED型号的函数,这里用到的是u8g2_Setup_ssd1306_i2c_128x64_noname_f ,保留这个函数,其他删除掉或者注释掉。
1234567891011#include "u8g2.h"/* ...
嵌入式实践实习
嵌入式实践实习知识
大二下时长一周半多半周的嵌入式实习,由粤嵌的工程师教授知识。
环境及工具:Ubuntu 18.04,arm-linux-gcc 5.4.0,粤嵌GEC6818开发板
以下是此次实习中get到的一下知识以及遇到的一些问题。
2023.05.09
gcc : c语言编译器
g++ : c++编译器
gdb : c/c++调试器
binutils : 二进制工具集
MinGW : MinGW 是让Windows 用户可以用上 GNU 工具,比如GCC。
Cygwin : Cygwin 提供完整的类Unix 环境,Windows 用户不仅可以使用GNU 工具,理论上Linux 上的程序只要用Cygwin 重新编译,就可以在Windows 上运行。
如果程序只用到C/C++ 标准库,可以用MinGW 或Cygwin 编译。
如果程序还用到了POSIX API,则只能用Cygwin 编译。
cmd 输入 sysdm.cpl 打开环境变量设置
cygwin64 和 MinGW 的 gcc 和 g++ 只能有一个能使用,不能同时使用。
通过修改环境变量的优先级 顺序从上到下, ...
Ubuntu共享文件夹问题
Ubuntu 18.04 每次重启后共享文件夹未显示问题。
虽然虚拟机设置了总是启用共享文件夹,但是每次重启虚拟机之后还是未显示共享文件夹。
通过以下命令查看共享文件夹是否存在。
1vmware-hgfsclient
这边查询到共享文件夹是存在的,在 /mnt/hgfs 下进行 ls 查看目录时,共享文件夹并没显示。
使用以下命令可以得到解决,但是重启虚拟机之后仍然会出现找不到共享文件夹的问题。
1sudo vmhgfs-fuse .host:/ /mnt/hgfs -o nonempty -o allow_other
显然这种方法是不优的,因此采用下述方法,把这个命令放在 /etc/rc.local文件夹下,即可每次开机自动执行。
普通用户下执行命令打开 rc.local 文件:
1sudo vim /etc/rc.local
写入
123#!/bin/sh -esudo vmhgfs-fuse .host:/ /mnt/hgfs -o nonempty -o allow_other
在 /etc 目录下输入 cat rc.local 查看是否添加成功。
在 /etc 目录下 ...
硬件通讯协议
常见硬件通讯协议
一些基础概念
串行通信协议
同步通信(asynchronous data communication):以数据块为单位传输,收发方必须使用同一时钟源。
异步通信(synchronous data communication):以字符为单位传输,两个字符之间传输的时间间隔不固定的,但同个字符内部的时间间隔是固定的,收发方无需使用同一时钟源,只要时钟信号的频率相同即可。
异步通信通过传送字符内的起始位来进行同步,而同步通信采用共用外部时钟来进行同步。
通俗点来说:同步通信就是舔狗发微信找女神,对方一直不回复,但舔狗一直在那等待回复;异步通信就是一个比较聪明点的舔狗发微信找女神,对方一直不回复,但舔狗不在那一直等待回复,选择了干其他事情。
数据传送方式
单工:只有一个固定方向进行传送数据。
半双工:双方都可以进行传送数据,但不能同时传送和接收数据,即只存在一方传送,一方接收。
全双工:双方都可以进行发送数据,并且可以同时传送和接收数据。
常见电平标准
TTL 电平:全双工,1:2.4V~5V,0:0.
电平类型
通信方式
逻辑1
逻辑0
TTL 电平
全双工
...
梯度下降法
1412.6980v8.pdf (arxiv.org)
duchi11a.dvi (jmlr.org)
CSC321 Winter 2014: lecture notes (toronto.edu)
[1212.5701] ADADELTA: An Adaptive Learning Rate Method (arxiv.org)
cs229.stanford.edu/proj2015/054_report.pdf
[1212.5701] ADADELTA: An Adaptive Learning Rate Method (arxiv.org)
lee16.pdf (mlr.press)
1609.04747.pdf (arxiv.org)
正则化方法
什么是正则化(Regularization)
深度学习可能存在过拟合问题——高方差,有两个解决方法,一个是正则化,另一个是准备更多的数据,这是非常可靠的方法,但你可能无法时时刻刻准备足够多的训练数据或者获取更多数据的成本很高,但正则化通常有助于避免过拟合或减少你的网络误差。
规范化中并没有对偏置项进行规范化,因为即使对偏置进行规范化操作也并不会对结果改变太多,所以,在某种程度上,对不对偏置进行规范化其实就是一种习惯了。然而,需要注意的是,有一个大的偏置并不会像大的权重那样会让神经元对输入太过敏感。所以我们不需要对大的偏置所带来的学习训练数据的噪声太过担心。同时,允许大的偏置能够让网络更加灵活。因为大的偏置让神经元更加容易饱和,这有时候是我们所要达到的效果。所以,我们通常不会对偏置进行规范化。
正则化方法
L1正则化
L1 规范化是在未规范化的代价函数上加上一个权重绝对值的和:
Cost=Loss+λn∑w∣∣w∣∣1Cost = Loss + \frac{\lambda}{n}\sum_w \vert \vert w \vert \vert_1
Cost=Loss+nλw∑∣∣w∣ ...
权重初始化
为什么要初始化权重
训练神经网络需要指定权重的初始值,而一个好的初始化方法将有助于网络学习。
好的初始化可以加快梯度下降、模型收敛;减小梯度下降收敛过程中训练和泛化出现误差的几率;
在一个多层的神经网络的正向传播和反向传播中,可知经常会出现连乘的计算,假设激活函数为线性函数,则 y=WnWn−1⋅⋅⋅W2W1xy = W_n W_{n-1}···W_2W_1xy=WnWn−1⋅⋅⋅W2W1x ,当权重 W 小于 1 时,由于连乘可知结果很容易出现指数级减小;当权重 W 大于 1 时,由于连乘可知结果很容易出现指数级爆炸式增长;
梯度消失和梯度爆炸问题都是因为网络太深,网络权值更新不稳定造成的,本质上是因为梯度反向传播中的连乘效应。
通过选择好的初始化权重一般可以有效减小这种问题的出现。
初始化权重方法
零初始化(不推荐)
通常,将所有权重初始化为零会导致网络无法打破对称性。
当所有初始值相同时,例如将每个权重初始化为0,然后进行反向传播时,所有权重将具有相同的梯度,因此也将具有相同的更新。这就是所谓的对称性。这意味着所有节点都将学习相同的东西,而我们不希望这样做,因为我们希望网 ...
损失函数
何为损失函数
常见的损失函数
均方差(MSE)损失(Mean Squared Error Loss)
均方差(MSE)损失是机器学习、深度学习回归任务中最常用的一种损失函数,也称为L2 Loss,它是模型预测值 y^\hat yy^ 与真实样本值 yyy 之间差值的平方和。
L2(x)=(y−y^)2L_2(x)=(y-\hat y)^2
L2(x)=(y−y^)2
JMSE=1N∑i=1N(yi−y^i)2J_{MSE}=\frac{1}{N}\sum_{i=1}^{N}(y_i-\hat y_i)^2
JMSE=N1i=1∑N(yi−y^i)2
令 n=1,以y−y^y-\hat yy−y^为横轴,MSE值为纵轴,得函数图形如下:
可见MSE函数曲线光滑连续且处处可导,便于使用梯度下降算法,并且随着误差的减小,梯度也在减小,有利于收敛。
由平方项可知,当 y−y^<1y-\hat y < 1y−y^<1,MSE给予较小的惩罚,缩小误差;当 y−y^>1y-\hat y > 1y−y^>1,MSE给予较大的惩罚,放大误差;可 ...
激活函数
何为激活函数
激活函数(Activation Function)是一种添加到人工神经网络中的函数,旨在帮助网络学习数据中的复杂模式。在神经元中,输入的input经过一系列加权求和后作用于另一个函数,这个函数就是这里的激活函数。
激活函数可以分为线性激活函数(线性方程控制输入到输出的映射,如f(x)=x等)以及非线性激活函数(非线性方程控制输入到输出的映射,比如Sigmoid、Tanh、ReLU、LReLU、PReLU、Swish 等)
因为神经网络中每一层的输入输出都是一个线性求和的过程,下一层的输出只是承接了上一层输入函数的线性变换,所以如果没有激活函数,那么无论你构造的神经网络多么复杂,有多少层,最后的输出都是输入的线性组合,纯粹的线性组合并不能够解决更为复杂的问题。而引入激活函数之后,我们会发现常见的激活函数都是非线性的,因此也会给神经元引入非线性元素,使得神经网络可以逼近其他的任何非线性函数,这样可以使得神经网络应用到更多非线性模型中。
为了增强网络的表示能力和学习能力,神经网络的激活函数都是非线性的,通常具有以下几点性质:
连续并可导(允许少数点上不可导),可导的激活函 ...
TensorFlow 笔记2
数据读取处理
1. 文件读取
以下用到的队列都为tf.train.QueueRunner对象,每个 QueueRunner 都负责一个阶段,tf.train.start_queue_runners()函数会要求图中的每个 QueueRunner 启动它的运行队列操作的线程。因此需要在会话中进行线程操作(结束后需回收线程)。
tf.train.Coordinator()线程协调器,通过它来对线程进行管理和协调;创建一个线程协调器对象coord = tf.train.Coordinator(),coord.request_stop():请求停止,coord.join(threads= ):回收线程。
tf.train.start_queue_runners(sess=,coord=)收集图中所有的队列线程,默认同时启动线程。sess:所在的会话,coord:线程协调器。
1.1 构造文件名队列
将需要读取的文件的文件名(一般为相对路径)放入文件队列。
tf.train.string_input_producer(string_tensor,num_epochs=None,shuffle=T ...