尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
MicroPython传感器实战:从ADC到I2C单总线,读完就能调通
把传感器接到开发板上跑通数据是我在实际项目里最容易被卡住的一道坎。前几篇聊MicroPython的基础语法、GPIO和中断这期终于进入传感器应用也是很多朋友问得最多的一块到底该怎么在MicroPython里稳定读取各种传感器数据而不是一通电就飘、一接上就读不到、一抖动就重启。这篇博文我准备用真实调试的顺序来讲先搞清楚哪些传感器适合用MicroPython操作然后从最简单的模拟量读数开始再走I2C、单总线这类数字协议最后聊一聊我踩过的坑和排查方法。内容不追求教科书式的全面而是从实战出发把我调试过的板子和模块经验整理成一份可以直接照着做的笔记适合刚开始玩MicroPython、准备拿传感器做小项目的朋友参考。1. 为什么在MicroPython里做传感器应用这么顺手1.1 把硬件调试变成Python交互用MicroPython读传感器最大的体验提升就是不用编译、不用烧录直接进REPL敲指令就能看数据。我早期做嵌入式都是C语言流程改一个延时函数要重新编译烧录看串口输出还要连调试器。换到MicroPython之后连上USB串口先把传感器模块接好然后用machine库读一次寄存器当场就能看到返回值是不是合理范围再决定要不要继续调电路。这个交互式调试习惯直接改变了我做传感器驱动的节奏。原来是一整套驱动写完再debug现在变成先确认硬件通路、再验证原始数据、最后封装业务逻辑。每到一个环节都会在REPL里确认一次排查起来效率高很多也大幅降低了对示波器和逻辑分析仪的依赖很多低级接线错误直接在Python里就能发现。不过这里也要提醒一下MicroPython底层不是C语言那种实时响应GPIO翻转时间也不是纳秒级。对于DHT11这类单总线协议里要求微秒级时序的传感器MicroPython的解释执行会带来不小的不确定性后面我会专门讲这个问题。1.2 传感器接口类型和MicroPython的对应关系很多新手在选传感器的时候只看功能不看接口类型买回来才发现自己的开发板不支持或者接线方式完全搞不懂。我习惯把传感器接口分成三类对应到MicroPython里不同的操作方式。第一类是模拟量输出比如光敏电阻、电位器、MEMS麦克风模块。这类传感器输出一个连续电压值MicroPython里用ADC类去读取重点要搞清楚参考电压、ADC位数和分压电路后面我会详细拆解。第二类是数字量脉冲输出比如一些风速传感器、流量计按频率输出方波。MicroPython里通过计数引脚或者定时器捕获方式处理但严格来说它不算是直接读取传感器寄存器更像是在做脉冲测量。第三类是基于总线的数字传感器常见的有I2C、SPI、单总线。温度传感器BME280、湿度传感器DHT11、六轴姿态传感器MPU6050都属于这一类。这类传感器一般输出校准后的真实物理量MicroPython里通过I2C、SPI、onewire等模块来操作。这里要特别注意MicroPython对常见芯片都有官方或社区驱动库很多传感器不需要自己从头写寄存器读写代码优先找现成库能省大量时间。这三类接口对硬件接线和软件方式要求完全不同。我建议入手新传感器前先看数据手册确认输出类型再决定用哪个MicroPython模块。少走弯路的第一步就从这个判断开始。1.3 传感器应用的基础硬件准备做传感器应用硬件清单比较固定我不列特别复杂的东西就说说每次调试时手边一定会放的几样。首当其冲是一块支持MicroPython的开发板推荐选带Wi-Fi的型号方便后续数据上传。然后是传感器模块若干尽量选3.3V可用的版本避免电平兼容问题。还需要面包板和杜邦线这个不用说调试阶段必备。多电压稳压模块有时也要备一个多个传感器同时上电时靠开发板的3.3V稳压器常常不够用。接线上有几个原则我每次都先确认先共地所有模块的地线必须和开发板地线连在一起再对电平传感器供电如果是5V它的输出信号不一定是3.3V能被接受的最后检查电源分配两个以上传感器最好不要全从开发板引脚取电必要时用稳压模块单独供电。下表是我常用的一个接线规范参考用到不同协议时思路一致。连接对象开发板引脚传感器侧备注电源3V3VCC确认模块是否支持3.3V地GNDGND必须共地I2C时钟SCLSCL很多模块用SCL/SCK标I2C数据SDASDA部分模块标注为SDI/SDO模拟量ADC引脚OUT/AOUT避开默认PWM占用脚单总线任意GPIODATA/OUT可能需要上拉电阻按照这个表接线能避免大量低级错误。前期有一次我把SCL和SDA接反了REPL里i2c.scan()返回空列表排查一个小时才反应过来最基础的检查反而最容易被忽略。2. 从模拟量开始用ADC读取光敏电阻2.1 ADC原理没那么神秘模拟量传感器输出的是一段连续电压单片机不能直接理解“连续”必须通过模数转换器把电压变成一个数字。MicroPython里的machine.ADC就是封装了这套转换过程你拿到的返回值本质上是一个整数比如12位精度下范围是0到4095。这个数字和实际电压之间怎么换算取决于你的开发板。很多开发板的ADC参考电压是3.3V那么数字值raw对应的电压就是raw * 3.3 / 4095。有些开发板支持不同衰减档位设置之后量程可能从1.1V变成3.6V这一点必须查对应引脚说明。我用过最简单的模拟量传感器就是光敏电阻模块它内部是一个光敏电阻和一个固定电阻构成分压电路环境光变化时输出电压跟着变化。MicroPython里拿这个电压值就可以做环境光判断比如控制LED亮度或者记录光照变化趋势。实际使用时不要迷信某个百分百精确的“光照度lux值”除非你用了校准过的照度传感器。光敏电阻更适合做相对判断比如“现在比早上亮了多少”而不是“现在是325勒克斯”理解这个定位调试方向就不会偏。2.2 电路计算和引脚选型模拟量电路中最常见的场景是传感器本身只是一个可变电阻那你就需要自己搭一个分压电路。比如光敏电阻在强光下阻值比如5k在暗处可能到100k你可以串一个10k固定电阻从中间引出电压到ADC引脚。分压输出电压公式是Vout VCC * R2 / (R1 R2)这里R1是光敏电阻R2是固定电阻。如果不知道具体阻值范围直接用10k到20k之间试多数情况下都能得到一个适合ADC采样的电压区间。选ADC引脚时我有一个原则先查开发板的引脚说明避开默认被Wi-Fi、Flash、PWM占用的引脚。有些开发板虽然标了ADC但和系统内部有共用关系读取时会受到干扰导致数值跳变明显。用不常复用且外设独立的ADC通道读数会稳定很多。读取代码非常短核心逻辑就是初始化ADC、循环读取、打印原始值和电压值。from machine import ADC, Pin import time # 选择开发板上合适的ADC引脚 adc ADC(Pin(34)) # 部分开发板需要设置ADC衰减以扩大量程 adc.atten(ADC.ATTN_11DB) while True: raw adc.read() voltage raw * 3.3 / 4095 print(raw , raw, voltage , voltage) time.sleep(0.2)如果你手上的开发板没有atten这种接口比如某些型号直接用machine.ADC不需要衰减配置那就可以跳过这一行。关键是把量程搞清楚避免读数长期停留在4095或者0那往往说明量程设置和电路范围不匹配。2.3 读数抖动怎么治模拟量读数有个常见毛病数值一直在一定范围跳。比如稳定光线下数字值在1800附近上下波动。这个不一定是传感器坏了是模拟信号本身带噪声加上ADC采样离散化造成的自然现象。直接读取一次就拿来用很多时候不够稳定。我试过最简单的办法是连续采样多次然后取平均值。代码里维护一个滑动窗口每采一个新值就把最早的那个丢掉这样既能反映实时变化又能降低随机抖动。from machine import ADC, Pin import time adc ADC(Pin(34)) adc.atten(ADC.ATTN_11DB) window [] while True: raw adc.read() window.append(raw) if len(window) 10: window.pop(0) avg sum(window) // len(window) print(raw , raw, avg , avg) time.sleep(0.05)这里用time.sleep(0.05)控制采样间隔太快也没意义ADC转换本身需要时间太慢又会让滤波结果滞后。调试时可以先打印原始值观察噪声幅度再根据噪声大小决定滑动窗口长度不要一上来就猜参数。注意一点取平均会带来一定滞后。如果项目里需要快速响应比如用手电筒快速晃动照传感器取平均窗口太大反而会抹平变化。这种情况下用中值滤波更合适或者减少窗口长度到3左右。廉价传感器本来响应就有延迟滤波过度会让系统变得很迟钝。3. I2C总线实战读BME280还给OLED屏幕显示3.1 为什么第一个数字传感器选I2CI2C总线只用两根线就能挂多个设备是最适合新手入门的数字通信方式。MicroPython自带machine.I2C语法清晰配合i2c.scan()一行代码就能看到总线上有哪些设备。相比单总线那种严格时序I2C对延时要求宽松得多用MicroPython操作时不容易出现莫名其妙的时序失败。我曾做过一个小环境监测板BME280负责采集温湿度气压OLED屏幕负责显示两者都是I2C设备挂在同一条总线上。整个数据链路就是传感器每次读到数据再通过I2C写入OLED的缓存并刷新显示非常直观。I2C虽然简单但有一个必须先搞明白的点它是开漏结构SCL和SDA两根线必须靠上拉电阻拉到高电平。很多成品模块上已经自带上拉电阻直接接线就能用。但如果你用的是裸芯片或者自己画的PCB忘了加上拉电阻最常见的结果就是scan()返回空列表。如果你不确定模块有没有上拉可以外接两个4.7k欧姆电阻分别把SCL和SDA接到3.3V。这一步不止是“补一个电阻”而是把总线空闲电平拉到确定状态否则设备没法正确识别开始和停止信号。3.2 I2C接线和地址确认不能跳过接线这一步我建议按固定套路走先看模块丝印再查自己开发板的I2C引脚最后用scan()验证。from machine import Pin, I2C i2c I2C(0, sclPin(22), sdaPin(21), freq400000) print(i2c.scan())正常情况会打印一个类似[118]的列表表示在地址0x76发现一个设备。如果你接了BME280这个地址很常见。如果scan()返回空列表优先怀疑接线而不是代码。上下颠倒了SCL和SDA、模块没有供电、地线没共哪一个都比代码出错概率大。BME280有个需要注意的点芯片地址可能是0x76也可能是0x77取决于SDO引脚电平。如果地址冲突比如总线上还有一个地址同样是0x76的设备那就需要把其中一个模块的SDO引脚拉高或接地来改地址。这种“地址唯一性”是I2C挂多个设备时必须考虑的。3.3 MicroPython读取BME280的两种姿势第一种是对已有库的直接调用。社区里很多MicroPython固件包中已经带BME280驱动。你只要把固件所需的驱动文件传到开发板然后在代码里导入就行。from machine import Pin, I2C import bme280 import time i2c I2C(0, sclPin(22), sdaPin(21), freq400000) while True: sensor bme280.BME280(i2ci2c, address0x76) print(sensor.values) time.sleep(1)bme280.BME280(i2ci2c)这种形式在很多驱动里都是标准写法。有些驱动会返回一个元组包含温度、气压、湿度有些驱动则是用读属性方式获取单个值。拿到原始数据后别急着直接用先打印一次看看单位是什么很多时候库已经把温度做了100倍放大需要自己除以100才能得到摄氏度。第二种是手动读寄存器。这种方式适合想学原理或者驱动库不兼容的场合。手动读不复杂但步骤多要读控制寄存器来触发测量再读校准寄存器获取并组合出校准参数最后再把测量结果代入校准公式。我自己只在调试特殊芯片时候才这么干日常项目里找现成库真的更省事。3.4 OLED显示组合时的供电考量当BME280和OLED同时工作供电问题就开始冒头了。OLED模块工作时电流有几毫安到几十毫安BME280也有工作电流如果再加上开发板本身的Wi-Fi射频3.3V稳压器输出的电流余量不够总线电平就可能被拉低表现多为偶发scan()失败或者读数错误。我的做法是低功耗小项目单接一个OLED和一个传感器可以直接从开发板3.3V取电传感器数量三个以上就外接独立的3.3V稳压模块和开发板共地但不在开发板稳压器上硬挤。数据线上可以串联1k欧姆小电阻避免模块端出现意外短路时烧坏引脚这个小习惯救过我不少次。显示代码本身很简单核心就是根据屏幕尺寸设置宽高然后往缓冲区写字符串最后统一刷新。from machine import Pin, I2C import ssd1306 i2c I2C(0, sclPin(22), sdaPin(21), freq400000) oled ssd1306.SSD1306_I2C(128, 64, i2c) oled.fill(0) oled.text(Temp: 27.3C, 0, 0) oled.text(Hum: 42.5%, 0, 16) oled.show()这里我踩过一个比较典型的坑OLED的I2C地址通常是0x3C但如果模块背面有地址选择焊盘改到0x3D后代码还按0x3C访问就黑屏。所以我总建议无论用哪个驱动库都先单独执行一次scan()确认设备实际地址再写业务代码。4. 单总线不只简单DHT11和DS18B20的不同脾气4.1 单总线为什么容易出问题单总线协议最大的特点是设备既能供电又能传数据只需一根数据线。听起来很省线代价是时序要求严格。DHT11、DS18B20都归这一类。MicroPython虽然带了dht库用起来很便利但因为它内部时序实现依赖解释执行某些开发板跑DHT11时会出现偶发读取失败。如果你遇到OSError: [Errno 110] ETIMEDOUT别急着怀疑传感器坏了很可能是总线时序不允许中途有任何过长的阻塞。拿着REPL手动执行测量刚好被其他后台任务打断就容易超时。我做过的实测经验是DHT11读取间隔必须大于1秒最好等到1.5秒左右。数据手册说响应周期很慢如果你在循环里紧挨着读第二次第二次大概率失败。这并不是MicroPython特有的问题C语言里也一样只不过MicroPython解释执行后失败概率更明显。4.2 DHT11的读取和重试策略dht.DHT11这个驱动在MicroPython标准库中的用法很固定。from machine import Pin import dht import time sensor dht.DHT11(Pin(15)) for _ in range(10): try: sensor.measure() print(sensor.temperature(), sensor.humidity()) except OSError as e: print(read fail, e) time.sleep(1)这里的关键是try重试。我第一次直接用measure()放在循环里没加异常处理结果项目跑到几分钟后就卡在异常里。后来加了重试逻辑并在两次测量之间固定用sleep兜底问题基本消失。DHT11的测量值还有个特点稳定但粗糙温度分辨率通常1度湿度分辨率1%。它适合做人体舒适度的大致判断不适合做高精度记录。很多朋友拿到手发现精度不够然后去折腾校准其实不如直接换数字传感器。DHT11的优点是好买、便宜、接线简单用在环境状态提示类小项目里足够。4.3 DS18B20的读取流程和DHT11完全不同DS18B20虽然也是单总线但使用方式比DHT11更接近“总线设备”它支持总线上挂多个地址不同的传感器。MicroPython里的ds18x20库封装得比较完善。import time import onewire import ds18x20 from machine import Pin ow onewire.OneWire(Pin(4)) ds ds18x20.DS18X20(ow) roms ds.scan() print(found:, roms) while True: ds.convert_temp() time.sleep_ms(750) for rom in roms: print(ds.read_temp(rom)) time.sleep(1)DS18B20在标准寄生供电模式下温度转换期间数据线会被拉低所以MicroPython驱动有个固定延迟。你习惯了I2C那种即时读寄存器之后刚接触DS18B20会有点不习惯发转换命令之后不能让出时间必须等转换结束再去读温度。如果真的要求多传感器同时连续测量建议用外部供电把传感器VDD接到3.3VGND接GND只有DQ接数据引脚。这样转换过程中传感器不占用数据线整体可靠性会好很多。4.4 单总线在线缆延长和上拉问题上的教训单总线的数据线距离很敏感跟I2C不同长线在MicroPython单总线驱动下更容易读到错误值。我试过用一米多的杜邦线连接DS18B20结果扫描不到任何设备换短线后立刻正常。多数情况下数据线到3.3V之间接一个4.7k上拉电阻就能改善。模块板通常自带但如果你直接把DS18B20引脚焊到排线没有上拉就会出问题。还有一个坑是有些工作电压5V的模块如果给3.3V供电传感器可以被搜索到但读取结果不稳定因为本质上没达到最低工作区间我建议直接按数据手册推荐电压来。如果你需要从原来5V环境切换到3.3V环境注意旧传感器既有模块和数据线最好重新检查一遍供电范围。曾经有个传感器模块在5V下一直好好的挪到3.3V后偶尔输出异常排查半天是模块板载稳压器压差不够换模块后解决。5. MPU6050运动传感器原始数据怎么变成有用角度5.1 加速度计和陀螺仪的分工MPU6050是六轴运动传感器内部包含三轴加速度计和三轴陀螺仪。加速度计能感知重力方向和线性加速度陀螺仪能感知角速度变化。单独看加速度计对静态姿态很准但动态时候信噪比差陀螺仪动态响应好但会随时间漂移。这两者正好互补所以常见做法是把它们融合起来。MicroPython里读取原始数据很容易难的是数据处理这一层。很多初学者直接从网上拷了一段“读MPU6050”的代码打印出一堆不断变化的数字却不知道怎么转成角度原因就在这里。5.2 读取MPU6050的原始数据和校准MicroPython社区里常见现成的MPU6050驱动用法通常如下。from machine import Pin, I2C import time from mpu6050 import MPU6050 i2c I2C(0, sclPin(22), sdaPin(21), freq400000) mpu MPU6050(i2c) while True: accel mpu.accel gyro mpu.gyro print(accel:, accel, gyro:, gyro) time.sleep(0.05)返回的加速度值一般以g为单位比如静止平放时Z轴接近1其他轴接近0。陀螺仪值一般以度/秒为单位。如果打印出来的Z轴不在1附近先做硬件校验模块是否平放、供电是否稳定、模块有没有贴在振动源上再做软件校准。软件校准的核心是采集静止状态下多组陀螺仪数据求平均作为零偏。这个方法很实用比如水平静止时陀螺仪Z轴输出是0.5那么在每次读入数据后都减去0.5再参与角度计算。加速度计如果想校准也可以反复翻转采集极值但大多数项目中简单闭环校准就够。5.3 一阶互补滤波是从原始数据到角度的最短路径最常用的融合方法是一阶互补滤波。它简单到可以用一个公式描述当前角度由上一时刻角度加上陀螺仪角速度积分得到然后和加速度计算出的角度做加权融合。import math import time alpha 0.98 pitch 0.0 roll 0.0 last_time time.ticks_ms() while True: now time.ticks_ms() dt time.ticks_diff(now, last_time) / 1000.0 last_time now accel mpu.accel gyro mpu.gyro acc_pitch math.atan2(accel[0], accel[2]) * 180 / math.pi acc_roll math.atan2(accel[1], accel[2]) * 180 / math.pi pitch alpha * (pitch gyro[1] * dt) (1 - alpha) * acc_pitch roll alpha * (roll gyro[0] * dt) (1 - alpha) * acc_roll print(pitch, roll) time.sleep_ms(20)这里gyro[1]是绕Y轴的角速度积分后影响pitchgyro[0]是绕X轴的角速度影响roll。alpha越大越依赖陀螺仪角度响应快但会漂移alpha越小越依赖加速度计姿态稳定但动态滞后。0.98是比较常用的中间值具体还要根据你的采样周期和传感器噪声来微调。我调试时的经验是先把采样周期固定下来再调alpha。如果代码循环里加入显示刷新后周期变长dt就必须更新否则积分结果会出错。有些资料里直接把dt写死成0.02一旦刷新变慢角度就会明显发散这个细节很值得留意。5.4 传感器固定方式对数据影响很大MPU6050对安装固定的要求非常高我踩过一次很深刻的坑用双面胶把传感器粘在板子上旋转测试时角度数据明显乱跳一开始以为是代码问题后来发现是传感器本身在胶面上轻微晃动导致加速度计读数混入大量振动噪声。重新用螺丝固定后数据立刻稳定很多。所以你的机械结构越稳处理算法就越简单。反过来如果结构松垮一味调滤波参数是压不住噪声的。在项目早期就设计好固定方式能省很多调试时间。还有一个容易忽略的是采样率。MicroPython里读写I2C并不快循环里做的计算越多采样周期越长。如果你做的是小角度倾斜检测20ms采一次样够用如果是快速运动姿态捕捉可能就要考虑降低循环里的打印频率或者把部分计算放到外部处理器上。打印本身也超级拖慢速度调试时打印实际部署时要把高频打印去掉。6. 常见问题与排查技巧实录6.1 设备扫描不到先查供电和接线再怀疑代码我每次排查I2C和单总线设备无法识别时都按同一个顺序来。先看模块电源灯是否亮再量一下VCC和GND之间的电压是否正常然后用万用表或逻辑分析仪确认SCL和SDA有没有被拉高。如果一切正常再进行代码级检查核查引脚号是否写错。有个真实案例让我印象很深一个传感器模块怎么scan都扫不到最后发现是我把地线接到了另一个模块的GND上共地关系完全断开。那种情况模块灯亮但和开发板之间没有公共参考点信号无法形成回路自然读不到数据。这个错误非常隐蔽因为只从外观上看每一根线都接在应该接的位置上。6.2 数据偶尔跳动或者读失败这类问题在DHT11和模拟量传感器上很常见在I2C传感器上偶尔也会出现。常见原因是供电波动。Wi-Fi模块发射时瞬间电流很大同一稳压器下传感器数据就容易异常。我一般给传感器模块单独供电或者至少把传感器电源和主控的数字电源分开。另一个原因是采样时序问题。I2C在MicroPython里面使用freq400000并不一定总比100000好线路较长时高频通信更容易出错。如果你的传感器离开发板比较远把频率降到100kHz试试多数时候能改善。这不是“侥幸能通就行”的问题而是了解I2C的上升沿质量受到线缆电容影响后的合理选择。6.3 多个传感器共存时总线地址冲突I2C总线上每个设备必须有独立地址如果两个模块地址相同数据就会相互干扰常见表现是读出的数值偶尔对、偶尔错或者一个能读一个不能。解决办法要么换设备要么查模块的数据手册找地址焊盘把其中一个地址改掉。单总线则不太存在地址冲突DS18B20采用64位唯一ROM码天然支持一总线上挂多个同型号设备。这也是我推荐温度采集项目用DS18B20而不是DHT11的原因之一多路采集在硬件上简单很多。6.4 传感器排查速查表我把自己在多个项目里踩过的典型问题整理成一个速查表排错时我直接对照着看效率高很多。现象最常见原因排查顺序I2C扫描不到设备接线错误或缺少上拉4个步骤1查共地2查电压3查引脚占用4查地址ADC读数固定在0或4095量程设置或分压匹配不对先查传感器输出范围再查ADC配置DHT11偶发读取超时两次读取时间太近或时序被阻塞延长间隔加异常重试换上拉电阻DS18B20转换后读数偏高转换时间不足或寄生供电不稳延长sleep_ms改用外部供电姿态角度随时间漂移陀螺仪零偏未校准或dt不准静止采集零偏计算实际采样间隔OLED显示异常但总线正常屏幕地址与实际不符先scan()确认地址再初始化6.5 几条我觉得比代码更值钱的经验传感器应用做多了以后我发现最大的瓶颈往往不在写代码而在调试耐心和量化思维。每接到一个新传感器我都会先做一次“20分钟基线测试”不写业务逻辑只打印原始值记录它在稳定状态下波动范围、响应外部变化时的取值变化以及异常出现的频率。这份基线数据会决定后面要不要滤波、要不要校准、要不要加错误重试。比如你看一个模拟量传感器静止时波动只有±2个数字值那完全可以直接用单次采样不用滤波。如果波动有±100就说明电路布局或供电有问题靠软件滤波解决不了根本问题还得回到硬件去检查。还有一件事值得刻意练习把传感器数据保存成文件。调试板子时还可以在屏幕上打印当数据量变大或者传感器装上不方便连串口时把时间戳和读数写成CSV文件后面就能用其他工具分析。MicroPython里用普通文件操作就能做到这个习惯让我回看过好多次问题现场比拍屏幕照片舒服得多。传感器应用看起来是硬件题本质上又带着软件味。MicroPython的优势在于让你快速验证想法把复杂寄存器操作挡在身后。尤其当我做环境监测、姿态检测、数据采集这类项目时先用MicroPython把传感器调通后续再根据性能需求考虑是否下沉到更低层实现整个开发节奏非常舒服。希望这篇连载能帮你少走我当年绕过的弯路特别是把“寻找问题”的思路学到手比记住某个库的调用方式更重要。
RELATED

相关推荐

SpringBoot个人博客系统从零到一:选型、设计、实现与部署

SpringBoot个人博客系统从零到一:选型、设计、实现与部署

做了这么多年开发,接到最多的需求就是“帮我做个个人博客”,一到毕业季更多,十个学生里恨不得五个都是博客系统。刚开始我不太理解,为什么大家都扎堆做这个,后来带过几个毕设项目才明白,博客系统这个题目&a…

📅 2026/10/13 2:21:44
RISC-V IDE MRS使用笔记(十四):用户反馈功能

RISC-V IDE MRS使用笔记(十四):用户反馈功能

RISC-V IDE MRS使用笔记(十四):用户反馈功能 今天给大家带来MRS用户反馈功能的分享,开发者们可以通过该功能向MRS技术支持提交:MRS相关操作咨询、改进建议或嵌入式开发中遇到的问题,用户也可以将上述内容直…

📅 2026/10/13 2:21:44
从设备树到App:嵌入式Linux安卓驱动全链路实战

从设备树到App:嵌入式Linux安卓驱动全链路实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/13 2:21:44
MORE NEWS

更多资讯

📰

C++高阶数据结构——红黑树原理、旋转与代码实现

目录 前言: 一,红⿊树的概念 思考:红黑树如何确保最长路径不超过最短路径的2倍 红⿊树的效率: 二,红黑树与AVL树对比 三,红黑树的实现 红⿊树的结构 红黑树的插入 情况一:插入的是根节点…

📰

华为云码道 CodeArts 打造热水器升数:你家 13 升的热水器,冬天其实只有 8.8 升

你家 13 升的热水器,冬天其实只有 8.8 升 先说这东西是什么 一个零依赖的单页网页。你填四个数:机器标称升数、进水温度、想洗的温度、花洒实际流量。它告诉你三件事——这台机器此刻最多能给你多少升热水、够不够你家花洒、要撑住这个流量得买多大升数…

📰

C数据结构(顺序表)进阶(遗忘复习跟进C++):C++17标准

第一次写这么多内容&#xff0c;可否支持一下&#x1f64f;。 单链表目录前言流程规划初始编码1. 第一个问题&#xff1a;explicit 是什么2. std::size_t 是什么意思3. 为什么不把 4 直接写在 capacity_ 之后4. data_ std::make_unique<int[]>(capacity_); 是什么意思4.…

📰

高并发框架选型:别只看Star数,压测数据才是硬道理

1. 高并发选型的第一步&#xff1a;别让当年的Star数替你背锅上个月我去一个做跨境物流的团队帮忙排查问题。他们的库存服务在双月大促期间&#xff0c;单机峰值QPS一过800就开始大面积超时&#xff0c;数据库连接池被打穿&#xff0c;现场值班的人一边重启实例一边手动改熔断阈…

📰

电动汽车集群并网调度的分布式鲁棒优化模型及Matlab实现

接手过电动汽车有序充电项目的朋友应该都有这种体会&#xff1a;真到排第二天的充放电计划时&#xff0c;最让人头疼的往往不是求解器不够快&#xff0c;而是你根本说不清楚明天早上 8 点到底有多少辆车插着充电枪、每辆车还剩多少电、有多少车主愿意响应调度。电动汽车集群并网…

📰

OpenMontage深度解析:5.4万Star的开源视频神器,是革命还是半成品?

最近&#xff0c;一个叫 OpenMontage 的开源项目在GitHub上火了&#xff0c;Star数突破 5.4万&#xff0c;被不少人称为“视频创作者的终极福音”。 它号称是 首个开源、由AI智能体驱动的视频生产系统&#xff0c;能直接把你的AI编程助手&#xff08;比如Claude Code、Cursor、…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬