【树莓派学习笔记】新入手的树莓派4B

之前玩树莓派都是胡乱玩,这一次把学习来的东西记录一下,方便日后查阅。借着双十一的东风入手了新的树莓派4B,昨天开始了一些基础配置。

本文首发于2019-11-2:知乎


获得新设备:树莓派4B

功能:好多


树莓派4B更新了硬件配置,把两个USB2.0接口升级到了USB3.0接口,无线网卡支持5GHz频段,板载蓝牙支持蓝牙5.0,HDMI接口换为两个microHDMI支持双4K视频输出,供电接口升级为最流行的USB-C接口。
另外RAM提供三种可选配置:1GB、2GB、4GB。本着既然可选那就顶配的原则,我购买了4GB的配置。 ​

树莓派图片视角1

另外我还购买了某宝商家提供的金属外壳套餐,着实给树莓派添加了一股工业气息。
值得一提的是这个外壳降温效果很好,昨天的升级过程中能把CPU温度压在45℃以下。
链接不贴了,想要购买链接的私信。
这几张图我在拍摄的时候把风扇装反了,希望各位不要被我误导。 ​ 树莓派图片视角2

说完了第一视角的外观,开始进入正题,也就是昨天的配置工作。

安装系统

树莓派4最低支持到Debian 10 (buster),因此只能安装截止目前(2019-11-2)最新的系统。
树莓派官网下载最新的系统,我选的是Raspbian Buster with desktop,这个固件尺寸不大不小,又有GUI,也有一些必要的软件。 ​

Raspbian Buster系统下载选择界面

把固件烧写到SD卡的方法这里不谈,网上方法很多,就是用Win32DiskImager去搞,没啥好说的。
在漫长的下载和烧录之后就是配置软件源,一直用清华大学开源镜像站的软件源,虽然偶尔崩掉但是速度还是可以的。
而且清华大学的同学写的帮助文档也简洁明了,没有必要重复。
注意到后文中我在进行包管理的时候使用的都是apt而非apt-get,至于这是为什么这里不谈,最直接的原因是apt指令给显示一个进度条。

CPU温度

刚才说到散热问题,我有测量温度。这里温度测量使用的是树莓派自身的功能。
查看文件/sys/class/thermal/thermal_zone0/temp可以看到当前CPU温度乘1000的值,或者也可以使用指令/opt/vc/bin/vcgencmd measure_temp来查看温度。


习得新玩意:/sys/class/thermal/thermal_zone0/temp/opt/vc/bin/vcgencmd measure_temp

功能:测量CPU温度


既然有散热那免不了烤机测试。

git clone https://github.com/xukejing/rpi-cpu-stress.git
cd rpi-cpu-stress
chmod a+x stress.sh
./stress.sh

经过测试,烤机10分钟CPU温度稳定在48℃左右。
上面代码作者测量的数据表明如果不加散热片和风扇,烤机10分钟CPU最高也就到83℃,不会触发降频。

AP模式-WiFi基站

无线调试过于诱人,于是考虑让树莓派建立一个WiFi基站来从其他设备无线ssh到树莓派来调试。
这里使用的是流行的create_ap,没有很多烦心事。
这个工具很古老了,作者的GitHub上能有两三年没有更新了,已经是成熟的工具了。

create_ap已经停止维护,原repo已经被作者归档,推荐使用linux-wifi-hotspot

# 克隆GitHub上的代码库
git clone https://github.com/oblique/create_ap.git
# 进入文件夹
cd create_ap
# 安装
sudo make install

安装完成之后需要安装一些依赖包,具体的依赖可以去作者的git上去查看。

sudo apt install util-linux procps hostapd iproute2 iw haveged dnsmasq

测试指令如下。 ssid:RPi, passwd: 88888888

sudo create_ap --no-virt -g 192.168.14.1 wlan0 eth0 RPi 88888888

在执行测试指令的时候报错了,基站没有建立成功。
错误内容我忘记截图了,但是我能记得错误信息里提到了一个RF-kill的东西。
说的是建立过程中出了一点小问题,原因是RF-kill阻止了什么东西。
我查阅了一下资料,rfkill工具是内核级别管理工具,可以打开和关闭设备的蓝牙和WiFi。

rfkill list

上面的指令会列出所有可用设备。对于我的树莓派来说是这个样子的。
rfkill list

使用blockunblock指令可以屏蔽或者解除屏蔽某个设备。
比如这里可以用rfkill block 0来屏蔽0号设备也就是WLAN。
这样之后就会导致WLAN不可用,导致上面的create_ap失败。
使用unblock指令可以打开设备。比如这里我的蓝牙是关闭的,那么使用指令rfkill unblock 1就可以打开蓝牙。


习得新工具:rfkill

功能:无线电传输设备管理


当时我的WLAN是被block的,所以这里执行rfkill unblock 0就解决了上面的问题。 测试无问题后将指令添加到开机启动脚本。编辑文件/etc/rc.local,在exit 0之前添加指令即可。

sudo create_ap --no-virt -g 192.168.14.1 --daemon wlan0 eth0 RPi 88888888

注意:这里必须要有--no-virt--daemon选项,前者是禁止虚拟什么东西,后面是将create_ap放在后台运行。

想要查看正在运行的ap,可以使用如下指令。

create_ap --list-running

其他用法参考帮助文档。

create_ap --help

复习工具:create_ap

功能:建立WiFi基站


树莓派与USB转TTL模块

我是用的是CP201x系列模块,树莓派对市面上大部分USB转TTL提供内核级别的驱动支持。
即插即用,比windows方便多了。 ​

CP201x俯视图CP201x与树莓派

插上模块之后执行指令lsusb查看USB设备。 ​ lsusb


习得新工具:lsusb

功能:查看USB设备


注意到Device 005就是我的串口模块。执行指令ls /dev/ttyUSB*来查看所有USB串口设备。 ​ ls dev

可以看到识别成了/dev/ttyUSB0,这比较重要,后面的指令里要用到。


习得新目录:/dev/*

包含内容:所有设备,其中tty设备为串口设备。


​ 使用指令stty -F /dev/ttyUSB0查看比特率。

stty


习得新工具:stty

功能:查看串口设备的设置


查看设备连接信息并筛选出我们的串口设备信息,使用指令dmesg | grep ttyUSB0查看结果如下。 ​ dmesg


习得新工具:dmesg

功能:查看设备信息


设备连接成功,下一步使用Python编程测试串口控制。
使用指令pip3 list | grep serial查看已安装的Python包是否包括pyserial。
这里因为使用Python3所以是pip3

pip3-list​{:.border}

可以看到已经安装了,版本为3.4。一般来讲都是系统默认安装的。
如果没有安装那么使用指令sudo pip3 install pyserial即可。
使用Python指令python3 -m serial.tools.list_ports查看可用的串口。 ​ python3-list_ports

注意到有两个可用串口,ttyAMA0是一个板载串口,引出到了树莓派的针脚上。
实际上树莓派板载两个串口,默认情况下有一个单独时钟的串口分配给了蓝牙,这个串口时钟稳定。
另一个串口时钟源是CPU内核的时钟,分配给了这个针脚上的外接串口,这个串口时钟会有一些不稳定。
这些细节不谈,以后有用再说。

下一步开始写脚本来测试串口功能。
将模块上的TXD引脚和RXD引脚进行短接,这样读写能同时测试。 ​ 串口模块测试

使用Python3交互界面进行测试。 ​ python3 serial

注意到有一行字符串的问题。
Python3与Python2的字符串有一些差别,这里在串口发送的时候要标注字符串编码方式。
pyserial有好多别的函数,这里不细说,可以参考官方文档详细了解。


习得新Python库:pyserial

功能:串口通信编程


USB摄像头

之前的文章中我用的摄像头一直是树莓派官方的CSI摄像头,那个摄像头的排线实在是不方便。
这一波我换了USB摄像头,树莓派提供内核级别的驱动,即插即用非常方便。 ​ usb摄像头

这个摄像头景深很大,手动调焦调好了之后很大的距离内不需要对焦。
查看图像设备使用到了上面学到的新知识。使用指令lsusb来查看USB设备,使用ls /dev/video*来查看视频输入设备。 ​ ls /dev/video*

注意到Device 007是摄像头连接前后多出来的设备,包括/dev/video0也是如此。
为了查看摄像头对焦的情况,需要实时查看摄像头内容,使用指令sudo apt install luvcview安装工具luvcview
我手上的摄像头仅仅支持到30帧,像素支持多少我忘了。使用指令可以查看摄像头图像。

luvcview -d /dev/video0 -i 30 -s 640x480

上面是使用设备/dev/video0在30帧下像素为640x480的指令,接了显示器的情况下可以看到摄像头图像。


习得新工具:luvcview

功能:实时显示摄像头图像


焦距调好之后尝试拍照,上面的工具拍照支持很不友好,因此使用指令sudo apt install fswebcam安装另一个工具fswebcam。 拍照指令如下。

fswebcam /dev/video0 -r 640x480 --no-timestamp --no-banner --jpeg -95 --delay 3 --save test.jpg

使用设备拍摄640*480的图片,没有时间戳,没有图片下方一个可恶的红条条,存为jpg格式质量95,延时三秒拍摄,文件名称test.jpg。 ​

USB摄像头拍摄结果


习得新工具:fswebcam

功能:拍照


OpenCV安装和测试

之前的时候OpenCV都是源码编译安装,那样虽然能使用最新的库函数但也会耗费大量的时间和精力甚至最后会迎来失败。
这一次我们使用apt包管理工具来安装OpenCV。使用以下指令来安装。

sudo apt install libcv-dev libopencv-dev

安装完成之后库函数会自动添加到系统链接目录下,非常方便,Python和C++都能使用。

在Python3下使用如下脚本来测试。 ​ python3 cv

可以看到我们安装的版本为3.2.0,不是最新的版本,但是可以用。

编写Python脚本进行摄像头测试。

import cv2

cap = cv2.VideoCapture(0)

while(cap.isOpened()):
	ret,frame = cap.read()
	cv2.imshow('capture', frame)
	key = cv2.waitKey(1)
	if key & 0x00FF == ord('q'):
		break
	
cap.release()
cv2.destroyAllWindows()

这个脚本的功能是打开摄像头显示图像,按下键盘上的q键退出。 然后进行C++代码测试。保存在main.cpp下。

#include <opencv2/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <vector>
#include <cstdio>

int main (int argc, char **argv)
{
	auto image = cv::imread(argv[1], cv::IMREAD_COLOR );

	if (argc != 2 || !image.data) {
		fprintf(stdout, "No image data\n");
		return -1;
	}

	cv::Mat image_gray;
	cv::cvtColor(image, image_gray, cv::COLOR_RGB2GRAY);
	// 如果想在图形界面查看图像对比可以取消这几行行的注释
	// cv::namedWindow("image", cv::WINDOW_AUTOSIZE);
	// cv::namedWindow("image gray", cv::WINDOW_AUTOSIZE);

	// cv::imshow("image", image);
	// cv::imshow("image gray", image_gray);

	try
	{
		std::vector<int> compression_params;
		compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
		compression_params.push_back(95);
		cv::imwrite("out.jpg", image_gray, compression_params);
	}
	catch (std::runtime_error& ex)
	{
		fprintf(stderr, "Exception converting image to JPG format: %s\n", ex.what());
		return 1;
	}

	fprintf(stdout, "Saved JPG file gray\n");

	cv::waitKey(0);
    cv::destroyAllWindows();
	return 0;
}

编写Makefile脚本如下。

CC=g++
# 可运行文件
TARGET=main
# C文件
SRCS=main.cpp
# 目标文件
OBJS=$(SRCS:.cpp=.o)
# 库文件
# DLIBS = -lopencv_core -lopencv_imgproc -lopencv_highgui
DLIBS=$(shell pkg-config --libs opencv)
# 链接为可运行文件
$(TARGET):$(OBJS)
	$(CC) -o $@ $^ $(DLIBS)
clean:
	rm -f $(TARGET) $(OBJS)
# 编译规则 $@代表目标文件 $< 代表第一个依赖文件
%.o:%.cpp
	$(CC) -o $@ -c $<

Makefile和main.cpp应当放在同一目录下,在该目录下执行指令make可以编译。编译完成后目录下应有以下文件。 ​ tree

绿色的是可执行文件,*.o是编译的obj文件,test.jpg是刚才我用摄像头拍的照片,这里拿来测试。
使用指令./main test.jpg可以进行测试。可以观察到马上生成一个新的out.jpg
tree

结果是这样的。

out

参考文献

树莓派官方网站:Raspberry Pi Foundation

清华大学开源软件镜像站:tuna

CPU温度:https://my.oschina.net/yehun/blog/1633498(2022.8.15已失效)

烤机测试:树莓派4该选多大的散热器,来个烤机压力测试吧

create_ap:create_ap

rfkill:用rfkill命令管理蓝牙和wifi

USB转TTL:树莓派连接USB转串口的使用

USB摄像头:树莓派接入USB摄像头

安装OpenCV:通过apt方式安装opencv

图片保存问题:Opencv 图像读取与保存问题