nano智能小车1:arduino相关知识
链接: Arduino(2) Mega2560和外部设备串口通信.
arduino
arduino 串口通讯
可用引脚
RX:10,11,12,13,14,15,50,51,52,53,A8(62),A9(63),A10(64),A11(65),A12(66),A13(67),A14(68),A15(69);
-
Serial.available()
获取到串口缓冲区接收到的字节数,最多可保存64Bytes -
Serial.begin(speed)
初始化串口,可配置串口的各项参数。speed:波特率 -
Serial.find(target)
从串口缓冲区读取数据,直至读到指定的字符串。target:需要搜寻的字符串或字符 -
Serial.flush()
等待正在发送的数据发送完成。早期版本里可用来清空接收缓冲区。 -
Serial.peek()
返回一字节的数据,但不会从接收缓冲区删除该数据 -
Serial.print(val, format)
将数据以ASCII码形式输出。val:需要输出的数据 format:数据输出的格式 -
Serial.read()
从串口读取数据,每读取一个字节,就会从接收缓冲区移除一字节的数据。 -
Serial.readBytes(buffer, length)
从接收缓冲区读取指定长度的字符,并将其存入一个数组。buffer:用于存储数据的数组(char[]或者byte[]) length:需要读取的字符长度 -
Serial.write(val)
输出数据到串口,以字节形式。val:发送的数据
nano
nano的gpio库
GPIO的BCM和BOARD编码规则
第一种编号是BOARD编号,这和树莓派电路板上的物理引脚编号相对应。使用这种编号的好处是,你的硬件将是一直可以使用的,不用担心树莓派的版本问题。因此,在电路板升级后,你不需要重写连接器或代码。
第二种编号是BCM规则,是更底层的工作方式,它和Broadcom的片上系统中信道编号相对应。在使用一个引脚时,你需要查找信道号和物理引脚编号之间的对应规则。对于不同的树莓派版本,编写的脚本文件也可能是无法通用的。
BCM 编号是树莓派上常用的 GPIO 引脚编号方式,它使用芯片上的引脚功能编号,更为常用和灵活。
board 编号使用物理引脚位置进行编号,适合于那些依赖于物理布局的项目和连接。当你需要直接指定物理引脚位置时,使用 board 编号更为直观。
选择使用 BCM 编号还是 board 编号取决于你的项目需求和个人偏好。一般来说,BCM 编号是更常用的方式,因为它提供了更大的灵活性,并且在各种树莓派模型之间保持一致。
sudo apt-get -y python-pip // 安装pip
sudo pip install rpi.gpio // 安装rpi gpio库
import RPi.GPIO as GPIO // 导入gpio库
GPIO.setmode(GPIO.BMC) // 设置gpio模式 BMC或者BOARD模式
add_event_detect和wait_for_edge()
wait_for_edge(); // 边缘检测
// 中断检测
// 参数:引脚号、边沿变化模式、回调函数、检测的时间间隔
add_event_detect(BtnPin, GPIO.BOTH, callback=detect, bouncetime=200);
python
try语法
程序执行顺序
1、普通语句逐行执行,自上而下。遇到赋值语句时,从右到左。
2、函数的执行过程
从上往下执行,参考先执行函数名,不执行函数内部,只有函数被调用时才执行。
3、类的执行是从上往下,先只执行函数名(其他部分顺序执行)
当实例化类对象时,会执行_init_,所以类的执行顺序是先执行__new__,再执行__init__,再执行普通方法,最后执行__del__
if name == ‘main’
如果if name == ‘main’ 所在模块是被直接运行的,则该语句下代码块被运行,如果所在模块是被导入到其他的python脚本中运行的,则该语句下代码块不被运行。
from和import
// # 使用import语句可以导入整个模块,然后通过模块名来访问其中的函数、类等对象。
import math // 使用math模块中的函数result = math.sqrt(25)
// 使用from import语句可以选择性地导入模块中的特定对象,而不需要通过模块名来访问。例如:
from math import sqrt //直接使用sqrt函数,无需使用模块名
= import math
sqrt=math.sqrt // from math import * 等价于 import math
result = sqrt(25)
// 使用as关键字给模块或对象起别名,以简化访问。
import math as m
result = m.sqrt(25)
logging
inspect 打印行号
import inspect
def __LINE__():
stack_t = inspect.stack()
ttt = inspect.getframeinfo(stack_t[1][0])
return ttt.lineno
def print_line_number():
frame = inspect.currentframe()
lineno = frame.f_back.f_lineno
print(f'Line {lineno}: Hello, World! ')
print(f'Line {lineno}: print("Hello, World!")')
print_line_number() // 使用时
print(f’')用法
print(f’') 是格式化字符串(f-string)的语法,它允许你在字符串中嵌入表达式,这些表达式在运行时会被其值所替换。f 或 F 前缀表示这是一个格式化字符串字面量。
在 f’’ 或 F’’ 中的大括号 {} 内,你可以放入任何有效的Python表达式。当 print 函数执行时,这些表达式会被求值,并且其结果会被插入到字符串的相应位置。
name = "Alice"
print(f"Hello, {name}!") # 输出:Hello, Alice!
x = 5
y = 10
print(f"The sum of {x} and {y} is {x + y}.") # 输出:The sum of 5 and 10 is 15.
person = {"name": "Bob", "age": 30} # 字典元素
print(f"{person['name']} is {person['age']} years old.") # 输出:Bob is 30 years old.
pi = 3.141592653589793 # 格式化数字
print(f"The value of pi is approximately {pi:.2f}.") # 输出:The value of pi is approximately 3.14.
glob 查找文件与目录
lob是python中的内置模块,该模块主要是用来查找文件与目录的。
*:匹配0个或多个字符;
**:匹配所有文件、目录、子目录和子目录里的文件(3.5版本新增);
?:代匹配一个字符;
[]:匹配指定范围内的字符,如[0-9]匹配数字,[a-z]匹配小写字母;
glob.glob() # 返回符合匹配条件的所有文件的路径;返回类型[list]
glob.iglob() # 返回一个迭代器对象,需要循环遍历获取每个元素,得到的也是符合匹配条件的所有文件的路径;
glob.escape() # escape可以忽略所有的特殊字符,就是星号、问号、中括号;
numpy使用
array 数组
np.array() //通过传入可迭代对象创建,基本方法np.array()
>>> np.array([1,2,3,4,5]) # 列表变数组
array([1, 2, 3, 4, 5])
>>> np.array((1,2,3,4,5)) # 元组变数组
array([1, 2, 3, 4, 5])
>>> np.array(range(3)) # range变数组
array([0, 1, 2])
>>> np.array([[1,2,3],[4,5,6]]) # 二维数组
array([[1, 2, 3],
[4, 5, 6]])
>>> np.array([[1,2],[3,4]],dtype = float)
array([[1., 2.], # 创建时显式指定数据类型
[3., 4.]])
floor 返回底限
# ndarray或标量。x中每个元素的底限。如果x是标量,则这是标量。
np.floor(x, /, out=None, *, where=True,
casting='same_kind', order='K', dtype=None,
subok=True[, signature, extobj]) = <ufunc 'floor'>
arry=np.floor([1.2,3,4,5.5])
>>> arry
array([1., 3., 4., 5.])
>>> arry2=np.floor(3)
>>> arry2
3.0
random 随机种子
np.random.seed() # 设置随机种子
np.random.shuffle() # 此功能用于通过改组其内容就地修改序列。
# range创造出来的数组,不能随机。
ary = np.array([1,2,3,4,5])
>>> ary
array([1, 2, 3, 4, 5])
>>> np.random.shuffle(ary)
>>> ary
array([4, 3, 5, 1, 2])
>>>
landtxt 加载文件
# fname:输入文件的路径或已打开的文件对象。可以是文件名、文件路径或已打开的文件对象。
# dtype:输出数组的数据类型,默认为float。可以通过这个参数指定读取数据的类型,如int、float、str等。
# delimiter:数据项之间的分隔符,默认为None,表示任何空白字符(空格、换行符、制表符等)都可以作为分隔符。也可以指定具体的分隔符,如逗号,、分号;等。
# skiprows:要跳过的行数(从文件开始算起),默认为0,即不跳过任何行。如果文件中包含标题行或不需要的行,可以通过这个参数来跳过它们。
# usecols:一个整数序列或逗号分隔的字符串,用于指定要读取的列。例如,# usecols=(1, 4, 5)表示只读取第2列、第5列和第6列的数据。
# unpack:如果为True,则将数据读入结构的数组。对于具有多个列的文本文件,此选项可以将每一列读入一个单独的数组中。
#ndmin:指定输出数组的最小维度数。例如,如果数据是一维的,但希望输出为二维数组,可以设置ndmin=2。
numpy.loadtxt(fname, dtype=<class 'float'>, delimiter=None, skiprows=0, usecols=None, unpack=False, ndmin=0)
ary np.loadtxt('**/**.txt',delimiter='')
expand_dims 指定维度拓展
# a 要增加维度的数组
# 指定轴的索引,轴索引可以是正数、负数或者一个包含多个轴索引的元组。正数索引从0开始,表示从左到右的轴;负数索引从-1开始,表示从右到左的轴。当指定一个轴索引时,expand_dims会在该轴之前插入一个新的维度。
numpy.expand_dims(a, axis)
>>> ary = np.array(range(5))
>>> ary_expand = np.expand_dims(ary,axis = 0)
>>> ary.shape
(5,)
>>> ary_expand.shape
(1, 5)
Matplotlib
Matplotlib 是一个 Python 中的 2D 绘图库, pyplot 模块是一个方便使用 Matplotlib 的接口。
# 当matplotlib使用交互式后端时,可实现交互式绘图。
# 如果处于交互模式,新创建的图形将会立刻显示,修改图形(即运行新的绘图语句)时原图形会立即重绘,matplotlib.pyplot.show()不会阻塞显示。此时shell可以输入新的命令。
# 如果处于非交互模式,新创建的图形或修改图形时,图形不会立即显示(当执行matplotlib.pyplot.show()时才会显示),matplotlib.pyplot.show()会阻塞显示。此时shell不可以输入新的命令。
# 简短来说,交互模式最大的特点即每执行一个绘图命令就会重绘一次图形。
matplotlib.pyplot.isinteractive() #查询交互式绘图模式状态。
matplotlib.pyplot.ion() #开启交互式绘图模式。
matplotlib.pyplot.ioff() #关闭交互式绘图。
# 清除画板的三种表示
matplotlib.pyplot.cla() # Clear axis即清除当前图形中的当前活动轴。其他轴不受影响。
matplotlib.pyplot.clf() #清除当前 figure 的所有axes,但是不关闭这个 window,所以能继续复用于其他的 plot
matplotlib.pyplot.close() # Close a figure window
True or ‘all’:所有子图共享x/y轴
False or ‘none’:所有子图的x/y轴都是独立的。
‘row’:每行子图共享x/y轴
‘col’:每列子图共享x/y轴
subplots
默认值为True。False:函数返回值为Axes对象二维数组。True:压缩函数返回值中 ~matplotlib.axes.Axes对象的维度。
fig:~.figure.Figure对象
ax:.axes.Axes 对象或Axes对象数组。
参数 | 意义 |
---|---|
rows, ncols | 子图网格的行/列数。可选参数。整数,默认值为1。 |
sharex, sharey | 控制子图共享x或y轴的行为。布尔值或{‘none’, ‘all’, ‘row’, ‘col’},默认值为False。 |
squeeze | 控制函数返回值中子图元组的维度。可选参数。布尔值, |
subplot_kw | 用于向创建子图时的底层函数 ~matplotlib.figure.Figure.add_subplot传递关键字参数。可选参数。字典。 |
gridspec_kw | 用于向创建子图网格时用到的 ~matplotlib.gridspec.GridSpec类的构造函数传递关键字参数。可选参数。字典。 |
**fig_kw: | 用于向 .pyplot.figure 传递关键字参数。可选参数。字典。函数的返回值为二元组。 |
sharex,sharey:控制子图共享x或y轴的行为。布尔值或{‘none’, ‘all’, ‘row’, ‘col’},默认值为False
- True or ‘all’:所有子图共享x/y轴
- False or ‘none’:所有子图的x/y轴都是独立的。
- ‘row’:每行子图共享x/y轴
- ‘col’:每列子图共享x/y轴
squeeze:控制函数返回值中子图元组的维度。可选参数。布尔值,默认值为True。
- 值为False:函数返回值为Axes对象二维数组。
- 值为True:压缩函数返回值中 ~matplotlib.axes.Axes对象的维度。子图数量为1,返回一个单独的Axes对象(标量)。子图结构为Nx1或 1xM ,返回一个Axes对象的一维数组。子图结构为NxM,返回一个Axes对象的二维数组。
# subplot和subplots的区别在绘制多合一显示的图时有所区别
# subplots() 既创建了一个包含子图区域的画布,又创建了一个 figure 图形对象,而 subplot() 只是创建一个包含子图区域的画布。
# 返回值是一个元组,包括一个图形对象和所有的 axes 对象。其中 axes 对象的数量等于 nrows * ncols,且每个 axes 对象均可通过索引值访问(从1开始)。子图数量为1,返回一个单独的Axes对象(标量)。子图结构为Nx1或 1xM ,返回一个Axes对象的一维数组。子图结构为NxM,返回一个Axes对象的二维数组。
# matplotlib.pyplot.subplots(nrows=1, ncols=1, *, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None, **fig_kw)
matplotlib.pyplot.figure() #绘制一个空图
matplotlib.pyplot.subplot() #绘制一个带坐标的图
matplotlib.pyplot.subplots() #绘制一个带坐标的图
argparse
import argparse # 引入argparse包
parser = argparse.ArgumentParser() # 创建参数对象
parser.add_argument() # 添加参数
args = parser.parse_args() # 类似于类的实例化,解析对象
OpenCv
读取图像
# 读取图像 filepath:要读入图片的完整路径 flags:读入图片的标志
# cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道
# cv2.IMREAD_GRAYSCALE:读入灰度图片
# cv2.IMREAD_UNCHANGED:顾名思义,读入完整图片,包括alpha通道
cv2.imread(filepath,flags)读入一副图片。
img = cv2.imread('1.jpg',cv2.IMREAD_COLOR)
显示图像
# 显示图像
# window_name:是一个字符串,表示窗口的标题。如果你用相同的名称调用多次imshow,OpenCV会显示相同的图像,而不是创建一个新的窗口。
# img:是你要显示的图像,它必须是一个有效的图像对象。
cv.imshow(window_name, img)
imgFile = "../images/imgLena.tif" # 读取文件的路径
img1 = cv2.imread(imgFile, flags=1) # flags=1 读取彩色图像(BGR)
img2 = cv2.imread(imgFile, flags=0) # flags=0 读取为灰度图像
cv2.namedWindow("canny", 0)
cv2.resizeWindow("canny", 300, 300) # 设置窗口大小
cv2.imshow("Demo1", img1) # 在窗口 "Demo1" 显示图像 img1
cv2.imshow("Demo2", img2) # 在窗口 "Demo2" 显示图像 img2
# 等待按键命令, 然后自动关闭单位为毫秒。
# 若在等待时间内按下任意键则返回按键的ASCII码,程序继续运行。
# 若没有按下任何键,超时后返回-1。参数为0表示无限等待。
key = cv2.waitKey(0)
cv2.destroyAllWindow() # 销毁所有窗口
cv2.destroyWindow(wname)# 销毁指定窗口
保存图像
# 第一个参数是要保存的文件名,第二个参数是要保存的图像。
# 可选的第三个参数,它针对特定的格式:对于JPEG,其表示的是图像的质量,用0 - 100的整数表示,默认95;对于png ,第三个参数表示的是压缩级别,默认为3。
cv2.imwrite(file,img,num)保存一个图像。
cv2.imwrite('1.png',img, [int(cv2.IMWRITE_JPEG_QUALITY), 95])
cv2.imwrite('1.png',img, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])
操作图像
# 翻转图像,flipcode控制翻转效果。
# flipcode = 0:沿x轴翻转;flipcode > 0:沿y轴翻转;flipcode < 0:x,y轴同时翻转
imgflip = cv2.flip(img,1)
# copy img
imgcopy = img.copy()
# 颜色空间转换,彩色图像转为灰度图像
img2 = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
# 灰度图像转为彩色图像
img3 = cv2.cvtColor(img,cv2.COLOR_GRAY2RGB)
窗口置顶
import win32
import win32gui
import win32con
hwnd = win32gui.FindWindow(None, label_win_name)# 获取句柄,然后置顶
CVRECT=cv2.getWindowImageRect(label_win_name)
win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 0,0,CVRECT[2],CVRECT[3], win32con.SWP_SHOWWINDOW)