580|2

2

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【得捷电子Follow me第2期】任务1-4提交 [复制链接]

 

先放最终图片:

   

 

第一部分 视频

https://training.eeworld.com.cn/video/38561

 


 

第二部分 总结报告

任务1 汉字显示

使用了文泉驿点阵宋体12px,保证屏幕能容纳更多的信息。ttf字体先导入FontForge,再以常用汉字和ASCII字符在 bdftopcf font converter (gitee.io) 生成一个python脚本,在FontForge中直接执行,就能筛选出需要保留的字符,删去其余字符并保存为pcf格式后,字体文件尽占用309KB

代码:

text_group = displayio.Group(scale=1, x=0, y=0)
text_chinese_test = label.Label(
     font_cn, text="汉字显示", color=0xFFFFFF, x=0, y=1 * LINE_HEIGHT
)

​

 

任务2 联网

直接使用CircuitPython的wifi库连接AP并获取IP地址,将其显示在OLED屏幕上

代码:

​
wifi.radio.connect(WIFI_SSID, WIFI_PASSWORD)
wifi_ip = wifi.radio.ipv4_address

......

text_wifi_ssid = label.Label(
    font_cn, text=f"SSID: {WIFI_SSID}", color=0xFFFFFF, x=0, y=2 * LINE_HEIGHT
)
text_wifi_ip = label.Label(
    font_cn, text=f"IP: {wifi_ip}", color=0xFFFFFF, x=0, y=3 * LINE_HEIGHT
)

​

 

任务3 控制板载Neopixel LED

使用adafruit包内的neopixel库,初始化灯珠,在主循环内轮询检测按键触发,触发案件后将灯珠颜色进行红-绿-蓝循环,并将当前灯珠状态显示在屏幕上

代码:

neopixel = neopixel.NeoPixel(board.NEOPIXEL, 1)
neopixel.brightness = 0.1

button = digitalio.DigitalInOut(board.BUTTON)
button.direction = digitalio.Direction.INPUT
button.pull = digitalio.Pull.UP

......

if button.value == False:
    neopixel_status += 1
    neopixel_status = neopixel_status % 3
    neopixel.fill(
        (
            0xFF << ((neopixel_status) * 8) & 0xFF,
            0xFF << ((neopixel_status) * 8) >> 8 & 0xFF,
            0xFF << ((neopixel_status) * 8) >> 16 & 0xFF,
        )
    )

text_neopixel_status = label.Label(
    font_cn,
    text=f"Color: { {0: 'Red', 1: 'Green', 2: 'Blue'}.get(neopixel_status, 'Unknown') }",
    color=0xFFFFFF,
    x=0,
    y=4 * LINE_HEIGHT,
)

 

自选任务:天气时钟

因为和风天气API强制使用gzip压缩,使用了高德天气API以省去一些处理过程。使用adafruit_request库发送https请求,并解析校验返回的json数据。并根据设定的时间间隔刷新数据

时间方面,使用ntp对时,并将时间存储在由rtc库实现的内置rtc中,在主循环内轮询更新时间

 

代码:

def get_weather(data) -> bool:
    requests = adafruit_requests.Session(
        socketpool.SocketPool(wifi.radio), ssl.create_default_context()
    )
    data.update(
        requests.get(
            "https://restapi.amap.com/v3/weather/weatherInfo?key=%s&city=%s"
            % (AMAP_WEATHER_KEY, AMAP_CITY_CODE)
        ).json()
    )
    # print(data)
    if not data["infocode"] or data["infocode"] != "10000":
        return False
    data.update(data["lives"][0])

    return True

rtc.RTC().datetime = adafruit_ntp.NTP(
    socketpool.SocketPool(wifi.radio),
    tz_offset=8,
    server="ntp.aliyun.com",
    socket_timeout=20,
).datetime

text_datetime = label.Label(
    font_cn, 
    text="%04d-%02d-%02d %02d:%02d:%02d"
    % (
        time.localtime().tm_year,
        time.localtime().tm_mon,
        time.localtime().tm_mday,
        time.localtime().tm_hour,
        time.localtime().tm_min,
        time.localtime().tm_sec,
    ),
    color=0xFFFFFF,
    x=0,
    y=5 * LINE_HEIGHT,
)
text_weekday = label.Label(
    font_cn,
    text=f"{ {0: '周一', 1: '周二', 2: '周三', 3: '周四', 4: '周五', 5: '周六', 6: '周日'}.get(time.localtime().tm_wday) }",
    color=0xFFFFFF,
    x=0,
    y=6 * LINE_HEIGHT,
)

if weather_last_update_time < time.monotonic() - WEATHER_INTERVAL:
    weather_last_update_time = time.monotonic()
    get_weather(weather_data)

text_weather = label.Label(
    font_cn,
    text=f"{weather_data['weather']} 气温{weather_data['temperature']}度",
    color=0xFFFFFF,
    x=0,
    y=7 * LINE_HEIGHT,
)

 

最后,整合了以上四个任务的完整代码如下:

import board
import displayio
import time
import wifi
import neopixel
import digitalio
import rtc
import socketpool
import ssl
import adafruit_requests
import adafruit_ntp
from adafruit_display_text import label
from adafruit_bitmap_font import bitmap_font

WIFI_SSID = ""
WIFI_PASSWORD = ""
LINE_HEIGHT = 12
AMAP_WEATHER_KEY = ""
AMAP_CITY_CODE = ""
WEATHER_INTERVAL = 300

display = board.DISPLAY

neopixel = neopixel.NeoPixel(board.NEOPIXEL, 1)
neopixel.brightness = 0.1

button = digitalio.DigitalInOut(board.BUTTON)
button.direction = digitalio.Direction.INPUT
button.pull = digitalio.Pull.UP

font_cn_file = "fonts/WenQuanYiBitmapSongmedium-12.pcf"
font_cn = bitmap_font.load_font(font_cn_file)


def get_weather(data) -> bool:
    requests = adafruit_requests.Session(
        socketpool.SocketPool(wifi.radio), ssl.create_default_context()
    )
    data.update(
        requests.get(
            "https://restapi.amap.com/v3/weather/weatherInfo?key=%s&city=%s"
            % (AMAP_WEATHER_KEY, AMAP_CITY_CODE)
        ).json()
    )
    # print(data)
    if not data["infocode"] or data["infocode"] != "10000":
        return False
    data.update(data["lives"][0])

    return True


def main():
    neopixel_status = 4
    weather_data = {}
    weather_last_update_time = 0

    wifi.radio.connect(WIFI_SSID, WIFI_PASSWORD)
    wifi_ip = wifi.radio.ipv4_address

    rtc.RTC().datetime = adafruit_ntp.NTP(
        socketpool.SocketPool(wifi.radio),
        tz_offset=8,
        server="ntp.aliyun.com",
        socket_timeout=20,
    ).datetime

    while True:
        text_group = displayio.Group(scale=1, x=0, y=0)
        text_chinese_test = label.Label(
            font_cn, text="汉字显示", color=0xFFFFFF, x=0, y=1 * LINE_HEIGHT
        )
        text_wifi_ssid = label.Label(
            font_cn, text=f"SSID: {WIFI_SSID}", color=0xFFFFFF, x=0, y=2 * LINE_HEIGHT
        )
        text_wifi_ip = label.Label(
            font_cn, text=f"IP: {wifi_ip}", color=0xFFFFFF, x=0, y=3 * LINE_HEIGHT
        )

        if button.value == False:
            neopixel_status += 1
            neopixel_status = neopixel_status % 3
            neopixel.fill(
                (
                    0xFF << ((neopixel_status) * 8) & 0xFF,
                    0xFF << ((neopixel_status) * 8) >> 8 & 0xFF,
                    0xFF << ((neopixel_status) * 8) >> 16 & 0xFF,
                )
            )

        text_neopixel_status = label.Label(
            font_cn,
            text=f"Color: { {0: 'Red', 1: 'Green', 2: 'Blue'}.get(neopixel_status, 'Unknown') }",
            color=0xFFFFFF,
            x=0,
            y=4 * LINE_HEIGHT,
        )

        text_datetime = label.Label(
            font_cn,
            text="%04d-%02d-%02d %02d:%02d:%02d"
            % (
                time.localtime().tm_year,
                time.localtime().tm_mon,
                time.localtime().tm_mday,
                time.localtime().tm_hour,
                time.localtime().tm_min,
                time.localtime().tm_sec,
            ),
            color=0xFFFFFF,
            x=0,
            y=5 * LINE_HEIGHT,
        )
        text_weekday = label.Label(
            font_cn,
            text=f"{ {0: '周一', 1: '周二', 2: '周三', 3: '周四', 4: '周五', 5: '周六', 6: '周日'}.get(time.localtime().tm_wday) }",
            color=0xFFFFFF,
            x=0,
            y=6 * LINE_HEIGHT,
        )

        if weather_last_update_time < time.monotonic() - WEATHER_INTERVAL:
            weather_last_update_time = time.monotonic()
            get_weather(weather_data)

        text_weather = label.Label(
            font_cn,
            text=f"{weather_data['weather']} 气温{weather_data['temperature']}度",
            color=0xFFFFFF,
            x=0,
            y=7 * LINE_HEIGHT,
        )

        text_group.append(text_chinese_test)
        text_group.append(text_wifi_ssid)
        text_group.append(text_wifi_ip)
        text_group.append(text_neopixel_status)
        text_group.append(text_datetime)
        text_group.append(text_weekday)
        text_group.append(text_weather)

        display.show(text_group)
        time.sleep(1)


if __name__ == "__main__":
    main()

 

 


 

第三部分 代码汇总

 

代码压缩包在此处:https://download.eeworld.com.cn/detail/eew_zfsM67/629919

 

心得体验

 

Adafruit的板子确实设计的很棒,在一些细节的处理上做的很到位,果然贵有贵的道理。CircuitPython这个开发模式确实简单且易于上手,对于刚接触嵌入式开发的新人来说应该是一个很好的入门途径。与Arduino框架相比,Adafruit移植的扩展库包高度封装,风格较为统一,也涵盖了绝大部分常用的外设。Python的编写和独特的程序写入方式以及REPL对新手来说也都是很不错的简化。


最后,仍然感谢Digikey举办本次活动,为广大开发者送上免费的开发板以及配件

 

最新回复

这个帖子真是太棒了!内容丰富,观点鲜明,让人受益匪浅。感谢楼主分享   详情 回复 发表于 2023-11-27 07:42
点赞 关注
 
 

回复
举报

6593

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

将时间存储在由rtc库实现的内置rtc中,在主循环内轮询更新时间,这个方法好

 
 
 

回复

735

帖子

5

TA的资源

纯净的硅(高级)

板凳
 

这个帖子真是太棒了!内容丰富,观点鲜明,让人受益匪浅。感谢楼主分享

 
 
 

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

查找数据手册?

EEWorld Datasheet 技术支持

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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

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

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

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