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

家用万兆网络实践:紧凑型家用服务器静音化改造(二)

大家好,这篇文章我们继续分享家里网络设备的万兆升级和静音改造经验,希望对有类似需求的朋友有所帮助。

写在前面

在上一篇《家用网络升级实践:低成本实现局部万兆(一)》中,我们留下了一些待解决的问题。现在让我们一起来完成这些未完成的部分。

还记得曾经提到的上面的配件嘛

回顾一下上篇文章提到的内容:

不过这台设备本身运行的时候,就会有一些风扇声音,启动的时候比较大声,运行的时候相对安静,但是还有一些声音。作为计划不再按需启动使用,而是和其他设备一样长时间开机使用的设备,我计划对它进行一些改造,在改造结束后,再进行测试,这样对我而言更有意义。

这次改造的是图中上面的设备:Gen10 Plus

关于这台设备的详细介绍,我在之前写过一篇文章《省心和颜值兼顾的 HomeLab 设备:HPE MicroServer Gen10 Plus v2(一)》,感兴趣的朋友可以去看看,这里就不重复介绍了。

其实把服务器搬回家里使用,既能提供安静可靠的实验环境,又能实现高性价比,这并不是我一个人的想法。网上有很多志同道合的玩家,都在分享各种实用的解决方案。

先回顾一下,2021年我写过一篇《廉价的家用工作站方案:前篇》,主要介绍了基于笔记本的方案。文章里我详细对比了实验开发环境中,在相同配置 (核心、内存、磁盘)下服务器的使用成本。这些“家用服务器”到现在还在我家里稳定运行,发挥着它们的价值。算下来,从 2015 年开始,这个方案已经使用了 10 年之久。

不过除了这种性价比方案外,传统服务器作为专业计算设备还是有其独特优势的:可以插入大量ECC内存、提供更稳定的虚拟化支持。特别是在需要持续运行服务或处理大规模数据时,这些优势就特别明显。(相信经常处理海量数据的朋友们都深有体会)

这篇文章能够成文,要特别感谢 zhaoyingpu 以及众多先行者的实践验证和探索。在接下来的内容中,我会详细介绍这篇文章凝聚了多少人的心血。

让我们开始吧。

定义问题

在明确改造方案之前,我们先来理清楚目前遇到的问题。

设备使用环境与噪音困扰

这台设备作为一台家用服务器使用,最让人头疼的就是噪音问题。即便我把服务器放在机柜里,确实能降低不少运行噪音,但那个服务器使用的工业风扇的“呼呼”声依然很明显。

如果你也用过 HPE 的 Gen8、Gen10 这类服务器,肯定知道它们对硬件特别“挑剔”。一旦安装了不在官方认证列表里的 PCIe 扩展卡,风扇就会立刻开启“狂暴模式”。问题是,我们实际需要用的扩展卡,不可能都在它的认证列表里。

另外,服务器自带的 iLO 芯片也是个“麻烦制造者”。用着用着它就会发热,然后又把风扇调到最大转速,制造吵闹的噪音。

考虑到这是要长期使用的设备,我不想和之前一样只能在需要的时候才开机。特别是完成万兆网络改造后,如果噪音问题得不到解决,那就太影响日常使用了。

值得一提的是,硬盘噪音倒不是问题。因为我用的都是SSD,既安静又不会产生太多热量。

噪音从何而来?

通过前面的分析,我们可以看到设备噪音主要是来自风扇。而风扇为什么会发出噪音,主要有两个原因:一是设备预设的温控策略不够优化,二是当某些部件温度升高时,采用了简单粗暴的降温方案。

这其实和产品的目标市场有关。在海外市场,很多用户会把设备放在办公室、机房,甚至是车库、阳台使用。这些场景下,用户对噪音的容忍度都比较高。从厂商角度看,优化降噪方案需要投入额外成本,但这些投入并不能提升计算、存储、网络性能。对主力用户群来说,他们更在意性能而不是噪音,所以厂商也就缺乏改进的动力。

另外,让设备在更低温的环境下运行,也能降低厂商的维护和售后成本。因为芯片和其他零部件出现故障,往往是因为过热、过冷或者环境太潮湿导致的。所以对厂商来说,让风扇保持高速运转是个省事又省钱的选择,反正用的是用户的电。

应对问题的挑战的策略

想解决设备噪音问题,最直接的方法无非是两个思路:一是更换静音风扇,二是想办法降低设备温度,避免风扇高速运转。听起来简单,但实际操作中还是有不少挑战需要克服。

让我们来看看具体有哪些难点:

首先,HPE服务器用的风扇接口与市面上常见的消费级静音风扇不兼容。这就限制了我们能用的风扇选择范围。

其次,就算找到合适的风扇可以更换,服务器默认的风扇控制策略是全速运转。即便装上了静音风扇,在这种策略下依然可能达不到理想的降噪效果,毕竟这是物理规律决定的。

再者,降噪改造必须在保证设备运行安全的前提下进行。我们需要确保更换风扇后,各个零部件不会因为散热不足而过热损坏。

最后还要考虑成本问题。这不仅包括初次改造的投入,还要考虑到后续的备件更换,以及其他设备改造的可能性。我们需要一个长期可持续的解决方案,而不是一次性的权宜之计。

既然已经理清了这些挑战,接下来就让我们一个个攻克它们。先从最基础的风扇选择开始说起吧。

解决方案

从问题到解决方案的转变,让我想起之前在知乎社区学到的一个观点:只要有问题,就一定能找到答案。

选择服务器风扇的替代

先说说我的改造经历。在 2021 年时,我在《近期家用设备(NUC、猫盘、路由器)散热升级记录》这篇文章中分享过给 NUC 8 迷你主机做散热改造的经验。

2021,NUC8 迷你主机散热改造

当时遇到的问题和现在很类似,这类小巧机箱的设计往往没有充分考虑散热需求,或者说它们的设计初衷可能就是低负载运行,某种程度上确实浪费了设备性能。我当时选择了经典的黑色“猫扇”来进行替换,效果相当不错:设备在高负载时只有轻微噪音,平时更是安静得几乎听不到声音。

这次的改造,我依然选择了猫扇,具体型号是经典配色的 NF-A8 。

计划中使用的猫扇:经典配色 NF-A8

选这款的原因也很简单:我这台服务器平时就是用来跑些虚拟化环境和一些突发性的轻量应用,再加上处理一些万兆网络中转任务。在这种低负载场景下,低转速的猫扇优势特别明显(当然,如果是高转速场景就另当别论了)。

不过在动手改造前,我们还是得先了解下新旧风扇的性能差异。

HPE Gen10 Plus v2 原装风扇性能参数

原装的风扇是台达电子生产的 PFB0812GHE(80x80x38mm 12V DC 10.2W,产品规格 datasheet),最高能转到 6100 转,噪音 55.5 分贝,气流量 86.4 CFM(约146.8 m³/h),风压 22 mmAq。

NF-A8 性能参数

而我们选的NF-A8,虽然尺寸完全一致(免去了改装螺丝位的麻烦),但满载时只有 17.7 分贝,甚至能降到 13.8 分贝(1750转)。满载转速只有 2200 转,最低能到 450 转,气流量是 55.5 m³/h,风压 2.37 mm H₂O。

虽然不能简单地用线性计算来比较两个风扇的性能,但从这些数据也能看出一些门道。新风扇的最大转速只有原装的“六二折”左右,气流量是“四七折”,风压更是只有原来的十分之一。所以要提醒大家的是**:既然最大散热能力减弱了,用新风扇时就得特别注意控制整机的发热情况,不然真的会“压不住”。**

合理规划降低热量产生

前文提到,我们选择了性能较弱但更安静的风扇,虽然让耳朵舒服了,但机器的散热能力相应下降。因此,我们需要合理规划设备的使用方式。

在我的使用方案中,这台设备仅运行 ESXi 虚拟化服务,主要负责 IO、存储和网络类服务,尽可能减少 CPU 这个主要发热源的热量产生。

查阅惠普官方介绍,HPE ProLiant MicroServer Gen10 Plus v2 被定位为一款经济实惠、小巧的入门级服务器。

设备可用的 CPU 型号对比

官方提供的 CPU 选项包括 Intel Xeon E-2314(2.80GHz)和 Intel Pentium Gold G6405(4.10GHz),TDP 分别为 65W 和 58W,核心配置为 4c4t 和 2c4t。我选择的 CC 150 CPU 实际功耗约 60W 出头,但拥有更多核心(8c16t)。由于其功耗与官方高配 E-2314 相近(甚至略低),理论上产生的热量应该不会更多,无需额外增加散热能力。

存储方面,我仅使用固态硬盘,并优先选择可搭配金属支架的 2.5 寸 SATA SSD。相比机械硬盘,SSD 本身发热就更少;而 SATA 接口相比 NVMe,由于速度较慢且散热面积更大,发热量也更低。配合散热支架使用后,风扇主要只需要负责 CPU、主板和网卡的散热工作。

实际效果如何?这是运行一天后的数据:

设备运行时的前半部分温度采样

设备运行时的后半部分温度采样

改造后的温度数据显示,规划内的设备温度都保持在较低水平。与其他用户相比,AHCI HD Max 温度低了约 10 度,BMC(iLO 位置)温度也降低了接近 10 度。如果想进一步降温,可以参考 HPE 海外社区用户的改装方案(有损改装)。

此前提到,iLO 控制芯片过热会导致风扇疯转以加强换气,产生噪音。如果再插入 PCIe 扩展卡,更会影响风道,让风扇徒劳运转,徒增声噪。

为解决这个问题,我们需要两个改进。首先是增加 iLO 的主动散热能力,比如加装散热器。参考了 Chiphell 社区用户 zhengwenxi1989 在 2022 年分享的《Gen10 Plus iLO 芯片低成本完美散热》方案。我暂时选择让气流带走散热器上的热量,而不是导向大散热器,后续可能会调整。

iLO 使用的散热器

虽然原本打算采用同款方案,但考虑到物流时间,加上手头有一块理论散热性能更好的利民 SSD 散热器,就先用起来了。我用 3M 普通胶带替换了原有双面胶,后续可能还会更换,先观察一段时间效果。

除了通过更好的散热器增加被动散热面积外,我也借鉴原方案增加了主动散热。

降低 iLO 温度的主动散热小风扇

这款风扇和原始方案中的略有不同,使用方式也有变化,下文详细展开。

接管设备风扇调度策略

接下来要解决的是一个比较有挑战的问题,如何接管惠普服务器的风扇控制。

这个问题的复杂之处在于,惠普服务器使用的是特殊的风扇控制方案,与普通消费级风扇有很大区别。如果我们想用噪音更小的风扇替换原装的,不仅要考虑接口兼容性的问题,还需要调整控制策略,避免低转速风扇一直以高速运转。

本文使用的小巧的 “控制器” 方案

这个问题其实早有开源社区的先行者们在探索解决方案。2020年,GitHub 用户Max-Sum 分享了一个项目 Max-Sum/HP-fan-proxy。这个方案是在 Reddit 用户executivul 在2017年提出的方案(Arduino nano 实现代码)基础上优化而来,通过简化硬件设计,采用软件方案来解决问题。

惠普风扇接口定义

这些前期工作的意义重大,不仅提供了代码参考,还给出了如何制作兼容惠普风扇接口(2x3 PHD2.0 connector)的细节,以及明确的接口定义说明。

在此特别感谢七年前那些先行者们。不管是进行静音改造的实践者,还是参与可行性讨论并提供建议的社区成员,比如这些讨论帖 7vxo5n/hp_dl380e_g8_arduino_fan_control_project/、72k3jf/faking_the_fan_signal_on_a_dl380_g7/,都为这个方案的最终成型贡献了力量。

九个月前,一个专门针对 Gen10 Plus 和猫扇的新方案出现了:zhaoyingpu/hpe-gen10-fan-proxy。这个项目参考了 2019 年的一篇技术笔记《Solving the DL180 G6 Fan Controller Problem》,并在 Max-Sum 方案的基础上做了改进。感谢这位 70 后 DIY 玩家的分享,让我在配件选购方面省去了很多摸索的时间,可以更专注于软件部分的优化。

由于我在硬件方面还算是个新手,我 fork 了 zhaoyingpu 的项目 soulteary/hpe-gen10-fan-proxy,增补了相关资料。后续的实验性改动我也会记录在这个仓库中(目前已经把之前的改动还原了,等稳定后再更新到仓库)。

核心代码逻辑如下:

#include <FastLED.h>/* 定义引脚相关的宏 */
#define pinOfPin(P) (((P) >= 0 && (P) < 8) ? &PIND : (((P) > 7 && (P) < 14) ? &PINB : &PINC))
#define pinIndex(P) ((uint8_t)(P > 13 ? P - 14 : P & 7))
#define pinMask(P) ((uint8_t)(1 << pinIndex(P)))
#define isHigh(P) ((*(pinOfPin(P)) & pinMask(P)) > 0) /* 判断引脚是否为高电平 */
#define isLow(P) ((*(pinOfPin(P)) & pinMask(P)) == 0) /* 判断引脚是否为低电平 *//* 引脚和常量定义 */
const int pwmInPin = A1;     /* 输入PWM信号的引脚 */
const int pwmOutPin = 9;     /* 输出PWM信号的引脚 */
const int pwm2OutPin = 10;   /* 第二个输出PWM信号的引脚 */
const int rpmInPin = 4;      /* RPM输入引脚 */
const int hpeTachPin = A2;   /* HPE转速信号输出引脚 */
const int normalTachPin = 3; /* 正常转速信号输出引脚 */
const uint16_t pwmTop = 320; /* PWM的顶值 */
const int sample = 25000;    /* 读取PWM的样本数量 */
const float pwmMap[4] = {0.1, 0.2, 0.5, 1.0}; /* PWM映射值 */
/* const float pwmMap[4] = {0, 1.0, 0, 1.0}; */
const int rpmUpper = 6000;                    /* 最大RPM */
const int rpmLower = 60;                      /* 最小RPM */
const float timer2Freq = 16000000 / 1024 / 2; /* Timer2频率 */
const int timer2RpmLower = 900;               /* Timer2最低RPM */
const float pwm2OutDutty = 0.45;              /* 第二个PWM输出的占空比 */volatile uint32_t pulseCount = 0; /* 脉冲计数,使用volatile确保在中断中安全更新 *//* 脉冲计数函数 */
void counter() { pulseCount++; }/* 中断服务例程,处理RPM输入引脚的中断 */
ISR(PCINT2_vect) {if (digitalRead(rpmInPin) == HIGH) /* 检查引脚状态 */pulseCount++;                    /* 增加脉冲计数 */
}void setup() {/* 配置Timer 1以产生25 kHz的PWM信号 */TCCR1A = 0;                                                                     /* 重置配置 */TCCR1B = 0;                                                                     /* 重置配置 */TCNT1 = 0;                                                                      /* 重置计数器 */TCCR1A = _BV(COM1A1) /* 非反向PWM信号 */ | _BV(COM1B1) /* 同上 */ | _BV(WGM11); /* 模式10:相位校正PWM,TOP = ICR1 */TCCR1B = _BV(WGM13) /* 同上 */ | _BV(CS10);                                     /* 预分频器 = 1 */ICR1 = pwmTop;                                                                  /* 设置TOP值为320 *//* 配置Timer 2以产生7.8125 kHz的PWM信号,用于转速模拟 */TCCR2A = 0;TCCR2B = 0;TCNT2 = 0;TCCR2A = _BV(COM2B1) /* 非反向PWM信号 */ | _BV(WGM20);              /* 模式5:相位校正PWM,TOP = OCR2A */TCCR2B = _BV(WGM22) /* 同上 */ | _BV(CS20) | _BV(CS21) | _BV(CS22); /* 预分频器 = 1024 */OCR2A = 255;                                                        /* 设置OCR2A为255 *//* 设置引脚模式 */pinMode(pwmInPin, INPUT); /* 输入PWM引脚 *//* Tachometer output signal need pullup to 5v, ref https://noctua.at/pub/media/wysiwyg/Noctua_PWM_specifications_white_paper.pdf */pinMode(rpmInPin, INPUT_PULLUP); /* RPM输入引脚,启用上拉电阻 */pinMode(pwmOutPin, OUTPUT);      /* 输出PWM引脚 */pinMode(pwm2OutPin, OUTPUT);     /* 第二个输出PWM引脚 */pinMode(hpeTachPin, OUTPUT);     /* HPE转速信号输出引脚 */pinMode(normalTachPin, OUTPUT);  /* 正常转速信号输出引脚 *//* 设置初始状态 */digitalWrite(hpeTachPin, LOW);                     /* HPE转速信号初始化为LOW */analogWrite25k(pwm2OutPin, pwm2OutDutty * pwmTop); /* 输出第二个PWM信号 *//** 启用中断* attachInterrupt(digitalPinToInterrupt(rpmInPin), counter, RISING);* Enable PCIE2 Bit3 = 1 (Port D)*/PCICR |= B00000100; /* 启用PCIE2中断 *//* Select PCINT20 Bit4 = 1 (Pin D4) */PCMSK2 |= _BV(rpmInPin); /* 选择要监测的引脚 *//* 禁用Nano Mini板的RGB灯 */CRGB leds[3] = {{0, 0, 0},{0, 0, 0},{0, 0, 0},};FastLED.addLeds<WS2812, 2, GRB>(leds, 3); /* 添加LED */FastLED.show();                           /* 更新LED状态 */Serial.begin(115200);           /* 初始化串口通信 */Serial.println("HP fan proxy"); /* 输出初始化信息 */
}/* 读取HPE PWM信号 */
float readHpePWM(int pin, int sample) {uint32_t total = 0; /* 总样本计数 */uint32_t low = 0;   /* 低电平计数 */for (uint16_t i = 0; i < sample; i++) {low += isLow(pin); /* 统计低电平持续时间 */total++;           /* 增加总样本计数 */}/* 返回反转的PWM值 */return ((float)low / total);
}/* 读取Intel PWM信号 */
float readIntelPWM(int pin, int sample) {uint32_t total = 0; /* 总样本计数 */uint32_t low = 0;   /* 高电平计数 */for (uint16_t i = 0; i < sample; i++) {low += isHigh(pin); /* 统计高电平持续时间 */total++;            /* 增加总样本计数 */}/* 返回正常的PWM值 */return ((float)low / total);
}/* 在指定引脚输出PWM信号 */
void analogWrite25k(int pin, int value) {switch (pin) {case 9:OCR1A = value; /* 设置引脚9的PWM值 */break;case 10:OCR1B = value; /* 设置引脚10的PWM值 */break;default:/* 不支持的引脚 */break;}
}uint32_t pulseFanPrev = 0;
uint32_t clockPrev = 0;/* 将输入值映射到指定范围 */
float map_to_float(float x, float in_min, float in_max, float out_min, float out_max) {return ((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min);;
}void loop() {/* 处理第一次循环 */if (pulseFanPrev == 0 && clockPrev == 0) {pulseFanPrev = pulseCount; /* 记录脉冲计数 */clockPrev = millis();      /* 记录时间 */delay(1000);               /* 等待1秒 */return;                    /* 返回以开始下一次循环 */}/* 计算RPM */uint32_t clockLoopBegin = millis();          /* 记录循环开始时间 */uint32_t pulse = pulseCount - pulseFanPrev;  /* 计算脉冲数 */uint32_t clock = clockLoopBegin - clockPrev; /* 计算时间间隔 */pulseFanPrev = pulseCount;                   /* 更新上一次脉冲计数 */clockPrev = millis();                        /* 更新上一次时间 *//* 计算RPM(每分钟转速) */uint32_t rpm = pulse * 1000 * 60 / 2 / clock; /* 根据脉冲和时间计算转速 */digitalWrite(hpeTachPin, rpm > 0 ? LOW : HIGH); /* 根据转速状态输出信号 *//* 读取反转PWM信号并输出映射值 */float pwmOut;float pwmIn = readHpePWM(pwmInPin, sample); /* 读取PWM输入信号 */if (pwmIn >= pwmMap[1])                     /* 根据输入PWM值选择输出 */pwmOut = pwmMap[3];else if (pwmIn <= pwmMap[0])pwmOut = pwmMap[2];elsepwmOut = map_to_float(pwmIn, pwmMap[0], pwmMap[1], pwmMap[2], pwmMap[3]); /* 映射输入PWM */uint16_t out = uint16_t(pwmOut * pwmTop); /* 将输出PWM值转换为整型 */analogWrite25k(pwmOutPin, out);           /* 输出PWM信号 *//* 打印调试信息 */Serial.print("iLO: ");Serial.print(pwmIn * 100);Serial.print("% Out: ");Serial.print(pwmOut * 100);Serial.print("% RPM: ");Serial.print(rpm);Serial.print(" : ");Serial.print(pulse);Serial.print(" / ");Serial.println(clock);/* 固定1Hz的控制,并输出正常的转速信号 */clock = millis() - clockLoopBegin; /* 计算循环持续时间 */int rpmIn = pwmIn * rpmUpper;      /* 将输入PWM转换为RPM值 */if (rpmIn > timer2RpmLower) {int freq = timer2Freq / (rpmIn * 2 / 60); /* 根据RPM计算频率 */OCR2A = freq;                             /* 更新OCR2A值 */analogWrite(normalTachPin, freq / 2);     /* 输出正常转速信号 */delay(1000 - clock);                      /* 等待剩余时间 */} else if (rpmIn > 0) {int count = max(rpmIn, rpmLower) * 2 / 60; /* 计算输出脉冲的数量 */float half = 1000.0 / count / 2;           /* 计算每个脉冲的持续时间 */for (int i = 0; i < count * 2 - 1; ++i) {digitalWrite(normalTachPin, (i & 1) ? LOW : HIGH); /* 交替输出高低电平 */uint32_t now = millis() - clockLoopBegin;          /* 记录当前时间 *//* Serial.println(now); */uint32_t next = clock + half * (i + 1); /* 计算下一个脉冲的时间 */delay(next - now);                      /* 等待下一个脉冲 */}digitalWrite(normalTachPin, LOW);  /* 结束脉冲输出 */clock = millis() - clockLoopBegin; /* 更新循环时间 */if (clock < 1000) {delay(1000 - clock); /* 等待直到1秒结束 */}} else {delay(1000 - clock); /* 如果RPM为0,等待剩余时间 */}
}

代码具体的使用方法,我们先按下不表,等讨论完所有相关问题的解决方案后再详细展开。

确保备件来源可持续

在这个改造方案中,我们需要准备以下几类配件:

  • HPE Gen10 系列替换用的大号风扇
  • 适配 HPE 主板的风扇接口配件
  • Arduino Nano Mini 开发板
  • iLO 散热器
  • iLO 区域芯片专用小风扇
  • 各类连接线材(包括数据线、电源线)、接线端子、绝缘胶带等

在 zhaoyingpu/hpe-gen10-fan-proxy 项目主页上,作者提供了各个关键零件的网店地址。经过验证,这些配件都有稳定的供应渠道和替换方案,不用担心断货问题(不必担心损耗)。

改造使用的配件

上图展示了我这次改造所使用的具体配件型号。如果你能找到更经济的替代品,完全可以自行更换。考虑到制作过程中可能出现的失误和后期使用中的耗损,我准备了一些备用配件,总成本为 250.07 元。如果你有把握一次成功,实际成本可以控制在 175.9 元左右。

定制数据线接口

由于我没有专业的压线工具和配件座子的簧片端子,所以需要寻求硬件 DIY 达人的帮助。在北京同城找到了一家店铺,店主非常耐心地为我讲解制作流程,并帮我压制了六套线材(具体制作过程会在后文详述)。

数据线半成品

这部分花费了 179 元。如果你对自己 DIY 整合有信心,只需要制作一套线材的话,并且不着急使用设备的话,成本可以降到 99 元内(同城高时效运费占据成本大头)。

值得一提的是,在完成这次改造后,我发现了一个更优的方案,可以将这部分成本降至 20 元,而且硬件可靠性更高。

在解决了上述四个主要技术难题后,我们就可以开始动手改造了。

动手实战

理论部分已经讲完,现在让我们开始动手实践环节。

软件部分:Arduino 控制程序的刷写

参考的原始项目和开发板的网店店铺对于开发板的软件使用说明都比较有限。不过经过一番研究,我找到了最简单的使用方法。(如果你想深入了解,我已经把相关资料整理在了 GitHub 仓库中:soulteary/hpe-gen10-fan-proxy/vendor/docs、soulteary/hpe-gen10-fan-proxy/vendor/misc)

首先,我们需要搭建Arduino的开发环境。请从 Arduino 官网下载 IDE(我使用的是2.3.4版本)。

切换界面语言

为了让教程更容易理解,建议先把 IDE 的界面语言调整为中文。

连接 Arduino 开发板到电脑后,我们就可以测试是否能正常进行程序烧录了。如果你的系统无法识别开发板串口,可以在这里下载对应驱动:soulteary/hpe-gen10-fan-proxy/vendor/drivers。

允许加载三方驱动

对于 macOS 较新系统版本的用户,你需要在系统安全设置中允许“CH34x VCP Driver”,然后重新插入开发板,这样系统就能识别设备串口了。

安装必要的插件

无论是测试程序还是后续的风扇控制程序,我们都会用到LED功能,所以需要在IDE中安装 “FastLED” 和 “Atmega328 IO” 这两个插件。

接下来,为了验证开发板能够正常工作,我编写了一个有趣的程序,可以让开发板的LED灯随机闪烁并产生呼吸灯效果。如果你也想尝试,这段代码已经开源在 soulteary/hpe-gen10-fan-proxy/arduino-test.ino。

#include <FastLED.h>
#define uchar unsigned char
#define RGB_PIN   2         // RGB灯使用IO2进行控制
#define NUM_LEDS  3         // RGB灯的数量
CRGB leds[NUM_LEDS];       // CRGB是结构体类型// 呼吸效果参数
const int BREATH_STEPS = 50;  // 呼吸渐变步数
const int BREATH_DELAY = 20;  // 每步延时(ms)
float breathBrightness = 0;   // 当前亮度
float breathDelta = 1.0;      // 亮度变化方向// 定义颜色结构体
struct Color {uchar r;uchar g;uchar b;
};void RGB_Init(void) {FastLED.addLeds<WS2812, RGB_PIN, GRB>(leds, NUM_LEDS);
}// 带亮度控制的RGB灯控制函数
void RGB_Control(uchar cresset, uchar red, uchar green, uchar blue, float brightness) {leds[cresset] = CRGB(red * brightness,green * brightness,blue * brightness);FastLED.show();
}// 生成随机颜色
Color getRandomColor() {Color c;// 随机选择一个主色调switch(random(6)) {case 0:c = {255, 0, 0};    // 红break;case 1:c = {0, 255, 0};    // 绿break;case 2:c = {0, 0, 255};    // 蓝break;case 3:c = {255, 255, 0};  // 黄break;case 4:c = {255, 0, 255};  // 紫break;case 5:c = {0, 255, 255};  // 青break;}return c;
}void setup() {Serial.begin(115200);RGB_Init();randomSeed(analogRead(0)); // 初始化随机数生成器// 设置输出引脚for(int i = 3; i <= 13; i++) {pinMode(i, OUTPUT);digitalWrite(i, LOW);}
}void loop() {// 为每个LED生成随机颜色Color colors[NUM_LEDS];for(int i = 0; i < NUM_LEDS; i++) {colors[i] = getRandomColor();}// 呼吸效果循环for(int step = 0; step < BREATH_STEPS; step++) {// 更新呼吸亮度breathBrightness += breathDelta * (1.0 / BREATH_STEPS);// 在到达最大或最小亮度时改变方向if(breathBrightness >= 1.0) {breathBrightness = 1.0;breathDelta = -1.0;} else if(breathBrightness <= 0.0) {breathBrightness = 0.0;breathDelta = 1.0;// 在完成一次呼吸周期后重新生成随机颜色for(int i = 0; i < NUM_LEDS; i++) {colors[i] = getRandomColor();}}// 更新所有LEDfor(int i = 0; i < NUM_LEDS; i++) {RGB_Control(i, colors[i].r, colors[i].g, colors[i].b, breathBrightness);}delay(BREATH_DELAY);}// 随机延时,增加闪烁的不规则性delay(random(100, 500));
}

让我们开始上传程序:首先在IDE中选择正确的主板型号,然后将程序代码复制粘贴进去。

将测试程序上传开发板

找到界面左上角的上传按钮(看起来像个“前进”箭头),点击它就会开始编译和上传程序到开发板。

LED 灯光测试

等待几秒钟后,你就能看到开发板上的LED开始闪烁变幻,宛如 “闪亮的灯球”。

完成调度程序编译上传

当我们确认开发板能正常工作、编译和运行测试程序后,就可以用相同的方式上传我们真正需要的风扇调度程序了。将上文“接管设备风扇调度策略”中的代码复制粘贴到 IDE 中,进行相同的编译、上传动作后,这样我们就完成了第一版惠普服务器风扇控制程序的部署。

硬件部分:最终部件制作

我们先来制作主板侧的风扇连接线。根据前文中开发者 Max-Sum 提供的风扇接脚定义(用于控制风扇调度)和开发板官方提供的接口定义,将定制好的接线插入 2x3 PHD2.0 连接器中:

开发板接口定义

开发板和连接器的对应关系如下:

  • 1 号位:红色线,连接开发板 VIN
  • 2 号位:预留空位
  • 3 号位:蓝色线,连接开发板 A1
  • 4 号位:黄色线,连接开发板 A2
  • 5、6 号位:接地线,连接开发板 GND(其中 5 号位需要制作特殊的 “Loop” 线与 6 号位连通)

制作主板风扇连接线

完成后和原厂版本对比,除了特殊的 “Loop” 线外,基本一致。

那么开发板如何与风扇连接呢?还记得我们购买的猫扇包装里就配备了需要的材料。

其他两根线的制作

之前提到的猫扇配件中包含延长线、减速线和一转二线。由于我们需要连接两个风扇,可以直接使用一转二线。具体步骤是:

  • 将一转二线风扇接口对侧的电源接口剪掉,剥出金属线待焊接
  • 把延长线剪下来,取其外层热缩管,剪成合适长度套在新制作的线材上,起到保护作用

接线方案相对简单,不过因为用了成品线,颜色会和之前有些不同:

  • 3PIN 线:蓝色接开发板 D1,黄色接 VIN
  • 4PIN 线:蓝色接开发板 D2,黄色接 VIN,绿色接 D4
  • 两根线的黑色都接开发板 GND

将线和开发板进行焊接组装

最终完成后的开发板造型别致,像是游戏里一个有着三条长腿的生物。

将开发板和风扇、主板连接

接下来的步骤是拆除原装风扇,安装上猫扇,并用我们事先焊接好的开发板将 HP 主板和两个风扇连接起来。

iLO 散热风扇处理细节

我选用的 iLO 降温风扇采用上透风下密封设计,底部是带线塑料结构,顶部是金属。为避免短路,我用绝缘胶带重新包裹了风扇,并用 3M 双面胶垫高固定。未来可能会进一步优化,提升底部芯片的散热效果,不过还是先使用一段时间再说。

iLO 散热器装配

与 Chiphell 原帖子中的方案不同,我没有选择朝向 CPU 散热器的风向设计。这是因为在 Gen10 Plus v2 机箱中,PCIe 扩展插槽的垂直挡板会阻挡气流。特别是在安装了双万兆网卡之后,合上机箱后能够保持的有效风道其实就只剩下从机箱前部到后部的这条直通路径了。

虽然散热器自带的硅胶垫具有一定粘性,但为了稳妥起见,我还是额外使用了 3M 胶带来固定。在进风口位置,我安装了一个主动散热风扇,将冷空气直接吹向大面积的散热器表面。散热器的末端正对着机箱背部,配合机箱风扇的气流方向,理论上能够有效地将热量导出机箱。不过,这个散热方案的实际效果,还需要通过更长期的使用来验证和优化。

到这里,我们的硬件静音改造就告一段落了,也解决了开篇提到的日常安静使用需求。

接下来,让我们回到万兆网络实践这个话题。

万兆网络实践

在上一篇《家用网络升级实践:低成本实现局部万兆(一)》的“Gen 10 Plus 启用万兆网络”部分,我们将万兆网卡安装到了 Gen10 Plus,系统直接识别了这张网卡(免驱动)。

iLO 和 ESXi 默认识别双万兆网卡

ESXi 系统内识别情况

在 ESXi 系统中,我们可以看到系统正确识别了网卡的速率。

支持切换硬件直通

在 ESXi 系统中,我们还可以设置硬件直通,分配给某个操作系统使用。

Gen10 Plus 机箱,漂亮的网络灯光跃动

如果仅仅是给设备增加两个网口来实现万兆组网,未免太过“儿戏”了。毕竟还要考虑后续增加其他设备的问题,而且不是所有设备都支持光口的万兆连接。

计划升级网络接入的设备

还记得上一篇文章中提到的那款支持双万兆网口、4个2.5G网口的交换机吗?

再次入手便宜的螃蟹芯片交换机

上次购买之后,正好我又获得了一些购物补贴,就再入手了一台这个待机功耗仅 1 瓦的设备吧。

计划升级网络接入的设备

将新交换机放在设备旁边,看起来还真有点“父与子”的感觉。

计划升级网络接入的设备

我最终选择的网络拓扑方案是:从主交换机引出一根10G线连接到 Gen10 Plus,Gen10 Plus 的另一个 10G 光口连接到交换机,这台交换机的另一个光口则连接下一台交换机或其他光口设备。这样不仅满足了 10G 连接需求,还能顺便完成多个设备的 2.5G 网络接入,即便所有设备同时和 Gen10 Plus 进行数据交互,也不会出现数据阻塞。

在保证安静运行的前提下,这是目前发热最少、成本最低的方案。交换机无需风扇,也不会产生多余的热量(相比之下,多口交换机还是会有一定发热和噪音)。

交换机电源略大

当然,这个方案也存在一些不足。多个交换机就需要多个电源接口,而且因为是经济型交换机,电源适配器没有特别注重体积和美感设计,三个适配器就占用了整个插板的空间,造成了一定的插座资源(插口)浪费。

最后

好了,写到这里,我们的第二部分的改造就完成了。

我还有一些东西在陆续的物流过程中,关于文章中提到的改进,我想在后续的文章中继续补充和展开。包括并不仅限于更低成本、更简单的 DIY 配件验证,对于这台设备和网络中其他设备的可靠性保障、风扇代理开源程序的持续优化等等。

我们下篇文章再见!

–EOF


我们有一个小小的折腾群,里面聚集了一些喜欢折腾、彼此坦诚相待的小伙伴。

我们在里面会一起聊聊软硬件、HomeLab、编程上、生活里以及职场中的一些问题,偶尔也在群里不定期的分享一些技术资料。

关于交友的标准,请参考下面的文章:

致新朋友:为生活投票,不断寻找更好的朋友

当然,通过下面这篇文章添加好友时,请备注实名和公司或学校、注明来源和目的,珍惜彼此的时间 😄

关于折腾群入群的那些事


如果你觉得内容还算实用,欢迎点赞分享给你的朋友,在此谢过。

如果你想更快的看到后续内容的更新,请戳 “点赞”、“分享”、“收藏” ,这些免费的鼓励将会影响后续有关内容的更新速度。


本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)

本文作者: 苏洋

创建时间: 2025年01月05日
统计字数: 19422字
阅读时间: 39分钟阅读
本文链接: https://soulteary.com/2025/01/05/homelab-10-gigabit-network-practice-silent-transformation-of-compact-home-servers.html

相关文章:

家用万兆网络实践:紧凑型家用服务器静音化改造(二)

大家好&#xff0c;这篇文章我们继续分享家里网络设备的万兆升级和静音改造经验&#xff0c;希望对有类似需求的朋友有所帮助。 写在前面 在上一篇《家用网络升级实践&#xff1a;低成本实现局部万兆&#xff08;一&#xff09;》中&#xff0c;我们留下了一些待解决的问题。…...

“AI智能实训系统:让学习更高效、更轻松!

大家好&#xff0c;作为一名资深产品经理&#xff0c;今天我来跟大家聊聊一款备受瞩目的产品——AI智能实训系统。在这个人工智能技术飞速发展的时代&#xff0c;AI智能实训系统应运而生&#xff0c;为广大学习者提供了全新的学习体验。那么&#xff0c;这款产品究竟有哪些亮点…...

【Linux 之一 】Linux常用命令汇总

Linux常用命令 ./catcd 命令chmodclearcphistoryhtoplnmkdirmvpwdrmtailunamewcwhoami 我从2021年4月份开始才开始真正意义上接触Linux&#xff0c;最初学习时是一脸蒙圈&#xff0c;啥也不会&#xff0c;啥也不懂&#xff0c;做了很多乱七八糟&#xff0c;没有条理的笔记。不知…...

Git 从入门到精通

一、环境配置 下载地址&#xff1a;https://git-scm.com/downloads/ 二、用户配置 找到git bash git --version 查看当前版本 git config --global user.name szhipeng625 设置用户名 git config --global user.email szhipeng625gmail.com 设置邮箱 git config --global …...

【Uniapp-Vue3】创建自定义页面模板

大多数情况下我们都使用的是默认模板&#xff0c;但是默认模板是Vue2格式的&#xff0c;如果我们想要定义一个Vue3模板的页面就需要自定义。 一、我们先复制下面的模板代码&#xff08;可根据自身需要进行修改&#xff09;&#xff1a; <template><view class"…...

Ansible之批量管理服务器

文章目录 背景第一步、安装第二步、配置免密登录2.1 生成密钥2.2 分发公钥2.3 测试无密连接 背景 Ansible是Python强大的服务器批量管理 第一步、安装 首先要拉取epel数据源&#xff0c;执行以下命令 yum -y install epel-release安装完毕如下所示。 使用 yum 命令安装 an…...

android compose 串口通信

1.添加依赖 implementation("io.github.xmaihh:serialport:2.1.1") 2.添加SerialHelper派生类 class SerialPortHelper(portName:String,baudRate:Int): SerialHelper(portName,baudRate) {var receivedDataBuffer mutableListOf<Byte>()override fun onDa…...

ios脚本巨魔商店多巴胺越狱基本操作教程

准备工作 确认设备兼容性&#xff1a;A9-A11&#xff08;iPhone6s&#xff0d;X&#xff09;&#xff1a;iOS15.0-16.6.1&#xff1b;A12-A14&#xff08;iPhoneXR&#xff0d;12PM&#xff09;&#xff1a;iOS15.0-16.5.1&#xff1b;A15-A16&#xff08;iPhone13&#xff0d…...

NLP项目实战——基于Bert模型的多情感评论分类(附数据集和源码)

在当今数字化的时代&#xff0c;分析用户评论中的情感倾向对于了解产品、服务的口碑等方面有着重要意义。而基于强大的预训练语言模型如 Bert 来进行评论情感分析&#xff0c;能够取得较好的效果。 在本次项目中&#xff0c;我们将展示如何利用 Python 语言结合transformers库&…...

.NET framework、Core和Standard都是什么?

对于这些概念一直没有深入去理解&#xff0c;以至于经过.net这几年的发展进化&#xff0c;概念越来越多&#xff0c;越来越梳理不容易理解了。内心深处存在思想上的懒惰&#xff0c;以为自己专注于Unity开发就好&#xff0c;这些并不属于核心范畴&#xff0c;所以对这些概念总是…...

Mybatis原理简介

看到Mybatis的框架图&#xff0c;可以清晰的看到Mybatis的整体核心对象&#xff0c;我更喜欢用自己的图来表达Mybatis的整个的执行流程。如下图所示&#xff1a; 原理详解&#xff1a; MyBatis应用程序根据XML配置文件创建SqlSessionFactory&#xff0c;SqlSessionFactory在根…...

腾讯云AI代码助手-公司职位分析AI助手

作品简介 腾讯云AI代码助手是一款智能工具&#xff0c;专注于为公司提供职位分析服务。通过自然语言处理和机器学习技术&#xff0c;它能快速解析职位描述&#xff0c;提取关键信息&#xff0c;并提供数据驱动的洞察&#xff0c;帮助公司优化招聘流程和职位设计。 技术架构 …...

腾讯云AI代码助手编程挑战赛-解忧助手

作品简介 何以解忧,唯有杜康。而随着Ai的发展,解忧不再只有杜康还有Ai,使用的是腾讯云AI代码助手来生成的所有代码&#xff0c;使用方便&#xff0c;快捷&#xff0c;高效。 技术架构 采用了全后端分离的架构&#xff0c;前端使用Vue.js&#xff0c;腾讯云的AI服务处理自然语…...

Sentinel服务保护 + Seata分布式事务

服务保护 【雪崩问题】微服务调用链路中某个服务&#xff0c;引起整个链路中所有微服务都不可用。 【原因】&#xff1a; 微服务相互调用&#xff0c;服务提供者出现故障。服务调用这没有做好异常处理&#xff0c;导致自身故障。调用链中所有服务级联失败&#xff0c;导致整个…...

【Leetcode·中等·数组】59. 螺旋矩阵 II(spiral matrix ii)

题目描述 英文版描述 Given a positive integer n, generate an n x n matrix filled with elements from 1 to n(2) in spiral order. Example 1: Input: n 3 Output: [[1,2,3],[8,9,4],[7,6,5]] 提示&#xff1a; 1 < n < 20 英文版地址 https://leetcode.com…...

WebSocket 扩展生态:协议与框架

在前七篇文章中,我们深入探讨了 WebSocket 的基础原理、开发实践和实战案例。今天,让我们把视野扩展到 WebSocket 的生态系统,看看有哪些扩展协议和框架可以帮助我们更好地开发 WebSocket 应用。我曾在一个大型即时通讯项目中,通过合理使用这些工具,将开发效率提升了 50%。 扩…...

MySQL —— 在CentOS9下安装MySQL

MySQL —— 在CentOS9下安装MySQL 1.查看自己操作系统的版本2.找到对应的安装源3.上传我们在windows下&#xff0c;下载的文件&#xff0c;解压4.执行rpm命令&#xff0c;启用MySQL8仓库5.执行dnf install -y mysql-community-server6.设置开机自启动7.获得初始密码8.登录MySQL…...

用VS C#构建Windows服务【纯操作版,附带项目地址】

1.点击“创建新项目”,选择“Windows 服务(.NET Framework)” 2、给项目命名 3、双击“Service1.cs”,右键,选择“添加安装程序”,就会生成一个“ProjectInstaller.cs”文件 4、双击“ProjectInstaller.cs”文件,右键“serviceProcessInstaller1”,选择“属性…...

1.UGUI相关

1.这一种UIcanvas下的组件,会显示在3d物体之前 2.可以设置3d物体在UI界面之前。选中第二个模式。这时候会指定一个摄像机。一般情况下&#xff0c;不用主摄像机。需要新建一个专门给UI的摄像机。相当于设置距离摄像机的远近。两个layer 可以理解成 章节&#xff0c;关卡。相同…...

大语言模型训练的数据集从哪里来?

继续上篇文章的内容说说大语言模型预训练的数据集从哪里来以及为什么互联网上的数据已经被耗尽这个说法并不专业&#xff0c;再谈谈大语言模型预训练数据集的优化思路。 1. GPT2使用的数据集是WebText&#xff0c;该数据集大概40GB&#xff0c;由OpenAI创建&#xff0c;主要内…...

Android 来电白名单 只允许联系人呼入电话

客户需求只允许通讯录中联系人可以呼入电话。参考自带的黑名单实现 CallsManager.java类中的onSuccessfulIncomingCall方法有一些过滤器&#xff0c;可以仿照黑名单的方式添加自己的过滤器。 packages/services/Telecomm/src/com/android/server/telecom/CallsManager.java …...

StarRocks Awards 2024 年度贡献人物

在过去一年&#xff0c;StarRocks 在 Lakehouse 与 AI 等关键领域取得了显著进步&#xff0c;其卓越的产品功能极大地简化和提升了数据分析的效率&#xff0c;使得"One Data&#xff0c;All Analytics" 的愿景变得更加触手可及。 虽然实现这一目标的道路充满挑战且漫…...

plane开源的自托管项目

Plane 是一个开源的自托管项目规划解决方案&#xff0c;专注于问题管理、里程碑跟踪以及产品路线图的设计。作为一款开源软件&#xff0c;Plane 的代码托管在 GitHub 平台上&#xff0c;允许任何人查看和贡献代码。它为用户提供了便捷的项目创建与管理手段&#xff0c;并配备了…...

WebLogic安全基线

WebLogic安全基线 一、 用户权限1 、检查weblogic 的启动用户2 、用户权限整改3 、使用普通用户重启weblogic 二、账户共用1 、检查weblogic 控制台的账户2 、账户共用整改3 、测试登录weblogic 控制台新账户 三、 账户清理1 、检查weblogic 控制台的账户2 、帐户清理整改 四、…...

复杂园区网基本分支的构建

目录 1、各主机进行网络配置。2、交换机配置。3、配置路由交换&#xff0c;进行测试。4、配置路由器接口和静态路由&#xff0c;进行测试。5、最后测试任意两台主机通信情况 模拟环境链接 拓扑结构 说明&#xff1a; VLAN标签在上面的一定是GigabitEthernet接口的&#xff0c…...

设计模式-结构型-组合模式

1. 什么是组合模式&#xff1f; 组合模式&#xff08;Composite Pattern&#xff09; 是一种结构型设计模式&#xff0c;它允许将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得客户端对单个对象和组合对象的使用具有一致性。换句话说&#xff0c;组合模式允…...

32单片机从入门到精通之用户界面——用户界面(十四)

不论你现在处于什么样的困境和挑战&#xff0c;不要放弃希望和努力。成功之路不会一帆风顺&#xff0c;但是只要你坚定信念&#xff0c;勇敢面对困难&#xff0c;努力奋斗&#xff0c;就一定能够战胜困难&#xff0c;迈向成功的道路。困难和挫折只是暂时的&#xff0c;而坚持和…...

Redis 优化秒杀(异步秒杀)

目录 为什么需要异步秒杀 异步优化的核心逻辑是什么&#xff1f; 阻塞队列的特点是什么&#xff1f; Lua脚本在这里的作用是什么&#xff1f; 异步调用创建订单的具体逻辑是什么&#xff1f; 为什么要用代理对象proxy调用createVoucherOrder方法&#xff1f; 对于代码的详细…...

NFS 组件容器化部署实战指南

文章目录 前言部署NFS服务器K8S部署NFS问题记录 前言 使用nfs-client-provisioner这个应用&#xff0c;利用nfs server给kubernets提供作为持久化后端&#xff0c;并且动态提供pv。所有节点需要安装nfs-utils组件&#xff0c;并且nfs服务器与kubernets worker节点都能网络连通…...

LCE(Local Cascade Ensemble)预测模型和LSTM(Long Short-Term Memory)模型在效果和特点上存在显著差异

LCE&#xff08;Local Cascade Ensemble&#xff09;预测模型和LSTM&#xff08;Long Short-Term Memory&#xff09;模型在效果和特点上存在显著差异。以下是对两者的比较&#xff1a; 一、效果比较 LCE模型&#xff1a; 优势&#xff1a;LCE结合了随机森林和XGBoost的优势&a…...

rk3568平台Buildroot编译实践:内核rootfs定制 及常见编译问题

目录 编译前准备常规编译流程定制内核修改内核 参数并增量 保存修改rootfs并增量 保存修改rootfs包下载源rootfs软件包增删refBuildroot 是一个用于自动化构建嵌入式 Linux 系统的工具。它通过使用简单的配置文件和 Makefile,能够从源代码开始交叉编译出一个完整的、可以运行在…...

头歌python实验:网络安全应用实践-恶意流量检测

第1关:re 库的使用 本关任务:编写一个能正则匹配出 ip 地址的小程序。 re 的主要功能函数 常用的功能函数包括: compile、search、match、split、findall(finditer)、sub(subn)。 re.search 函数 re.search 扫描整个字符串并返回第一个成功的匹配。 函数语法: re…...

Linux内核编程(二十一)USB应用及驱动开发

一、基础知识 1. USB接口是什么&#xff1f; USB接口&#xff08;Universal Serial Bus&#xff09;是一种通用串行总线&#xff0c;广泛使用的接口标准&#xff0c;主要用于连接计算机与外围设备&#xff08;如键盘、鼠标、打印机、存储设备等&#xff09;之间的数据传输和电…...

机器学习实战——决策树:从原理到应用的深度解析

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​ ​​​ ​​ 决策树&#xff08;Decision Tree&#xff09;是一种简单而直观的分类与回归模型&#xff0c;在机器学习中广泛应用。它的…...

计算机网络的定义与发展历程

计算机网络的定义 计算机网络是指通过通信设备和传输介质将分布在不同地点的计算机及其相关设备&#xff08;如打印机、服务器等&#xff09;连接起来&#xff0c;按照一定的通信协议进行数据交换与资源共享的系统。计算机网络的基本功能包括&#xff1a;信息的传输、资源共享…...

什么是Kafka?有什么主要用途?

大家好&#xff0c;我是锋哥。今天分享关于【什么是Kafka&#xff1f;有什么主要用途&#xff1f;】面试题。希望对大家有帮助&#xff1b; 什么是Kafka&#xff1f;有什么主要用途&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Kafka 是一个分布式流…...

Ubuntu 24.04 LTS系统安装Docker踩的坑

一开始我跟着Docker给出的官网文档 Ubuntu | Docker Docs 流程走&#xff0c;倒腾了两个多小时&#xff0c;遇到了各种坑&#xff0c;最后放弃了。在我们使用脚本安装Docker命令前&#xff0c;我们先把已经安装的Docker全部卸载掉。 卸载Docker 1.删除docker及安装时自动安装…...

算法基础 - 冒泡排序

文章目录 1、原理演示2、示例一 冒泡排序是一种简单的排序算法&#xff0c;它重复地遍历要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果它们的顺序错误就把它们交换过来。重复进行直到没有再需要交换的元素&#xff0c;这意味着数列已经排序完成。 冒泡排序法采用…...

为答疑机器人扩展问题分类与路由功能

1.意图识别 2. 构建路由模块 简单的意图识别 from chatbot import llmfrom config.load_key import load_key load_key()prompt 【角色背景】 你是一个问题分类路由器&#xff0c;需要识别问题的类型。 --- 【任务要求】 问题的类型目前有&#xff1a;公司内部文档查询、内…...

如何解决 /proc/sys/net/bridge/bridge-nf-call-iptables 文件缺失的问题

在使用 Linux 系统&#xff0c;尤其是在容器化环境&#xff08;如 Docker、Kubernetes&#xff09;中时&#xff0c;我们可能会遇到如下错误信息&#xff1a; [ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptabl…...

道品科技智慧农业与云平台:未来农业的变革之路

随着全球人口的不断增长&#xff0c;农业面临着前所未有的挑战。如何在有限的土地和资源上提高农业生产效率&#xff0c;成为了各国政府和农业从业者亟待解决的问题。智慧农业的兴起&#xff0c;结合云平台的应用&#xff0c;为农业的可持续发展提供了新的解决方案。 ## 一、智…...

芯片详细讲解,从而区分CPU、MPU、DSP、GPU、FPGA、MCU、SOC、ECU

目录 芯片的概念结构 芯片的派系划分 通用芯片&#xff08;CPU&#xff0c;MPU&#xff0c;GPU&#xff0c;DSP&#xff09; 定制芯片&#xff08;FPGA&#xff0c;ASIC&#xff09; 芯片之上的集成&#xff08;MCU&#xff0c;SOC&#xff0c;ECU&#xff09; 软硬件的匹…...

2025年01月09日Github流行趋势

1. 项目名称&#xff1a;khoj 项目地址url&#xff1a;https://github.com/khoj-ai/khoj项目语言&#xff1a;Python历史star数&#xff1a;22750今日star数&#xff1a;1272项目维护者&#xff1a;debanjum, sabaimran, MythicalCow, aam-at, eltociear项目简介&#xff1a;你…...

OpenCV计算机视觉 06 图像轮廓检测(轮廓的查找、绘制、特征、近似及轮廓的最小外接圆外接矩形)

目录 图像轮廓检测 轮廓的查找 轮廓的绘制 轮廓的特征 面积 周长 根据面积显示特定轮廓 轮廓的近似 给定轮廓的最小外接圆、外接矩形 外接圆 外接矩形 图像轮廓检测 轮廓的查找 API函数 image, contours, hierarchy cv2.findContours(img, mode, method) 代入参…...

安装完docker后,如何拉取ubuntu镜像并创建容器?

1. 先docker拉取ubuntu镜像 docker search ubuntu #搜索ubuntu 镜像 docker pull ubuntu:22.04 #拉取ubuntu 镜像 docker images #下载完成后&#xff0c;查看已经下载的镜像 docker run --name ubuntu_container -dit ubuntu:22.04 /bin/bash # docker container -l 2.…...

C++中的表达式

文章目录 算数操作符位操作符bitset对象或整型值的使用将位移操作符用作IO 赋值操作符赋值操作符的右结合性赋值操作具有低优先级 自增和自减操作符条件操作符sizeof操作符优先级new和delete表达式类型转换何时发生隐式转换显示转换旧式强制类型转换 C中的表达式由一个或多个操…...

直流无刷电机控制(FOC):电流模式

目录 概述 1 系统框架结构 1.1 硬件模块介绍 1.2 硬件实物图 1.3 引脚接口定义 2 代码实现 2.1 软件架构 2.2 电流检测函数 3 电流环功能实现 3.1 代码实现 3.2 测试代码实现 4 测试 概述 本文主要介绍基于DengFOC的库函数&#xff0c;实现直流无刷电机控制&#x…...

LabVIEW水轮发电机组振动摆度故障诊断

本文介绍了基于LabVIEW的水轮发电机组振动摆度故障诊断系统的设计与实施过程。系统在通过高效的故障诊断功能&#xff0c;实现水轮发电机组的振动、温度等关键指标的实时监控与智能分析&#xff0c;从而提高电力设备的可靠性和安全性。 ​ 项目背景 随着电力行业对设备稳定性…...

《暗时间》读书笔记

前言 2003年&#xff0c;刘未鹏在杂志上发表了自己的第一篇文章&#xff0c;并开始写博客。最初的博客较短&#xff0c;也较琐碎&#xff0c;并夹杂着一些翻译的文章。后来渐渐开始有了一些自己的心得和看法。在这8年里&#xff0c;作者平均每个月写1篇博客或更少&#xff0c;…...

【SQL】COUNT()函数 用法详解

COUNT()函数 COUNT函数用法&#xff1a;COUNT ( [ALL | DISTINCT] column | expression | *) ALL关键字指示统计所有值&#xff0c;而DISTINCT关键字强制函数仅对不同的值进行操作。 默认情况下&#xff0c;使用ALL选项。条件表达式 COUNT()函数中条件表达式加 OR null。例如…...