当前位置: 首页 > article >正文

基于立创·天猛星MSPM0G3507开发板的电机PID控制实战:编码器测速、定距与曲线显示

基于立创·天猛星MSPM0G3507开发板的电机PID控制实战编码器测速、定距与曲线显示最近有不少参加电赛或者刚开始学电机控制的朋友问我PID算法听起来挺复杂到底怎么在单片机上跑起来又怎么调参呢正好我手头有块立创·天猛星MSPM0G3507开发板用它配合一个带编码器的直流电机和一块小屏幕做了一个完整的PID控制小项目。这个项目麻雀虽小五脏俱全涵盖了编码器测速、PID算法实现、速度与距离双闭环控制还能实时显示曲线和参数非常适合用来入门实战。通过这篇教程我会手把手带你走一遍整个流程。你不需要有深厚的控制理论背景只要跟着做就能理解PID是怎么在嵌入式系统里“活”起来的并掌握关键的调试技巧。咱们的目标很明确让电机乖乖听话让它转多快就转多快让它走多远就走多远并且一切变化都能在屏幕上看得清清楚楚。1. 项目总览与硬件连接在动手写代码之前咱们先搞清楚要做什么以及手头的“家伙事儿”怎么连起来。这个项目要实现两个核心功能定速控制和定距控制。定速就是让电机稳定在某个转速比如每分钟100转运行定距则是让电机精确转动一定的圈数比如正好转10圈停下。为了实现这两个目标我们需要三个关键部分协同工作感知反馈靠电机上的编码器来“看”电机实际转得多快、转了多少。思考控制由MSPM0G3507单片机运行PID算法计算出发给电机的控制指令。执行输出通过单片机的PWM信号驱动电机驱动模块比如TB6612、DRV8833等从而控制电机转动。此外我们还需要一块屏幕比如OLED或TFT LCD来显示PID参数、目标值、实际值以及它们的变化曲线这样调试起来就直观多了。硬件连接其实很简单思路清晰就行编码器通常有A、B两相输出将它们分别连接到MSPM0G3507的任意两个支持编码器接口QEI或外部中断EINT的GPIO引脚上。编码器供电接3.3V或5V地线接GND。电机驱动模块模块的PWM输入引脚接单片机的一个定时器通道用于产生PWM方向控制引脚接另一个GPIO。电机驱动模块的电源VM接电机所需的电压比如12V逻辑电源VCC接3.3V或5V。务必确保电机电源与单片机电源共地屏幕根据屏幕类型I2C或SPI将对应的SCL/SDA或SCK/MOSI等引脚连接到单片机的相应外设引脚上。注意在连接电机驱动模块和大功率电机时强烈建议使用独立的电源为电机供电并使用逻辑电平隔离或确保共地良好以避免电机启动和停止时产生的电流冲击和噪声干扰单片机正常工作甚至导致复位或损坏。2. 基础模块驱动编码器与PWM地基打牢房子才稳。在实现高级的PID控制之前我们必须先让两个最基础的模块可靠工作读取编码器获取速度/位置以及输出PWM驱动电机。2.1 编码器测速与位置读取带编码器的电机其编码器就像一个高精度的“眼睛”电机每转动一个微小角度就会输出一组脉冲。通过测量一定时间内的脉冲数就能算出速度通过累计脉冲总数就能知道位置转过的角度或圈数。MSPM0G3507的Timer模块支持正交编码器接口QEI模式这是读取编码器最准确、最省CPU资源的方式。它会自动根据A、B两相的相位关系判断正反转并递增或递减计数器的值。配置QEI的步骤通常如下以TI的DriverLib库为例初始化GPIO将连接编码器A、B相的引脚配置为外设功能模式映射到对应的Timer单元。配置Timer为QEI模式选择一个16位或32位定时器将其工作模式设置为编码器模式。设置计数模式与预分频根据编码器线数每转脉冲数和期望的计数范围设置计数模式例如在A、B相每个边沿都计数分辨率最高和预分频。使能定时器启动编码器计数。// 示例使用Timer_A0作为编码器接口 (伪代码具体函数名参考TI DriverLib) #include “ti_msp_dl_config.h” void Encoder_Init(void) { // 1. 配置GPIO为Timer外设功能 DL_GPIO_setPeriphMode(ENCODER_A_PORT, ENCODER_A_PIN, DL_GPIO_PERIPH_MODE_SECONDARY); DL_GPIO_setPeriphMode(ENCODER_B_PORT, ENCODER_B_PIN, DL_GPIO_PERIPH_MODE_SECONDARY); DL_GPIO_setPinConfig(ENCODER_A_PORT, ENCODER_A_PIN, PIN_CONFIG_MUX_FUNC); DL_GPIO_setPinConfig(ENCODER_B_PORT, ENCODER_B_PIN, PIN_CONFIG_MUX_FUNC); // 2. 3. 配置Timer_A0为QEI模式 DL_TimerA_setQeiMode(TIMER_A0_INST, DL_TIMER_A_QEI_MODE_X4, // 4倍频模式A/B相每个边沿都计数 DL_TIMER_A_QEI_INVERT_NONE); // 不反转输入极性 DL_TimerA_setPrescaler(TIMER_A0_INST, DL_TIMER_A_PRESCALER_DIVIDE_1); // 预分频1 // 4. 启动定时器开始计数 DL_TimerA_startCounter(TIMER_A0_INST); } // 读取当前编码器计数值用于计算位置 int32_t Encoder_GetCount(void) { return (int32_t)DL_TimerA_getCount(TIMER_A0_INST); }有了位置计数速度怎么算呢一个经典的方法是M法测速在固定的时间间隔T比如10ms内读取编码器计数值的变化量ΔCount。那么速度Speed单位转/分钟RPM的计算公式为Speed (RPM) (ΔCount / (编码器线数 * 4)) / T * 60这里“编码器线数*4”是因为我们使用了4倍频模式。ΔCount就是本次采样时刻的计数值减去上一次采样时刻的计数值。这个计算过程可以放在一个定时中断里完成确保速度更新的周期是固定的。2.2 PWM输出配置PWM脉冲宽度调制是控制电机转速和转向的“缰绳”。通过改变PWM波形的占空比高电平时间占整个周期的比例可以等效地改变输出到电机的平均电压从而控制转速。在MSPM0G3507上我们通常使用一个Timer模块的PWM输出通道来控制电机速度再用一个普通的GPIO来控制方向高电平正转低电平反转。配置PWM输出的关键步骤初始化GPIO将PWM输出引脚配置为对应的Timer外设功能。配置Timer为PWM模式设置定时器的计数模式通常为上/下计数或边沿对齐、周期值决定PWM频率和比较值决定占空比。设置PWM频率和初始占空比PWM频率不宜过高开关损耗大或过低电机噪音大、转速不稳对于普通直流有刷电机1kHz到20kHz都是常见范围。初始占空比设为0让电机处于停止状态。// 示例配置Timer_A1的某个通道输出PWM (伪代码) void PWM_Init(void) { // 1. 配置PWM引脚 DL_GPIO_setPeriphMode(PWM_PORT, PWM_PIN, DL_GPIO_PERIPH_MODE_PRIMARY); DL_GPIO_setPinConfig(PWM_PORT, PWM_PIN, PIN_CONFIG_MUX_FUNC); // 2. 配置Timer_A1为PWM模式 DL_TimerA_setMode(TIMER_A1_INST, DL_TIMER_A_MODE_PWM_UP_DOWN); // 上下计数模式中心对齐PWM DL_TimerA_setPeriod(TIMER_A1_INST, PWM_PERIOD); // 设置周期值PWM频率 系统时钟 / (PWM_PERIOD * 预分频) DL_TimerA_enableCaptureComparePwmOutput(TIMER_A1_INST, PWM_CHANNEL); // 使能指定通道的PWM输出 // 3. 设置初始占空比为0% DL_TimerA_setCompareValue(TIMER_A1_INST, PWM_CHANNEL, 0); // 启动定时器 DL_TimerA_startCounter(TIMER_A1_INST); } // 函数设置PWM占空比 (范围: 0.0 ~ 1.0) void PWM_SetDuty(float duty) { uint32_t compareValue; if(duty 0.0f) duty 0.0f; if(duty 1.0f) duty 1.0f; compareValue (uint32_t)(duty * (float)PWM_PERIOD); DL_TimerA_setCompareValue(TIMER_A1_INST, PWM_CHANNEL, compareValue); }3. PID控制算法的实现与整定核心部分来了PID控制器就像一个有经验的“老司机”它根据“目标速度”期望值和“实际速度”测量值之间的偏差来调整PWM这个“油门”让偏差尽可能小。3.1 PID算法原理与离散化PID是比例P、积分I、微分D三个环节的缩写。咱们用开车来类比比例P当前偏差有多大就按比例给多大的控制量。偏差大了就多踩点油门偏差小了就少踩点。反应快但容易刹不住车超调或者在目标值附近来回晃静差。积分I把过去一段时间的偏差累积起来。主要用于消除静差。比如车一直比目标速度慢一点积分项就会慢慢增加油门直到完全消除这个微小偏差。微分D预测偏差未来的变化趋势。如果偏差正在快速减小比如快达到目标速度了就提前松点油门防止冲过头。它能增加系统稳定性抑制超调。在单片机里我们处理的是离散的数字信号所以要用离散化的PID公式。最常用的是位置式PIDu(k) Kp * e(k) Ki * Σe(j) Kd * [e(k) - e(k-1)]其中u(k)是当前时刻第k次采样的输出控制量比如PWM占空比。e(k)是当前时刻的偏差e(k) 目标值 - 测量值。Kp,Ki,Kd就是我们需要整定的三个参数。Σe(j)是从开始到当前时刻所有偏差的累加积分项。[e(k) - e(k-1)]是本次偏差与上次偏差的差值微分项。在实际编程中我们通常会把积分项Ki * Σe(j)写成Ki * integral并设置一个积分限幅防止积分饱和误差一直累积导致输出巨大。微分项也可以采用不完全微分等形式来抑制高频噪声。3.2 代码实现一个实用的PID结构体下面是一个在嵌入式系统中非常实用的PID控制器结构体和初始化函数。我习惯把PID相关的所有变量打包在一起这样管理多个控制器比如速度环和位置环会很方便。typedef struct { float target; // 目标值 float measure; // 测量值 float err; // 当前误差 float err_last; // 上一次误差 float integral; // 积分项累加值 float output; // PID输出值 float Kp; float Ki; Kd; float integral_limit; // 积分限幅 float output_limit; // 输出限幅 } PID_Controller; void PID_Init(PID_Controller *pid, float kp, float ki, float kd, float i_limit, float o_limit) { pid-Kp kp; pid-Ki ki; pid-Kd kd; pid-integral_limit i_limit; pid-output_limit o_limit; pid-target 0.0f; pid-measure 0.0f; pid-err 0.0f; pid-err_last 0.0f; pid-integral 0.0f; pid-output 0.0f; } float PID_Calculate(PID_Controller *pid, float target, float measure) { float differential; pid-target target; pid-measure measure; pid-err pid-target - pid-measure; // 积分项计算并限幅防止饱和 pid-integral pid-err; if(pid-integral pid-integral_limit) pid-integral pid-integral_limit; if(pid-integral -pid-integral_limit) pid-integral -pid-integral_limit; // 微分项计算不完全微分可在此处实现 differential pid-err - pid-err_last; pid-err_last pid-err; // PID输出计算 pid-output pid-Kp * pid-err pid-Ki * pid-integral pid-Kd * differential; // 输出限幅 if(pid-output pid-output_limit) pid-output pid-output_limit; if(pid-output -pid-output_limit) pid-output -pid-output_limit; return pid-output; }3.3 参数整定让电机“听话”的秘诀PID参数整定是个经验活但也是有章可循的。对于电机速度控制我推荐先P、再I、最后D的试凑法并且一定要在闭环即编码器反馈正常的情况下进行。初始化将Ki和Kd设为0输出限幅设为安全值比如对应最大占空比0.8积分限幅设一个中等值。调比例P给一个较小的目标速度比如50 RPM。从小到大慢慢增加Kp。你会看到电机开始转动并且实际速度向目标值靠近。当Kp增大到出现明显抖动或持续振荡时说明P太大了。将Kp回调到振荡消失此时系统响应较快且稳定。记下这个Kp值。调积分I保持Kp为刚才的值引入一个很小的Ki。观察电机速度。如果存在静差稳定后速度略低于目标值就缓慢增大Ki直到静差被消除。Ki太大会引起低频振荡或超调。如果出现振荡就减小Ki。合适的Ki能消除静差且不影响动态响应。调微分D可选速度环对微分项不太敏感且编码器噪声容易被微分放大。如果系统超调严重可以尝试加入很小的Kd来抑制。注意微分项对噪声非常敏感如果使用一定要确保编码器信号干净或者使用不完全微分、对测量值进行低通滤波。提示定距控制位置环的参数整定思路类似但通常需要更小的比例增益和更谨慎的积分、微分因为位置环更容易振荡。可以先让速度内环稳定工作再在外层套上位置环进行调试。4. 系统整合与功能实现现在我们把各个模块像拼图一样组合起来实现定速和定距功能并把数据送到屏幕上显示。4.1 定速控制实现定速控制是单环系统速度PID环。它的输入是目标速度反馈是编码器计算出的实际速度输出是PWM占空比。程序逻辑可以放在一个固定的定时中断比如1ms或5ms中执行这个周期就是PID的控制周期。PID_Controller speed_pid; // 声明一个速度PID控制器 float target_speed_rpm 100.0f; // 目标速度100 RPM float current_speed_rpm; // 当前速度 float pwm_duty; // PWM占空比 // 在定时中断服务函数中 void Timer_ISR(void) { // 1. 读取编码器值计算当前速度 (假设有函数Get_Speed_RPM()) current_speed_rpm Get_Speed_RPM(); // 2. 进行PID计算 pwm_duty PID_Calculate(speed_pid, target_speed_rpm, current_speed_rpm); // 注意PID输出可能是-1.0~1.0需要根据你的电机驱动逻辑映射到0~1.0的占空比和方向 // 例如if(pwm_duty 0) { 方向正转; PWM_SetDuty(pwm_duty); } // else { 方向反转; PWM_SetDuty(-pwm_duty); } // 3. 更新PWM输出 PWM_SetDuty(fabsf(pwm_duty)); // 取绝对值作为占空比 Set_Motor_Direction(pwm_duty 0 ? FORWARD : REVERSE); // 设置方向 // 4. (可选) 将目标值、实际值、PID输出等数据存入缓冲区供显示线程使用 Update_Display_Data(target_speed_rpm, current_speed_rpm, speed_pid.output); }4.2 定距控制实现定距控制是双环系统外环是位置环内环是速度环。外环PID根据“目标位置”总脉冲数和“当前位置”编码器累计值计算出“目标速度”然后将这个目标速度交给内环的速度PID去跟踪执行。这种结构也叫串级PID抗干扰能力更强。PID_Controller position_pid; // 声明一个位置PID控制器 PID_Controller speed_pid; // 速度PID控制器复用 int32_t target_position_count 10000; // 目标位置10000个计数 int32_t current_position_count; // 当前位置 float inner_target_speed; // 内环速度环的目标速度 // 在定时中断服务函数中 void Timer_ISR(void) { // 1. 读取编码器当前位置 current_position_count Encoder_GetCount(); // 2. 外环位置环PID计算输入是位置偏差输出是期望速度 inner_target_speed PID_Calculate(position_pid, (float)target_position_count, (float)current_position_count); // 对inner_target_speed进行限幅避免内环无法跟踪 // 3. 读取当前速度 current_speed_rpm Get_Speed_RPM(); // 4. 内环速度环PID计算跟踪外环给出的期望速度 pwm_duty PID_Calculate(speed_pid, inner_target_speed, current_speed_rpm); // 5. 更新PWM输出 PWM_SetDuty(fabsf(pwm_duty)); Set_Motor_Direction(pwm_duty 0 ? FORWARD : REVERSE); // 6. 更新显示数据 Update_Display_Data(target_position_count, current_position_count, inner_target_speed, current_speed_rpm); }4.3 曲线与参数显示图形化显示是调试的“眼睛”。我们可以利用屏幕的绘图功能绘制两条曲线一条是目标值水平线或斜坡另一条是实际测量值。看着实际值曲线如何追赶并稳定在目标值线上PID参数的效果一目了然。显示逻辑可以放在主循环中以较低的频率比如10Hz刷新避免占用过多CPU。显示内容可以包括实时曲线目标值 vs. 实际值速度或位置。数值显示当前目标值、实际值、PID输出值。参数显示与调节当前的Kp, Ki, Kd值。如果屏幕支持触摸或外接了按键甚至可以实时修改这些参数观察系统响应变化这是最有效的学习方式。5. 调试心得与常见问题做完以上所有步骤你的电机应该已经能受控运行了。但在实际调试中你可能会遇到下面这些“坑”这里分享一些我的处理经验电机不转或抖动严重检查硬件首先确认电机驱动模块供电是否正常PWM和方向信号是否到达驱动模块。用万用表测量电机两端电压。检查编码器编码器接线是否正确A、B相有没有接反在转动电机时用逻辑分析仪或单片机读取GPIO状态看是否有脉冲变化。参数问题PID参数尤其是Kp是否太小先尝试给一个固定的、较小的PWM占空比看电机能否正常转动排除软件算法问题。速度控制存在静差增大Ki这是消除静差的主要手段。但要注意积分限幅防止积分饱和。检查测量编码器测速计算是否正确M法测速的时间窗口T是否准确可以在屏幕上打印出原始的脉冲计数变化量来验证。系统振荡来回晃动P太大这是最常见的原因。减小Kp。I太大积分作用过强也会引起振荡尤其是低频振荡。减小Ki。控制周期不合适PID计算和执行的周期太快或太慢都可能引发不稳定。对于电机速度控制1ms到10ms是比较常见的范围。定距控制到终点时过冲或抖动切换控制模式当位置接近目标时比如最后10%的路程可以将位置环的输出目标速度进行限幅逐渐降低允许的最大速度实现“软着陆”。加入死区当位置误差小于某个很小值时直接停止PWM输出避免在终点附近因微小误差而持续抖动。这个项目虽然不大但完整地走通了嵌入式运动控制的经典流程传感器反馈、控制器计算、执行器输出、人机交互。希望你能通过动手实践真正理解PID不再是书本上的公式而是能让物理世界中的电机精准运行的强大工具。调试过程可能会有些曲折但当你看到电机最终平稳、准确地按照你的指令运行时那种成就感就是学习嵌入式最大的乐趣。

相关文章:

基于立创·天猛星MSPM0G3507开发板的电机PID控制实战:编码器测速、定距与曲线显示

基于立创天猛星MSPM0G3507开发板的电机PID控制实战:编码器测速、定距与曲线显示 最近有不少参加电赛或者刚开始学电机控制的朋友问我,PID算法听起来挺复杂,到底怎么在单片机上跑起来,又怎么调参呢?正好,我手…...

突破百度网盘限速壁垒:baidu-wangpan-parse直链解析技术全攻略

突破百度网盘限速壁垒:baidu-wangpan-parse直链解析技术全攻略 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 在数字化协作时代,百度网盘作为国内用户…...

Python flask 大学生运动会管理系统的分析与设计

目录项目技术支持可定制开发之功能创新亮点源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作项目技术支持 前端开发框架:vue.js 数据库 mysql 版本不限 数据库工具:Navicat/SQLyog/ MySQL Workbench等都可以 后端语言框架支持&am…...

Stable Yogi Leather-Dress-Collection实战案例:ACG周边设计师的皮衣风格探索

Stable Yogi Leather-Dress-Collection实战案例:ACG周边设计师的皮衣风格探索 1. 引言:当二次元角色穿上定制皮衣 作为一名ACG周边设计师,你是否曾为笔下角色千篇一律的服装风格而苦恼?或者,在构思新的角色设定时&am…...

突破式重构:GHelper轻量级硬件控制工具的性能优化革命

突破式重构:GHelper轻量级硬件控制工具的性能优化革命 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops. Control tool for ROG Zephyrus G14, G15, G16, M16, Flow X13, Flow X16, TUF, Strix, Scar and other models 项目地址…...

自定义字面量实战

1、非修改序列算法这些算法不会改变它们所操作的容器中的元素。1.1 find 和 find_iffind(begin, end, value):查找第一个等于 value 的元素,返回迭代器(未找到返回 end)。find_if(begin, end, predicate):查找第一个满…...

从协议到PCB:PCIe高速硬件设计实战指南

1. 从协议到PCB:为什么PCIe硬件设计是个“瓷器活” 大家好,我是老张,在高速硬件设计这个行当里摸爬滚打了十几年,从早期的PCIe 2.0一路做到现在的PCIe 5.0,踩过的坑比走过的路还多。今天想和大家聊聊一个听起来高大上、…...

从仿真到真机:人形机器人强化学习策略部署实战

1. 从仿真到真机:为什么这一步如此艰难? 在Gazebo里看着自己训练的人形机器人健步如飞,那种成就感别提多爽了。但当你兴冲冲地把模型文件拷出来,准备让实验室那台“铁疙瘩”也动起来时,现实往往会给你当头一棒——机器…...

解析信号构建与瞬时特征提取:希尔伯特变换在Python、C++、MATLAB中的实战

1. 希尔伯特变换:信号处理中的“相位魔法师” 如果你玩过收音机或者调过吉他弦,大概对“频率”和“相位”这两个词不陌生。简单说,频率就是信号抖动的快慢,相位就是抖动起始的“时间点”。在分析一个复杂信号,比如一段…...

Windows系统下Stable Diffusion Web UI的本地部署与远程访问全攻略

1. 为什么要在Windows上自己搭一个AI画室? 如果你最近刷到过那些“一句话生成神图”的视频,心里肯定痒痒的。Midjourney、DALL-E这些在线工具好用是好用,但要么要排队,要么有生成次数限制,最要命的是,你辛辛…...

Windows下npm EPERM权限错误的终极解决方案:从根源避免权限冲突

1. 为什么你的npm总在Windows上报EPERM错误? 如果你在Windows上搞前端开发,我敢打赌,你肯定见过这个让人血压飙升的错误提示:npm ERR! code EPERM,后面跟着一串 operation not permitted。这玩意儿就像个幽灵&#xff…...

智能眼镜视觉系统AIGlasses OS Pro实战:四大模式一键开启体验

智能眼镜视觉系统AIGlasses OS Pro实战:四大模式一键开启体验 最近我花了一周时间,深度体验了AIGlasses OS Pro这套智能视觉系统。说实话,刚开始我有点怀疑——一个纯本地运行的视觉系统,塞进眼镜这种小设备里,真能做…...

Python射线检测实战:trimesh与python-mesh-raycast性能对比与应用选择

1. 为什么你需要关心Python射线检测? 如果你正在捣鼓3D项目,比如机器人导航、游戏开发、三维重建,或者像我之前做的一个无人机避障模拟系统,那你大概率会遇到一个经典问题:怎么判断一条射线(想象成一道激光…...

直流电流采样电路实战指南:从检流电阻到霍尔传感器的四种方案解析

1. 为什么电流采样是硬件设计的“基本功”? 大家好,我是老张,一个在硬件和嵌入式领域摸爬滚打了十多年的工程师。今天想和大家聊聊一个看似基础,但实际项目中“坑”特别多的技术点——直流电流采样。不管你是在做电池管理系统&…...

csdn营销模板

学习资源 如果你是也准备转行学习网络安全(黑客)或者正在学习,这里开源一份360智榜样学习中心独家出品《网络攻防知识库》,希望能够帮助到你 知识库由360智榜样学习中心独家打造出品,旨在帮助网络安全从业者或兴趣爱好者零基础快…...

基于瑞萨RA2 MCU的智能陪伴时钟嵌入式设计

1. 项目概述“智能陪伴时钟”是一款面向家庭场景的嵌入式智能终端设备,其核心设计目标并非单纯提供时间显示功能,而是通过硬件感知、网络协同与人机交互的有机融合,构建一种具象化的情感连接通道。项目以陶瓷灯丝时钟为物理载体,采…...

从零到一:ROS Noetic下UR5机械臂抓取仿真的完整避坑指南

1. 环境准备:从零搭建你的ROS Noetic仿真舞台 嘿,朋友们,如果你刚接触ROS和机械臂仿真,看到UR5、MoveIt!、Gazebo这些名词可能有点发怵。别担心,几年前我第一次搞这个的时候,也是从一脸懵开始的。今天我就带…...

告别复杂配置:5分钟搞定ESXi上Ubuntu 22.04的SSH远程访问(含Cpolar固定TCP地址设置)

告别复杂配置:5分钟搞定ESXi上Ubuntu 22.04的SSH远程访问(含固定公网地址设置) 每次想快速搭建一个临时的开发环境或者测试服务器,你是不是都得花上大半天时间折腾网络配置、端口转发,甚至还得去研究路由器后台&#x…...

2024前端字体优化指南:从阿里巴巴普惠体到可变字体实战

2024前端字体优化实战:从品牌定制到性能极致的全链路方案 去年我们团队接手了一个面向全球市场的金融科技产品重构,设计稿里指定了一款精致的品牌字体。上线后,市场团队却收到了大量来自Windows用户的反馈,抱怨界面文字“发虚”、…...

Flask项目打包成EXE的终极指南:PyInstaller常见报错与解决方案大全

Flask项目打包成EXE的终极指南:PyInstaller常见报错与解决方案大全 你是否曾花费数周时间精心打磨了一个Flask应用,它在本地的开发服务器上运行得丝滑流畅,但当你试图将它分享给同事、客户或学生时,却陷入了一场“环境配置”的噩梦…...

从零起步探索SEO,让网站访客源源不断流入

在探索SEO的过程中,理解每个模块的内涵和相互关系至关重要。内容优化是连接关键词研究与外部链接建设的枢纽。通过优质的内容,不仅可以吸引目标用户,还能提升他们在网站上的体验和互动。在撰写内容时,需关注用户需求,确…...

CVAT本地部署全攻略:从Docker镜像构建到团队协作配置(2024避坑指南)

CVAT本地部署全攻略:从Docker镜像构建到团队协作配置(2024避坑指南) 如果你正在为计算机视觉项目寻找一个功能强大、可定制且支持团队协作的标注平台,那么CVAT(Computer Vision Annotation Tool)很可能已经…...

java基于SSM框架的房屋租赁系统的设计与实现论文

目录引言系统需求分析系统设计系统实现系统测试总结与展望参考文献附录(可选)项目技术支持源码LW获取详细视频演示 :文章底部获取博主联系方式!同行可合作引言 研究背景与意义国内外研究现状论文研究内容与目标 系统需求分析 功…...

java基于ssm框架的企业员工管理系统 毕业论文

目录引言系统需求分析系统设计系统实现系统测试总结与展望参考文献附录项目技术支持源码LW获取详细视频演示 :文章底部获取博主联系方式!同行可合作引言 研究背景与意义:阐述企业员工管理系统在现代企业管理中的重要性,以及基于S…...

cv_unet_image-colorization镜像部署常见问题与解决方案汇总

cv_unet_image-colorization镜像部署常见问题与解决方案汇总 1. 引言 如果你正在尝试部署cv_unet_image-colorization这个黑白照片上色工具,可能会遇到各种问题。从环境配置到模型加载,从权限问题到性能优化,每个环节都可能成为部署路上的绊…...

基于Qt与ElaWidgetTools:从零构建一个现代化跨平台即时通讯客户端

1. 为什么选择Qt和ElaWidgetTools来造一个“现代”聊天软件? 如果你和我一样,是个喜欢折腾的开发者,想自己动手做一个既好看又好用的跨平台聊天软件,那技术选型绝对是第一步,也是最让人纠结的一步。市面上客户端框架那…...

从握手到长连:HTTPS与WSS的架构协同与本地开发实践

1. 从一次“握手”说起:HTTPS与WSS的协同基础 想象一下,你正在和一个朋友打电话。拨通电话、互相确认身份、然后开始聊天,这个过程和我们今天要聊的HTTPS与WSS的“握手”非常像。只不过,在互联网世界里,这个“握手”过…...

瀚高数据库(HighGoDB)Windows环境下的安装与实战配置指南

1. 为什么选择在Windows上部署瀚高数据库? 如果你是一名Java或.NET开发者,日常工作环境就是Windows,那么你很可能遇到过这样的场景:公司项目需要从MySQL或Oracle迁移到一个更符合特定安全要求的国产数据库。这时候,瀚高…...

Enhanced Tensor Low-Rank and Sparse Representation Recovery for Incomplete Multi-View Clustering

1. 论文基本信息 发表时间:2023 年 发表 venue:The Thirty-Seventh AAAI Conference on Artificial Intelligence (AAAI-23) 2. 核心思想 该论文针对不完整多视图聚类(Incomplete Multi-View Clustering, IMVC)问题,提出了一种名为 ETLSRR(Enhanced Tensor Low-Rank and…...

中国SaaS正式进入AI时代

今天看见大崔把一年一度的中国SaaS大会改名为中国企业AI大会,遂感叹:中国SaaS时代(2015-2025),正式结束了。(1)目前中国SaaS公司,在资本方面:上市难融资难卖出难在业务方…...