【工业树莓派 CM0 Dev Board】扩展板设计

【工业树莓派 CM0 Dev Board】扩展板设计

本文介绍了树莓派 CM0 Dev Board 单板计算机扩展板 PCB 设计,包括原理图、资源参数、环境搭建、工程测试等。

项目介绍

  • 扩展板设计:PCB、资源分布、参数特点、原理图等;
  • 环境搭建:安装所需 python 库;
  • 工程测试:驱动 DHT11、ADC、AHT10、LM75、数码管、步进电机等。

扩展板

树莓派 Easy 扩展板

详见:树莓派Easy扩展板 - 立创开源硬件平台 .

资源

  • DHT11 温湿度
  • 4 路独立按键
  • 4 颗单色 LED
  • 6 颗 WS2812 彩色 LED
  • HX1838 红外接收
  • GL5528 光敏电阻
  • 旋转电位器
  • 无源蜂鸣器

接口

  • 硬件 I2C 接口
  • 0.96 寸 I2C OLED 接口
  • 超声波模块接口
  • CH340E 芯片 USB 转 TTL 串口
  • 预留数字拓展引脚
  • 模拟拓展通道

原理图

环境搭建

创建并激活虚拟环境

bash 复制代码
python -m venv .venv
source .venv/bin/activate

终端执行如下指令,安装所需 python 库

bash 复制代码
pip install pillow # image processing library
pip install adafruit-circuitpython-ssd1306 # oled library
pip install adafruit-circuitpython-dht # dht11 driver library
pip install adafruit-circuitpython-pcf8591 # pcf8591 library
pip install adafruit-circuitpython-ahtx0 # aht10 library
pip install adafruit-circuitpython-pct2075 # lm75 library

DHT11

使用 adafruit_dht 库函数和单总线协议读取 DHT11 温湿度数据,并通过 adafruit_ssd1306 或 luma.oled 库函数实现 OLED 显示。

代码

python 复制代码
import time
import board
import busio
import adafruit_dht
import adafruit_ssd1306
from PIL import Image, ImageDraw, ImageFont

# 初始化DHT11 物理引脚7
dht = adafruit_dht.DHT11(board.D4, use_pulseio=False)

# 初始化I2C OLED 物理3/5
i2c = busio.I2C(board.SCL, board.SDA)
oled = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c)
w, h = oled.width, oled.height
img = Image.new("1", (w, h))
draw = ImageDraw.Draw(img)

# 加载字体
try:
    # 系统矢量字体,支持缩放
    big_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 20)
except:
    # 默认字体
    big_font = ImageFont.load_default()

def screen_clear():
    draw.rectangle((0,0,w,h), fill=0)

try:
    while True:
        screen_clear()
        try:
            temp = dht.temperature
            hum = dht.humidity
            draw.text((0, 0), f"Temp: {temp:.1f} C", font=big_font, fill=255)
            draw.text((0, 28), f"Humi: {hum} %RH", font=big_font, fill=255)
        except RuntimeError as e:
            draw.text((0, 0), "Read Error", font=big_font, fill=255)
        oled.image(img)
        oled.show()
        time.sleep(2)
except KeyboardInterrupt:
    pass
finally:
    dht.exit()
    oled.fill(0)
    oled.show()

保存代码。

效果

终端执行指令 python dht11_oled.py 运行程序;

板载 OLED 显示 DHT11 采集的环境温湿度数据;

ADC

使用 adafruit_pcf8591 库函数和 IIC 总线协议读取 A1 引脚(旋转电位器)输入的模拟电压,并通过串口打印。

代码

python 复制代码
import time
import board
import adafruit_pcf8591.pcf8591 as PCF
from adafruit_pcf8591.analog_in import AnalogIn

# 初始化I2C总线
i2c = board.I2C()
# 创建PCF8591实例,默认地址0x48
pcf = PCF.PCF8591(i2c)

# 绑定Ax输入通道
adc = AnalogIn(pcf, PCF.A1)

# 循环打印电压
while True:
    # 原始归一化数值(0~65535)
    raw = adc.value
    # 换算实际电压
    volt = (raw / 65535) * adc.reference_voltage
    print(f"A1通道电压:{volt:.2f} V,原始值:{raw}")
    time.sleep(1)

保存代码。

效果

终端执行指令 python pcf8591_print.py 运行程序;

旋转电位器旋钮,调整 ADC 输入电压;

终端打印 A1 采样电压值和原始值;

呼吸灯

结合 PCF8591 芯片控制 AOUT 模拟输出,实现 LED 渐变效果。

代码

python 复制代码
import time
import board
import adafruit_pcf8591.pcf8591 as PCF
from adafruit_pcf8591.analog_out import AnalogOut

# I2C初始化
i2c = board.I2C()
pcf = PCF.PCF8591(i2c)
dac_out = AnalogOut(pcf, PCF.OUT)

# 阈值参数
VOLT_THRESHOLD = 2.3    # LED点亮电压阈值
V_REF = 3.3              # PCF8591基准电压
DAC_THRESHOLD = round(VOLT_THRESHOLD / V_REF * 65535)  # 45676
DAC_MAX = 65535

print(f"LED点亮DAC阈值:{DAC_THRESHOLD},对应电压{VOLT_THRESHOLD}V")
try:
    while True:
        # 渐亮:从阈值升到最大
        for dac_val in range(DAC_THRESHOLD, DAC_MAX + 1, 256):
            dac_out.value = dac_val
            volt = (dac_val / 65535) * V_REF
            #print(f"DAC:{dac_val:5d} 电压:{volt:.2f}V LED亮")
            time.sleep(0.02)
        
        # 渐暗:从最大降到阈值,低于阈值直接归零,LED熄灭
        for dac_val in range(DAC_MAX, DAC_THRESHOLD - 1, -256):
            dac_out.value = dac_val
            volt = (dac_val / 65535) * V_REF
            #print(f"DAC:{dac_val:5d} 电压:{volt:.2f}V LED亮")
            time.sleep(0.02)
        
        # 完全熄灭阶段(保持0V,停顿0.5秒)
        dac_out.value = 0
        #print("DAC:0     电压:0.00V LED熄灭")
        time.sleep(0.5)

except KeyboardInterrupt:
    # Ctrl+C退出,关闭LED
    dac_out.value = 0
    print("\n程序结束,DAC清零")

保存代码。

效果

终端执行指令 python aout_breath.py 运行程序;

板载 LED 呈现呼吸灯效果;

AHT10

使用杜邦线连接板载 IIC 排针接口和 AHT10 传感器模块,实现环境温湿度的串口打印。

代码

python 复制代码
import time
import board
import adafruit_ahtx0

# Create sensor object, communicating over the board's default I2C bus
i2c = board.I2C()  # uses board.SCL and board.SDA
sensor = adafruit_ahtx0.AHTx0(i2c)

try:
    while True:
        print("\nTemperature: %0.1f C" % sensor.temperature)
        print("Humidity: %0.1f %%" % sensor.relative_humidity)
        time.sleep(2)
except KeyboardInterrupt:
    pass
finally:
    print("Exiting....")

保存代码。

效果

终端执行指令 python aht_print.py 运行程序;

终端连续打印环境温湿度数据;

LM75

使用杜邦线连接板载 IIC 排针接口和 LM75 传感器模块,实现环境温度的串口打印。

模块 PCB 设计详见:LM75模块 - 立创开源硬件平台 .

由于板载 PCF8591 默认地址 0x48,与 LM75 默认 IIC 地址相同,因此需短接 A1(或 A2) 与 VCC,对应地址为 0x4a (0x4c)。

代码

python 复制代码
import time
import board
import adafruit_pct2075

# 初始化 I2C 总线
i2c = board.I2C()

sensor = adafruit_pct2075.PCT2075(i2c, address=0x4c)

try:
    while True:
        temp = sensor.temperature
        print(f"温度:{temp:.2f} ℃")
        time.sleep(0.5)
except KeyboardInterrupt:
    print("程序退出")

保存代码。

效果

终端执行指令 python lm75_print.py 运行程序;

终端打印实时温度数据;

数码管

使用 GPIO 控制数码管显示 CPU 温度。

代码

python 复制代码
import RPi.GPIO as GPIO
import time
import threading

# ==================== 74HC595 引脚定义 ====================
# 使用 BCM 编号,可根据实际接线修改
LATCH = 9   # RCLK (STCP)
CLOCK = 10   # SRCLK (SHCP)
DATA  = 11   # DS    (SER)

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(LATCH, GPIO.OUT)
GPIO.setup(CLOCK, GPIO.OUT)
GPIO.setup(DATA,  GPIO.OUT)

# ==================== 共阳数码管段码 ====================
# 段码:dp g f e d c b a
SMG_DUAN = [
    0b11000000,  # 0
    0b11111001,  # 1
    0b10100100,  # 2
    0b10110000,  # 3
    0b10011001,  # 4
    0b10010010,  # 5
    0b10000010,  # 6
    0b11111000,  # 7
    0b10000000,  # 8
    0b10010000,  # 9
]

# ==================== 595 移位发送 ====================
def shift_out(byte):
    for i in range(8):
        bit = (byte >> (7 - i)) & 1
        GPIO.output(DATA, bit)
        GPIO.output(CLOCK, GPIO.HIGH)
        GPIO.output(CLOCK, GPIO.LOW)

# ==================== 显示函数 ====================
def show(left, right, dot=False):
    seg_l = SMG_DUAN[left % 10]
    seg_r = SMG_DUAN[right % 10]
    if dot:
        seg_r &= 0b01111111   # 共阳:点亮小数点(dp 拉低)

    GPIO.output(LATCH, GPIO.LOW)
    shift_out(seg_r)          # 先送右边(级联时后到高位)
    shift_out(seg_l)
    GPIO.output(LATCH, GPIO.HIGH)

# ==================== 读取 CPU 温度 ====================
def get_cpu_temp():
    try:
        with open('/sys/class/thermal/thermal_zone0/temp', 'r') as f:
            temp_str = f.read().strip()
        return int(temp_str) / 1000.0   # 转为摄氏度
    except Exception as e:
        print("读取温度失败:", e)
        return 0.0

# ==================== 全局变量与锁 ====================
current_left = 0
current_right = 0
current_dot = False
lock = threading.Lock()

# ==================== 刷新线程(防止闪烁)====================
def display_loop():
    """独立线程持续刷新数码管,避免主循环 sleep 导致闪烁"""
    while running:
        with lock:
            l, r, d = current_left, current_right, current_dot
        show(l, r, d)
        time.sleep(0.005)   # 5ms 刷新一次,视觉无闪烁

# ==================== 主程序 ====================
running = True

try:
    # 启动显示刷新线程
    t = threading.Thread(target=display_loop, daemon=True)
    t.start()

    while True:
        temp = get_cpu_temp()
        print("CPU 温度: {:.1f} °C".format(temp))

        with lock:
            if temp >= 10:
                # 两位数:显示整数,如 42
                t_round = round(temp, 0)
                current_left = int(t_round // 10)
                current_right = int(t_round % 10)
                current_dot = False
            else:
                # 个位数:显示一位小数,如 8.5
                t_round = round(temp * 10) / 10
                current_left = int(t_round)
                current_right = int((t_round * 10) % 10)
                current_dot = True

        time.sleep(1)   # 每秒更新一次温度数值

except KeyboardInterrupt:
    print("\n程序已停止")

finally:
    running = False
    t.join(timeout=0.5)
    GPIO.output(LATCH, GPIO.LOW)
    GPIO.cleanup()

保存代码。

效果

终端执行指令 python segment_cpu.py 运行程序;

数码管显示 CPU 温度值;

步进电机

树莓派 CM0 控制 GPIO 输出电平,结合 A4988 模块实现 42 步进电机驱动,并显示旋转状态,包括转速、角度和方向。

模块 PCB 设计详见:42步进电机A4988扩展板 - 立创开源硬件平台 .

代码

终端执行指令 touch stepmotor_oled.py 新建文件,并添加如下代码

python 复制代码
import board
import busio
import adafruit_ssd1306
from PIL import Image, ImageDraw, ImageFont
import os
import time
import datetime
import threading
import RPi.GPIO as GPIO

# ---------------------- OLED 初始化 ----------------------
# I2C 总线初始化,树莓派默认SDA=GPIO2(SDA), SCL=GPIO3(SCL)
i2c = busio.I2C(board.SCL, board.SDA)
# SSD1306 128*64 0x3C地址
WIDTH = 128
HEIGHT = 64
oled = adafruit_ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c, addr=0x3C)

# 清空屏幕缓存
oled.fill(0)
oled.show()

# 创建绘图缓冲区
image = Image.new("1", (WIDTH, HEIGHT))
draw = ImageDraw.Draw(image)

# 字体
font_main = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 14)
font_small = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 12)

# ---------------------- 运行状态变量 ----------------------
current_angle = 180
speed_ms = 0.2
direct_text = "CW"
running = True

# 独立屏幕刷新线程
def screen_task():
    while running:
        now = datetime.datetime.now()
        date_str = now.strftime("%Y-%m-%d")
        time_str = now.strftime("%H:%M:%S")

        # 每次刷新前清空画布
        draw.rectangle((0, 0, WIDTH, HEIGHT), fill=0)

        # 左侧时间信息
        draw.text((0, 0), date_str, font=font_small, fill=1)
        draw.text((0, 11), time_str, font=font_main, fill=1)

        # 左侧电机运行状态
        info_dir = f"Dir: {direct_text}"
        info_speed = f"V: {speed_ms}ms"
        info_angle = f"Ang: {abs(current_angle)}deg"
        draw.text((2, 24), info_dir, font=font_small, fill=1)
        draw.text((2, 36), info_speed, font=font_small, fill=1)
        draw.text((2, 48), info_angle, font=font_small, fill=1)

        # 将PIL图像写入OLED并刷新
        oled.image(image)
        oled.show()

        time.sleep(0.1)

# ---------------------- 电机驱动函数 ----------------------
STEP = 9
DIR = 10
EN = 11
PULSE_PER_360DEG = 1600  # 8 细分
PULSE_PER_DEG = PULSE_PER_360DEG / 360

GPIO.setmode(GPIO.BCM)
GPIO.setup(STEP, GPIO.OUT)
GPIO.setup(DIR, GPIO.OUT)
GPIO.setup(EN, GPIO.OUT)
GPIO.output(EN, GPIO.LOW)

def run_angle(degree, speed):
    global direct_text
    pulses = int(abs(degree) * PULSE_PER_DEG)
    if degree > 0:
        GPIO.output(DIR, GPIO.HIGH)
        direct_text = "CW"
    else:
        GPIO.output(DIR, GPIO.LOW)
        direct_text = "CCW"

    delay_s = speed / 1000.0
    # 脉冲输出
    for _ in range(pulses):
        GPIO.output(STEP, GPIO.HIGH)
        time.sleep(delay_s)
        GPIO.output(STEP, GPIO.LOW)
        time.sleep(delay_s)

if __name__ == "__main__":
    # 启动后台屏幕线程
    t = threading.Thread(target=screen_task, daemon=True)
    t.start()

    try:
        while True:
            current_angle = 180
            run_angle(current_angle, speed_ms)
            time.sleep(1)

            current_angle = -180
            run_angle(current_angle, speed_ms)
            time.sleep(1)

    except KeyboardInterrupt:
        running = False
        time.sleep(0.2)
        # 清屏
        oled.fill(0)
        oled.show()
        # 电机释放
        GPIO.output(EN, GPIO.HIGH)
        GPIO.cleanup()
        print("程序退出,屏幕与电机已释放")

保存代码。

效果

  • 终端执行指令 python a4988_run.py 运行程序;

  • OLED 显示日期、时间、步进电机状态,包括方向、速度、角度等;

  • 步进电机正反交替旋转;

总结

本文介绍了树莓派 CM0 Dev Board 单板计算机扩展板 PCB 设计,包括原理图、资源参数、环境搭建、工程测试等,为相关产品的快速开发和应用设计提供了参考。

相关推荐
会编程的土豆2 小时前
MySQL 入门:库、表、行、主键是什么
linux·数据库·网络协议·http
Yolanda_20222 小时前
在vscode终端中可使用pip,但是cmd终端中找不到命令 pip问题的解决
vscode·python·conda·pip
嵌入式-老费2 小时前
esp32开发与应用(添加数据分区)
单片机·嵌入式硬件
2301_764441332 小时前
用动力学系统(微分方程)为 Kernberg 的客体关系单元提供数学化的操作定义,把“自体—客体“这对心理结构建模成一个二维耦合系统
数据结构·python·算法·数学建模
dogstarhuang2 小时前
用 Doubao-Seed-Evolving + Python 免费写一个网页正文提取工具(实战教程)
爬虫·python·ai编程
△曉風殘月〆2 小时前
如何在Linux中安装Qt开发环境
linux·运维·qt
嵌入式-老费3 小时前
esp32开发与应用(OTA升级)
嵌入式硬件
猫头虎3 小时前
什么是ZCode for GLM-5.2?
开发语言·人工智能·python·科技·算法·ai编程·ai写作
心运软件3 小时前
Python实战:中国大学排行榜数据采集与可视化大屏
后端·python