树莓派(CM4) 学习记录 #1

树莓派基础功能

0 文章索引

树莓派4 学习记录 #2

树莓派5 踩坑记录 #3

1 镜像烧录(EMMC版本)

1.1 下载镜像

这里我选择不带桌面的版本 Raspberry Pi OS Lite

镜像下载

1.2 进入烧录模式

  • 首先需要将CM4 boot短接,然后通过Micro USB /Type C 接口转USB接口连接电脑,再连接电源
  • 此时,电脑设备管理器通用串行总线设备中会识别出一个BCMxxx Boot的设备
  • 运行rpiboot(引导加载程序),等待运行结束,在我的电脑上面会出现一个U盘的盘符
  • 使用SDFormatter格式化EMMC
  • 烧录的准备工作就完成了!!!

1.3 烧写镜像

  • (不推荐)使用Win32DiskImager烧写镜像,需要将下载的 .xz 结尾的镜像文件解压得到 .img 结尾的镜像文件,然后进行烧写
  • (推荐)使用官方的树莓派镜像烧录器 Raspberry Pi Imager进行烧录,可以直接使用 .xz 文件烧录,还能设置主机名、开启ssh服务、ssh登录用户名密码、wifi、语音
  • 烧录完毕之后,在我的电脑会识别出一个U盘的盘符
  • 如果是使用Win32DiskImager烧写镜像,还需要开启下ssh服务和设置登录的用户名密码:
  • 在根目录下新建一个名称为ssh的文件(没有后缀名)来开启ssh服务
  • 创建 userconf.txt文件,该文件内输入用户名和密码的密文,以下例子,用户名为pi,密码为raspberry的密文
1
pi:$6$4ilokQRQxmURT.py$aJWBQ5yniJJPwV3CKawYJcnSK5JZGhrVZYF3K4omRUFv6KL0MysEH7F4NZRMNMcYF.U3xsQvWrx7ZL2GKxuv.1

下载 Raspberry Pi Imager

1.4 烧录完成并重启

  • 烧录完毕断开电源,断开和电脑的连接线,将BOOT断开,重新上电
  • 连接网线,然后使用shell工具连接树莓派

2 系统软件安装

  • sudo passwd root 设置root密码

2.1 安装wiringpi

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 选择要保存的目录
cd download 
 
# 下载deb包
wget https://github.com/WiringPi/WiringPi/releases/download/2.61-1/wiringpi-2.61-1-armhf.deb
 
# 安装deb包
sudo dpkg -i wiringpi-latest.deb

# 查看版本
gpio -v

# 查看gpio信息
gpio readall

# 查看板子详细信息
pinout
gpio readall 返回信息

gpio readall 返回信息

3 python 脚本编写

3.1 RPi.GPIO 模块使用

3.1.1 导入模块

1
import RPi.GPIO as GPIO

3.1.2 针脚编号

有两种编号可以用来定位针脚(参考上方的图 “gpio readall 返回信息”):

第一种方式是使用 BOARD 编号系统,使用Physical编号,即物理的编号位置。

第二种方式是使用 BCM 编号,使用BCM的编号。

1
GPIO.setmode(GPIO.BOARD)

或者

1
GPIO.setmode(GPIO.BCM)

3.1.3 设置输入输出

1
2
3
4
5
# 配置为输入的通道
GPIO.setup(pin_num, GPIO.IN)

# 配置为输出的通道
GPIO.setup(pin_num, GPIO.OUT)

pin_num 是针脚的编号

3.1.4 针脚电压

1
2
3
4
5
6
7
8
# 查看针脚电压状态
GPIO.input(pin_num)

# 设置针脚输出高电压
GPIO.output(pin_num, GPIO.HIGH)

# 设置针脚输出低电压
GPIO.output(pin_num, GPIO.LOW)

苹果有个app PiHelper 能直接在手机上修改针脚的输入输出和高低电压,很方便

3.1.5 清理

脚本结束后的清理,恢复所有使用过的通道状态为输入,该操作仅会清理脚本使用过的 GPIO 通道。

1
GPIO.cleanup()

4 UART开启

CM4有6个UART,其中默认的开启的串口UART0UART1都是GPIO14GPIO15 可以通过shell命令查看

1
dtoverlay -h uart0
uart0串口信息 GPIO14输出GPIO15输入

uart0串口信息 GPIO14输出GPIO15输入

现在要开启剩余的4个UART串口

4.1 修改config.txt

1
vi /boot/config.txt

在文本末尾加上

1
2
3
4
dtoverlay=uart2
dtoverlay=uart3
dtoverlay=uart4
dtoverlay=uart5

添加完重启

1
reboot

4.2 查看UART串口信息

4.2.1 查看串口是否开启

1
dmesg | grep tty
ttyAMA1~4都开启了

ttyAMA1~4都开启了

4.2.2 查看串口对应的GPIO口

1
sudo cat /sys/kernel/debug/pinctrl/fe200000.gpio-pinctrl-bcm2711/pinmux-pins
串口和针脚的对应关系很明显了

串口和针脚的对应关系很明显了

可以得出各 UART 串口与 GPIO 对应关系:

GPIO14 = TXD0 -> ttyAMA0

GPIO0 = TXD2 -> ttyAMA1

GPIO4 = TXD3 -> ttyAMA2

GPIO8 = TXD4 -> ttyAMA3

GPIO12 = TXD5 -> ttyAMA4

————————————

GPIO15 = RXD0 -> ttyAMA0

GPIO1 = RXD2 -> ttyAMA1

GPIO5 = RXD3 -> ttyAMA2

GPIO9 = RXD4 -> ttyAMA3

GPIO13 = RXD5 -> ttyAMA4

图片更明显

图片更明显

4.2.3 测试串口是否连通

要测试 ttyAMA1 是否通,首先短接 GPIO0GPIO1 ,然后重启树莓派

1
2
# 查看串口波特率
stty -F /dev/ttyAMA1

编写python脚本测试发送和接收消息

1
2
3
4
5
6
7
8
9
import serial

uart = serial.Serial(port="/dev/ttyAMA1", baudrate=9600)

send = uart.write("Hello World\n".encode("gbk"))
print(send)

rev = uart.readline()
print(rev)

在树莓派上执行

1
python aurt-test.py
执行结果

执行结果

其他串口的测试同上

5 蓝牙通讯

5.1 和手机蓝牙配对

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 进入蓝牙配对界面
bluetoothctl

# 扫描蓝牙设备
scan on

# 找到自己手机的蓝牙地址并配对
power on
agent on
pair 40:F9:46:50:32:69

5.2 与手机通讯

要与手机通讯必须先修改一些配置

  1. sudo usermod -G bluetooth -a pi 添加用户到蓝牙组

  2. sudo nano /etc/systemd/system/dbus-org.bluez.service 修改蓝牙配置文件

    蓝牙配置文件修改后

    蓝牙配置文件修改后

    ExecStart=/usr/libexec/bluetooth/bluetoothd -C

    ExecStartPost=/usr/bin/sdptool add SP

  3. sudo reboot 重启树莓派

  4. hciconfig -a 查看蓝牙名称

  5. sudo systemctl status bluetooth 查看蓝牙服务状态

  6. sudo hciconfig hci0 piscan 设置蓝牙可被发现

  7. sudo rfcomm watch hci0 等待蓝牙设备连接

使用手机上的蓝牙调试的app连接树莓派的蓝牙

连接成功

连接成功

连接成功后可以看到多出来一个串口 /dev/rfcomm0,通过这个串口和手机通信

写个python脚本向串口发送数据和接收数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import serial

# 连接串口
uart = serial.Serial(port="/dev/rfcomm0", baudrate=9600)

# 发送数据
send = uart.write("Hello World rfcomm0\n".encode("gbk"))

# 接收数据
while True:
    rev = uart.read(24).decode('utf-8')
    print(rev)

5.3 蓝牙天线配置为外置天线

编辑 /boot/config.txt 文件

sudo nano /boot/config.txt

在文件末尾加入一行配置:

dtparam=ant2

如何将树莓派 CM4 的 WiFi 天线配置为外置天线

5.4 设置蓝牙一直可见

1
2
3
4
5
6
7
8
# 进入蓝牙控制台
sudo bluetoothctl

# 开启蓝牙可见
discoverable on 

# 设置蓝牙一直可见
discoverable-timeout 0

5.5 将rfcomm配置成服务

新建文件 rfcomm.service

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[Unit]
Description=RFCOMM service
After=bluetooth.service
Requires=bluetooth.service

[Service]
Restart=on-failure
ExecStart=/usr/bin/rfcomm watch hci0

[Install]
WantedBy=multi-user.target

放在/etc/systemd/system/目录下,完成后执行systemctl daemon-reloadsystemctl enable rfcomm

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 启动
systemctl start rfcomm

# 停止
systemctl stop rfcomm

# 重启
systemctl restart rfcomm

# 状态
systemctl status rfcomm

5.6 自动确认蓝牙的配对请求设置

配置bluetoothctl的代理模式为NoInputNoOutput 这将允许树莓派自动确认来自其他设备的配对请求,而无需用户手动确认

以下是具体的步骤:

1
2
3
4
5
6
7
8
9
# 进入蓝牙控制台
bluetoothctl

# 代理模式设置
agent off

agent NoInputNoOutput

default-agent

设置完后,蓝牙配对时只需要在连接端点击配对确认

但是这种方法在退出quit蓝牙控制会话的时候就失效了

用Python写一个脚本解决

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
def auto_pair():
    # 启动bluetoothctl会话
    bluetoothctl = subprocess.Popen(['bluetoothctl'], stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE,
                                    text=True)

    # 配置代理模式和启用自动确认模式
    commands = [
        'power on',  # 打开蓝牙适配器
        'agent off',  # 启用配对模式
        'discoverable on',  # 启用可被其他设备检测到的模式
        'agent NoInputNoOutput',  # 设置代理模式为NoInputNoOutput
        'default-agent'  # 将代理设置为默认代理
    ]

    for cmd in commands:
        bluetoothctl.stdin.write(cmd + '\n')
        bluetoothctl.stdin.flush()
        time.sleep(1)  # 等待一些时间,确保每个命令有足够的时间执行

    bluetoothctl.wait()

5.7 蓝牙socket通讯

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import bluetooth


# 设置蓝牙服务
server_sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
server_sock.bind(("", bluetooth.PORT_ANY))
server_sock.listen(1)

logger.info("等待手机连接...")
client_sock, client_info = server_sock.accept()
logger.info("手机已连接!")
logger.info(client_info)

如上是一个手机连接树莓派蓝牙的实例

建立socket通讯后,即可通过client_sock.send()client_sock.recv()来发送和接收数据

0%