【ESP32】DIY一个电子测光仪

这里写目录标题

  • 0 前言
  • 1 开箱
  • 2 过程
    • 2.1 下载固件
    • 2.2 烧录固件
    • 2.3 编程环境 Thonny
    • 2.4 点灯大师
    • 2.5 TFT屏幕
    • 2.6 BH1750传感器
  • 成果展示


0 前言

开发板:ESP32-S3-5691
开发环境:circuitpython+thony


1 开箱


2 过程

2.1 下载固件

使用circuitpython的方式开发,需要先安装circuitpython

我手里的开发板是ESP32-S3 5691 找到对应型号的开发板 找到对应的固件,烧录进去
(这里要注意选择本开发板的固件,不要选错了,我第一次就烧录错了,只有按键和LED可以使用,LCD不能使用,问了陈工,陈工说固件烧录错了,哈哈哈)

在这里插入图片描述
开发板资料网址:https://learn.adafruit.com/esp32-s3-reverse-tft-feather
固件网址:https://circuitpython.org/board/adafruit_feather_esp32s3_reverse_tft/

进入固件的网址之后,下载固件,下载UF2文件,如图所示,我已经下载好了
在这里插入图片描述

2.2 烧录固件

  • 用数据线将核心板链接电脑后双击 RST 按钮
  • 电脑将弹出 FTHRS3BOOT 驱动器
  • 将下载好的固件拖进去即可完成 circuitpython的安装

安装好的样子

在这里插入图片描述

2.3 编程环境 Thonny

推荐使用编程环境Thonny

安装传送门:Thonny, Python IDE for beginner
安装网址:https://thonny.org/

小伙伴们可以自行安装

2.4 点灯大师

安装好编程环境之后,我们就开始写我们的第一个代码,我们作为点灯大师最熟悉的还是点亮一个LED。

复制例程

import board
import digitalio
import timeled = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUTwhile True:led.value = Truetime.sleep(0.5)led.value = Falsetime.sleep(0.5)

将例程粘贴到Thonny中,点击绿色的运行按钮,即可看到现象。

在这里插入图片描述

现象是对的:背面的红色LED在闪烁,1S亮灭一次
点亮LED之后,信心大增,开始点亮LCD屏幕吧!!!

2.5 TFT屏幕

开发板板载一块TFT屏幕,ST7789,此屏幕需要依赖库文件,我们先下载它的库文件
下载地址:https://github.com/adafruit/Adafruit_CircuitPython_ST7789

方法:https://learn.adafruit.com/esp32-s3-reverse-tft-feather/displayio-example
https://github.com/adafruit/Adafruit_CircuitPython_Display_Text

先在github下载这两个文件夹,从中选取所需移植的文件

  • adafruit_st7789.py
  • adafruit_display_text

将下载好的这两个文件,复制粘贴到开发板的lib文件夹下即可

ST7789屏幕的例程代码:https://github.com/adafruit/Adafruit_CircuitPython_ST7789

import board
import displayio
# Starting in CircuitPython 9.x fourwire will be a seperate internal library
# rather than a component of the displayio library
try:from fourwire import FourWire
except ImportError:from displayio import FourWirefrom adafruit_st7789 import ST7789displayio.release_displays()spi = board.SPI()
while not spi.try_lock():pass
spi.configure(baudrate=24000000) # Configure SPI for 24MHz
spi.unlock()
tft_cs = board.D5
tft_dc = board.D6display_bus = FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=board.D9)display = ST7789(display_bus, width=240, height=240, rowstart=80)# Make the display context
splash = displayio.Group()
display.root_group = splashcolor_bitmap = displayio.Bitmap(240, 240, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0xFF0000bg_sprite = displayio.TileGrid(color_bitmap,pixel_shader=color_palette,x=0, y=0)
splash.append(bg_sprite)while True:pass

CV到code.py
运行,LCD没有反应……
寻找解决方法:https://learn.adafruit.com/esp32-s3-reverse-tft-feather/displayio-example
在这一页里其实介绍了怎么使用LCD,最开始没有仔细看在这里插入图片描述

DisplayIO Example
Your board comes with a lovely TFT display built right in. You can use the display with CircuitPython and the displayio module. This module allows you to easily write Python code that lets you create graphics.
CircuitPython Usage
To use with CircuitPython, you need to first install the adafruit_display_text library, and its dependencies, into the lib folder on your CIRCUITPY drive. Then you need to update code.py with the example script.
Thankfully, we can do this in one go. In the example below, click the Download Project Bundle button below to download the necessary libraries and the code.py file in a zip file. Extract the contents of the zip file, and copy the entire lib folder and the code.py file to your CIRCUITPY drive.
Your CIRCUITPY/lib folder should contain the following folders:

  • /adafruit_display_text
  • /adafruit_bitmap_font

翻译一下就是

DisplayIO 示例
您的主板内置了一个可爱的 TFT 显示屏。您可以将显示器与 CircuitPython 和 displayio 模块一起使用。此模块允许您轻松编写用于创建图形的 Python 代码。
CircuitPython 用法
要与 CircuitPython 一起使用,您需要首先将 adafruit_display_text 库及其依赖项安装到 CIRCUITPY 驱动器上的 lib 文件夹中。然后,您需要使用示例脚本更新 code.py。
值得庆幸的是,我们可以一次性完成此操作。在下面的示例中,单击下面的 Download Project Bundle 按钮,以 zip 文件的形式下载必要的库和 code.py 文件。解压缩 zip 文件的内容,并将整个 lib 文件夹和 code.py 文件复制到 CIRCUITPY 驱动器
您的 CIRCUITPY/lib 文件夹应包含以下文件夹:

  • /adafruit_display_text
  • /adafruit_bitmap_font

那我们现在需要按照官方给出的步骤操作即可。

在这里插入图片描述
下载这个zip文件,解压,将里面的文件复制粘贴到开发板的lib文件夹下面

\Adafruit_Feather_ESP32-S2_Reverse_TFT\display\CircuitPython 9.x 文件夹下的文件有两个

  • lib
  • code.py

整个 lib 文件夹和 code.py 文件复制到 CIRCUITPY 驱动器
然后就发现,lib文件夹下多了几个后缀为.mpy的文件
在这里插入图片描述
在这里插入图片描述
现在,我们再运行一下程序试试,能否点亮TFT屏幕

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT"""
This test will initialize the display using displayio and draw a solid green
background, a smaller purple rectangle, and some yellow text.
"""
import board
import terminalio
import displayio
from adafruit_display_text import label# First set some parameters used for shapes and text
BORDER = 20
FONTSCALE = 2
BACKGROUND_COLOR = 0x00FF00  # Bright Green
FOREGROUND_COLOR = 0xAA0088  # Purple
TEXT_COLOR = 0xFFFF00display = board.DISPLAY# Make the display context
splash = displayio.Group()
display.root_group = splashcolor_bitmap = displayio.Bitmap(display.width, display.height, 1)
color_palette = displayio.Palette(1)
color_palette[0] = BACKGROUND_COLORbg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
splash.append(bg_sprite)# Draw a smaller inner rectangle
inner_bitmap = displayio.Bitmap(display.width - BORDER * 2, display.height - BORDER * 2, 1
)
inner_palette = displayio.Palette(1)
inner_palette[0] = FOREGROUND_COLOR
inner_sprite = displayio.TileGrid(inner_bitmap, pixel_shader=inner_palette, x=BORDER, y=BORDER
)
splash.append(inner_sprite)# Draw a label
text = "Hello World!"
text_area = label.Label(terminalio.FONT, text=text, color=TEXT_COLOR)
text_width = text_area.bounding_box[2] * FONTSCALE
text_group = displayio.Group(scale=FONTSCALE,x=display.width // 2 - text_width // 2,y=display.height // 2,
)
text_group.append(text_area)  # Subgroup for text scaling
splash.append(text_group)while True:pass

在这里插入图片描述

终于点亮了这块屏幕

2.6 BH1750传感器

BH1750 数字光传感器模块的优点以及信号的获取

  • 硬件接线,本传感器是I2C协议的,开发板后面的丝印有显示SCL、SDA、3V3、GND,先把硬件接线完成

  • 源码:https://github.com/adafruit/Adafruit_CircuitPython_ST7789

  • 在github里下载库文件adafruit_st7789.py,然后放到lib文件夹下,复制源码

import time
import board
import adafruit_bh1750i2c = board.I2C()
sensor = adafruit_bh1750.BH1750(i2c)while True:print("%.2f Lux"%sensor.lux)time.sleep(1)

运行代码,效果如下:
在这里插入图片描述
在这里插入图片描述
可以读取到传感器的数据

参考大佬的代码:
https://forum.eepw.com.cn/thread/387489/1/#2
https://share.eepw.com.cn/share/download/id/394263

import time
import board
import terminalio
import displayio
import adafruit_bh1750
import math
from digitalio import DigitalInOut, Direction, Pull
from adafruit_display_text import label
from adafruit_bh1750 import Resolution#keypad
KEY_NULL = 0
KEY_D0   = 1
KEY_D1   = 2
KEY_D2   = 4key0 = DigitalInOut(board.BOOT0)
key1 = DigitalInOut(board.D1)
key2 = DigitalInOut(board.D2)def keyInit():key0.direction = Direction.INPUTkey0.pull = Pull.UPkey1.direction = Direction.INPUTkey1.pull = Pull.DOWNkey2.direction = Direction.INPUTkey2.pull = Pull.DOWNdef keyDetect():key_value = KEY_NULLif key0.value == 0:key_value +=KEY_D0if key1.value:key_value +=KEY_D1if key2.value:key_value +=KEY_D2return key_valuedef isKeyPressed():key_value = keyDetect()if key_value:time.sleep(0.01) if key_value == keyDetect():return key_valuereturn 0# display
BORDER = 20
TEXT_HIGH = 26
FONTSCALE = 2
BACKGROUND_COLOR = 0x00FF00  # Bright Green
FOREGROUND_COLOR = 0xAA0088  # Purple
TEXT_COLOR = 0xFFFF00        # Yellow
TEXT_COLOR_RED = 0xFF0000    # Red
TEXT_COLOR_WHITE = 0xFFFFFF  # White# BH1750
i2c = board.I2C()
sensor = adafruit_bh1750.BH1750(i2c)AV = ['1  ','1.4','2  ','2.8','4  ','5.6','8  ','11 ','16 ','22 ','32 '
]
TV = ['1     ','1/2   ','1/4   ','1/8   ','1/15  ','1/30  ','1/60  ','1/125 ','1/250 ','1/500 ','1/1000'
]
SV = ['100 ','200 ','400 ','800 ','1600'
]def showCameraInfo(svIdx : int, avIdx : int):lux = sensor.luxev = math.floor(2 + math.log(lux / 10) / math.log(2))display = board.DISPLAYsplash = displayio.Group()display.root_group = splashtext_Line0 = "LUX: " + ("%0.2f" % lux)text_Line0_area = label.Label(terminalio.FONT, text=text_Line0, color=TEXT_COLOR)text_Line0_group = displayio.Group(scale=FONTSCALE, x=0, y=TEXT_HIGH  // 2)text_Line0_group.append(text_Line0_area)splash.append(text_Line0_group)text_Line1 = "EV: " + str(ev)text_Line1_area = label.Label(terminalio.FONT, text=text_Line1, color=TEXT_COLOR)text_Line1_group = displayio.Group(scale=FONTSCALE, x=0, y=TEXT_HIGH * 2 - TEXT_HIGH  // 2)text_Line1_group.append(text_Line1_area)splash.append(text_Line1_group)text_Line2 = "F: " + AV[avIdx]text_Line2_area = label.Label(terminalio.FONT, text=text_Line2, color=TEXT_COLOR)text_Line2_group = displayio.Group(scale=FONTSCALE, x=0, y=TEXT_HIGH * 3 - TEXT_HIGH  // 2)text_Line2_group.append(text_Line2_area)splash.append(text_Line2_group)text_Line3 = "ISO: " + SV[svIdx]text_Line3_area = label.Label(terminalio.FONT, text=text_Line3, color=TEXT_COLOR)text_Line3_group = displayio.Group(scale=FONTSCALE, x=0, y=TEXT_HIGH * 4 - TEXT_HIGH  // 2)text_Line3_group.append(text_Line3_area)splash.append(text_Line3_group)text_Line4 = "S: " + TV[ev + svIdx - avIdx]text_Line4_area = label.Label(terminalio.FONT, text=text_Line4, color=TEXT_COLOR)text_Line4_group = displayio.Group(scale=FONTSCALE, x=0, y=TEXT_HIGH * 5 - TEXT_HIGH  // 2)text_Line4_group.append(text_Line4_area)splash.append(text_Line4_group)def cameraInfoHdl(old_key_value : int):key_value = old_key_valuesvIdx = 0avIdx = 0showCameraInfo(svIdx, avIdx)while True:key_value=isKeyPressed()if old_key_value != key_value:old_key_value = key_valueif key_value == KEY_D0:breakelif key_value == KEY_D1:svIdx += 1if len(SV) <= svIdx :svIdx = 0showCameraInfo(svIdx, avIdx)elif key_value == KEY_D2:avIdx +=1if avIdx >= len(AV):avIdx = 0showCameraInfo(svIdx, avIdx)def showLux(mode : int):display = board.DISPLAYsplash = displayio.Group()display.root_group = splashif mode == 0:text_mode = "Mode High"elif mode == 1:text_mode = "Mode Low"elif mode == 2:text_mode = "Mode Middle"text_mode_area = label.Label(terminalio.FONT, text=text_mode, color=TEXT_COLOR)text_mode_group = displayio.Group(scale=FONTSCALE, x=0, y=display.height // 4)text_mode_group.append(text_mode_area)splash.append(text_mode_group)text_lux = ("%0.2f" % sensor.lux) + "Lux"text_lux_area = label.Label(terminalio.FONT, text=text_lux, color=TEXT_COLOR)text_lux_group = displayio.Group(scale=FONTSCALE, x=0, y=display.height // 2)text_lux_group.append(text_lux_area)splash.append(text_lux_group)def luxHdl(old_key_value : int):key_value = old_key_valuei = 0showLux(i)while True:key_value=isKeyPressed()if old_key_value != key_value:old_key_value = key_valueif key_value == KEY_D0:breakelif key_value == KEY_D1:i += 1if i == 1:sensor.set_mode(Resolution.LOW)elif i == 2:sensor.set_mode(Resolution.MID)elif i == 3:sensor.set_mode(Resolution.HIGH)i = 0showLux(i)def showHelloEEPW():display = board.DISPLAYsplash = displayio.Group()display.root_group = splashcolor_palette = displayio.Palette(1)"""color_bitmap = displayio.Bitmap(display.width, display.height, 1)color_palette[0] = BACKGROUND_COLORbg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)splash.append(bg_sprite)""""""inner_bitmap = displayio.Bitmap(display.width, display.height - BORDER * 2, 1)inner_palette = displayio.Palette(1)inner_palette[0] = FOREGROUND_COLORinner_sprite = displayio.TileGrid(inner_bitmap, pixel_shader=inner_palette, x=0, y=BORDER)splash.append(inner_sprite)"""text = "EEPW & DigiKey"text_area = label.Label(terminalio.FONT, text=text, color=TEXT_COLOR)text_width = text_area.bounding_box[2] * FONTSCALEtext_group = displayio.Group(scale=FONTSCALE, x=display.width // 2 - text_width // 2, y=display.height // 2)text_group.append(text_area)splash.append(text_group)def showEEPWHdl(old_key_value : int):key_value = old_key_valueshowHelloEEPW()while True:key_value=isKeyPressed()if old_key_value != key_value:old_key_value = key_valueif key_value == KEY_D0:breakdef showFunctionMenu(index: int):display = board.DISPLAYsplash = displayio.Group()display.root_group = splashtext_line0 = "EEPW & DigiKey"if index == 0:text_line0_area = label.Label(terminalio.FONT, text=text_line0, background_color=TEXT_COLOR_WHITE, color=TEXT_COLOR_RED)else:text_line0_area = label.Label(terminalio.FONT, text=text_line0, color=TEXT_COLOR)text_line0_group = displayio.Group(scale=FONTSCALE, x=0, y=TEXT_HIGH  // 2)text_line0_group.append(text_line0_area)splash.append(text_line0_group)text_line1 = "Lux Control"if index == 1:text_line1_area = label.Label(terminalio.FONT, text=text_line1, background_color=TEXT_COLOR_WHITE, color=TEXT_COLOR_RED)else:text_line1_area = label.Label(terminalio.FONT, text=text_line1, color=TEXT_COLOR)text_line1_group = displayio.Group(scale=FONTSCALE, x=0, y=TEXT_HIGH * 2 - TEXT_HIGH  // 2)text_line1_group.append(text_line1_area)splash.append(text_line1_group)text_line2 = "ISO"if index == 2:text_line2_area = label.Label(terminalio.FONT, text=text_line2, background_color=TEXT_COLOR_WHITE, color=TEXT_COLOR_RED)else:text_line2_area = label.Label(terminalio.FONT, text=text_line2, color=TEXT_COLOR)text_line2_group = displayio.Group(scale=FONTSCALE, x=0, y=TEXT_HIGH * 3 - TEXT_HIGH  // 2)text_line2_group.append(text_line2_area)splash.append(text_line2_group)# Main function
key_value = 0
old_key_value = key_value
i = 0
keyInit()
showFunctionMenu(i)
while True:# 按键检测key_value = isKeyPressed()if old_key_value != key_value:old_key_value = key_valueif key_value == KEY_D0:if i == 0:showEEPWHdl(key_value)elif i == 1:luxHdl(key_value)elif i == 2:cameraInfoHdl(key_value)elif key_value == KEY_D1:if i == 0:i = 2else:i -= 1elif key_value == KEY_D2:if i == 2:i = 0else:i += 1showFunctionMenu(i)

成果展示

上电后,按D1和D2切换选择功能项,选中的功能项会高亮显示,按D0是确定按键,进入当前的功能。
在这里插入图片描述

进入亮度检测模式后,按D1键切换亮度检测精度,D2键刷新亮度,D0键返回上一级

在这里插入图片描述

进入logo界面,按D0键返回上一级

在这里插入图片描述

进入ISO界面,按D2切换光圈大小,D1键切换ISO,D0键退出

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/14104.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

MSA+抑郁症模型总结

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&#x1f3a5; 希望在…

解决Jenkins使用 Git 参数插件拉取 commit 列表缓慢问题

Jenkins使用 Git 参数插件拉取 commit 列表缓慢问题 项目问题问题描述解决方案具体实现 项目问题 在 Jenkins 中使用 Git 参数插件 进行参数化构建&#xff0c;具有多方面的重要性和好处。这不仅提高了构建的灵活性和透明度&#xff0c;还能大大提升开发和运维效率。以下是使用…

黑马智数Day7

获取行车管理计费规则列表 封装接口 export function getRuleListAPI(params) {return request({url: parking/rule/list,params}) } 获取并渲染数据 import { getRuleListAPI } from /apis/carmounted() {this.getRuleList() }methods: {// 获取规则列表async getRuleList(…

员工电脑怎么监控?这些电脑监控软件必备

在当今远程办公、灵活工时盛行的时代&#xff0c;如何掌握员工的在线活动、确保工作效率和数据安全成为许多企业关注的焦点。电脑监控软件作为管理工具中的关键一环&#xff0c;可以有效帮助企业了解员工的在线行为&#xff0c;避免效率低下和数据泄露等风险。今天我们就来介绍…

学习干货|实战学习应急响应之Windows日志分析,网络安全零基础入门到精通教程!

前言 本次环境将从大赛内与实战环境相结合去了解在应急响应中Windows日志分析的几个关键点&#xff0c;符合大赛及真实环境案例&#xff0c;本次环境将从WEB层面的日志分析到主机内的几种关键日志分析和重点功能进行排查 题目描述&#xff1a;某台Windows服务器遭到攻击者入侵…

零基础光伏人,数据计算轻松拿捏

在可再生能源领域&#xff0c;光伏产业以其清洁、可再生的特点日益受到全球关注。然而&#xff0c;对于初学者或“零基础光伏人”而言&#xff0c;光伏项目涉及的一系列数据计算和专业知识往往显得复杂而难以入手。幸运的是&#xff0c;随着技术的进步&#xff0c;一系列光伏计…

一文搞懂链表相关算法

目录 链表的逆序和截断 逆序 截断 查找链表的中间节点 力扣题 博主主页&#xff1a;东洛的克莱斯韦克-CSDN博客 链表的逆序和截断 逆序 推荐使用头插法逆序&#xff0c;首先要 new 一个虚拟头节点——newNode。如下图 链表的头节点为head&#xff0c;由cur指针指向head&a…

红外热成像技术开启光伏检测新视界

随着全球对可再生能源需求的不断增加&#xff0c;光伏发电系统的应用日益广泛。然而&#xff0c;光伏组件在长期运行中可能会出现各种故障&#xff0c;如热斑效应、隐裂、接线盒故障等&#xff0c;这些问题不仅影响光伏系统的发电效率&#xff0c;还可能引发安全隐患。 红外热成…

基于vue框架的的社区智慧养老系统1mo30(程序+源码+数据库+调试部署+开发环境)

系统程序文件列表 项目功能&#xff1a;老人,员工,老人档案,养生视频,社区医生,就医信息,在线咨询,咨询回复,菜品信息,点餐订单,服务预约,通知信息,服务评价,健康关爱,新闻公告,监控日志 开题报告内容 以下是一份基于Vue框架的社区智慧养老系统的开题报告&#xff0c;详细阐述…

龙蜥8.6 配置用户登录次数和锁定策略(已亲测)

操作系统&#xff1a;龙蜥8.6 x86_64 查看是否安装pam模块 rpm -qa | grep pam 查看可以使用的认证模块&#xff0c;因为有的系统是pam_tally2. cd /etc/pam.d ls 经过查看&#xff0c;该服务器是使用的pam_faillock 模块 打开/etc/pam.d/password-auth 的 PAM 配置文件…

【6.4】位运算-判断是否存在重复元素

一、题目 给定一个整数数组&#xff0c;判断 是否存在重复元素 。如果存在一值在数组中 出现至少两次 &#xff0c;函数返回 true 。如果数组中每个元素都不相同&#xff0c;则返回 false 。 示例 1: 输入: [ 1 , 2 , 3 , 1 ] 输出: true 示例 2: 输入: [ 1 , 2 , 3 , 4 ] 输出…

PCB打样下单流程

PCB打样下单流程 一、PCB打样在线下单流程1&#xff0e;平台登录2&#xff0e;PCB打样领券3&#xff0e;进入下单系统4&#xff0e;上传PCB文件5&#xff0e;PCB订单界面 PCB&#xff08;印刷电路板&#xff09;打样是验证设计、优化性能和推进项目进度的关键环节。随着互联网的…

Python爬虫知识体系-----正则表达式-----持续更新

数据科学、数据分析、人工智能必备知识汇总-----Python爬虫-----持续更新&#xff1a;https://blog.csdn.net/grd_java/article/details/140574349 文章目录 一、正则基础1. 为什么使用正则2. 正则与re模块简介 二、正则表达式1. 匹配单个字符与数字2. 限定符3. 定位符4. 选择匹…

yolo标签自动标注(使用python和yolo方法)

yolo代码自动标注 1.引言1.初阶“自动标注”&#xff0c;给每个图像都生成一个固定的标注文件&#xff0c;进而在labglimg中对矩形框进行微调&#xff0c;减少标注的工作量2.高阶自动标注&#xff0c;利用我们训练好的&#xff08;但是没有特别精准的&#xff09;yolo文件先对每…

在 WPF 中,如何使用命令来替代事件处理?

在 WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;命令是一种非常强大的替代传统事件处理的方法&#xff0c;特别适用于 MVVM&#xff08;Model-View-ViewModel&#xff09;架构。命令可以实现界面&#xff08;View&#xff09;和逻辑&#xff08;…

语音 AI 革命:未来,消费者更可能倾向于与 AI 沟通,而非人工客服

「未来&#xff0c;消费者更可能倾向于与 AI 沟通&#xff0c;而非人工客服&#xff0c;因为这将成为解决问题的最高效途径。」 这篇来自 Bessemer Venture Partners 的报告&#xff0c;是目前为止对语音 AI 在企业应用上最完整清晰的一次梳理。 核心要点&#xff1a; 尽管市…

过去几年电子学习的趋势

近年来&#xff0c;在技术和不断变化的学习者期望的推动下&#xff0c;电子学习已经发展成为一种适应性强、沉浸式和社会化的教育形式。个性化已成为最具影响力的趋势之一&#xff0c;Coursera和LinkedIn Learning等平台为个人量身定制内容。这些平台使用人工智能来建议课程、跟…

Java基础-Java多线程机制

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 一、引言 二、多线程的基本概念 1. 线程与进程 2. 多线程与并发 3. 多线程的优势 三、Java多线程的实…

springboot 之 整合springdoc2.6 (swagger 3)

版本 springboot 3.3.5 jdk 17 springdoc 2.6.0 依赖pom <dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.6.0</version> </dependency>注解对比…

Zabbix部署

1.集群规划 进程虚拟机节点1虚拟机节点2虚拟机节点3zabbix-agent√√√zabbix-server√PostgreSQL√zabbix-web√ 2.准备工作 默认在虚拟机节点2安装kafka、在虚拟机节点3安装redis 2.1关闭3台节点防火墙 sudo systemctl stop firewalld.service sudo systemctl disable fi…