慕容雪花

  • 2023-11-11
  • 回复了主题帖: 【得捷电子Follow me第3期】基于ESP32-C3的阅读光线提示器设计

    EPTmachine 发表于 2023-11-11 09:58 太卷了吧,今天我才把针脚焊上
    我是昨天上午焊的,

  • 回复了主题帖: 【得捷电子Follow me第3期】基于ESP32-C3的阅读光线提示器设计

    lugl4313820 发表于 2023-11-11 10:14 ssd1306,你的库可以下载到吗,我是试了N次都不行。
    来点魔法

  • 发表了主题帖: 【得捷电子Follow me第3期】基于ESP32-C3的阅读光线提示器设计

    本帖最后由 慕容雪花 于 2023-11-11 08:36 编辑 [localvideo]49021c1c4fbdb8a45c00c491e612b0ef[/localvideo]   核心板卡介绍: 特性 • 强大的 CPU:ESP32-C3,32 位 RISC-V 单核处理器,运行频率高达 160 MHz • 完整的WiFi子系统:符合IEEE 802.11b/g/n协议,支持Station模式、SoftAP模式、SoftAP+Station模式、混杂模式 • 蓝牙 LE 子系统:支持蓝牙 5 和蓝牙网状网络的功能 • 超低功耗:深度睡眠功耗约43μA • 更好的射频性能:可连接外部射频天线 • 电池充电芯片:支持锂电池充放电管理 • 丰富的片上资源:400KB SRAM、4MB板载闪存 • 超小尺寸:小至拇指 (20x17.5mm) XIAO 系列经典外形,适用于可穿戴设备和小型项目 • 可靠的安全功能:支持 AES-128/256、哈希、RSA、HMAC、数字签名和安全启动的加密硬件加速器 • 丰富的接口:1xI2C、1xSPI、2xUART、11xGPIO(PWM)、4xADC、1xJTAG • 单面元件布局、支持表面贴装设计   官方维基:https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/   引脚图如下:     扩展板硬件资源: https://wiki.seeedstudio.com/Seeeduino-XIAO-Expansion-Board/ https://www.seeedstudio.com/Seeeduino-XIAO-Expansion-board-p-4746.html?queryID=bd1aef586d96a08ad9a2e813c1931aa7&objectID=4746&indexName=bazaar_retailer_           任务1:使用MicroPython系统(必做任务) 电脑上的IDE使用的是THONNY。下面介绍如何给C3刷写最新的MICROPYTHON固件是:ESP32_GENERIC_C3-20231005-v1.21.0.bin 1. 去Micropython官网下载C3最新固件:https://micropython.org/download/ESP32_GENERIC_C3/   2. 检查电脑上Python的版本是否为3.4以上,因为接下来要用到pip安装刷新工具。     3. 安装esptool刷新工具 pip install esptool -i https://pypi.tuna.tsinghua.edu.cn/simple some-package 确认串口号是否安装正确: esptool.py --h      4. 开发板连接电脑,确认串口号   5.清空开发板FLASH esptool.py --chip esp32c3 --port COM23 erase_flash     6.给C3刷入最新的固件 esptool.py --chip esp32c3 --port COM23 --baud 460800 write_flash -z 0x0 ESP32_GENERIC_C3-20231005-v1.21.0.bin     7. 重新插拔USB,打开THONNY软件,右下角选择ESP32   如上图所示,最新的Micropython固件已经刷入成功,并且可以进行正常的Python运算!   任务2:驱动扩展板上的OLED屏幕(必做任务) 1. 在THONNY IDE里面下载SSD1306的驱动   2. 添加相关的初始化代码 from machine import Pin, I2C from ssd1306 import SSD1306_I2C i2c=I2C(0,sda=Pin(6), scl=Pin(7), freq=400000) oled = SSD1306_I2C(128, 64, i2c) oled.text("WELCOME!", 0, 0) oled.text("This is EEWORLD", 0, 16) oled.text("FOLLOW ME 3", 0, 32) oled.text("JOIN US", 0, 48) oled.show() 注意事项: ! Before using it, it is required for me to state the software/firmware I'm using here is designed for the ESP32C3 chip. Hence when you are trying to use pin, make sure the General Purpose Input/Output instead of the pin on the board. For example, when you are trying to use the pin in the first row on the left. Make sure it is GPIO2 instead of A0 or D0. 3. 实物效果: 4. 代码:   任务3:控制蜂鸣器播放音乐(必做任务) 扩展板上A3引脚连接了一个无源蜂鸣器。     通过PWM的不同占空比和频率即可控制蜂鸣器发出不同的声音,甚至播放音乐! # Buzzer settings buzzer_pin = machine.Pin(5, machine.Pin.OUT) buzzer = machine.PWM(buzzer_pin) buzzer.freq(1047) 下面以比较简单的小星星乐谱为例来用C3扩展板上的蜂鸣器播放音乐。   下面是C调音符与频率对照关系:   # 定义音调频率 tones = {'1': 262, '2': 294, '3': 330, '4': 349, '5': 392, '6': 440, '7': 494, '-': 0} # 定义小星星旋律 melody = "1155665-4433221-5544332-5544332-1155665-4433221" while True: # Play the song for tone in melody: freq = tones[tone] if freq: # 调整PWM的频率,使其发出指定的音调 buzzer.duty(1000) # Set duty cycle for sound buzzer.freq(freq) # Set frequency of the note else: buzzer.duty(0) # 空拍时一样不上电 # 停顿一下 (四四拍每秒两个音,每个音节中间稍微停顿一下) time.sleep_ms(400) buzzer.duty(0) # 设备占空比为0,即不上电 time.sleep_ms(100)   实物展示: [localvideo]b17bf831a9361536d4172268ba2f839f[/localvideo]   代码:   任务4:连接WiFi网络(必做任务) 使用Micropython连接网络是比较简单的: def scan_and_connect(): station = network.WLAN(network.STA_IF) station.active(True) print("Scanning for WiFi networks, please wait...") for ssid, bssid, channel, RSSI, authmode, hidden in station.scan(): print("* {:s}".format(ssid)) print(" - Channel: {}".format(channel)) print(" - RSSI: {}".format(RSSI)) print(" - BSSID: {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}".format(*bssid)) print() while not station.isconnected(): print("Connecting...") station.connect(wifi_ssid, wifi_password) time.sleep(10) print("Connected!") print("My IP Address:", station.ifconfig()[0]) 连接成功后,控制台输出相应的IP地址: * TP-LINK_2804 - Channel: 6 - RSSI: -92 - BSSID: 34:96:72:c2:28:04 * Hi32003Y7A1102300133002447F41513 - Channel: 6 - RSSI: -92 - BSSID: 08:31:8b:62:7f:41 Connected! My IP Address: 192.168.0.104 接下来我会通过url访问心知天气并获取上海本地的天气信息。其中,心知天气返回的json格式的数据: url = "https://api.seniverse.com/v3/weather/now.json?key=请替换自己的KEY&location=shanghai&language=zh-Hans&unit=c" while True: # Perform HTTP GET request on a non-SSL web response = urequests.get(url) # Check if the request was successful if response.status_code == 200: # Parse the JSON response weather = ujson.loads(response.text) print(weather) # Extract the "datetime" field for New York current_weather = weather["results"][0]["now"] # Get the Temperature current_temperature = current_weather["temperature"] # Clear the OLED display oled.fill(0) # Display the New York date and time on separate lines oled.text("Shanghai Temperature:", 0, 0) oled.text(current_temperature, 0, 10) # Update the display oled.show() else: oled.text("Failed to get the weather") # Update the display oled.show() time.sleep(30) 控制台的输出结果如下: {'results': [{'location': {'name': '\u4e0a\u6d77', 'path': '\u4e0a\u6d77,\u4e0a\u6d77,\u4e2d\u56fd', 'timezone': 'Asia/Shanghai', 'timezone_offset': '+08:00', 'id': 'WTW3SJ5ZBJUY', 'country': 'CN'}, 'last_update': '2023-11-10T18:30:32+08:00', 'now': {'text': '\u591a\u4e91', 'code': '4', 'temperature': '14'}}]} 实物展示: [localvideo]48d1d511413842c63df7ee5d9f427dd9[/localvideo]   代码:      任务5:使用外部传感器(必做任务) 本次驱动温湿度传感器AHT20:       安装驱动:   核心代码: from ahtx0 import AHT20 # Oled init i2c=machine.I2C(0,sda=Pin(6), scl=Pin(7), freq=400000) oled = SSD1306_I2C(128, 64, i2c) oled.text("This is TASK5", 0, 0) oled.text("aht20", 0, 16) oled.text("Temp:", 0, 32) oled.text("Humi:", 0, 48) oled.show() #aht20 aht = AHT20(i2c) def ahtxx(): temp = aht.temperature humi = aht.relative_humidity print("\n") print(temp) print("\n") print(humi) #print("\n"); #print('{:.2f}'.format(humi)) oled.fill_rect(50,32,40,30,0) # 局部清屏 oled.text('{:.2f}'.format(temp), 50, 32) oled.text('{:.2f}'.format(humi), 50, 48) oled.show() time.sleep(1)  实物展示:   实物展示: [localvideo]ca78415d9bc9da3148a8ab0f04383b5e[/localvideo]   代码:        任务6:分任务3:开灯提醒器 监测环境光强度,如果光线太暗,通过屏幕和蜂鸣器提醒用户开灯,达到保护视力的效果。本次任务使用到了 Grove Light Sensor v1.2这是一个模拟光传感器,最大350lux对应ADC的4095 还有一个红色的led,Grove接口,非常方便使用 oled,用于显示当前lux值,如果光照亮度低于50,则表示很暗,蜂鸣器报警并且红色LED亮并且OLED屏幕输出警告:TOO DARK!       主要代码: #led led_red = machine.Pin(20, Pin.OUT) led_red.off() #adc adc = machine.ADC(Pin(2)) adc.atten(machine.ADC.ATTN_11DB) adc.width(machine.ADC.WIDTH_12BIT) #4095 # Buzzer settings buzzer_pin = machine.Pin(5, machine.Pin.OUT) buzzer = machine.PWM(buzzer_pin) buzzer.freq(1047) def lightSensor(): temp = adc.read() print("\n") print("lightsensor value: ") print(temp) lux_float = temp*350*1.0/4095; oled.fill_rect(50,32,77,30,0) # 局部清屏 oled.text('{:.2f}'.format(lux_float), 50, 32) if lux_float < 50: oled.text("Too dark!", 50, 48) buzzer.duty(512) # Turn off the sound led_red.on() else: buzzer.duty(0) # Turn off the sound led_red.off() oled.show() time.sleep(1)   实物展示: [localvideo]5b9a454cfc47cfa1d7d4b3fdfcf055a1[/localvideo]   代码:   总结: 非常开心能够参加这一期的FOLLOW ME活动,通过本次活动,我从micropython固件刷入esp32c3,到驱动OLED,联网,获取天气信息以及驱动aht20温湿度传感器,到最后做出来一个简易阅读提醒器。自己学习到了非常多的知识,也提升了自己的知识,希望follow me活动越办越好!   参考文档: 1. https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/ 2. https://wiki.seeedstudio.com/XIAO_ESP32C3_MicroPython/

  • 2023-10-22
  • 发表了主题帖: 浅谈ADI推动汽车行业发展的一些应用场景

    本帖最后由 慕容雪花 于 2023-10-22 16:16 编辑 ADI在诸多的工业应用场景提供了非常高精尖的先进产品,从智能手环里面的加速度计到哈勃望远镜上的运放和变换器,以及在高性能飞机、深空探测器、精确打击武器等应用中使用的高可靠性解决方案。   对于我所在的汽车制造行业,尤其是其中的细分领域-汽车线束制造行业,本着“立足生成,放飞思路”的宗旨,整理了自己对一些浅显理解。 汽车整车电子电器架构下的汽车电线束架构简化, 汽车电线束制造流程以及 汽车电线束总布置 汽车内的空气质量检测与噪声控制ANC   一、整车电子电器架构下的汽车电线束架构简化 整车电线束是整车系统的神经系统,重要性不言而喻,而其重量也占到了整车重量的3%~5%。而且随着ADAS以及智能座舱系统的加速更新迭代,整车电线束系统日趋复杂。因此采用新架构,使用新的总线技术来优化整车架构势在必行。   在降低整车电线束系统复杂性和重量方面,不得不提ADI推出的车用音频总线(A2B®)技术。该技术向未来的车辆信息娱乐系统提供关键支持。根据官方提供的数据,使用该技术后相关布线重量减少75%,并且可提供高保真音频,同时提高燃油效率。A2B产品系列可实现语音识别和主动降噪等多种应用。   A2B 是一种高带宽双向数字音频总线。A2B 能够在很长的距离上(节点间的距离最长达15 m,整个菊花链长度超过40 m),使用一条非屏蔽双绞线传输I2S/TDM/PDM数据和I2C控制信息以及时钟和供电信号。 A2B可用作自己内置嵌入式子网的网络,或与其他较长的距离协议结合使用的端点传输总线。时钟在单个A2B 网络中的所有节点上同步。同时在系统中的每个节点上接收麦克风和串行音频数据。【2】   二、汽车电线束制造流程 在汽车线束制造过程中,有一个需要非常耗时的环节就是电线束的组装工作。比如如下是一个保险丝盒的示意图。里面涉及到了导线,端子,连接器等物料。     1. 这一系列物料的分类是一个可以利用MAX78000来构建人工智能设备,利用摄像头以及图像分类算法来自动分类端子,导线,盲堵和密封塞,大大节约人为分类成本。 2. 线束组装的时候,复杂的线束看板非常大,前后工人完成的工作的时间如果不能得到平衡,耗时久的工序就会导致整个制作过程耗时长。因此可以利用机器视觉来计算不同工位的完成时间,供后台分析使用,从而优化耗时大的工位。 3. 物料不够的时候,机器视觉判断,然后提醒系统物料短缺,减少等待时间。   三、汽车电线束总布置: 汽车生产制造主要有四大工艺,冲焊涂总。 冲压车间现在冲压车间的自动化水平很高,大批量的使用自动冲压设备和传动装置。 焊装车间先进的焊装车间大批量使用焊接机器人,机器人对焊点质量,焊接一致性等的保障程度都很高,不会有“人”疲劳问题,情绪波动问题等。 涂装车间涂装车间的设备是封闭性的,大量的设备使用,维修人员也是不可替代的部分。 总装车间总装配车间的自动化水平最低,人员使用量最大。因为总装车间的装配性特点,需要把各种零件装配成一台整车。【1】 一个真实的案例是有一个客户在总装阶段少安装一个导线(回路)导致该车型发生召回,损失不少。可以设想如果使用了无线连接技术,在终端设备与连接器之间建立通信连接后,可以获取该连接器的二维平面图、三维图以及电气连接性以及相关孔位/引脚。这将从某种程度上有效的避免这类错误的发生。这种成本与车辆召回相比,应该是非常经济的。   这其中可能用到的技术是:DeepCover® secure NFC/RFID应答机(标签)和收发器(读取器)采用双向安全模型来实现非常安全的免接触通信。我们的RFID收发器IC包含基于FIPS 180-4标准的安全散列算法-256 (SHA-256)安全认证器协处理器。与我们的NFC应答机IC配对时,双向安全模型会强制进行双向认证。每个NFC标签包含一个专有的64位ROM ID和UID,用作该应用中的电子序列号。我们的安全NFC和RFID读取器支持新的工业和医疗应用,例如节点-设备安全验证、自动化设备配置、使用限制设置以及实现传感器-标签。   基于ADI的NFC技术,在关键的连接器上面使用NFC标签。在总装的时候使用终端设备快速扫一扫便可以定位零件连接线,防止接反、漏接电路,从而尽可能避免影响电气功能。   四、汽车内的空气质量检测与噪声控制ANC 此外,还想到可以借助ADI的《适用于室内空气质量监测的挥发性有机化合物检测器》来用来检测汽车VOC,保障车内空气质量,避免损害司乘身体健康。该方案的电路针对Figaro TGS8100传感器进行了优化,传感器由 MOS检测芯片和集成加热器(利用MEMS技术形成于硅 基板)构成。适当修改硬件和软件,便可使用其他MOS 传感器。 测试是在气体腔中利用一氧化碳完成。结果与传感器数据 手册规格进行了相关性分析。 该电路利用金属氧化物传感器检测挥发性有机化合 物组成的气体,从而测量室内空气质量。传感器由加热电 阻和检测电阻组成。当加热检测电阻时,其值随不同气体 的浓度而改变。   以及使用ADI的汽车主动降噪技术ANC来给司乘人员一个安静的驾乘体验。   总结: ADI的先进技术被广泛的应用在汽车行业的各个分支,涵盖了汽车研发,制造,充电桩,车联网等方方面面。本文稍加总结了一些自己对一些浅显理解,难免有纰漏,敬请指正。   参考文献: 作者:北方车厘子,链接:https://www.zhihu.com/question/574465855/answer/2843049053 作者:ADI,链接: C²B大幅降低汽车摄像头的线束成本 https://www.analog.com/cn/product-category/automotive-audio-bus.html 作者:ADI,链接:https://www.analog.com/cn/product-category/nfcrfid-products.html    

  • 2023-10-15
  • 发表了主题帖: 【得捷电子Follow me第2期】基于ESP32S3-FHR的联网天气时钟【终版】

    [localvideo]698b1873676d20f5c1cf5f0a9e7edb75[/localvideo]   Adafruit 是国外一家非常知名的创客公司。本次FOLLOW-ME活动提供的Adafruit ESP32-S3 TFT Feather是一款富有特色的开源硬件,开发板使用乐鑫ESP32-S3芯片,支持WiFi和蓝牙能,自带高清TFT彩色显示屏。板载丰富的资源与外设接口。   搭载 Xtensa® 32 位 LX7 双核处理器,主频高达 240 MHz,内置 512 KB SRAM (TCM),具有 45 个可编程 GPIO 管脚和丰富的通信接口,集成 2.4 GHz Wi-Fi 和 Bluetooth 5 (LE),配备原生 USB,可用作键盘/鼠标、MIDI 设备、磁盘驱动器等; 获得FCC / CE认证,带有4 MB闪存和2 MB PSRAM; 彩色 1.14“ IPS TFT,240x135 像素——采用 ST7789 芯片组的高清彩色显示屏,可从任何角度观看; 电源选项 - USB C 型或锂聚合物电池,通过 USB-C 供电时可为内置电池充电; LiPoly 电池监控器 - LC709203 芯片主动监控电池的电压和充电状态/通过 I2C 报告电池电量百分比; 重置和DFU(BOOT0)按钮以进入ROM引导加载程序; 内置原生USB串行端口,不需要单独的电缆,串行调试输出引脚(可选,用于检查硬件串行调试控制台); 用于 I2C 设备的 STEMMA QT 连接器,具有可切换电源,可进入低功耗模式; 板载 NeoPixel 具有引脚控制电源,可实现低功耗,用于多种状态显示; 在深度睡眠模式下,可从Lipoly连接获得80~100uA的电流消耗; 可与Arduino或CircuitPython一起使用。 这款板卡的实物图如下: 这款板卡的引脚图如下: 电路原理图如下: Arduino环境搭建: ESP32S3使用自带的USB替代传统的串口芯片进行代码烧录,本文提供了简短视频: [localvideo]fcf3a57344e295a1de7fc53c0a4d4517[/localvideo]   任务1:控制屏幕显示中文(要求:完成屏幕的控制,并且能显示中文) 首先是屏幕的驱动,本文选择的是Arduino开发平台,在库管理器里面找到本开发板的屏幕驱动库。 之后在源代码中包含相应的头文件: #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7789.h> // Hardware-specific library for ST7789 #include <SPI.h> 接着进行屏幕初始化: void setup(void) { Serial.begin(9600); Serial.println("***************************************************"); Serial.println(F("Hello! Feather TFT Test. Today is August 31th.")); Serial.println("***************************************************"); // turn on backlite pinMode(TFT_BACKLITE, OUTPUT); digitalWrite(TFT_BACKLITE, HIGH); // turn on the TFT / I2C power supply pinMode(TFT_I2C_POWER, OUTPUT); digitalWrite(TFT_I2C_POWER, HIGH); delay(10); // initialize TFT tft.init(135, 240); // Init ST7789 240x135 tft.setRotation(3); tft.fillScreen(ST77XX_BLACK); Serial.println(F("Initialized")); } 其次是中文显示,参考了论坛网友[1]的字模提取方案,针对要显示的中文,提前准备好16*16大小的字模, 最后可以通过调用tft.drawBitmap()像绘制图片一下把想要显示的中文显示出来。 tft.fillScreen(ST77XX_BLACK); tft.setCursor(0, 0); static uint8_t i, j; tft.drawBitmap(0, 0, str_f_DIAN, 16, 16, ST77XX_GREEN); tft.drawBitmap(16, 0, str_f_ZI, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*2, 0, str_f_GONG, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*3, 0, str_f_CHENG, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*4, 0, str_f_SHI, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*5, 0, str_f_JIE, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*7, 0, str_f_DE, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*8, 0, str_f_JIE2, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*9, 0, str_f_DIAN, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*10, 0, str_f_ZI, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*0, 32, str_f_WANG, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*1, 32, str_f_LUO, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*2, 32, str_f_LIAN, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*3, 32, str_f_JIE3, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*4, 32, str_f_ZHONG, 16, 16, ST77XX_GREEN); 效果展示: 代码:   任务2:网络功能使用(任务要求:完成网络功能的使用,能够创建热点和连接到WiFi) 要使用Wi-Fi相关功能,首先要包含如下头文件: #include <WiFi.h> 针对STA与AP混合模式,需要定义各自的SSID与PASSWORD: / Set WiFi credentials #define WIFI_SSID "TP-LINK_XXX" #define WIFI_PASS "XXXXXXXXXXX" // Set AP credentials #define AP_SSID "Adafruit-S3-FTHR" #define AP_PASS "followme" 接着启动AP与STA模式: // Begin Access Point WiFi.mode(WIFI_AP_STA); WiFi.softAP(AP_SSID, AP_PASS); // Begin WiFi WiFi.begin(WIFI_SSID, WIFI_PASS); // Connecting to WiFi... Serial.print("Connecting to "); Serial.print(WIFI_SSID); while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.print("."); } STA模式启动成功后,开发板连接到指定的AP即家里的路由器。可以看到S3已经有了自己对IP地址,并且电脑也连接到了路由器,可以PING通S3开发板。 接下来测试一下AP接入点模式,即电脑或者手机可以连接到S3开发板。   可以看到电脑已经连接成功到S3开发板提供的AP。 [localvideo]6510b5d1f10d1faf5045b674bdb6bac9[/localvideo] 代码:   任务3:控制WS2812B(要求:使用DFROBOT的旋转编码器控制板载Neopixel LED的显示和颜色切换) 本节介绍了如何在Arduino环境下驱动本次活动板卡自带的一颗WS2812 RGB灯珠(即Adafruit称之为NeoPixel)。板载的这颗NeoPixel与S3的IO33引脚相连接,可以从电路图看出:   另外订购活动产品的时候,还手痒痒凑单了一个DFROT家的旋转编码器,型号是:SEN0235,官方WIKI: https://wiki.dfrobot.com.cn/_SKU_SEN0235_360%E5%BA%A6%E7%BC%96%E7%A0%81%E5%99%A8%E5%BC%80%E5%85%B3   编码器有VCC, GND, A相输出,B相输出,以及按键按下输出的低电平信号,共5个信号。分别连接到TFT FTHR开发板的,3.3V, GND以及GPIO 18,17,16           之后初始化相关引脚为输入,并设置中断: /** Oct 13rd add code for SEN0235 ---- Begin---- **/ pinMode(encoderPinA, INPUT); pinMode(encoderPinB, INPUT); pinMode(buttonPin, INPUT); digitalWrite(encoderPinA, HIGH); //turn pullup resistor on digitalWrite(encoderPinB, HIGH); //turn pullup resistor on digitalWrite(buttonPin, HIGH); //turn pullup resistor on //call updateEncoder() when any high/low changed seen //on interrupt 0 (pin 2), or interrupt 1 (pin 3) attachInterrupt(digitalPinToInterrupt(encoderPinA), updateEncoder, CHANGE); attachInterrupt(digitalPinToInterrupt(encoderPinB), updateEncoder, CHANGE); attachInterrupt(digitalPinToInterrupt(buttonPin), updateEncoder_BtnPressed, FALLING); /** Oct 13rd add code for SEN0235 ---- End---- **/ 下面是官方提供的解析旋转编码器顺时针还是逆时针旋转的参考代码: void updateEncoder() { int MSB = digitalRead(encoderPinA); //MSB = most significant bit int LSB = digitalRead(encoderPinB); //LSB = least significant bit int encoded = (MSB << 1) | LSB; //converting the 2 pin value to single number int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; lastEncoded = encoded; //store this value for next time } 最终在循环中,根据编码器的值来决定NEO-PIXEL的色彩: switch(readEncoderValue()%4){ case 0: tft.fillRect(16*10,32,32,16,ST77XX_BLACK); tft.drawBitmap(16*10, 32, str_f_HONG, 16, 16, ST77XX_RED); tft.drawBitmap(16*11, 32, str_f_SE, 16, 16, ST77XX_RED); tft.fillCircle(16*13, 38, 10, ST77XX_RED); colorWipe(strip.Color(255, 0, 0) , 1000); // Red break; case 1: tft.fillRect(16*10,32,32,16,ST77XX_BLACK); tft.drawBitmap(16*10, 32, str_f_LV, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*11, 32, str_f_SE, 16, 16, ST77XX_GREEN); tft.fillCircle(16*13, 38, 10, ST77XX_GREEN); colorWipe(strip.Color( 0, 255, 0) , 1000); // Green break; case 2: tft.fillRect(16*10,32,32,16,ST77XX_BLACK); tft.drawBitmap(16*10, 32, str_f_LAN, 16, 16, ST77XX_BLUE); tft.drawBitmap(16*11, 32, str_f_SE, 16, 16, ST77XX_BLUE); tft.fillCircle(16*13, 38, 10, ST77XX_BLUE); colorWipe(strip.Color( 0, 0, 255) , 1000); // Blue break; case 3: tft.fillRect(16*10,32,32,16,ST77XX_BLACK); tft.fillCircle(16*13, 38, 10, ST77XX_BLACK); rainbowFade2White(3, 3, 1); break; default: break; } 完整代码: 实物照片:     演示视频: [localvideo]6c2fb9ab7223fb896cb1105cefe9ca00[/localvideo]   任务4:分任务1:日历&时钟——完成一个可通过互联网更新的万年历时钟,并显示当地的天气信息 之前注册过心知天气,所以任务4的天气部分继续使用这个免费的天气API服务。如果是第一次使用心知天气,需要去注册然后获取key。 本任务我选择的API是:https://seniverse.yuque.com/hyper_data/api_v3/nyiu3t。获取指定城市的天气实况。付费用户可获取全部数据,免费用户只返回天气现象文字、代码和气温 3 项数据。 在Arduino环境下,需要使用到ArduinoJson库来解析心知天气返回的JSON格式的数据,因此先要安装一下这个库。 #include <ArduinoJson.h> 在尝试FreeRTOS的过程中,遇到了问题,板卡反复重启。后来把线程的Stack从1024字节调整到4096字节,问题解决。 对于天气和时间,分别需要与心知天气服务器与NTP时间服务器进行交互,因此在setup()里面分别创建两个线程来对应处理。 xTaskCreatePinnedToCore( Task_Weather_Get , "Task_Weather_Get" , 4096 // Stack size , NULL , 1 // Priority , NULL , 0); xTaskCreatePinnedToCore( Task_NTP_Time_Get , "Task_NTP_Time_Get" , 4096 // Stack size , NULL , 1 // Priority , NULL , 0); 天气获取核心代码: // 向心知天气服务器服务器请求信息并对信息进行解析 void httpRequest(String reqRes){ WiFiClient client; // 建立http请求信息 String httpRequest = String("GET ") + reqRes + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"; Serial.println(""); Serial.print("Connecting to "); Serial.print(host); // 尝试连接服务器 if (client.connect(host, 80)){ Serial.println(" Success!"); // 向服务器发送http请求信息 client.print(httpRequest); Serial.println("Sending request: "); Serial.println(httpRequest); // 获取并显示服务器响应状态行 String status_response = client.readStringUntil('\n'); Serial.print("status_response: "); Serial.println(status_response); // 使用find跳过HTTP响应头 if (client.find("\r\n\r\n")) { Serial.println("Found Header End. Start Parsing."); } weather_query_delay = 1000*60*60; // 利用ArduinoJson库解析心知天气响应信息 parseInfo(client); } else { weather_query_delay = 3000; Serial.println(" connection failed!"); } //断开客户端与服务器连接工作 client.stop(); } 心知天气返回的是Json格式的数据,因此需要用ArduinoJson来解析,提取感兴趣的天气内容。     NTP时间获取需要先初始化NTP Server,国内还是选择阿里云的NTP服务稳定些,端口号123   接着初始化Ntp服务器  void Ntp_Init(void){ // Initialize a NTPClient to get time timeClient.begin(); // Set offset time in seconds to adjust for your timezone, for example: // GMT +1 = 3600 // GMT +8 = 28800 // GMT -1 = -3600 // GMT 0 = 0 timeClient.setTimeOffset(28800); } void Task_NTP_Time_Get(void *pvParameters){ (void) pvParameters; // 通过NTP Server获取时间,日期 for(;;){ while(!timeClient.update()) { timeClient.forceUpdate(); } // The formattedDate comes with the following format: // 2018-05-28T16:00:13Z // We need to extract date and time formattedDate = timeClient.getFormattedDate(); Serial.println(formattedDate); // Extract date int splitT = formattedDate.indexOf("T"); dayStamp = formattedDate.substring(0, splitT); Serial.print("DATE: "); Serial.println(dayStamp); // Extract time timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1); Serial.print("HOUR: "); Serial.println(timeStamp); tft.fillRect(0,0,240,16,ST77XX_BLACK); tft.setCursor(0, 0); tft.setTextColor(ST77XX_WHITE); tft.setTextSize(2); tft.print(dayStamp); tft.setCursor(136, 0); tft.print(timeStamp); delay(1000); } } 此外,由于物料采购的时候买了一个Sipeed的M0Sense开发板,RISC-V的,小板子带了麦克风和六轴,虽然体积小但是性能挺好。 因此在WSL2里面搭建了基于Linux的开发环境,参考:https://en.wiki.sipeed.com/hardware/zh/maixzero/sense/start.html#%E9%85%8D%E7%BD%AE%E7%BC%96%E8%AF%91%E5%B7%A5%E5%85%B7%E9%93%BE%E8%B7%AF%E5%BE%84 void dma_ch0_irq_callback(struct device* dev, void* args, uint32_t size, uint32_t state) { int16_t* adc_buffer = raw_adc_buffer[pingpong_idx]; pingpong_idx = !pingpong_idx; device_read(device_find("adc"), 0, raw_adc_buffer[pingpong_idx], sizeof(raw_adc_buffer[0]) / sizeof(uint8_t)); /* size need convert to uint8_t*/ /* min: 6339, max: 9165 mid: 7752 */ uint32_t res_all = 0; for (int i = 0; i < SAMPLE_COUNT; i++) { adc_buffer[i] = (((uint32_t*)adc_buffer)[i] & 0xffff) >> 2; res_all += (uint32_t)adc_buffer[i]; } for (int i = 0; i < SAMPLE_COUNT; i++) { adc_buffer[i] -= res_all / SAMPLE_COUNT; adc_buffer[i] <<= 6; printf("%5d", adc_buffer[i]); printf(i % 16 == 15 ? "\r\n" : ", "); /*added by alexboo 2023/10/15*/ if(adc_buffer[i] > 1000 || (adc_buffer[i] + 1000 < 0)){ gpio_write(GPIO_PIN_27, 1); printf("**************** %5d\r\n", adc_buffer[i]); }else{ gpio_write(GPIO_PIN_27, 0); } } } 主要的思路是当声音pcm值超过一定阈值后,控制一个数字GPIO引脚输出高电平,否则输出低电平。     在WSL里面编译生成UF2     之后把这个文件拖拽到M0sense的U盘即可完成烧录。 打开串口,在没有人说话的时候,输出数据如下: 在有人说话的时候:   实物展示: [localvideo]42905afb32618e921ee0f9f03ec6f0f8[/localvideo]     代码:   活动心得 参加本次follow me活动自己收获非常多,不仅掌握了在Windows环境下用arduino开发esp32s3芯片还熟悉了在wsl2环境下开发sipeed m0芯片,并且成功了完成了各项指定任务。还有感触很深的是热心网友的无私分享,群里热烈的讨论让一开始手足无措的小白也能很快上手。期待新一期的活动!

  • 2023-10-13
  • 回复了主题帖: 【得捷电子Follow me第2期】基于ESP32S3-FHR的联网天气时钟

    审核老师您好:任务3,控制neo-pixel部分增加了旋转编码器,详细内容在评论区。原帖已经无法编辑。谢谢理解。

  • 回复了主题帖: 【得捷电子Follow me第2期】基于ESP32S3-FHR的联网天气时钟

    任务3-改进:   参加本次follow-me活动的时候,还手痒痒凑单了一个DFROT家的旋转编码器,型号是:SEN0235,官方WIKI: https://wiki.dfrobot.com.cn/_SKU_SEN0235_360%E5%BA%A6%E7%BC%96%E7%A0%81%E5%99%A8%E5%BC%80%E5%85%B3   编码器有VCC, GND, A相输出,B相输出,以及按键按下输出的低电平信号,共5个信号。分别连接到TFT FTHR开发板的,3.3V, GND以及GPIO 18,17,16   之后初始化相关引脚为输入,并设置中断: /** Oct 13rd add code for SEN0235 ---- Begin---- **/ pinMode(encoderPinA, INPUT); pinMode(encoderPinB, INPUT); pinMode(buttonPin, INPUT); digitalWrite(encoderPinA, HIGH); //turn pullup resistor on digitalWrite(encoderPinB, HIGH); //turn pullup resistor on digitalWrite(buttonPin, HIGH); //turn pullup resistor on //call updateEncoder() when any high/low changed seen //on interrupt 0 (pin 2), or interrupt 1 (pin 3) attachInterrupt(digitalPinToInterrupt(encoderPinA), updateEncoder, CHANGE); attachInterrupt(digitalPinToInterrupt(encoderPinB), updateEncoder, CHANGE); attachInterrupt(digitalPinToInterrupt(buttonPin), updateEncoder_BtnPressed, FALLING); /** Oct 13rd add code for SEN0235 ---- End---- **/ 下面是官方提供的解析旋转编码器顺时针还是逆时针旋转的参考代码: void updateEncoder() { int MSB = digitalRead(encoderPinA); //MSB = most significant bit int LSB = digitalRead(encoderPinB); //LSB = least significant bit int encoded = (MSB << 1) | LSB; //converting the 2 pin value to single number int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; lastEncoded = encoded; //store this value for next time } 最终在循环中,根据编码器的值来决定NEO-PIXEL的色彩: switch(readEncoderValue()%4){ case 0: tft.fillRect(16*10,32,32,16,ST77XX_BLACK); tft.drawBitmap(16*10, 32, str_f_HONG, 16, 16, ST77XX_RED); tft.drawBitmap(16*11, 32, str_f_SE, 16, 16, ST77XX_RED); tft.fillCircle(16*13, 38, 10, ST77XX_RED); colorWipe(strip.Color(255, 0, 0) , 1000); // Red break; case 1: tft.fillRect(16*10,32,32,16,ST77XX_BLACK); tft.drawBitmap(16*10, 32, str_f_LV, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*11, 32, str_f_SE, 16, 16, ST77XX_GREEN); tft.fillCircle(16*13, 38, 10, ST77XX_GREEN); colorWipe(strip.Color( 0, 255, 0) , 1000); // Green break; case 2: tft.fillRect(16*10,32,32,16,ST77XX_BLACK); tft.drawBitmap(16*10, 32, str_f_LAN, 16, 16, ST77XX_BLUE); tft.drawBitmap(16*11, 32, str_f_SE, 16, 16, ST77XX_BLUE); tft.fillCircle(16*13, 38, 10, ST77XX_BLUE); colorWipe(strip.Color( 0, 0, 255) , 1000); // Blue break; case 3: tft.fillRect(16*10,32,32,16,ST77XX_BLACK); tft.fillCircle(16*13, 38, 10, ST77XX_BLACK); rainbowFade2White(3, 3, 1); break; default: break; } 完整代码: 实物照片:           演示视频: [localvideo]48ab19b3094ffecf58ac33f46c06b32b[/localvideo]      

  • 2023-10-08
  • 回复了主题帖: 颁奖:邀您云逛展《TE Connectivity ——中国国际工业博览会》报名有好礼!

    感谢论坛!!这次非常幸运!

  • 2023-10-07
  • 发表了主题帖: 【DigiKey创意大赛】-1-物料收到

    等了大概半个月,收到了从得捷发出的ST板卡,先晒个美照           当初选择这块板子就是看中了它的外设非常丰富,并且主控足够强大。从官网获取它的相关资源: 所有功能 STM32H7B3LIH6QU基于ARM®架构的微控制器,提供2M字节的FLASH存储器和1.4MB RAM,BGA225封装。 4.3英寸(480x272像素)TFT彩色LCD模块,包含带RGB接口的电容式触摸屏 Wi‑Fi®模块符合802.11 b/g/n USB OTG HS 音频编解码器 512-Mbit Octo-SPI NOR 闪存 128-Mbit SDRAM 2个用户LED 用户按钮和复位按钮 Fanout子板 1x FDCAN 板连接器: 摄像头(8位) 带Micro-AB的USB 立体声耳机插孔,包括模拟麦克风输入 用于外部扬声器的音频插孔 microSD™卡 TAG-Connect10引脚尺寸 Arm® Cortex® 10引脚 1.27mm螺距调试连接器,STDC14尺寸 ARDUINO® Uno V3扩展连接器 STMod+ 扩展连接器 音频子板扩展接口 External I2C扩展连接器 灵活的电源选项: ST-LINK USB VBUS, USB OTG HS 连接器或外部电源 具有USB重新枚举功能的板上STLINK-V3E调试器/编程器:大容量存储器、虚拟COM端口和调试端口 提供了全面的免费软件库和例程,可从STM32Cube MCU软件包获得 支持多种集成开发环境(IDE),包括IAR™、Keil®、基于GCC的IDE。

  • 2023-09-22
  • 回复了主题帖: 【得捷电子Follow me第2期】基于ESP32S3-FHR的联网天气时钟

    lugl4313820 发表于 2023-9-21 16:13 用ardunio来玩成,相比python又多了一个开发选项。
    是的,Arduino比较适合我这种菜鸡

  • 2023-09-21
  • 加入了学习《得捷电子Follow+me第2期》,观看 得捷电子Follow+me第2期

  • 2023-09-01
  • 回复了主题帖: 【Microchip WBZ451 Curiosity】6.ADC和温度传感器

    大佬v5!

  • 2023-08-31
  • 发表了主题帖: 【得捷电子Follow me第2期】基于ESP32S3-FHR的联网天气时钟

    本帖最后由 慕容雪花 于 2023-9-21 09:58 编辑 [localvideo]21c1e386265540d13d733245ce8c519f[/localvideo] Adafruit 是国外一家非常知名的创客公司。本次FOLLOW-ME活动提供的Adafruit ESP32-S3 TFT Feather是一款富有特色的开源硬件,开发板使用乐鑫ESP32-S3芯片,支持WiFi和蓝牙能,自带高清TFT彩色显示屏。板载丰富的资源与外设接口。 搭载 Xtensa® 32 位 LX7 双核处理器,主频高达 240 MHz,内置 512 KB SRAM (TCM),具有 45 个可编程 GPIO 管脚和丰富的通信接口,集成 2.4 GHz Wi-Fi 和 Bluetooth 5 (LE),配备原生 USB,可用作键盘/鼠标、MIDI 设备、磁盘驱动器等; 获得FCC / CE认证,带有4 MB闪存和2 MB PSRAM; 彩色 1.14“ IPS TFT,240x135 像素——采用 ST7789 芯片组的高清彩色显示屏,可从任何角度观看; 电源选项 - USB C 型或锂聚合物电池,通过 USB-C 供电时可为内置电池充电; LiPoly 电池监控器 - LC709203 芯片主动监控电池的电压和充电状态/通过 I2C 报告电池电量百分比; 重置和DFU(BOOT0)按钮以进入ROM引导加载程序; 内置原生USB串行端口,不需要单独的电缆,串行调试输出引脚(可选,用于检查硬件串行调试控制台); 用于 I2C 设备的 STEMMA QT 连接器,具有可切换电源,可进入低功耗模式; 板载 NeoPixel 具有引脚控制电源,可实现低功耗,用于多种状态显示; 在深度睡眠模式下,可从Lipoly连接获得80~100uA的电流消耗; 可与Arduino或CircuitPython一起使用。 这款板卡的实物图如下:     这款板卡的引脚图如下:   电路原理图如下:   Arduino环境搭建: ESP32S3使用自带的USB替代传统的串口芯片进行代码烧录,本文提供了简短视频: [localvideo]80a8edf758a3623bf1879a957db4bfc4[/localvideo]   任务1:控制屏幕显示中文(要求:完成屏幕的控制,并且能显示中文) 首先是屏幕的驱动,本文选择的是Arduino开发平台,在库管理器里面找到本开发板的屏幕驱动库。     之后在源代码中包含相应的头文件: #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7789.h> // Hardware-specific library for ST7789 #include <SPI.h> 接着进行屏幕初始化: void setup(void) { Serial.begin(9600); Serial.println("***************************************************"); Serial.println(F("Hello! Feather TFT Test. Today is August 31th.")); Serial.println("***************************************************"); // turn on backlite pinMode(TFT_BACKLITE, OUTPUT); digitalWrite(TFT_BACKLITE, HIGH); // turn on the TFT / I2C power supply pinMode(TFT_I2C_POWER, OUTPUT); digitalWrite(TFT_I2C_POWER, HIGH); delay(10); // initialize TFT tft.init(135, 240); // Init ST7789 240x135 tft.setRotation(3); tft.fillScreen(ST77XX_BLACK); Serial.println(F("Initialized")); } 其次是中文显示,参考了论坛网友[1]的字模提取方案,针对要显示的中文,提前准备好16*16大小的字模,   在源代码中, const uint8_t PROGMEM str_f_DIAN[]={0x00,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x02,0x70,0x3F,0xB0,0x12,0x30,0x17,0xA0,0x1A,0x20,0x13,0xC0,0x0E,0x00,0x02,0x04,0x02,0x04,0x01,0xFC,0x00,0x00,0x00,0x00};/*"电",0*/ const uint8_t PROGMEM str_f_ZI[]={0x00,0x00,0x00,0x00,0x00,0xE0,0x0F,0x20,0x00,0x40,0x01,0x80,0x00,0x9C,0x0F,0xE0,0x30,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x04,0x80,0x03,0x00,0x00,0x00};/*"子",1*/ const uint8_t PROGMEM str_f_GONG[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x0F,0xC0,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x01,0x00,0x01,0x00,0x01,0x7E,0x7E,0x80,0x00,0x00,0x00,0x00,0x00,0x00};/*"工",2*/ const uint8_t PROGMEM str_f_CHENG[]={0x00,0x00,0x00,0x00,0x02,0x08,0x04,0xFC,0x0C,0x48,0x04,0x58,0x1C,0x20,0x68,0x08,0x16,0x70,0x1A,0x20,0x24,0xF0,0x44,0x20,0x04,0x3E,0x0B,0xC0,0x00,0x00,0x00,0x00};/*"程",3*/ const uint8_t PROGMEM str_f_SHI[]={0x00,0x00,0x00,0x00,0x00,0x30,0x01,0x30,0x01,0x20,0x09,0x20,0x09,0x2E,0x0F,0xF0,0x39,0x20,0x09,0x20,0x09,0xC0,0x08,0x00,0x08,0x78,0x0F,0x80,0x00,0x00,0x00,0x00};/*"世",4*/ const uint8_t PROGMEM str_f_JIE[]={0x00,0x00,0x00,0x00,0x17,0xF0,0x09,0x10,0x0F,0xE0,0x09,0x20,0x0F,0xC0,0x06,0x40,0x04,0x20,0x0C,0x58,0x14,0x44,0x64,0x40,0x04,0x40,0x08,0x40,0x10,0x40,0x00,0x00};/*"界",5*/ const uint8_t PROGMEM str_f_DE[]={0x00,0x00,0x00,0x00,0x04,0x78,0x09,0x88,0x10,0xC8,0x24,0xB0,0x08,0x40,0x19,0xF0,0x10,0x20,0x30,0xFE,0x53,0x10,0x10,0x90,0x10,0x10,0x10,0x10,0x00,0x70,0x00,0x20};/*"得",6*/ const uint8_t PROGMEM str_f_JIE2[]={0x00,0x00,0x00,0x40,0x08,0x40,0x08,0x70,0x08,0xC0,0x0C,0x78,0x38,0xDC,0x0D,0xF0,0x0A,0x70,0x18,0xC0,0x69,0x78,0x09,0xC0,0x0A,0x40,0x1C,0x38,0x00,0x0E,0x00,0x00};/*"捷",7*/ const uint8_t PROGMEM str_f_WANG[]={0x00,0x00,0x00,0x00,0x00,0x10,0x1F,0xF8,0x10,0x08,0x11,0x28,0x12,0x48,0x16,0xC8,0x12,0xA8,0x15,0x88,0x18,0x08,0x10,0x08,0x10,0x28,0x10,0x18,0x00,0x00,0x00,0x00};/*"网",10*/ const uint8_t PROGMEM str_f_LUO[]={0x00,0x00,0x00,0x00,0x00,0x40,0x08,0x40,0x10,0x80,0x14,0xF0,0x25,0x20,0x18,0xE0,0x10,0x60,0x39,0x98,0x02,0x24,0x0D,0xD8,0x71,0x10,0x01,0x30,0x00,0xC0,0x00,0x00};/*"络",11*/ const uint8_t PROGMEM str_f_LIAN[]={0x00,0x00,0x00,0x80,0x00,0xC0,0x10,0xB0,0x0B,0xC0,0x01,0x40,0x01,0x50,0x13,0xE0,0x10,0x44,0x17,0xF8,0x10,0x40,0x10,0x40,0x7C,0x40,0x03,0xFE,0x00,0x38,0x00,0x00};/*"连",12*/ const uint8_t PROGMEM str_f_JIE3[]={0x00,0x00,0x08,0x00,0x08,0x60,0x08,0x20,0x08,0x38,0x0C,0xD0,0x38,0xA0,0x08,0xAC,0x0D,0xD0,0x18,0x46,0x6F,0xF8,0x08,0xA0,0x08,0x70,0x08,0xC8,0x0B,0x04,0x00,0x00};/*"接",13*/ const uint8_t PROGMEM str_f_ZHONG[]={0x00,0x00,0x01,0x00,0x01,0x80,0x01,0x00,0x01,0x38,0x1F,0xD8,0x11,0x08,0x11,0x10,0x09,0xF0,0x0F,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00};/*"中",14*/ 最后可以通过调用tft.drawBitmap()像绘制图片一下把想要显示的中文显示出来。 tft.fillScreen(ST77XX_BLACK); tft.setCursor(0, 0); static uint8_t i, j; tft.drawBitmap(0, 0, str_f_DIAN, 16, 16, ST77XX_GREEN); tft.drawBitmap(16, 0, str_f_ZI, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*2, 0, str_f_GONG, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*3, 0, str_f_CHENG, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*4, 0, str_f_SHI, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*5, 0, str_f_JIE, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*7, 0, str_f_DE, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*8, 0, str_f_JIE2, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*9, 0, str_f_DIAN, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*10, 0, str_f_ZI, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*0, 32, str_f_WANG, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*1, 32, str_f_LUO, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*2, 32, str_f_LIAN, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*3, 32, str_f_JIE3, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*4, 32, str_f_ZHONG, 16, 16, ST77XX_GREEN); 效果展示:   代码:   任务2:网络功能使用(任务要求:完成网络功能的使用,能够创建热点和连接到WiFi) 要使用Wi-Fi相关功能,首先要包含如下头文件: #include <WiFi.h> 针对STA与AP混合模式,需要定义各自的SSID与PASSWORD: // Set WiFi credentials #define WIFI_SSID "TP-LINK_XXX" #define WIFI_PASS "XXXXXXXXXXX" // Set AP credentials #define AP_SSID "Adafruit-S3-FTHR" #define AP_PASS "followme" 接着启动AP与STA模式: // Begin Access Point WiFi.mode(WIFI_AP_STA); WiFi.softAP(AP_SSID, AP_PASS); // Begin WiFi WiFi.begin(WIFI_SSID, WIFI_PASS); // Connecting to WiFi... Serial.print("Connecting to "); Serial.print(WIFI_SSID); while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.print("."); } STA模式启动成功后,开发板连接到指定的AP即家里的路由器。可以看到S3已经有了自己对IP地址,并且电脑也连接到了路由器,可以PING通S3开发板。   接下来测试一下AP接入点模式,即电脑或者手机可以连接到S3开发板。   [localvideo]198c3ff02e1b557b28c852bd7f283e40[/localvideo] 可以看到电脑已经连接成功到S3开发板提供的AP。 实物展示:   代码:   任务3:控制WS2812B(要求:使用按键控制板载Neopixel LED的显示和颜色切换) 本节介绍了如何在Arduino环境下驱动本次活动板卡自带的一颗WS2812 RGB灯珠(即Adafruit称之为NeoPixel)   板载的这颗NeoPixel与S3的IO33引脚相连接,可以从电路图看出:   首先在库管理器中下载“Adafruit NeoPixel”库:   之后包含该库的头文件: #include <Adafruit_NeoPixel.h> //NeoPixel Related: // Which pin on the Arduino is connected to the NeoPixels? // On a Trinket or Gemma we suggest changing this to 1: #define LED_PIN 33 // How many NeoPixels are attached to the Arduino? #define LED_COUNT 1 // NeoPixel brightness, 0 (min) to 255 (max) #define BRIGHTNESS 50 // Set BRIGHTNESS to about 1/5 (max = 255) // Declare our NeoPixel strip object: Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRBW + NEO_KHZ800); 题目要求按键控制NeoPixel,板载一个RST按键,一个BOOT按键。BOOT连接到GPIO0,在程序运行期间可以拿来当作普通的GPIO使用。并且使能上拉,配置中断输入源。 Setup(){ pinMode(BUTTON_BOOT, INPUT_PULLUP); attachInterrupt( digitalPinToInterrupt(BUTTON_BOOT), onButtonPressed, FALLING); } void onButtonPressed(void){ colorSelector = buttonPressedNum%4; buttonPressedNum++; Serial.println("Inside ISR. buttonPressedNum = " + String(buttonPressedNum)); } void loop() { switch(colorSelector){ case 0: tft.fillRect(16*7,64,32,16,ST77XX_BLACK); tft.drawBitmap(16*7, 64, str_f_HONG, 16, 16, ST77XX_RED); tft.drawBitmap(16*8, 64, str_f_SE, 16, 16, ST77XX_RED); tft.fillCircle(16*11, 64, 20, ST77XX_RED); colorWipe(strip.Color(255, 0, 0) , 1000); // Red break; case 1: tft.fillRect(16*7,64,32,16,ST77XX_BLACK); tft.drawBitmap(16*7, 64, str_f_LV, 16, 16, ST77XX_GREEN); tft.drawBitmap(16*8, 64, str_f_SE, 16, 16, ST77XX_GREEN); tft.fillCircle(16*11, 64, 20, ST77XX_GREEN); colorWipe(strip.Color( 0, 255, 0) , 1000); // Green break; case 2: tft.fillRect(16*7,64,32,16,ST77XX_BLACK); tft.drawBitmap(16*7, 64, str_f_LV, 16, 16, ST77XX_BLUE); tft.drawBitmap(16*8, 64, str_f_SE, 16, 16, ST77XX_BLUE); tft.fillCircle(16*11, 64, 20, ST77XX_BLUE); colorWipe(strip.Color( 0, 0, 255) , 1000); // Blue break; case 3: tft.fillRect(16*7,64,32,16,ST77XX_BLACK); tft.fillCircle(16*11, 64, 20, ST77XX_BLACK); rainbowFade2White(3, 3, 1); break; default: break; } 效果展示: [localvideo]d5d2f8b8c419c8eec5a87756f00f7f2f[/localvideo] 代码:   任务4:分任务1:日历&时钟——完成一个可通过互联网更新的万年历时钟,并显示当地的天气信息 之前注册过心知天气,所以任务4的天气部分继续使用这个免费的天气API服务。如果是第一次使用心知天气,需要去注册然后获取key。 本任务我选择的API是:https://seniverse.yuque.com/hyper_data/api_v3/nyiu3t。获取指定城市的天气实况。付费用户可获取全部数据,免费用户只返回天气现象文字、代码和气温 3 项数据。   //心知天气 const char *host = "api.seniverse.com"; const char *privateKey = "替换成自己的KEY哦"; const char *city = "shanghai"; const char *language = "en"; struct WetherData{ char city[32]; char weather[64]; char high[32]; char low[32]; char humi[32]; };   在Arduino环境下,需要使用到ArduinoJson库来解析心知天气返回的JSON格式的数据,因此先要安装一下这个库。   #include <ArduinoJson.h>   在尝试FreeRTOS的过程中,遇到了问题,板卡反复重启。后来把线程的Stack从1024字节调整到4096字节,问题解决。   对于天气和时间,分别需要与心知天气服务器与NTP时间服务器进行交互,因此在setup()里面分别创建两个线程来对应处理。 xTaskCreatePinnedToCore( Task_Weather_Get , "Task_Weather_Get" , 4096 // Stack size , NULL , 1 // Priority , NULL , 0); xTaskCreatePinnedToCore( Task_NTP_Time_Get , "Task_NTP_Time_Get" , 4096 // Stack size , NULL , 1 // Priority , NULL , 0); 天气获取核心代码: void Task_Weather_Get(void *pvParameters){ (void) pvParameters; // 建立心知天气API当前天气请求资源地址 String reqRes = "/v3/weather/now.json?key=" + reqUserKey + + "&location=" + reqLocation + "&language=en&unit=" +reqUnit; for(;;){ // 向心知天气服务器服务器请求信息并对信息进行解析 httpRequest(reqRes); Serial.println("Next Weather Query will be " + String(weather_query_delay/1000/60) + " min later"); delay(weather_query_delay); } } // 向心知天气服务器服务器请求信息并对信息进行解析 void httpRequest(String reqRes){ WiFiClient client; // 建立http请求信息 String httpRequest = String("GET ") + reqRes + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"; Serial.println(""); Serial.print("Connecting to "); Serial.print(host); // 尝试连接服务器 if (client.connect(host, 80)){ Serial.println(" Success!"); // 向服务器发送http请求信息 client.print(httpRequest); Serial.println("Sending request: "); Serial.println(httpRequest); // 获取并显示服务器响应状态行 String status_response = client.readStringUntil('\n'); Serial.print("status_response: "); Serial.println(status_response); // 使用find跳过HTTP响应头 if (client.find("\r\n\r\n")) { Serial.println("Found Header End. Start Parsing."); } weather_query_delay = 1000*60*5; // 利用ArduinoJson库解析心知天气响应信息 parseInfo(client); } else { weather_query_delay = 3000; Serial.println(" connection failed!"); } //断开客户端与服务器连接工作 client.stop(); } 心知天气返回的是Json格式的数据,因此需要用ArduinoJson来解析,提取感兴趣的天气内容。   NTP时间获取需要先初始化NTP Server,国内还是选择阿里云的NTP服务稳定些,端口号123 接着初始化Ntp服务器  void Ntp_Init(void){ // Initialize a NTPClient to get time timeClient.begin(); // Set offset time in seconds to adjust for your timezone, for example: // GMT +1 = 3600 // GMT +8 = 28800 // GMT -1 = -3600 // GMT 0 = 0 timeClient.setTimeOffset(28800); } void Task_NTP_Time_Get(void *pvParameters){ (void) pvParameters; // 通过NTP Server获取时间,日期 for(;;){ while(!timeClient.update()) { timeClient.forceUpdate(); } // The formattedDate comes with the following format: // 2018-05-28T16:00:13Z // We need to extract date and time formattedDate = timeClient.getFormattedDate(); Serial.println(formattedDate); // Extract date int splitT = formattedDate.indexOf("T"); dayStamp = formattedDate.substring(0, splitT); Serial.print("DATE: "); Serial.println(dayStamp); // Extract time timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1); Serial.print("HOUR: "); Serial.println(timeStamp); tft.fillRect(0,0,240,16,ST77XX_BLACK); tft.setCursor(0, 0); tft.setTextColor(ST77XX_WHITE); tft.setTextSize(2); tft.print(dayStamp); tft.setCursor(136, 0); tft.print(timeStamp); delay(1000); } }   实物展示: [localvideo]fbd8fb27f916ee603f0d7aacf4246bcd[/localvideo]   代码:   总结: 非常感谢这次的Follow-Me活动。学习到了国外优秀的开源团队Adafruit的ESP32S3作品,设计非常精美。在Arduino环境里面也学会了如何显示汉字,如何联网,如何控制WS2812灯珠以及获取网络时间等,最终实现了一个具有天气和时间功能的小作品。   参考网友: 1. Lucheni  【得捷电子Follow me第2期】Arduino速通教程 bbs.eeworld.com.cn/thread-1254565-1-1.html 2. ESP32 BLE Server and Client (Bluetooth Low Energy) https://randomnerdtutorials.com/esp32-ble-server-client/ 3. ESP32 WebSocket Server: Display Sensor Readings https://randomnerdtutorials.com/esp32-websocket-server-sensor/ 4. ESP32 Useful Wi-Fi Library Functions (Arduino IDE) https://randomnerdtutorials.com/esp32-useful-wi-fi-functions-arduino/ 5. 太极创客 物联网平台 www.taichi-maker.com/homepage/iot-development/iot-platform/ 6. Getting Date and Time with ESP32 on Arduino IDE (NTP Client) https://randomnerdtutorials.com/esp32-ntp-client-date-time-arduino-ide/ 补充内容 (2023-10-14 13:54): 审核老师您好:任务3,控制neo-pixel部分增加了旋转编码器,详细内容在评论区。原帖已经无法编辑。谢谢理解。

  • 2023-08-28
  • 回复了主题帖: 【Microchip WBZ451 Curiosity】-5- 增加硬件UART

    swzswz 发表于 2023-8-27 15:12 烧录我用的pde工具,这个IDE确实不咋行
    好像是基于netbean...............一言难尽啊

  • 2023-08-21
  • 发表了主题帖: 【Microchip WBZ451 Curiosity】-8- BLE Custom Service开发体验

    本帖最后由 慕容雪花 于 2023-8-21 20:31 编辑 往期测评文章一览: 文章序号 标题 链接 1 【Microchip WBZ451 Curiosity】-1- 开箱 http://bbs.eeworld.com.cn/thread-1251951-1-1.html 2 【Microchip WBZ451 Curiosity】-2- 开发环境搭建 http://bbs.eeworld.com.cn/thread-1251952-1-1.html 3 【Microchip WBZ451 Curiosity】-3- 出厂BLE例程体验 http://bbs.eeworld.com.cn/thread-1252992-1-1.html 4 【Microchip WBZ451 Curiosity】-4- 从0创建简易BLE广播 http://bbs.eeworld.com.cn/thread-1253144-1-1.html 5 【Microchip WBZ451 Curiosity】-5- 增加硬件UART http://bbs.eeworld.com.cn/thread-1253425-1-1.html 6 【Microchip WBZ451 Curiosity】-6- gpio驱动 http://bbs.eeworld.com.cn/thread-1253445-1-1.html 7 【Microchip WBZ451 Curiosity】-7- EIC外部中断控制器的使用 http://bbs.eeworld.com.cn/thread-1253493-1-1.html   本文主要体验如何在Microchip的集成开发环境MPLABX IDE中,配合Maplab Harmony MCC插件来图形化开发BLE功能。先来个演示视频: [localvideo]894ad5ae6dbea52bcebb26ecf19bb2e9[/localvideo]   1. 老朋友MCC,虽然好用,但是还是卡,一如既往。     2. 在BLE基础配置中,确认不需要勾选GATT Client。在本文中,手机app作为GATT Client,WBZ451开发板作为GATT Server。     3. 在customized Service组件中,增加一个Service。Service名称有长度限制,注意UUID的小端存储模式。这里定义的UUID与手机app看到的有区别。     4. Service下面包含Characteristic。下图展示的是Characteristic 0。这个Characteristic用于读取按键状态,以及订阅按键状态变化。     5. Characteristic 1即第二个Characteristic,用户控制板载LED状态。类似Characteristic 0的UUID,都可以用在线的UUID生成器自动生成。   6. 点击Generate,自动生成代码。 7. 自动生成的代码存储在config\default\ble\service_ble     8. APP Task中,循环使用OS抽象层的OSAL_QUEUE_Receive()函数检测是否有相应的事件发生。 case APP_STATE_SERVICE_TASKS: { if (OSAL_QUEUE_Receive(&appData.appQueue, &appMsg, OSAL_WAIT_FOREVER)) { if(p_appMsg->msgId==APP_MSG_BLE_STACK_EVT) { // Pass BLE Stack Event Message to User Application for handling APP_BleStackEvtHandler((STACK_Event_T *)p_appMsg->msgData); } else if(p_appMsg->msgId==APP_MSG_BLE_CS_LED_EVT) { APP_CustomService_RGB_Handler((uint8_t *)((STACK_Event_T *)p_appMsg->msgData)); }else if(p_appMsg->msgId==APP_MSG_BLE_CS_BUTTON_EVT) { APP_CustomService_Button_Handler(); } } break; } 9. 手机app,通过ble gatt写入数据后,步骤8中会检测到相应的BLE事件,通过如下的函数调用,接受到的报文的msgId = APP_MSG_BLE_CS_LED_EVT.     之后,调用LED灯的处理函数: uint8_t APP_CustomService_RGB_Handler(uint8_t *p_cmd) { bleCSdata.RGB_LED.Red = p_cmd[0]; bleCSdata.RGB_LED.Green = p_cmd[1]; bleCSdata.RGB_LED.Blue = p_cmd[2]; //SYS_CONSOLE_PRINT ("[BLE] RGB LED data 0x%X 0x%X 0x%X \r\n",p_cmd[0],p_cmd[1],p_cmd[2]); SERCOM0_USART_Write((uint8_t *)"[BLE] RGB LED data Received\r\n",strlen("[BLE] RGB LED data Received\r\n")); if(bleCSdata.rgbOnOffStatus == LED_ON) { if(bleCSdata.RGB_LED.Red) RGB_LED_RED_Set(); else RGB_LED_RED_Clear(); if(bleCSdata.RGB_LED.Green) RGB_LED_GREEN_Set(); else RGB_LED_GREEN_Clear(); if(bleCSdata.RGB_LED.Blue) RGB_LED_BLUE_Set(); else RGB_LED_BLUE_Clear(); //SYS_CONSOLE_MESSAGE("[BLE] RGB SET\n\r"); } return SUCCESS; } 总结: 整体来讲,使用MPLABX IDE配合HARMONY MCC插件开发蓝牙BLE应用是非常方便的。尤其是MPLABX IDE自带的函数调用结构图非常方便的查看代码。

  • 发表了主题帖: 【Microchip WBZ451 Curiosity】-7- EIC外部中断控制器的使用

    本文体验PIC32单片机的EIC外部中断控制器模块,这个模块可以让外部引脚作为一个中断源。EIC配合开发板上的用户按键SW2:   MCC中添加EIC模块,然后配置相关参数:     配置引脚PB4的功能为EXTINT0     点击Generate,自动生成代码。   在代码中,注册一个中断回调函数,即用户按下SW2需要进行的处理。 /* Register external button interrupt callback */ EIC_CallbackRegister(BUTTON_1,APP_CustomService_Button_Callback,0); 在回调函数中,通过串口打印相关信息: void APP_CustomService_Button_Handler(void) { // SYS_CONSOLE_PRINT("[BLE] Custom Service Button Event : "); SERCOM0_USART_Write((uint8_t *)"[BLE] Custom Service Button Event :\r\n",strlen("[BLE] Custom Service Button Event :\r\n")); 串口输出如下,可以看到每次按键按下后,有相应的输出。     总结: PIC32单片机的EIC外部中断控制器使用起来比预期中要方便很多。相关的中文文档较少,需要阅读芯片手册。

  • 2023-08-20
  • 回复了主题帖: 【得捷电子Follow me第2期】任务3 控制WS2812B

    太快了,

  • 回复了主题帖: 【Microchip WBZ451 Curiosity】-5- 增加硬件UART

    不得不吐槽一下mplabx ide的烧录,时好时坏,早上还有问题,过了2h,又好了。。。。。。。

  • 回复了主题帖: 【Microchip WBZ451 Curiosity】-6- gpio驱动

    第5篇文章解决了UART后,更新了本文的代码,在单片机启动后打印: SERCOM0_USART_Write((uint8_t *)"Hello Welcome to WBZ451 World\r\n",strlen("Hello Welcome to WBZ451 World\r\n"));   在ble回调函数中:   void APP_BleGapEvtHandler(BLE_GAP_Event_T *p_event) { switch(p_event->eventId) { case BLE_GAP_EVT_CONNECTED: { /* TODO: implement your application code.*/ SERCOM0_USART_Write((uint8_t *)"Great! ^-^ Connect to GAP Center Device\r\n",strlen("Great! ^-^ Connect to GAP Center Device\r\n")); } break; case BLE_GAP_EVT_DISCONNECTED: { /* TODO: implement your application code.*/ SERCOM0_USART_Write((uint8_t *)"Ah oh... :( Disconnect to GAP Center Device\r\n",strlen("Ah oh... :( Disconnect to GAP Center Device\r\n")); } break; 实测结果如下:     很有趣!MCC配置工具使用熟练后,更会觉得它的强大!

  • 2023-08-19
  • 发表了主题帖: 【Microchip WBZ451 Curiosity】-6- gpio驱动

    本帖最后由 慕容雪花 于 2023-8-19 18:13 编辑 GPIO是非常重要的外设,本文以驱动WBZ451的PB7引脚为例,展示基于MPLABX ide MCC图形化配置工具的快速GPIO驱动设计。 WBZ451模块引脚不多,PB7在好奇开发板上连接到是用户LED,比较直观。       1. 从IDE主界面进入MCC:        2. 在PLUGINs下来菜单中,选择“Pin Configuration”,自此进入GPIO编辑界面。     3. 针对PB7,可以自定义引脚名称,设置Function为GPIO,方向为OUT   4. 在项目图中,点击System,展开Ports->Pin Configuration,可以看到步骤3中编辑的条目已经显示出来了。     5. 点击Generate,自动生成代码。   6. 到task.c中新创建一个Task:LED_BLINKY,专门用于点灯。 void SYS_Tasks ( void ) { /* Maintain system services */ /* Maintain Device Drivers */ /* Maintain Middleware & Other Libraries */ if (xTaskCreate(BM_Task, "BLE", TASK_BLE_STACK_SIZE, NULL , TASK_BLE_PRIORITY, NULL) != pdPASS) while (1); /* Maintain the application's state machine. */ /* Create OS Thread for APP_Tasks. */ xTaskCreate((TaskFunction_t) _APP_Tasks, "APP_Tasks", 1024, NULL, 1, &xAPP_Tasks); xTaskCreate((TaskFunction_t) _LED_Blinky, "LED_Tasks", 1024, NULL, 1, &xLED_Blinky); /* Start RTOS Scheduler. */ /********************************************************************** * Create all Threads for APP Tasks before starting FreeRTOS Scheduler * ***********************************************************************/ vTaskStartScheduler(); /* This function never returns. */ }   这个task的入口函数定义如下,其中精确延迟采用了freeRTOS推荐的API. void _LED_Blinky( void *pvParameters ){ while(1){ GPIO_RB7_Toggle(); vTaskDelay(1000/portTICK_PERIOD_MS); } } 7. 编译,烧录。 Currently loaded versions: Application version...........00.06.60 Boot version..................01.01.41 Script version................00.05.72 Script build number...........2889965820 Tool pack version ............1.11.1054 Target voltage detected Target device WBZ451 found. Device Revision Id = 0xfbf Device Id = 0x9b8f Calculating memory ranges for operation... Erasing... The following memory area(s) will be programmed: program memory: start address = 0x1004000, end address = 0x1025fff configuration memory boot config memory Programming/Verify complete 8. 结果:        

最近访客

< 1/2 >

统计信息

已有17人来访过

  • 芯积分:673
  • 好友:--
  • 主题:18
  • 回复:21
  • 课时:--
  • 资源:--

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言