494|0

10

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【得捷电子Follow me第2期】+基于CircuitPython的任务总结 【修改调整版】 [复制链接]

  本帖最后由 手下败酱 于 2023-12-13 11:20 编辑

//内容一:3-5分钟短视频//

上传视频:【得捷电子Follow me第2期】任务项目简-【得捷电子Follow me第2期】任务项目简介-EEWORLD大学堂

//内容二: 任务/项目总结报告//

项目介绍 

使用 Adafruit ESP32-S3 TFT Feather 这块MINI的开发板上的资源和一些模块在基于CircuitPython来实现以下几个项目任务的功能:

    1、任务1:控制屏幕显示中文(必做任务)

完成屏幕的控制,并且能显示中文

    2、任务2:网络功能使用(必做任务)

完成网络功能的使用,能够创建热点和连接到WiFi

    3、任务3:控制WS2812B(必做任务)

使用按键控制板载Neopixel LED的显示和颜色切换

    4、任务4:日历&时钟

完成一个可通过互联网更新的万年历时钟,并显示当地的天气信息

各任务功能对应的主要代码片段及说明&&各任务功能展示及说明

 

任务1:控制屏幕显示中文

 效果图

任务功能对应的主要代码片段及说明

准备工作:  Adafruit ESP32-S3 TFT Feather  板子  拿到板子之后把下载到的包(adafruit-circuitpython-adafruit_feather_esp32s3_tft-en_US-8.2.6.uf2)拖到电脑显示的U盘里面

 

还需要有几个工具,因为要显示的中文字,在库里面没有哦,所以需要自己生成或者使用别人整理好的字库文件,当然使用自己喜欢的字体是多么美好的一件事情啦。  FontSmaller_2.0  FontSmaller 字体文件子集化工具   

 u8g2_fontmaker   

链接已隐藏,如需查看请登录或者注册

这两个就是我生成bdf的字库的工具了,使用方法也非常简单

在自己电脑路径找一下自己喜欢的字体 C:\Windows\Fonts  打开FontSmaller_2.0  直接选中喜欢的字体,再出入自己需要显示的

  点击  OK 选择生成路径,这样字库就好了

 

再用u8g2_fontmaker转bdf一下就好了  具体用法去看一下reade me  就知道了 其实就是修改这个文件就行了,对了别忘记把刚刚转的字体文件放进 font 文件  

  

 

最后把生成的bdf文件拖进自己放字体的文件夹  听说把bdf转成pdf 加载速度会更快些 网站我也丢这里了

BDFtopCF字体转换器 (adafruit.github.io)

   以下为code.py 中的源代码说明

这段主要是导入相关的模块有板子自带的,也有存放在板子U盘中

#导入自带模块
import board
import displayio
#导入显示图片、显示位图字体模块等其他的
import adafruit_imageload
from adafruit_bitmap_font import bitmap_font

from adafruit_display_text.scrolling_label import ScrollingLabel

from adafruit_display_text import label
from adafruit_st7789 import ST7789

一些TFT屏幕的初始化,还有一些定义

# 使用固件自带的屏幕设备,不需要另行初始化屏幕参数
display = board.DISPLAY

# 创建本例程里的唯一图像组
group = displayio.Group()

# 加载字体并定义字体颜色为黑色
font = bitmap_font.load_font("/font/Jay_Chou-16.bdf")
nun_font = bitmap_font.load_font("/font/UPO-48.bdf")
color = 0xFFFFFF

    这段主要是对label的处理,先把显示的内容存放,再调用label函数  第一个函数是字体  第二个是显示的文本  第三个是显示的颜色  第四个是显示的背景颜色,最后一个是最大宽度,在设置一下ScrollingLabel函数实现滚动   最后显示图像数组,最后在主循环中循环滚动

############################显示##########################################
date = label.Label(font, text="       晴天 \n  – 周杰伦 (Jay Chou)", color=color)
date.x = 10
date.y = 10
group.append(date)

text1 = "\n 故事的小黄花\n 从出生那年就飘着\n 童年的荡秋千\n 随记忆一直晃到现在\n Re So So Si Do Si La\n So La Si Si Si Si La Si La So\n 吹着前奏望着天空\n 我想起花瓣试着掉落\n "
text_area = label.Label(font, text=text1, color=0x0000FF, background_color=0xFFAA00,max_characters=20)
#max_characters 显示的长度  animate_time 滚动的速度
text_area =ScrollingLabel(font,text=text1, max_characters=80, animate_time=0.26)

text_area.x = 10
text_area.y = 68
group.append(text_area)
###############################################################################
# 显示修改后的图像组
display.show(group)

#循环
while True:
        text_area.update()

这里是整个工程的文件

 任务1_中文显示.rar 

这是效果是视频

中文显示

 

任务2:网络功能使用(必做任务)

   效果图

:上图最上面显示的IP地址是已连接到WIFI,给分配的IP   最下面打印的那两行是创建的热点,WIFI名称以及WIFI密码 手机可以搜索到

 

  任务功能对应的主要代码片段及说明

首先是创建热点,这也非常简单,导入 import wifi 这个库

然后再调用 start_ap 这个函数,填入你的热点名称和密码 即可

也可以把创建的name 、password以及IP add 打印到屏幕上去,这里我只把  name 、password显示出来了,以下是全部代码

import os
import time
import ssl
import wifi
import socketpool
import microcontroller
import adafruit_requests

wifi.radio.start_ap("adafruit_wifi", "12345678")
print(f"NtworkName: adafruit_wifi")
print(f"Password: 12345678")

while True:
    pass

连接WIFI  配置下面这个文件就可以了

 

这是源码

任务2_创建WIFI_连接WIFI.rar (94.63 KB, 下载次数: 0)

 

任务3控制WS2812B(必做任务)

大概思路:

    先处理LED引脚的定义和LED 驱动 

    再去处理按键的一些定义和按键处理逻辑,还有屏幕的初始化

    最后在主循环中一直循环判断哪一个按键按下

    再去执行LED和TFT的效果

 

任务功能对应的主要代码片段及说明

    关于导入的相关库

# 导入board内置库
import board
# 导入neopixel内置库
import neopixel
import digitalio,terminalio,displayio
# 导入time内置库
import time
import key

from adafruit_display_text import label
# 从digitalio内置库导入DigitalInOut, Direction, Pull
from digitalio import DigitalInOut, Direction, Pull
# 从adafruit_led_animation.color库导入五种颜色定义
from adafruit_led_animation.color import  JADE,BLACK, ORANGE, GOLD, OLD_LACE

先去处理关于LED相关的引脚以及LED的驱动,这里我使用了两个引脚来驱动 WS2812 

#关于LED的定义**************************************************************************
led_io = digitalio.DigitalInOut(board.NEOPIXEL_POWER)
led_io.direction = digitalio.Direction.OUTPUT
led_io.value = True

pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)
# 亮度
pixel.brightness = 0.1

pixe2 = neopixel.NeoPixel(board.A0, 16)
# 亮度
pixe2.brightness = 0.1

这里就是我单独写的一个按键处理的文件。定义了5个按键都是独立按键

 # 初始化btn按钮对象
btn = DigitalInOut(board.BOOT0)
# 设置btn引脚为输入
btn.direction = Direction.INPUT
 # 设置btn引脚为上拉
btn.pull = Pull.UP
......
......
btn4 = DigitalInOut(board.A4)
# 设置btn1引脚为输入
btn4.direction = Direction.INPUT
# 设置btn引脚为上拉
btn4.pull = Pull.UP

def key():
    time.sleep(0.1) # sleep for debounce   
    if  btn.value==0:
        time.sleep(0.1) # sleep for debounce   
        if  btn.value==0:
            return 1
    elif btn1.value==0:
        return 2
    elif  btn2.value==0:
        return 3
    elif  btn3.value==0:
        return 4
    elif  btn4.value==0:
        return 5
    else  : 
          return 0

配置屏幕的参数,这里直接调用封装号的配置处理

#屏幕的基础配置
display= board.DISPLAY

下面就是主循环了:

# 进入while循环
while True:
#进入循环先一直判断按键按下
    key_value=key.key()

    # 判断按键是否按下
    if  key_value!=0:
        # 若按键按下,则根据余数指定led颜色
        time.sleep(0.1) #这里就是按键消抖
        print(key_value)  #打印哪一个按键按下
        if key_value == 1:  #按键1按下了,执行里面的程序
            pixel.fill((JADE))# 玉色
            pixe2.fill((JADE))# 玉色
            text ="JADE"
            text_area =label.Label(terminalio.FONT,text=text, color=JADE,x=10,y=30)
            text_group=displayio.Group(scale=2 ,x=0,y=0)
            text_group.append(text_area)
            display.show(text_group)
        elif  key_value == 2:
            pixel.fill((ORANGE))# 橙色
            pixe2.fill((ORANGE))# 橙色
            text ="ORANGE"
            text_area =label.Label(terminalio.FONT,text=text, color=ORANGE,x=10,y=30)
            text_group=displayio.Group(scale=2 ,x=0,y=0)
            text_group.append(text_area)
            display.show(text_group)
        elif  key_value == 3:
            pixel.fill((GOLD))# 金色
            pixe2.fill((GOLD))# 金色
            text ="GOLD"
            text_area =label.Label(terminalio.FONT,text=text, color=GOLD,x=10,y=30)
            text_group=displayio.Group(scale=2 ,x=0,y=0)
            text_group.append(text_area)
            display.show(text_group)
        elif  key_value == 4:
            pixel.fill((OLD_LACE))# 
            pixe2.fill((OLD_LACE))# 
            text ="OLD_LACE"
            text_area =label.Label(terminalio.FONT,text=text, color=OLD_LACE,x=10,y=30)
            text_group=displayio.Group(scale=2 ,x=0,y=0)
            text_group.append(text_area)
            display.show(text_group)
        elif  key_value == 5:
            pixel.fill((BLACK))# 黑色
            pixe2.fill((BLACK))# 黑色
            text ="BLACK"
            text_area =label.Label(terminalio.FONT,text=text, color=BLACK,x=10,y=30)
            text_group=displayio.Group(scale=2 ,x=0,y=0)
            text_group.append(text_area)
            display.show(text_group)

    else:
        # 空
        pass
VID_20231019_175535

这是源代码文件: 任务3_WS2812.rar (94.73 KB, 下载次数: 0)

任务4:日历&时钟——完成一个可通过互联网更新的万年历时钟,并显示当地的天气信息

完成一个可通过互联网更新的万年历时钟,并显示当地的天气信息

     效果图

首先把界面给弄好,文字显示位置,以及图片大小,文字大小都需要考虑,这些我都在 Pixso 上处理的

主要思路:

           先是处理界面根据在Pixso 上处理的图片,显示在TFT屏幕上面

# 使用固件自带的屏幕设备,不需要另行初始化屏幕参数
display = board.DISPLAY
############################图片显示##########################################
# 创建本例程里的唯一图像组
group = displayio.Group()

# 加载图片
image, palette = adafruit_imageload.load("/PIC/beijing.png")
# 是否开启透明
palette.make_transparent(1)

# 创建图片布局
grid = displayio.TileGrid(image, pixel_shader=palette)

# 将图片布局添加到图像组,由于是第一个添加的,默认是最下层
group.append(grid)

# 显示当前图像组
display.show(group)
###############################################################################
# 加载字体并定义字体颜色为黑色
font = bitmap_font.load_font("/font/MYout-24.bdf")
nun_font = bitmap_font.load_font("/font/UPO-48.bdf")
color = 0x000000

date = label.Label(font, text="10月 31日", color=color)
date.x = 25
date.y = 18
group.append(date)

# 初始化星期标签并设置x,y轴绘图坐标,然后将标签添加到图像组
week = label.Label(font, text="周六", color=color)
week.x = 179
week.y = 8
group.append(week)

# 初始化时间标签并设置x,y轴绘图坐标,然后将标签添加到图像组
time = label.Label(nun_font, text="22:59", color=0xF2C3BD)
# time.x = 20
# time.y = 60

time.x = 29
time.y = 65
group.append(time)

# 初始化天气标签并设置x,y轴绘图坐标,然后将标签添加到图像组
tempzh = label.Label(font, text="23°~34° 晴", color=color)
tempzh.x = 25
tempzh.y = 101
group.append(tempzh)

   再处理网络时间更新,调用RTC函数来更新时间 , 再去处理高德API接收的值,这里分别接收了 温度和天气信息

pool = socketpool.SocketPool(wifi.radio)
ntp = adafruit_ntp.NTP(pool, tz_offset=8, server="ntp.aliyun.com")

# 使用ntp时间更新系统时间
rtc.RTC().datetime = ntp.datetime

# 初始化requests对象
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())

def get_weather():
    # 设置城市id
    city = "410702"
    # 这个函数使用的是高德API,使用该API需要先去注册相关账户,申请key。
    key = "7121e4b427fa6f27704655b62db83d61"
    # 拼接天气链接url
    getweather_url = "https://restapi.amap.com/v3/weather/weatherInfo?city=" + city + "&key=" + key
    # 获取天气json数据
    response = requests.get(getweather_url)
    json_resp = response.json()
    # 关闭连接
    response.close()
    # 解析json数据,并返回温度和天气信息
    for da in json_resp["lives"]:
        #print(da["temperature"])
        return da["temperature"], da["weather"]
# 先创建一个status变量,用来在设备启动时获取天气信息
status = "boot"

  接下来就是不断在循环里面获取时间,以及天气信息

# 主循环
while True:

    # 每秒获取一次本地RTC时间
    t = time.localtime()
    # 首次启动或者本地RTC时间的分钟属性为0时,更新日期标签和天气标签
    if (status == "boot" or t.tm_sec == 0):
        # 更新日期标签
        date.text = "%d月%d日" % (t.tm_mon, t.tm_mday)
        week.text = get_wday(t.tm_wday)
        # 获取天气信息
        str_t, str_tz =  get_weather()
        # 更新温度标签
        temp.text = "%s°" % (str_t)
        # 更新天气标签
        tempzh.text = str_tz
        status = "updated"
        print(ssid)
        print(str(wifi.radio.ipv4_address) )
        # 每隔1秒 更新一次时钟标签,用于动态显示
    if (t.tm_sec % 2 == 0):
        timel_s.text = ":%02d" % ( t.tm_sec)
    else:
        timel.text = "%02d:%02d" % ( t.tm_hour, t.tm_min)
        timel_s.text = ":%02d" % ( t.tm_sec)

    key_value=key.key()
    # 判断按键是否按下
    if  key_value!=0:
        # 若按键按下,则对led_color求余数,根据余数指定led颜色
        time.sleep(0.1)
        print(key_value)
        if key_value == 1:
            pixel.fill((JADE))# 玉色
            pixe2.fill((JADE))# 玉色
            timel_s.color = JADE
            timel.color = JADE
        elif  key_value == 2:
            pixel.fill((ORANGE))# 橙色
            pixe2.fill((ORANGE))# 橙色
            timel_s.color = ORANGE
            timel.color = ORANGE
        elif  key_value == 3:
            pixel.fill((GOLD))# 金色
            pixe2.fill((GOLD))# 金色
            timel_s.color = GOLD
            timel.color = GOLD
        elif  key_value == 4:
            pixel.fill((PINK))# 
            pixe2.fill((PINK))# 
            timel_s.color = PINK
            timel.color = PINK
        elif  key_value == 5:
            pixel.fill((BLACK))# 黑色
            pixe2.fill((BLACK))# 黑色
            timel_s.color = BLACK
            timel.color = BLACK

    else:
        pass# 空
    # 刷新屏幕
    display.show(group)

下面是效果视频:
VID_20231019_175404

该工程文件: 任务4_天气时钟最终版.rar (124.3 KB, 下载次数: 0)

其他:LTR—329光传感器模块&MCP9808温度传感器

温度传感器(MCP9808)

        这款 I2C 数字温度传感器是我们见过的准确度更高的传感器之一,在传感器的 -40°C 至 +125°C 范围内的典型精度为 ±0.25°C,精度为 +0.0625°C。 它们适用于任何使用标准 i2c 的微控制器。有 3 个地址引脚,因此您最多可以将 8 个地址引脚连接到单个 I2C 总线,而不会发生地址冲突。最重要的是,宽电压范围使2.7V至5.5V电压可用!

引脚说明:

  • VIN (仅接头版本的 VDD) - 这是正电源和逻辑电平引脚。它可以是2.7-5.5VDC,因此适合与3或5V逻辑一起使用。电源 VIN (VDD),具有您计划在 i2c 线路上使用的任何逻辑电平。
  • GND - 这是接地电源和逻辑参考引脚。
  • SCL - 这是 I2C 时钟引脚。板上已经有一个 10K 上拉,因此请将其直接连接到微控制器上的 i2c 主时钟引脚
  • SDA - 这是 I2C 数据引脚。板上已经有一个 10K 上拉,因此请将其直接连接到微控制器上的 i2c 主数据引脚
  • Alert - 这是来自MCP9808的中断/警报引脚。芯片具有一定的功能,可以在芯片温度高于或低于设定量时“提醒”您。可以触发此输出以告知你。它是集电极开路,因此如果要从该引脚读取信号,则需要使用上拉电阻。
  • A0(以及 A1 和 A2)- 这些是地址选择引脚。由于在 i2c 总线上只能有一个具有给定地址的设备,因此如果要在共享 i2c 总线上放置多个MCP9808,则必须有一种方法来调整地址。A0/A1/A2引脚设置i2c地址的底部三位。电路板上有下拉电阻,因此将它们连接到VDD以将位设置为“1”。它们在通电时读取,因此解除电源并重新通电以重置地址

           默认地址0x18,地址可以通过将 A0/A1/A2 “添加”到0x18
          A0 设置值为 1 的最低位,A1 设置值为 2 的中间位,A2 设置值为 4 的高位。最终地址是 0x18 + A2 + A1 + A0
          因此,例如,如果 A2 与 VDD 绑定,A0 与 VDD 绑定,则地址为 0x18 + 4 + 1 = 0x1D。
          如果只有 A0 绑定到 VDD,则地址为 0x18 + 1 = 0x19
          如果只有 A1 绑定到 VDD,则地址为 0x18 + 2 = 0x1A
          如果只有 A2 绑定到 VDD,则地址为 0x18 + 4 = 0x1C

接线方式:

那接下来就是代码了

import time               #导入延时库
import board              #导入板子的资源库
import adafruit_mcp9808   #导入模块的库
i2c = board.I2C()                   # 使用板载的SDA和SCL
mcp = adafruit_mcp9808.MCP9808(i2c)  # 使用默认地址进行初始化:

while True:
    tempC = mcp.temperature
    tempF = tempC * 9 / 5 + 32   #转换成  F
    print("Temperature: {} C {} F ".format(tempC, tempF))
    time.sleep(4)

那如果把它添加到我的天气时钟上面呢:由于我往上面哈气,温度飙到了30多°

光传感器(LTR-329)
LTR-329 光传感器是一款简单且流行的低成本 I2C 数字光传感器,易于集成到您的项目中,以实现可靠和广泛的光测量。

 

 

LTR-329ALS-01 规格:

  • I2C 接口,最高快速模式 @ 400kbit/s,地址0x29(无法更改)
  • 超小型芯片LED封装
  • 内置温度补偿电路
  • 待机模式下的低有功功耗
  • 工作温度范围为 -30 C 至 +70 C
  • 符合 RoHS 和无卤素标准
  • 接近人眼光谱响应的光传感器
  • 对红外/紫外线光源的抗扰度
  • 自动抑制 50 / 60 Hz 灯光闪烁
  • 6 种动态范围,从 0.01 勒克斯到 64k 勒克斯
  • 16 位有效分辨率

     尺寸:25.4 毫米 x 17.7 毫米 x 4.6 毫米 / 1.0“ x 0.7” x 0.2”

引脚说明

  • VIN - 这是电源引脚。要为电路板供电,请为其提供与微控制器逻辑电平相同的功率 - 使用5V。
  • 3V - 这是稳压器的 3.3V 输出,如果您愿意,您可以从中获取高达 100mA 的电流。
  • GND - GND
  • SCL - I2C 时钟引脚,连接到微控制器 I2C 时钟线。该引脚经过电平转换,因此可以使用 3-5V 逻辑,并且该引脚上有一个 10K 上拉。
  • SDA - I2C 数据引脚,连接到您的微控制器 I2C 数据线。该引脚经过电平转换,因此可以使用 3-5V 逻辑,并且该引脚上有一个 10K 上拉。

它的使用方法也非常简单

调用LTR329的库,再显示到TFT屏上

import time
import board
from adafruit_ltr329_ltr303 import LTR329  #导入外部库
import displayio
# 导入外部库adafruit_display_text里的lable,用于显示标签
from adafruit_display_text import label
# 导入外部库adafruit_bitmap_font里的lable
from adafruit_bitmap_font import bitmap_font
i2c = board.I2C()  # 使用板载的SDA和SCL
time.sleep(0.1)  # 传感器需要100毫秒才能“启动”上电
ltr329 = LTR329(i2c)

#使用封装好的TFT驱动
display = board.DISPLAY  
#创建显示组 
group = displayio.Group()
#加载字体 
font = bitmap_font.load_font("/font/MYout-24.bdf")

#用于显示 光强度的参数
Visible_ = label.Label(font, text="00", color=0xFF0707)
Visible_.x = 5
Visible_.y = 18
group.append(Visible_)

#用于显示 红外线的参数
Infrared_ = label.Label(font, text="00", color=0xFF07C5)
Infrared_.x = 5
Infrared_.y = 68
group.append(Infrared_)

while True:
    Visible= ltr329.visible_plus_ir_light
    Infrared=ltr329.ir_light
    Visible_.text="Visible:  %d" %(Visible)
    Infrared_.text="Infrared:  %d" %(Infrared)

    print("Visible + IR:", ltr329.visible_plus_ir_light)
    print("Infrared    :", ltr329.ir_light)
    print()
    display.show(group)
    time.sleep(0.5)  # sleep0.5 S

对本活动的心得体会

                非常荣幸参见本次活动,也非常感谢得捷对这次活动的支持,通过这次任务的学习,也让我从一个Python小白,成功了入了门,通过实践的效果,也有了更加深刻的印象,我非常认为这样的活动非常不错,最起码,自己也是亲手操作了,期间我自己也遇到 了不少问题,通过观看,直播教学,还有大佬们的相关教程,也解决了不少问题,也可以说顺利结束了本次活动,这次是第二期活动,现在我已经期待着第三期活动了,最后还是要感谢得捷平台,还有一些大佬的教程

 

//内容三:可编译下载的代码//

任务源文件:https://download.eeworld.com.cn/detail/%E6%89%8B%E4%B8%8B%E8%B4%A5%E9%85%B1/629595#related

 

点赞 关注
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表