EPTmachine

  • 2024-03-01
  • 加入了学习《泰克MSO6B探索营》,观看 MSO6B技术介绍

  • 加入了学习《泰克MSO6B探索营》,观看 MSO6B-360度介绍

  • 2024-02-25
  • 发表了主题帖: 【得捷Follow me第4期】PiCO_W5500以太网应用

    ### ****[[ 演示视频 ]](https://training.eeworld.com.cn/video/39289 "[ 演示视频 ]")**** Digikey和EEWorld联合举行的FollowMe第四期,本期使用的板卡是WIZnet推出的RP2040搭配W5500开发板PICO W5500。该评估板可用于以太网应用的开发和测试,在其[产品介绍页面](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico)详细对其板载的芯片种类、芯片数据手册、评估板原理图和应用示例进行了介绍。 在Github上有官方提供的代码示例可供参考: - C/C++ Example - [Ethernet Example](https://github.com/Wiznet/RP2040-HAT-C) - [AWS Example](https://github.com/Wiznet/RP2040-HAT-AWS-C) - [Azure Example](https://github.com/Wiznet/RP2040-HAT-AZURE-C) - [Lwip Example](https://github.com/Wiznet/RP2040-HAT-LWIP-C) - [FreeRTOS Example](https://github.com/Wiznet/RP2040-HAT-FREERTOS-C) - [CircuitPython Example](https://github.com/Wiznet/RP2040-HAT-CircuitPython) - [MicroPython Example](https://github.com/Wiznet/RP2040-HAT-MicroPython) 该评估版给出的资源还是十分丰富,从简单的基础示例到复杂的综合应用都有可以借鉴的代码,学习起来还是很方便的。 # 入门任务开发环境搭建、Blink和串口输出任务 本次活动使用MicroPython作为开发语言,使用的软件位Thonny。Thonny软件的安装很简单,安装选项使用默认即可。 完成安装后,在软件的配置选项中选择使用到的代码解释器类型为MicroPython(Raspberry Pi Pico)。 要想在开发板上运行MicroPython的代码,需要将MicroPython的固件烧写到开发板上。首先从[MicroPython W550_EVB_PICO](https://micropython.org/download/W5500_EVB_PICO/)的发布页面下载对应该开发板的MicroPython固件。 按住开发板上的BootSel按键并上电或者在上电状态下,按住BootSel按键的同时,按下Run按键,开发板会进入BootLoader模式,在电脑上会出现一个RPI-RP2的大容量存储设备。 将下载的MicroPython固件发送到该设备,会自动完成固件的烧写。打开Thonny软件,在右下角选择显示出来的开发板。 在Shell中使用`help('modules')`指令可以查看当前固件中支持的函数类。 编写Blink的代码如下,实现对开发板上的LED灯的控制 ```python from machine import Pin import time led = Pin(25, Pin.OUT) def main(): while True: led.value(1) time.sleep(1) led.value(0) time.sleep(1) if __name__ == "__main__": main() ``` 点击工具栏中的Run按键即可运行上述代码,如果想在上电时就运行上述代码,新建一个`main.py`的文件,并上传到设备(这里指的是的pico w5500开发板)的根目录中,这样上电后程序会自动运行Blink的程序。 可以使用`print`函数向Shell输出信息。以下代码实现发送信息的功能。 ```python from machine import Pin import time led = Pin(25, Pin.OUT) def main(): while True: led.value(1) print('LED is on!\n') time.sleep(1) led.value(0) print('LED is off!\n') time.sleep(1) if __name__ == "__main__": main() ``` 运行程序后,在Thonny的Shell串口可以看到发出的信息。 # 基础任务一:主控板W55500初始化(静态IP配置),ping指令使用和数据包抓取 通过使用help指令可以查看network中包含的类,其中的`WIZNET5K`实现了WIZnet芯片的接口函数。可以很方面地使用板上的W5500外设,实现互联网应用。 通过`import`指令导入以下库,用于开启socket支持、GPIO驱动、SPI驱动、网络函数以及时间函数 ```python from usocket import socket from machine import Pin,SPI import network import time ``` 以下代码为W5500的初始化代码,初始化片上的SPI外设以及W5500芯片后,配置网络接口并测试网咯连接是否成功建立,建立成功后,在Shell中输出网卡的配置信息。 ```python #W5x00 chip init def w5x00_init(): spi=SPI(0,2_000_000, mosi=Pin(19),miso=Pin(16),sck=Pin(18)) nic = network.WIZNET5K(spi,Pin(17),Pin(20)) #spi,cs,reset pin nic.active(True) nic.ifconfig(('192.168.1.20','255.255.255.0','192.168.1.1','8.8.8.8')) while not nic.isconnected(): time.sleep(1) print(nic.regs()) print(nic.ifconfig()) ``` 接下来定义主函数如下,调用w5500芯片输出化函数,同时在main函数的循环中调用延时和GPIO翻转函数,用于提示系统正在运行。 ```python def main(): w5x00_init() while True: led.value(1) time.sleep(1) led.value(0) time.sleep(1) if __name__ == "__main__": main() ``` 文章[Python中`if __name__=='__main__':的作用](https://blog.csdn.net/heqiang525/article/details/89879056)对代码中的main函数调用规则进行了说明。 将上述代码整合到一起,在Thonny中打开文件并点击运行,可以看到Shell中输出了当前的开发板的静态IP配置信息。 在Windows中打开PowerShell,使用Ping指令检测与开发板的网络连接是否成功建立。 ```Shell ping 192.168.1.20 ``` 可以看到有以下的输出,说明W5500芯片正常运行, 使用wireshark抓取PC端的网络数据流,使用过滤条件`ip.addr=192.168.1.20`对抓取到数据进行过滤,可以得到ping指令的数据报,ping指令属于ICMP协议中的功能。 从结果中可以看到ping指令发送方和接收方的IP地址,以及其他的数据包信息。 # 基础任务二:主控板建立TCPIP服务器 该任务选择使用TCP功能进行实现服务器,Http应用使用的就是TCP协议,嵌入式的Web点灯是嵌入式终端作为HTTP Server,响应PC端的HTTP请求,从而实现网页控制板卡上的LED灯状态。 基础任务一实现了初始化W5500的函数和LED控制函数,在此基础上添加一个网页初始化函数,生成用于客户端显示的HTML网页。代码如下: ```python def web_page(): if led.value()==1: led_state="ON" else: led_state="OFF" html = """ Raspberry Pi Pico Web server - WIZnet W5100S Raspberry Pi Pico Web server & WIZnet Ethernet HAT Control LED PICO LED state: """ + led_state + """ ON OFF """ return html ``` 在主函数中创建一个socket,用于监听IP地址为192.168.1.20(这里为W5500的IP地址)网卡的端口80,在主循环中,在接收到PC端的客户端请求数据后,发送HTML数据,在接收到返回的数据后,检查其中是否有led_on或者led_off按钮对应的响应数据,据此改变板卡上LED灯的状态。 ```python def main(): w5x00_init() s = socket() s.bind(('192.168.1.20', 80)) s.listen(5) while True: conn, addr = s.accept() print('Connect from %s' % str(addr)) request = conn.recv(1024) request = str(request) #print('Content = %s' % request) led_on = request.find('/?led=on') led_off = request.find('/?led=off') if led_on == 6: print("LED ON") led.value(1) if led_off == 6: print("LED OFF") led.value(0) response = web_page() conn.send('HTTP/1.1 200 OK\n') conn.send('Connection: close\n') conn.send('Content-Type: text/html\n') conn.send('Content-Length: %s\n\n' % len(response)) conn.send(response) conn.close() if __name__ == "__main__": main() ``` 整合上述的代码并运行后,可以看到Shell中输出了相应的配置信息。 在PC端使用浏览器在对话框中输入`192.168.1.20`即可访问控制页面,点击页面上的按钮,即可实现对板卡上的LED灯控制。 使用WireShark捕获网口的通讯数据,添加`ip.addr=192.168.1.20`过滤出其中数据,可以看到传输的数据为TCP协议数据。 # 进阶任务:访问NTP服务器同步时间,获取时间并显示 NTP服务全称为Network Time Protocol,协议中定义了客户端和服务器两个用于数据交互的对象,客户端通过向服务器发送包含符合NTP协议要求的网络数据包,在服务器响应请求并返回相应的数据包之后,根据NTP协议解析其中的数据,即可得到需要的时间信息。 在Shell中输入`help('modules')`指令可以看到固件中已经包含了ntptime库,可以直接调用其中的ntp接口函数来获取当前的时间。 ```python import ntptime import time def sync_ntp(): ntptime.host = 'ntp1.aliyun.com' ntptime.settime() def main(): now = time.time() t = time.localtime(now) year, month, day, hour, minute, second, *_ = t time_str = f"{year}-{month:02d}-{day:02d} {hour:02d}:{minute:02d}:{second:02d}" print("时间:", time_str) if __name__ == "__main__": main() ``` 时间的数据效果如下图所示。 # 终极任务:实现FTP服务器 FTP全称为[File Transfer Protocol](https://en.wikipedia.org/wiki/Network_Time_Protocol),用于在网络中实现服务器与客户端的文件传输。 在开发板上实现FTP服务器的应用,借鉴已有的MicroPython实现FTP协议的示例,完成FTP服务器的搭建。ftpServer.py如下所示: ```python # # Small ftp server for ESP8266 ans ESP32 Micropython # # Based on the work of chrisgp - Christopher Popp and pfalcon - Paul Sokolovsky # # The server accepts passive mode only. # It runs in foreground and quits, when it receives a quit command # Start the server with: # # import ftp # # Copyright (c) 2016 Christopher Popp (initial ftp server framework) # Copyright (c) 2016 Robert Hammelrath (putting the pieces together # and a few extensions) # Distributed under MIT License # import socket import network import uos import gc def send_list_data(path, dataclient, full): try: # whether path is a directory name for fname in sorted(uos.listdir(path), key=str.lower): dataclient.sendall(make_description(path, fname, full)) except: # path may be a file name or pattern pattern = path.split("/")[-1] path = path[:-(len(pattern) + 1)] if path == "": path = "/" for fname in sorted(uos.listdir(path), key=str.lower): if fncmp(fname, pattern): dataclient.sendall(make_description(path, fname, full)) def make_description(path, fname, full): if full: stat = uos.stat(get_absolute_path(path, fname)) file_permissions = ("drwxr-xr-x" if (stat[0] & 0o170000 == 0o040000) else "-rw-r--r--") file_size = stat[6] description = "{} 1 owner group {:>10} Jan 1 2000 {}\r\n".format( file_permissions, file_size, fname) else: description = fname + "\r\n" return description def send_file_data(path, dataclient): with open(path, "rb") as file: chunk = file.read(512) while len(chunk) > 0: dataclient.sendall(chunk) chunk = file.read(512) def save_file_data(path, dataclient): with open(path, "wb") as file: chunk = dataclient.recv(512) while len(chunk) > 0: file.write(chunk) chunk = dataclient.recv(512) def get_absolute_path(cwd, payload): # Just a few special cases "..", "." and "" # If payload start's with /, set cwd to / # and consider the remainder a relative path if payload.startswith('/'): cwd = "/" for token in payload.split("/"): if token == '..': if cwd != '/': cwd = '/'.join(cwd.split('/')[:-1]) if cwd == '': cwd = '/' elif token != '.' and token != '': if cwd == '/': cwd += token else: cwd = cwd + '/' + token return cwd # compare fname against pattern. Pattern may contain # wildcards ? and *. def fncmp(fname, pattern): pi = 0 si = 0 while pi < len(pattern) and si < len(fname): if (fname[si] == pattern[pi]) or (pattern[pi] == '?'): si += 1 pi += 1 else: if pattern[pi] == '*': # recurse if (pi + 1) == len(pattern): return True while si < len(fname): if fncmp(fname[si:], pattern[pi+1:]): return True else: si += 1 return False else: return False if pi == len(pattern.rstrip("*")) and si == len(fname): return True else: return False def ftpserver(net, port=21, timeout=None): DATA_PORT = 13333 ftpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) datasocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ftpsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) datasocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ftpsocket.bind(socket.getaddrinfo("0.0.0.0", port)[0][4]) datasocket.bind(socket.getaddrinfo("0.0.0.0", DATA_PORT)[0][4]) ftpsocket.listen(1) ftpsocket.settimeout(timeout) datasocket.listen(1) datasocket.settimeout(None) msg_250_OK = '250 OK\r\n' msg_550_fail = '550 Failed\r\n' addr = net.ifconfig()[0] print("FTP Server started on ", addr) try: dataclient = None fromname = None do_run = True while do_run: cl, remote_addr = ftpsocket.accept() cl.settimeout(300) cwd = '/' try: # print("FTP connection from:", remote_addr) cl.sendall("220 Hello, this is Micropython.\r\n") while True: gc.collect() data = cl.readline().decode("utf-8").rstrip("\r\n") if len(data) > 8, DATA_PORT % 256)) dataclient, data_addr = datasocket.accept() print("FTP Data connection from:", data_addr) DATA_PORT = 13333 active = False elif command == "PORT": items = payload.split(",") if len(items) >= 6: data_addr = '.'.join(items[:4]) # replace by command session addr if data_addr == "127.0.1.1": data_addr = remote_addr DATA_PORT = int(items[4]) * 256 + int(items[5]) dataclient = socket.socket(socket.AF_INET, socket.SOCK_STREAM) dataclient.settimeout(10) dataclient.connect((data_addr, DATA_PORT)) print("FTP Data connection with:", data_addr) cl.sendall('200 OK\r\n') active = True else: cl.sendall('504 Fail\r\n') elif command == "LIST" or command == "NLST": if not payload.startswith("-"): place = path else: place = cwd try: cl.sendall("150 Here comes the directory listing.\r\n") send_list_data(place, dataclient, command == "LIST" or payload == "-l") cl.sendall("226 Listed.\r\n") except: cl.sendall(msg_550_fail) if dataclient is not None: dataclient.close() dataclient = None elif command == "RETR": try: cl.sendall("150 Opening data connection.\r\n") send_file_data(path, dataclient) cl.sendall("226 Transfer complete.\r\n") except: cl.sendall(msg_550_fail) if dataclient is not None: dataclient.close() dataclient = None elif command == "STOR": try: cl.sendall("150 Ok to send data.\r\n") save_file_data(path, dataclient) cl.sendall("226 Transfer complete.\r\n") except: cl.sendall(msg_550_fail) if dataclient is not None: dataclient.close() dataclient = None elif command == "DELE": try: uos.remove(path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "RMD" or command == "XRMD": try: uos.rmdir(path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "MKD" or command == "XMKD": try: uos.mkdir(path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "RNFR": fromname = path cl.sendall("350 Rename from\r\n") elif command == "RNTO": if fromname is not None: try: uos.rename(fromname, path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) else: cl.sendall(msg_550_fail) fromname = None elif command == "MDTM": try: tm=localtime(uos.stat(path)[8]) cl.sendall('213 {:04d}{:02d}{:02d}{:02d}{:02d}{:02d}\r\n'.format(*tm[0:6])) except: cl.sendall('550 Fail\r\n') elif command == "STAT": if payload == "": cl.sendall("211-Connected to ({})\r\n" " Data address ({})\r\n" "211 TYPE: Binary STRU: File MODE:" " Stream\r\n".format( remote_addr[0], addr)) else: cl.sendall("213-Directory listing:\r\n") send_list_data(path, cl, True) cl.sendall("213 Done.\r\n") else: cl.sendall("502 Unsupported command.\r\n") print("Unsupported command {} with payload {}".format( command, payload)) except Exception as err: print(err) finally: cl.close() cl = None except Exception as e: print(e) finally: datasocket.close() ftpsocket.close() if dataclient is not None: dataclient.close() # ftpserver() ``` 实际的运行效果,shell端的输出 在FTP客户端可以看到开发板上的文件系统中的文件,并可以对其进行操作。 # 总结 Follow Me本期使用的PICO_W5500开发板主要集中与以太网应用,ping指令学习了解到ICMP协议的作用以及wireshark的使用,HTTP应用了解到TCP协议的应用,NTP获取时间学习到服务器和客户端的数据通讯方式,FTP应用学习到网络中实现文件传输服务的方法。而且使用micropython已经编译好的固件,省去了开发底层驱动的烦恼,可以专注于TCP协议的学习,作为入门和学习的不二之选。 ### [代码包](https://download.eeworld.com.cn/detail/EPTmachine/630302 "代码包")

  • 2024-02-22
  • 加入了学习《 【得捷电子Follow me第4期】》,观看 【得捷Follow me第4期】简易FTP文件服务器

  • 加入了学习《 【得捷电子Follow me第4期】》,观看 【得捷Follow me第4期】入门任务:开发环境搭建

  • 2024-02-20
  • 加入了学习《直播回放: FollowMe 4 W5500-EVB-Pico 使用入门》,观看 W5500-EVB-Pico 使用入门

  • 2024-02-03
  • 回复了主题帖: 健康守护礼的入围名单:脉搏监测健康仪,测出“不觉得”(测评邀请券主场活动)

    个人信息确认无误

  • 2023-12-28
  • 加入了学习《ADI - 世健 工业嘉年华》,观看 ADI - 世健 工业嘉年华 开幕致辞

  • 2023-12-17
  • 上传了资料: Follow Me 第三季提交代码

  • 发表了主题帖: 【得捷电子Follow me第3期】+使用ESP32C3完成多个应用体验

    本帖最后由 EPTmachine 于 2023-12-17 22:42 编辑 很荣幸能获得Follow Me第三期的活动资格,本次使用的板卡是Seeed Studio XIAO ESP32C3。是一款基于 Espressif ESP32-C3 Wi-Fi/蓝牙双模芯片的 IoT 迷你开发板。ESP32-C3 是一款32 位 RISC-V CPU,具有强大的计算能力,包含FPU(浮点运算单元),可进行32 位单精度运算。它具有出色的射频性能,支持IEEE 802.11 b/g/n Wi-Fi和蓝牙 5 (LE)协议。正如其名,Seeed Studio XIAO ESP32C3具有小巧精致的外形,还可通过表面贴装整合到更复杂的PCB上。 本次活动指定的配件都是Seeed Studio出品的,在其官网上可以找到详细的板卡资料。 [XIAO ESP32C3介绍界面](https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/#component-overview)。 除了XIAO ESP32C3外,本次选购的配件包括了XIAO系列的通用拓展板(板载OLED、蜂鸣器、用户按键、SD卡插槽等外设)、外接天线、AHT20温湿度传感器、光照传感器等模块,可以用于实现常见的IOT应用。 开发板各个组件的实物连接图如下。 开发板的整体设计很紧凑,而且官网提供资料很丰富,便于开发者使用。 主要完成了以下几个任务,相应的代码如下 介绍视频:[https://training.eeworld.com.cn/video/38742] # 任务一:使用MicroPython系统 ### 安装Thonny 使用MicroPython进行编程需要在开发板和PC上安装和配置MicroPython环境。 在PC端,安装Thonny IDE,安装过程十分简单,安装选项选择默认即可。 Thonny 还提供了免安装的版本,两者的使用方式很简单,大家可以自行选择适合自己的版本。 ### 烧写ESP32C3固件 XIAO ESP32C3需要烧录相应的MicroPython镜像来支持MicroPython程序运行。在win10环境中需要安装Python和esptool支持程序的烧写。 在Python官网下载[Python3.11](https://www.python.org/downloads/)的安装包。在命令行中输入`python --version`查看安装的Python版本。 接下来安装esptool工具 ```shell pip install esptool ``` 从github上拉取[esptool的仓库](https://github.com/espressif/esptool.git)(这里感觉有点怪,win10的Python环境太乱了,我的电脑安装了很多Python版本,这里虽然运行成功了,不保证能复现。。。) ```shell git clone https://github.com/espressif/esptool.git ``` 在第一次烧录MicroPython的镜像时,需要进行全片的flash擦除,这里的COM23根据自己系统和端口不同更换为合适的参数。 ```Shell ./esptool.py --chip esp32c3 --port COM23 erase_flash ``` 从MicroPython的官网下载[ESP32C3的固件](https://micropython.org/download/esp32c3/),将固件放到epstool仓库的根目录。 然后从地址0x00开始烧写固件。 ```Shell ./esptool.py --chip esp32c3 --port COM23 --baud 921600 write_flash -z 0x0 ESP32_GENERIC_C3-20231005-v1.21.0.bin ``` ### 开发环境使用 Thonny 启动后提示环境配置,选择默认即可。 在View选项卡中选择需要显示的菜单,帮助开发者开发。 烧写的固件中自带了常用的测试工具,只需要编写几行代码就可以开始编写应用程序了。 Thonny中提供了可以用于输入命令行的Shell,可用于数据不同的Python指令。 在烧写的micropython固件中集成了系统功能函数,可用于查看系统的信息,了解运行的硬件平台的参数和固件的信息。通过输入`help('modules')`可以查看安装好的库。 使用import os导入系统功能函数,在shell调用相关的函数,比如os.uname即可得到系统的信息。 在Thonny操作界面的右侧可以看到本地文件和开发板上的文件系统,对其进行管理。 开发板上要自动运行程序,至少需要一个boot.py文件,该文件会在开发板上电后自动运行。编写下列函数并上传到开发板中。 ```python import os import gc BOARD_NAME = os.uname().machine gc.collect() print("开发板:%s" % BOARD_NAME) print("剩余内存: %0.2fM" % (gc.mem_free()/1024/1024)) ``` 输出结果如图 # 任务2:驱动扩展板上的OLED屏幕 任务二的目标是是使用扩展板上的OLED屏幕显示文字信息。该屏幕的驱动芯片为SSD1306,通讯协议为I2C,在官方提供的固件中提供了I2C的驱动函数,但是没有SSD1306的驱动函数。需要添加额外的驱动库,本文使用官方提供的ssd1306驱动库。 ## 硬件介绍 ESP32C3模组的IO引脚分布以及扩展板的引脚和功能分布如下图。 由图中信息可知IO引脚使用的是GPIO6(SDA)和GPIO7(SCL)。 ## 驱动库上传 在micropython中,第三方的驱动库一般都放在根目录下的lib文件夹中。 ![驱动库管理](Figure/03/%E9%A9%B1%E5%8A%A8%E5%BA%93%E7%AE%A1%E7%90%86.png) ## 软件编写 确定了OLED屏幕的驱动接口和驱动库,在此基础上就可以编写相应的应用程序了。 首先是显示文字,以下代码实现在OLED屏幕上显示文字 ```python import time from machine import Pin, SoftI2C import ssd1306 import math # ESP8266 Pin assignment i2c = SoftI2C(scl=Pin(7), sda=Pin(6))  # Adjust the Pin numbers based on your connections oled_width = 128 oled_height = 64 oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) oled.fill(0)  # Clear the screen oled.text("Hello, Seeder!", 10, 15) oled.text("/////", 30, 40) oled.text("(`3`)y", 30, 55) oled.show()  # Show the text ``` 效果如图所示。 接下来是在屏幕上显示图形。 ```pyhton import time from machine import Pin, SoftI2C import ssd1306 import math # ESP32C3 Pin assignment i2c = SoftI2C(scl=Pin(7), sda=Pin(6))  # Adjust the Pin numbers based on your connections oled_width = 128 oled_height = 64 oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) center_x = oled_width // 2 center_y = oled_height // 2 square_size = 6  # Size of each square num_squares = 12  # Number of squares angle_increment = 2 * math.pi / num_squares while True:     oled.fill(0)  # Clear the screen         for i in range(num_squares):         angle = i * angle_increment         x = int(center_x + (center_x - square_size-30) * math.cos(angle))         y = int(center_y + (center_x - square_size-30) * math.sin(angle))                  # Draw all squares         for j in range(num_squares):             angle_j = j * angle_increment             x_j = int(center_x + (center_x - square_size-30) * math.cos(angle_j))             y_j = int(center_y + (center_x - square_size-30) * math.sin(angle_j))                          oled.fill_rect(x_j, y_j, square_size, square_size, 1)  # Draw the square                  oled.fill_rect(x, y, square_size, square_size, 0)  # Erase the current square         oled.show()         time.sleep_ms(100)  # Pause before next iteration ``` 效果如图所示 # 任务3:使用蜂鸣器播放音乐 ## 硬件介绍 ESP32C3模组的IO引脚分布以及扩展板的引脚和功能分布如下图。 由图中信息可知控制蜂鸣器的引脚是GPIO5(PWM) ## 软件编写 蜂鸣器的控制GPIO或者PWM即可实现控制,以下代码实现简单的蜂鸣器提示 ```python import time from time import sleep import machine from machine import Pin, SoftI2C # Buzzer settings buzzer_pin = machine.Pin(5, machine.Pin.OUT) buzzer = machine.PWM(buzzer_pin) buzzer.freq(1047) # Buzzer working while True:     buzzer.duty(10)     time.sleep(1)     buzzer.duty(0)     time.sleep(1) ``` 以下代码实现控制蜂鸣器播放音乐 ```python import machine import time # Buzzer settings buzzer_pin = machine.Pin(5, machine.Pin.OUT) buzzer = machine.PWM(buzzer_pin) buzzer.freq(1047) # Defining frequency of each music note NOTE_C4 = 262 NOTE_D4 = 294 NOTE_E4 = 330 NOTE_F4 = 349 NOTE_G4 = 392 NOTE_A4 = 440 NOTE_B4 = 494 NOTE_C5 = 523 NOTE_D5 = 587 NOTE_E5 = 659 NOTE_F5 = 698 NOTE_G5 = 784 NOTE_A5 = 880 NOTE_B5 = 988 # Music notes of the song, 0 is a rest/pulse notes = [     NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,     NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,     NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,     NOTE_A4, NOTE_G4, NOTE_A4, 0,     NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,     NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,     NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,     NOTE_A4, NOTE_G4, NOTE_A4, 0,     NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,     NOTE_A4, NOTE_C5, NOTE_D5, NOTE_D5, 0,     NOTE_D5, NOTE_E5, NOTE_F5, NOTE_F5, 0,     NOTE_E5, NOTE_D5, NOTE_E5, NOTE_A4, 0,     NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,     NOTE_D5, NOTE_E5, NOTE_A4, 0,     NOTE_A4, NOTE_C5, NOTE_B4, NOTE_B4, 0,     NOTE_C5, NOTE_A4, NOTE_B4, 0,     NOTE_A4, NOTE_A4,     #Repeat of first part     NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,     NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,     NOTE_A4, NOTE_G4, NOTE_A4, 0,     NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,     NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,     NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,     NOTE_A4, NOTE_G4, NOTE_A4, 0,     NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,     NOTE_A4, NOTE_C5, NOTE_D5, NOTE_D5, 0,     NOTE_D5, NOTE_E5, NOTE_F5, NOTE_F5, 0,     NOTE_E5, NOTE_D5, NOTE_E5, NOTE_A4, 0,     NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,     NOTE_D5, NOTE_E5, NOTE_A4, 0,     NOTE_A4, NOTE_C5, NOTE_B4, NOTE_B4, 0,     NOTE_C5, NOTE_A4, NOTE_B4, 0,     #End of Repeat     NOTE_E5, 0, 0, NOTE_F5, 0, 0,     NOTE_E5, NOTE_E5, 0, NOTE_G5, 0, NOTE_E5, NOTE_D5, 0, 0,     NOTE_D5, 0, 0, NOTE_C5, 0, 0,     NOTE_B4, NOTE_C5, 0, NOTE_B4, 0, NOTE_A4,     NOTE_E5, 0, 0, NOTE_F5, 0, 0,     NOTE_E5, NOTE_E5, 0, NOTE_G5, 0, NOTE_E5, NOTE_D5, 0, 0,     NOTE_D5, 0, 0, NOTE_C5, 0, 0,     NOTE_B4, NOTE_C5, 0, NOTE_B4, 0, NOTE_A4 ] # Durations (in ms) of each music note of the song # Quarter Note is 250 ms when songSpeed = 1.0 durations = [     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 375, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 375, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 125, 250, 125,     125, 125, 250, 125, 125,     250, 125, 250, 125,     125, 125, 250, 125, 125,     125, 125, 375, 375,     250, 125,     #Rpeat of First Part     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 375, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 375, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 125, 250, 125,     125, 125, 250, 125, 125,     250, 125, 250, 125,     125, 125, 250, 125, 125,     125, 125, 375, 375,     #End of Repeat     250, 125, 375, 250, 125, 375,     125, 125, 125, 125, 125, 125, 125, 125, 375,     250, 125, 375, 250, 125, 375,     125, 125, 125, 125, 125, 500,     250, 125, 375, 250, 125, 375,     125, 125, 125, 125, 125, 125, 125, 125, 375,     250, 125, 375, 250, 125, 375,     125, 125, 125, 125, 125, 500 ] def play_song():     total_notes = len(notes)     for i in range(total_notes):         current_note = notes         wait = durations         if current_note != 0:             buzzer.duty(512)  # Set duty cycle for sound             buzzer.freq(current_note)  # Set frequency of the note         else:             buzzer.duty(0)  # Turn off the sound         time.sleep_ms(wait)         buzzer.duty(0)  # Turn off the sound while True:     # Play the song     play_song() ``` # 任务4:连接WiFi网络 ESP32C3支持Wifi功能,可以连接互联网,从网上获取信息,比如网络时间信息。 ## 连接网络 参考官方提供的代码,填入自己的wifi名称和密码,即可实现联网。 ```python import network import urequests import utime as time # Network settings wifi_ssid = "user_wifi" wifi_password = "user_passwd" 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]) # Execute the functions scan_and_connect() ``` 串口输出的结果如下: ```log Scanning for WiFi networks, please wait... ..... Connected! My IP Address: 192.168.170.168 ``` ## 获取网络时间并显示 网络时间的获取是通过向网络时间服务器发起请求,在返回的json字符串中提取相关的信息,配合之前实现的ssd1306显示功能,从而实现获取网络时间并显示的功能。 代码如下 ```python from machine import Pin, SoftI2C import ssd1306 from time import sleep import time import network import urequests import ujson # ESP32 Pin assignment # i2c = SoftI2C(scl=Pin(22), sda=Pin(21)) # ESP32C3 Pin assignment i2c = SoftI2C(scl=Pin(7), sda=Pin(6))  # Adjust the Pin numbers based on your connections oled_width = 128 oled_height = 64 oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) station = network.WLAN(network.STA_IF) station.active(True) # Network settings wifi_ssid = "user_wifi" wifi_password = "user_passwd" url = "http://worldtimeapi.org/api/timezone/America/New_York" print("Scanning for WiFi networks, please wait...") authmodes = ['Open', 'WEP', 'WPA-PSK' 'WPA2-PSK4', 'WPA/WPA2-PSK'] 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() # Continually try to connect to WiFi access point while not station.isconnected():     # Try to connect to WiFi access point     print("Connecting...")     station.connect(wifi_ssid, wifi_password)     time.sleep(10) # Display connection details print("Connected!") print("My IP Address:", station.ifconfig()[0]) 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         data = ujson.loads(response.text)         # Extract the "datetime" field for New York         ny_datetime = data["datetime"]         # Split the date and time components         date_part, time_part = ny_datetime.split("T")         # Get only the first two decimal places of the time         time_part = time_part[:8]         # Get the timezone         timezone = data["timezone"]                  # Clear the OLED display         oled.fill(0)                  # Display the New York date and time on separate lines         oled.text("New York Date:", 0, 0)         oled.text(date_part, 0, 10)         oled.text("New York Time:", 0, 20)         oled.text(time_part, 0, 30)         oled.text("Timezone:", 0, 40)         oled.text(timezone, 0, 50)         # Update the display         oled.show()     else:         oled.text("Failed to get the time for New York!")         # Update the display         oled.show() ``` 显示效果如图 # 任务5:使用外部传感器 ## 了解硬件 扩展板上提供了I2C和模拟转换接口,分别对应了ATH20温湿度传感器和模拟关线传感器。 [Grove AHT20介绍页面](https://wiki.seeedstudio.com/Grove-AHT20-I2C-Industrial-Grade-Temperature&Humidity-Sensor/)温湿度传感器的接口为I2C。其与扩展板的连接如图所示。 [Grove Light Sensor v1.2](https://wiki.seeedstudio.com/Grove-Light_Sensor/)对其进行了详细的介绍。模块与拓展板的连接如图所示。 ## 添加驱动库 AHT20驱动库地址为:[https://github.com/targetblank/micropython_ahtx0],调用以下指令拉取相关的代码。 ```bash git clone https://github.com/targetblank/micropython_ahtx0 ``` 将代码仓库中的ahtx0.py复制到设备的lib文件夹中,就可以在代码中使用温湿度传感器了。 ## 软件编写 首先编写读取温湿度传感器的代码,以下代码实现对温湿度传感器数据的读取。 ```python import utime from machine import Pin, I2C import ahtx0 i2c = I2C(0, scl=Pin(7), sda=Pin(6), freq=400000) sensor = ahtx0.AHT10(i2c) while True:     print("\nTemperature: %0.2f C" % sensor.temperature)     print("Humidity: %0.2f %%" % sensor.relative_humidity)              utime.sleep(1) ``` 通过串口打印出来的数据如下所示: 接下来通过ADC读取光照传感器的模拟信号,得到当前的光照强度。代码如下: ```python import utime from machine import Pin, ADC # 模拟量 sensor_dev = ADC(Pin(2)) sensor_dev.atten(ADC.ATTN_11DB)  # 这里配置测量量程为0~3.6V while True:     sensor_value = 0     for i in range(0,16):         sensor_value = sensor_value + sensor_dev.read()     sensor_value = sensor_value / 16     Vbattf = 2 * sensor_value / 1000.0     print("\nLight value is: %0.2f C" % Vbattf)         utime.sleep(1) ``` 光照强度的读取结果如下图所示: # 总结 本次活动提供的ESP32C3是为物联网应用设计的,配合MicroPython可以快速实现物联网应用的快速开发。

  • 发表了主题帖: 【得捷电子Follow me第3期】+任务5:使用外部传感器

    这次活动指定的器件中,包括两个传感器模组,ATH20温湿度传感器和模拟光线传感器,可以用于感知外部的环境信息。 ## 了解硬件 扩展板上提供了I2C和模拟转换接口,分别对应了ATH20温湿度传感器和模拟关线传感器。 [Grove AHT20介绍页面](https://wiki.seeedstudio.com/Grove-AHT20-I2C-Industrial-Grade-Temperature&Humidity-Sensor/)温湿度传感器的接口为I2C。其与扩展板的连接如图所示。 [Grove Light Sensor v1.2](https://wiki.seeedstudio.com/Grove-Light_Sensor/)对其进行了详细的介绍。模块与拓展板的连接如图所示。 ## 添加驱动库 AHT20驱动库地址为:[https://github.com/targetblank/micropython_ahtx0],调用以下指令拉取相关的代码。 ```bash git clone https://github.com/targetblank/micropython_ahtx0 ``` 将代码仓库中的ahtx0.py复制到设备的lib文件夹中,就可以在代码中使用温湿度传感器了。 ## 软件编写 首先编写读取温湿度传感器的代码,以下代码实现对温湿度传感器数据的读取。 ```python import utime from machine import Pin, I2C import ahtx0 i2c = I2C(0, scl=Pin(7), sda=Pin(6), freq=400000) sensor = ahtx0.AHT10(i2c) while True:     print("\nTemperature: %0.2f C" % sensor.temperature)     print("Humidity: %0.2f %%" % sensor.relative_humidity)              utime.sleep(1) ``` 通过串口打印出来的数据如下所示: 接下来通过ADC读取光照传感器的模拟信号,得到当前的光照强度。代码如下: ```python import utime from machine import Pin, ADC # 模拟量 sensor_dev = ADC(Pin(2)) sensor_dev.atten(ADC.ATTN_11DB)  # 这里配置测量量程为0~3.6V while True:     sensor_value = 0     for i in range(0,16):         sensor_value = sensor_value + sensor_dev.read()     sensor_value = sensor_value / 16     Vbattf = 2 * sensor_value / 1000.0     print("\nLight value is: %0.2f C" % Vbattf)         utime.sleep(1) ``` 光照强度的读取结果如下图所示: ## 总结 传感器应用属于嵌入式应用中的一大种类,micropython提供的丰富的生态可以帮助用户快速使用应用原型。

  • 2023-12-16
  • 发表了主题帖: 【得捷电子Follow me第3期】+任务4:连接WiFi网络

    ESP32C3支持Wifi功能,可以连接互联网,从网上获取信息,比如网络时间信息。 ## 连接网络 参考官方提供的代码,填入自己的wifi名称和密码,即可实现联网。 ```python import network import urequests import utime as time # Network settings wifi_ssid = "user_wifi" wifi_password = "user_passwd" 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]) # Execute the functions scan_and_connect() ``` 串口输出的结果如下: ```log Scanning for WiFi networks, please wait... ..... Connected! My IP Address: 192.168.170.168 ``` ## 获取网络时间并显示 网络时间的获取是通过向网络时间服务器发起请求,在返回的json字符串中提取相关的信息,配合之前实现的ssd1306显示功能,从而实现获取网络时间并显示的功能。 代码如下 ```python from machine import Pin, SoftI2C import ssd1306 from time import sleep import time import network import urequests import ujson # ESP32 Pin assignment # i2c = SoftI2C(scl=Pin(22), sda=Pin(21)) # ESP32C3 Pin assignment i2c = SoftI2C(scl=Pin(7), sda=Pin(6))  # Adjust the Pin numbers based on your connections oled_width = 128 oled_height = 64 oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) station = network.WLAN(network.STA_IF) station.active(True) # Network settings wifi_ssid = "user_wifi" wifi_password = "user_passwd" url = "http://worldtimeapi.org/api/timezone/America/New_York" print("Scanning for WiFi networks, please wait...") authmodes = ['Open', 'WEP', 'WPA-PSK' 'WPA2-PSK4', 'WPA/WPA2-PSK'] 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() # Continually try to connect to WiFi access point while not station.isconnected():     # Try to connect to WiFi access point     print("Connecting...")     station.connect(wifi_ssid, wifi_password)     time.sleep(10) # Display connection details print("Connected!") print("My IP Address:", station.ifconfig()[0]) 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         data = ujson.loads(response.text)         # Extract the "datetime" field for New York         ny_datetime = data["datetime"]         # Split the date and time components         date_part, time_part = ny_datetime.split("T")         # Get only the first two decimal places of the time         time_part = time_part[:8]         # Get the timezone         timezone = data["timezone"]                  # Clear the OLED display         oled.fill(0)                  # Display the New York date and time on separate lines         oled.text("New York Date:", 0, 0)         oled.text(date_part, 0, 10)         oled.text("New York Time:", 0, 20)         oled.text(time_part, 0, 30)         oled.text("Timezone:", 0, 40)         oled.text(timezone, 0, 50)         # Update the display         oled.show()     else:         oled.text("Failed to get the time for New York!")         # Update the display         oled.show() ``` 显示效果如图 ## 总结 wifi功能给了开发者获取外部信息的方式,使嵌入式设备接入网络,实现贴近实际的应用。

  • 发表了主题帖: 【得捷电子Follow me第3期】+任务3:使用蜂鸣器播放音乐

    Seeed Studio XIAO ESP32C3扩展板上,自带了一个无源蜂鸣器,可以用于提示音以及简单的音乐播放。 ## 硬件介绍 ESP32C3模组的IO引脚分布以及扩展板的引脚和功能分布如下图。 由图中信息可知控制蜂鸣器的引脚是GPIO5(PWM) ## 软件编写 蜂鸣器的控制GPIO或者PWM即可实现控制,以下代码实现简单的蜂鸣器提示 ```python import time from time import sleep import machine from machine import Pin, SoftI2C # Buzzer settings buzzer_pin = machine.Pin(5, machine.Pin.OUT) buzzer = machine.PWM(buzzer_pin) buzzer.freq(1047) # Buzzer working while True:     buzzer.duty(10)     time.sleep(1)     buzzer.duty(0)     time.sleep(1) ``` 以下为演示视频 [localvideo]7c4e0b3813efed42ef84bdd994997b88[/localvideo] 以下代码实现控制蜂鸣器播放音乐 ```python import machine import time # Buzzer settings buzzer_pin = machine.Pin(5, machine.Pin.OUT) buzzer = machine.PWM(buzzer_pin) buzzer.freq(1047) # Defining frequency of each music note NOTE_C4 = 262 NOTE_D4 = 294 NOTE_E4 = 330 NOTE_F4 = 349 NOTE_G4 = 392 NOTE_A4 = 440 NOTE_B4 = 494 NOTE_C5 = 523 NOTE_D5 = 587 NOTE_E5 = 659 NOTE_F5 = 698 NOTE_G5 = 784 NOTE_A5 = 880 NOTE_B5 = 988 # Music notes of the song, 0 is a rest/pulse notes = [     NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,     NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,     NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,     NOTE_A4, NOTE_G4, NOTE_A4, 0,     NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,     NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,     NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,     NOTE_A4, NOTE_G4, NOTE_A4, 0,     NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,     NOTE_A4, NOTE_C5, NOTE_D5, NOTE_D5, 0,     NOTE_D5, NOTE_E5, NOTE_F5, NOTE_F5, 0,     NOTE_E5, NOTE_D5, NOTE_E5, NOTE_A4, 0,     NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,     NOTE_D5, NOTE_E5, NOTE_A4, 0,     NOTE_A4, NOTE_C5, NOTE_B4, NOTE_B4, 0,     NOTE_C5, NOTE_A4, NOTE_B4, 0,     NOTE_A4, NOTE_A4,     #Repeat of first part     NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,     NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,     NOTE_A4, NOTE_G4, NOTE_A4, 0,     NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,     NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,     NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,     NOTE_A4, NOTE_G4, NOTE_A4, 0,     NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,     NOTE_A4, NOTE_C5, NOTE_D5, NOTE_D5, 0,     NOTE_D5, NOTE_E5, NOTE_F5, NOTE_F5, 0,     NOTE_E5, NOTE_D5, NOTE_E5, NOTE_A4, 0,     NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,     NOTE_D5, NOTE_E5, NOTE_A4, 0,     NOTE_A4, NOTE_C5, NOTE_B4, NOTE_B4, 0,     NOTE_C5, NOTE_A4, NOTE_B4, 0,     #End of Repeat     NOTE_E5, 0, 0, NOTE_F5, 0, 0,     NOTE_E5, NOTE_E5, 0, NOTE_G5, 0, NOTE_E5, NOTE_D5, 0, 0,     NOTE_D5, 0, 0, NOTE_C5, 0, 0,     NOTE_B4, NOTE_C5, 0, NOTE_B4, 0, NOTE_A4,     NOTE_E5, 0, 0, NOTE_F5, 0, 0,     NOTE_E5, NOTE_E5, 0, NOTE_G5, 0, NOTE_E5, NOTE_D5, 0, 0,     NOTE_D5, 0, 0, NOTE_C5, 0, 0,     NOTE_B4, NOTE_C5, 0, NOTE_B4, 0, NOTE_A4 ] # Durations (in ms) of each music note of the song # Quarter Note is 250 ms when songSpeed = 1.0 durations = [     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 375, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 375, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 125, 250, 125,     125, 125, 250, 125, 125,     250, 125, 250, 125,     125, 125, 250, 125, 125,     125, 125, 375, 375,     250, 125,     #Rpeat of First Part     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 375, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 375, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 250, 125, 125,     125, 125, 125, 250, 125,     125, 125, 250, 125, 125,     250, 125, 250, 125,     125, 125, 250, 125, 125,     125, 125, 375, 375,     #End of Repeat     250, 125, 375, 250, 125, 375,     125, 125, 125, 125, 125, 125, 125, 125, 375,     250, 125, 375, 250, 125, 375,     125, 125, 125, 125, 125, 500,     250, 125, 375, 250, 125, 375,     125, 125, 125, 125, 125, 125, 125, 125, 375,     250, 125, 375, 250, 125, 375,     125, 125, 125, 125, 125, 500 ] def play_song():     total_notes = len(notes)     for i in range(total_notes):         current_note = notes         wait = durations         if current_note != 0:             buzzer.duty(512)  # Set duty cycle for sound             buzzer.freq(current_note)  # Set frequency of the note         else:             buzzer.duty(0)  # Turn off the sound         time.sleep_ms(wait)         buzzer.duty(0)  # Turn off the sound while True:     # Play the song     play_song() ``` 以下为演示视频 [localvideo]72945ea4c9ad46a841fcb5d234db0590[/localvideo] ## 总结 蜂鸣器的使用简单,但是配合复杂的程序运行逻辑可以实现音乐播放这种应用。

  • 发表了主题帖: 【得捷电子Follow me第3期】+任务2:驱动扩展板上的OLED屏幕

    任务二的目标是是使用扩展板上的OLED屏幕显示文字信息。该屏幕的驱动芯片为SSD1306,通讯协议为I2C,在官方提供的固件中提供了I2C的驱动函数,但是没有SSD1306的驱动函数。需要添加额外的驱动库,本文使用官方提供的ssd1306驱动库。 ## 硬件介绍 ESP32C3模组的IO引脚分布以及扩展板的引脚和功能分布如下图。 由图中信息可知IO引脚使用的是GPIO6(SDA)和GPIO7(SCL)。 ## 驱动库上传 在micropython中,第三方的驱动库一般都放在根目录下的lib文件夹中。 ## 软件编写 确定了OLED屏幕的驱动接口和驱动库,在此基础上就可以编写相应的应用程序了。 首先是显示文字,以下代码实现在OLED屏幕上显示文字 ```python import time from machine import Pin, SoftI2C import ssd1306 import math # ESP8266 Pin assignment i2c = SoftI2C(scl=Pin(7), sda=Pin(6))  # Adjust the Pin numbers based on your connections oled_width = 128 oled_height = 64 oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) oled.fill(0)  # Clear the screen oled.text("Hello, Seeder!", 10, 15) oled.text("/////", 30, 40) oled.text("(`3`)y", 30, 55) oled.show()  # Show the text ``` 效果如图所示。 接下来是在屏幕上显示图形。 ```python import time from machine import Pin, SoftI2C import ssd1306 import math # ESP32C3 Pin assignment i2c = SoftI2C(scl=Pin(7), sda=Pin(6))  # Adjust the Pin numbers based on your connections oled_width = 128 oled_height = 64 oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) center_x = oled_width // 2 center_y = oled_height // 2 square_size = 6  # Size of each square num_squares = 12  # Number of squares angle_increment = 2 * math.pi / num_squares while True:     oled.fill(0)  # Clear the screen         for i in range(num_squares):         angle = i * angle_increment         x = int(center_x + (center_x - square_size-30) * math.cos(angle))         y = int(center_y + (center_x - square_size-30) * math.sin(angle))                  # Draw all squares         for j in range(num_squares):             angle_j = j * angle_increment             x_j = int(center_x + (center_x - square_size-30) * math.cos(angle_j))             y_j = int(center_y + (center_x - square_size-30) * math.sin(angle_j))                          oled.fill_rect(x_j, y_j, square_size, square_size, 1)  # Draw the square                  oled.fill_rect(x, y, square_size, square_size, 0)  # Erase the current square         oled.show()         time.sleep_ms(100)  # Pause before next iteration ``` 效果如图所示 ## 总结 OLED屏幕作为嵌入式应用中常见的人机交互设备,micropython提供了丰富的外设驱动和应用代码,可以快速实现用户的想法。

  • 发表了主题帖: 【得捷电子Follow me第3期】+任务1:使用MicroPython系统

    本文介绍使用MicroPython在XIAO ESP32C3上进行编程。 ## 环境配置 ### 安装Thonny 使用MicroPython进行编程需要在开发板和PC上安装和配置MicroPython环境。 在PC端,安装Thonny IDE,安装过程十分简单,安装选项选择默认即可。 Thonny 还提供了免安装的版本,两者的使用方式很简单,大家可以自行选择适合自己的版本。 ### 烧写ESP32C3固件 XIAO ESP32C3需要烧录相应的MicroPython镜像来支持MicroPython程序运行。在win10环境中需要安装Python和esptool支持程序的烧写。 在Python官网下载[Python3.11](https://www.python.org/downloads/)的安装包。在命令行中输入`python --version`查看安装的Python版本。 接下来安装esptool工具 ```shell pip install esptool ``` 从github上拉取[esptool的仓库](https://github.com/espressif/esptool.git)(这里感觉有点怪,win10的Python环境太乱了,我的电脑安装了很多Python版本,这里虽然运行成功了,不保证能复现。。。) ```shell git clone https://github.com/espressif/esptool.git ``` 在第一次烧录MicroPython的镜像时,需要进行全片的flash擦除,这里的COM23根据自己系统和端口不同更换为合适的参数。 ```Shell ./esptool.py --chip esp32c3 --port COM23 erase_flash ``` 从MicroPython的官网下载[ESP32C3的固件](https://micropython.org/download/esp32c3/),将固件放到epstool仓库的根目录。 然后从地址0x00开始烧写固件。 ```Shell ./esptool.py --chip esp32c3 --port COM23 --baud 921600 write_flash -z 0x0 ESP32_GENERIC_C3-20231005-v1.21.0.bin ``` ## 开发环境使用 Thonny 启动后提示环境配置,选择默认即可。 在View选项卡中选择需要显示的菜单,帮助开发者开发。 烧写的固件中自带了常用的测试工具,只需要编写几行代码就可以开始编写应用程序了。 Thonny中提供了可以用于输入命令行的Shell,可用于数据不同的Python指令。 在烧写的micropython固件中集成了系统功能函数,可用于查看系统的信息,了解运行的硬件平台的参数和固件的信息。通过输入`help('modules')`可以查看安装好的库。 使用import os导入系统功能函数,在shell调用相关的函数,比如os.uname即可得到系统的信息。 在Thonny操作界面的右侧可以看到本地文件和开发板上的文件系统,对其进行管理。 开发板上要自动运行程序,至少需要一个boot.py文件,该文件会在开发板上电后自动运行。编写下列函数并上传到开发板中。 ```python import os import gc BOARD_NAME = os.uname().machine gc.collect() print("开发板:%s" % BOARD_NAME) print("剩余内存: %0.2fM" % (gc.mem_free()/1024/1024)) ``` 输出结果如图 ## 注意事项 Thonny在Win10环境中使用MicroPython的包管理器会报错,在论坛里看到很多人出现这样的问题。 对于上述情况,简单的处理方式就是在本地的工程目录创建一个lib目录,在里面存放开发时所需要的外部库文件。需要更新时,将整个库文件整体上传即可。

  • 2023-12-06
  • 回复了主题帖: 测评颁奖:TI MSPM0L1306 LaunchPad™ 开发套件

    邮寄地址已确认正确,感谢EEWorld和TI!

  • 2023-11-18
  • 发表了主题帖: 【得捷电子Follow me第3期】+开发板硬件介绍

    本帖最后由 EPTmachine 于 2023-11-18 22:55 编辑 ## 开发板硬件介绍 很荣幸能获得Follow Me第三期的活动资格,本次使用的板卡是Seeed Studio XIAO ESP32C3。是一款基于 Espressif ESP32-C3 Wi-Fi/蓝牙双模芯片的 IoT 迷你开发板。ESP32-C3 是一款32 位 RISC-V CPU,具有强大的计算能力,包含FPU(浮点运算单元),可进行32 位单精度运算。它具有出色的射频性能,支持IEEE 802.11 b/g/n Wi-Fi和蓝牙 5 (LE)协议。正如其名,Seeed Studio XIAO ESP32C3具有小巧精致的外形,还可通过表面贴装整合到更复杂的PCB上。 本次活动指定的配件都是Seeed Studio出品的,在其官网上可以找到详细的板卡资料。 [XIAO ESP32C3介绍界面](https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/#component-overview)。 除了XIAO ESP32C3外,本次选购的配件包括了XIAO系列的通用拓展板(板载OLED、蜂鸣器、用户按键、SD卡插槽等外设)、外接天线、AHT20温湿度传感器、光照传感器等模块,可以用于实现常见的IOT应用。 拓展板的功能分布图如下 开发板各个组件的实物连接图如下。 开发板的整体设计很紧凑,而且官网提供资料很丰富,便于开发者使用。

  • 2023-11-16
  • 回复了主题帖: TI【LP_MSPM0L1306开发板】测评——Ennergy Trace使用以及示例学习

    其功能确实强大,不过还是因为用的处理器性能很强的。

  • 2023-11-15
  • 发表了主题帖: TI【LP_MSPM0L1306开发板】测评——Ennergy Trace使用以及示例学习

    Energy Trace介绍以及使用 在LaunchPad MSPM0L1306的用户手册中,介绍了拥有EnergyTrace技术的XDS110-ET板载调试探针。结合CCS开发工具,可以对板载的应用的电路进行测量。 CCS中的Energy Trace工具使用 连接开发板后,在非debug模式下,点击CCS的菜单栏中的EngeryTrace按钮,即可进入EnergyTrace操作界面。 点击开始按钮,即可实现对电路中电流的监控,完成后,可以通过切换不同的标签来实现对结果的查看。 总结 LaunchPad MSPM0L1306的板载调试器的EnergyTrace功能可以实现对电路中电流的测量,对电路的功耗进行评估,操作起来也很简单,在开发过程中可以为工程师提供参考。

  • 回复了主题帖: 【Microchip有奖活动颁奖】快来打造你的理想型单片机

    这个活动奖品发货了吗

统计信息

已有78人来访过

  • 芯积分:268
  • 好友:--
  • 主题:42
  • 回复:122

留言

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


现在还没有留言