EE-Bond

  • 2024-10-31
  • 发表了主题帖: 【2024 DigiKey创意大赛】独居老人居家宝

    本帖最后由 EE-Bond 于 2024-10-31 23:59 编辑 【项目背景与概述】        本项目旨在利用乐鑫开发板和麦克风阵列技术,打造一款智能化的老人家庭照护系统,为老年人提供更安全、更舒适的居家环境   【使用的板卡】 ESP32-S3-LCD-EV-Board:   麦克风阵列:   麦克风阵列控制板:   【视频】 视频   【作品功能】 为独居老人打造一款集对话、控制、告警、AI于一身的照护系统,具有如下核心功能: 1、语音控制家居 2、环境监测 3、老人遇险呼救 4、基于Home Assistant的家居控制   【功能框图】 使用AI实现对使用者呼救信息的判别     功能请看视频演示或下载代码使用。 【分享链接】 https://bbs.eeworld.com.cn/thread-1295335-1-1.html https://bbs.eeworld.com.cn/thread-1291494-1-1.html 【代码】 代码

  • 加入了学习《得捷电子Follow me第4期》,观看 得捷电子Follow me第4期

  • 上传了资料: 得捷大赛代码

  • 2024-10-03
  • 发表了主题帖: 【2024 DigiKey 创意大赛】进度分享,86面板开发指南

    本帖最后由 EE-Bond 于 2024-10-3 12:23 编辑 手头这块ESP32-S3-LCD-EV-Board开发板搭载一块480*480屏幕,显示效果也不错,搭建开发环境耗费了不少时间,主要的开发方式有ESP-IDF、VScode插件、ESP-IDE、Arduino。   以上所有开发方式我都试了个遍,最简单易用、功能也全的还是Arduino:移植好了lvgl、支持SquareLine工程、友好的界面,于是最终选择Arduino作为开发工具。   一、安装好Arduino后,需要安装这些库:注意lvgl的版本,lvgl (>= v8.3.9, < v9),     安装好以后,在文件-示例中可以看到这三个库就安装完成。   二、配置lvgl,需要进入到arduino的库目录下的lvgl文件夹,复制一份lv_conf_template.h到libraries下,并更名为lv_conf.h: 三、修改配置文件:         1、进入lv_conf.h将#if 0 修改为 #if 1 使文件生效。           2、打开ESP32_Display_Panel下的示例,ESP32_Display_Panel-LVGL-v8-Porting                     编辑ESP_Panel_Board_Supported.h文件,修改第十行为#define ESP_PANEL_USE_SUPPORTED_BOARD (1) :     四、编译之前需要修改配置,需要注意的是必须开启PSRAM,否则会导致严重错误,无限重启:   五、如果要使用examples和demos: /* 如果需要使用LVGL内置的 examples 和 demos , 需要取消下面这些头文件的注释: // #include <demos/lv_demos.h> // #include <examples/lv_examples.h> * 同时需要复制 `lvgl/examples` 到 `lvgl/src/examples`. 对于demos也是一样的操作:复制 `lvgl/demos` 到 `lvgl/src/demos`. lvgl/src目录下应该是这样的: 源文件位于lvgl库目录下 六、使用 在上述示例的void setup()函数的第一行: 是显示的文字内容,可以改成任何想要的英文(中文字库需要自行添加):   可以添加一个色环示例看看rgb色彩的效果: lv_example_colorwheel_1();     七、上传代码:                 最终显示效果:       总结:这样这个开发板的环境就搭建好了,目前自定义的ui还在设计中。。。

  • 2024-08-31
  • 加入了学习《FollowMe 第二季: 1 Adafruit Circuit Playground Express及任务讲解》,观看 Adafruit Circuit Playground Express 及任务讲解

  • 2024-08-25
  • 发表了主题帖: 【2024 DigiKey 创意大赛】ESP86面板(ESP32-S3-LCD-EV-Board)物料开箱

    本帖最后由 EE-Bond 于 2024-8-25 21:02 编辑 本次大赛所用物料共2个: Seeed 6麦克风阵列 ESP32-S3-LCD-EV-Board,所搭载的屏幕与家用86面板尺寸相同         到手给ESP32-S3-LCD-EV-Board上电,初始例程还挺精美,UI直接爱了: 开机页面:   初始智能家居面板:   休眠页面:     另外还有语音唤醒功能就不展示了,将一并在后续的创意制作进度中展示。 最后:感谢Digikey,感谢EEWorld。   ESP推荐的烧录工具:ESP Launchpad 可直接烧录官方例程,免去编译;后续开发环境搭建好后,也可以用它烧录编译好的程序。      

  • 加入了学习《【Follow me第二季第1期】使用circuitpython开发并完成全部任务》,观看 【Follow me第二季第1期】使用circuitpython开发并完成全部任务

  • 2024-02-25
  • 发表了主题帖: FolowMe第四期任务提交

    内容一:3-5分钟短视频 FollowMe第四期视频   内容二:任务总结报告 ■  入门任务二:开发环境搭建,BLINK,驱动液晶显示器进行显示(没有则串口HelloWorld) 开发环境使用Arduino ID + C++E完成前置任务,用Thonny + MicroPython完成终极任务。   BLINK程序直接使用Arduinio IDE内置的例程即可,不需要任何修改,直接编译上传代码。 void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { digitalWrite(LED_BUILTIN, HIGH); delay(1000; digitalWrite(LED_BUILTIN, LOW); delay(1000); } 展示:   ■ 基础任务一:完成主控板W5500初始化(静态IP配置),并能使用局域网电脑ping通,同时W5500可以ping通互联网站点;通过抓包软件(Wireshark、Sniffer等)抓取本地PC的ping报文,展示并分析。 本任务需要用Ethernet这个库,由于w5500和rp2040通过SPI连接,需要SPI库,以及进行域名解析的DNS库 #include <SPI.h> #include <Ethernet.h> #include <Dns.h> #include <EthernetICMP.h> IPAddress remoteip; DNSClient dnClient; char buffer[256]; SOCKET pingSocket = 0; EthernetICMPPing ping(pingSocket, (uint16_t)random(0, 255)); byte mac[] = { 0x0E, 0xA0, 0xBE, 0xE4, 0xFE, 0x0D }; void pingTest() { EthernetICMPEchoReply echoReply = ping(remoteip, 4); if (echoReply.status == SUCCESS) { sprintf(buffer, "Reply[%d] from: %d.%d.%d.%d: bytes=%d time=%ldms TTL=%d", echoReply.data.seq, echoReply.addr[0], echoReply.addr[1], echoReply.addr[2], echoReply.addr[3], REQ_DATASIZE, millis() - echoReply.data.time, echoReply.ttl); } else { sprintf(buffer, "Echo request failed; %d", echoReply.status); } Serial.println(buffer); } void setup() { Serial.begin(115200); while (!Serial) { ; // 等待串口连接 } IPAddress ip(192, 168, 10, 188); IPAddress myDns(192, 168, 10, 1); IPAddress gateway(192, 168, 10, 1); IPAddress subnet(255, 255, 255, 0); Serial.println("Ethernet Begin"); Ethernet.init(17); Ethernet.begin(mac, ip, myDns, gateway, subnet); Serial.print("My Mac address: "); byte macBuffer[6]; Ethernet.MACAddress(macBuffer); for (byte octet = 0; octet < 6; octet++) { Serial.print(macBuffer[octet], HEX); if (octet < 5) { Serial.print('-'); } } dnClient.begin(Ethernet.dnsServerIP()); const char domains[3][20] = { "www.eeworld.com.cn", "www.digikey.cn", "www.baidu.com" }; for (int i = 0; i < 3; i++) { if (dnClient.getHostByName(domains[i], remoteip) == 1) { Serial.print(domains[i]); Serial.print(" = "); Serial.println(remoteip); if (i < 3) pingTest(); } else Serial.println(F("dns lookup failed")); } } void loop() { remoteip.fromString("192.168.10.188"); pingTest(); delay(1000); } 展示:   ■ 基础任务二:主控板建立TCPIP或UDP服务器,局域网PC使用TCPIP或UDP客户端进行连接并发送数据,主控板接收到数据后,送液晶屏显示(没有则通过串口打印显示);通过抓包软件抓取交互报文,展示并分析。(TCP和UDP二选一,或者全都操作 抓包结果: 开发板首先设置静态ip连接网络,然后使用TCP,同时另一台PC通过TCP向开发板发送信息。 #include <Ethernet.h> byte mac[] = { 0xDE, 0xAD, 0xBE, 0xE1, 0xF2, 0xE3 }; IPAddress ip(192, 168, 10, 188); IPAddress gateway(192, 168, 10, 1); IPAddress myDns(8, 8, 8, 8); IPAddress subnet(255, 255, 255, 0); IPAddress setNet() { Serial.println("Ethernet Begin"); Ethernet.init(17); Ethernet.begin(mac, ip, myDns, gateway, subnet); Serial.print("My IP address: "); Serial.println(Ethernet.localIP()); Serial.print("My Mac address: "); byte macBuffer[6]; Ethernet.MACAddress(macBuffer); for (byte octet = 0; octet < 6; octet++) { Serial.print(macBuffer[octet], HEX); if (octet < 5) { Serial.print('-'); } } Serial.println(""); return Ethernet.localIP(); } EthernetServer server(5000); String server_loop() { String msg; EthernetClient client = server.available(); if (client) { Serial.println("new client"); while (client.connected()) { if (client.available()) { char c = client.read(); msg += String(c); } } } return msg; } void setup() { Serial.begin(115200); while (!Serial) ;//等待串口 setNet(); server.begin(); } void loop() { String msg = server_loop(); if (msg != "") { Serial.println(msg); } } PC端发送代码: import socket message = "Hello WIZNet-W5500-EVB-Pico, this is a message from vscode" ip_addr=("192.168.10.188",5000) client=socket.socket() client.connect(ip_addr) client.send(bytes(message,"utf-8")) client.close() 展示:   ■ 进阶任务:从NTP服务器(注意数据交互格式的解析)同步时间,获取时间送显示屏(串口)显示。 开发板设置静态IP后,访问国家Ntp授时网站cn.ntp.org.cn获取时间 #include <SPI.h> #include <Ethernet.h> #include <NTPClient.h> byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(192, 168, 10, 188); IPAddress myDns(192, 168, 10, 1); IPAddress gateway(192, 168, 10, 1); IPAddress subnet(255, 255, 255, 0); EthernetUDP Udp; NTPClient timeClient(Udp, "cn.ntp.org.cn"); void setup() { Serial.begin(115200); Serial.begin(9600); while(!Serial){ ; } Ethernet.init(17); Ethernet.begin(mac, ip, myDns, gateway, subnet); timeClient.begin(); } void loop() { timeClient.update(); Serial.print("Current time: "); Serial.println(timeClient.getFormattedTime()); char timeString[9]; // 用于保存格式化后的时.分.秒字符串 sprintf(timeString, "%02d.%02d.%02d", timeClient.getHours(), timeClient.getMinutes(), timeClient.getSeconds()); Serial1.println(timeString); // 输出时.分.秒格式的字符串 delay(5000); // 每5秒更新一次时间到串口显示屏 } 显示效果:         ■  终极任务二:使用外部存储器,组建简易FTP文件服务器,并能正常上传下载文件。 此任务用arduino实现较为困难,故使用Thonny + MicroPython实现,代码如下:   import gc import uos import time import socket import network from time import localtime from machine import Pin, SPI from micropython import const _LED_PIN = const(25) # 绿色 LED 引脚 _SPI_SPEED = const(2_000_000) # SPI 速率 _MOSI_PIN = const(19) # SPI MOSI 引脚 _MISO_PIN = const(16) # SPI MISO 引脚 _SCK_PIN = const(18) # SPI SCK 引脚 _CS_PIN = const(17) # SPI CS 引脚 _RST_PIN = const(20) # SPI RESET 引脚 FTP_ROOT_PATH = const("/Ftp") # FTP 根目录 month_name = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] # SPI 定义 spi=SPI(0, _SPI_SPEED, mosi=Pin(_MOSI_PIN), miso=Pin(_MISO_PIN), sck=Pin(_SCK_PIN)) nic = None """ W5500 初始化 """ def w5x00_init(): global nic # 网口初始化 nic = network.WIZNET5K(spi, Pin(_CS_PIN), Pin(_RST_PIN)) #spi,cs,reset pin nic.active(True) # 配置网络 nic.ifconfig(('192.168.10.188','255.255.255.0','192.168.10.1','8.8.8.8')) while not nic.isconnected(): time.sleep(1) print(nic.regs()) print("IP地址: %s" %nic.ifconfig()[0]) print("子网掩码: %s" %nic.ifconfig()[1]) print("网关: %s" %nic.ifconfig()[2]) print("DNS: %s" %nic.ifconfig()[3]) """ 响应文件列表请求 """ def send_list_data(path, dataclient, full): try: # whether path is a directory name for fname in uos.listdir(path): 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 uos.listdir(path): if fncmp(fname, pattern) == True: 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] tm = localtime(stat[7]) if tm[0] != localtime()[0]: description = "{} 1 owner group {:>10} {} {:2} {:>5} {}\r\n".format( file_permissions, file_size, month_name[tm[1]], tm[2], tm[0], fname) else: description = "{} 1 owner group {:>10} {} {:2} {:02}:{:02} {}\r\n".format( file_permissions, file_size, month_name[tm[1]], tm[2], tm[3], tm[4], fname) else: description = fname + "\r\n" return description """ 发送文件数据 """ def send_file_data(path, dataclient): try: with open(path, "rb") as file: chunk = file.read(512) print("chunk 0: ", len(chunk)) while len(chunk) > 0: print("chunk: ", len(chunk)) dataclient.sendall(chunk) chunk = file.read(512) except Exception as err: print("error: ", err.args, err.value, err.errno) """ 保存文件上传数据 """ def save_file_data(path, dataclient, mode): with open(path, mode) as file: chunk = dataclient.read(512) while len(chunk) > 0: file.write(chunk) chunk = dataclient.read(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 """ 文件名比较 """ 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:]) == True: return True else: si += 1 return False else: return False if pi == len(pattern.rstrip("*")) and si == len(fname): return True else: return False """ 启动FTP服务 """ def ftpserver(): 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", 21)[0][4]) datasocket.bind(socket.getaddrinfo("0.0.0.0", DATA_PORT)[0][4]) ftpsocket.listen(1) datasocket.listen(1) datasocket.settimeout(10) print("FTP服务启动成功!监听端口:21"); msg_250_OK = '250 OK\r\n' msg_550_fail = '550 Failed\r\n' try: dataclient = None fromname = None while True: cl, remote_addr = ftpsocket.accept() cl.settimeout(300) cwd = FTP_ROOT_PATH try: print("新的FTP连接来自: %s:%s" %(remote_addr[0], remote_addr[1])) cl.sendall("220 Welcome! This is the W5500_EVB_PICO!\r\n") while True: gc.collect() data = cl.readline().decode("utf-8").rstrip("\r\n") if len(data) <= 0: print("Client disappeared") break command = data.split(" ")[0].upper() payload = data[len(command):].lstrip() path = get_absolute_path(cwd, payload) print("命令={}, 参数={}, 路径={}".format(command, payload, path)) if command == "USER": cl.sendall("230 Logged in.\r\n") elif command == "SYST": cl.sendall("215 UNIX Type: L8\r\n") elif command == "NOOP": cl.sendall("200 OK\r\n") elif command == "FEAT": cl.sendall("211 no-features\r\n") elif command == "PWD": cl.sendall('257 "{}"\r\n'.format(cwd)) elif command == "CWD": try: files = uos.listdir(path) cwd = path cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "CDUP": cwd = get_absolute_path(cwd, "..") cl.sendall(msg_250_OK) elif command == "TYPE": # probably should switch between binary and not cl.sendall('200 Transfer mode set\r\n') elif command == "SIZE": try: size = uos.stat(path)[6] cl.sendall('213 {}\r\n'.format(size)) except: cl.sendall(msg_550_fail) elif command == "QUIT": cl.sendall('221 Bye.\r\n') break elif command == "PASV": addr = nic.ifconfig()[0] cl.sendall('227 Entering Passive Mode ({},{},{}).\r\n'.format( addr.replace('.',','), DATA_PORT>>8, DATA_PORT%256)) dataclient, data_addr = datasocket.accept() print("新的FTP数据连接来自: %s:%s" %(data_addr[0], data_addr[1])) elif command == "LIST" or command == "NLST": if not payload.startswith("-"): place = path else: place = cwd try: send_list_data(place, dataclient, command == "LIST" or payload == "-l") cl.sendall("150 Here comes the directory listing.\r\n") 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: send_file_data(path, dataclient) cl.sendall("150 Opening data connection.\r\n") 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, "wb") cl.sendall("226 Transfer complete.\r\n") except: cl.sendall(msg_550_fail) if dataclient is not None: dataclient.close() dataclient = None elif command == "APPE": try: cl.sendall("150 Ok to send data.\r\n") save_file_data(path, dataclient, "a") 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": try: uos.rmdir(path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "MKD": 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 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 finally: datasocket.close() ftpsocket.close() if dataclient is not None: dataclient.close() if __name__ == "__main__": print("run in main") w5x00_init() # 初始化网络 ftpserver() # 运行 FTP Server 效果:     内容三:可编译下载的代码   代码链接:代码   心得体会 本次FollowMe活动涵盖了从搭建开发环境到实现网络通讯、时间同步和文件传输等多个方面的技术内容,是一项非常全面和实用的项目。完成这些任务需要对嵌入式系统、网络通信、协议解析等知识有较深入的理解和掌握。 从入门任务开始,了解硬件和软件的基本交互,逐步深入学习和实践,帮助我建立起完整的技术体系。在基础任务中,通过网络通信实现局域网与互联网的连接,抓包分析可以帮助我们更深入地了解数据交互过程,发现问题和优化方案。进阶任务则更进一步地提高了网络通信的要求,需要在数据的接收与显示过程中做更多的处理操作。而终极任务则突破了单一功能,结合外部存储器和FTP协议,实现了文件的传输管理,扩展了功能的同时也加深了对整个系统的理解和应用。 在完成这些任务的过程中,需要不断尝试和调试,遇到问题就分析解决问题。同时,及时查阅文档和资料,积极参与相关领域的社区和讨论,向他人请教和分享经验也是非常重要的。另外,保持学习的热情和对技术的好奇心,不断提升自己的技术水平和解决问题的能力也是很重要的。 总而言之,完成这些任务帮助我建立起扎实的技术基础,培养解决问题的能力和创新意识。同时,也拓展了我对技术领域的认识和理解,为未来的学习和发展打下坚实的基础。感谢Digikey得捷电子,感谢EEWorld。 建议:多多开展此类活动,培养更多全栈工程师

  • 上传了资料: FollowMe第四期代码

最近访客

< 1/1 >

统计信息

已有11人来访过

  • 芯积分:43
  • 好友:--
  • 主题:4
  • 回复:0

留言

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


现在还没有留言