又酷又迷你的DIY服务器---bbServer 制作过程与经验分享

2023-01-222万
精华项目
AI 快速预览详细 收起
bbServer是一个基于香橙派5单板电脑的DIY服务器项目,通过GPIO控制OLED屏幕和RGB灯带,实现酷炫的视觉效果。该项目适用于运行Minecraft服务器,并支持多种服务配置。硬件清单包括香橙派5、OLED屏幕、RGB灯带等。最终效果是实现高性能、低功耗的家用服务器。难度等级适中,适合零基础新手入门。
bbServer 制作过程与经验分享

【简介】

bbServer 是一台高性能、低功耗、酷炫的家用服务器,通过单板电脑特有的 GPIO 完成屏幕和灯带的控制,配合单面镜和半透镜形成深渊灯的效果。作者的个人应用场景是用来运行 Minecraft 服务器,让游戏内的活动与服务器外围设备产生联动,例如当有玩家进入服务器时,会在 OLED 屏幕上显示,并且伴随着光效。

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图1

开源链接:
https://github.com/RealCorebb/bbServer

视频链接:
https://www.bilibili.com/video/BV1j24y1a7Ut/

【故事起因】

我一直想 DIY 一台能够放在家里 24 小时开机的服务器。我希望这台服务器功耗足够低,这样就不会被妈妈打。因为我想用它来运行 Minecraft 服务器,所以性能也需要稍微好一点。然而,低功耗和高性能之间存在着矛盾,我只有选择能耗比更高的芯片。
所以,我选择了香橙派5这类 ARM 架构的单板电脑,因为它省电、体积小,性能也高,而且可以像单片机一样控制一些电子元件。因此,我在服务器上添加 OLED 屏幕和 WS2812 RGB 灯带,借助 CircuitPython 就可以根据自己的想法尽情发挥,制作出这样一台低功耗、迷你、又好玩又酷炫的服务器。

【bbServer制作步骤】

1.购买所需物料
在开始制作bbServer之前,您需要准备以下物料:

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图2

(1)香橙派5,这是一款性价比非常高的RK3588S单板电脑,RK3588S是一个8nm制程ARM架构的SOC,有8核心(6大核+2小核),用来开中小型Minecraft服务器是非常稳妥且省电的。
(2)2.42寸OLED屏幕 (4PIN I2C版本)
(3)WS2812-2020 寻址RGB灯带(90LEDS/M)
(4)3D打印外壳
(5)单面镜+30%半透镜
(6)M2硬盘(2230或2242尺寸)
(7)散热片(19*19*5mm)
(8)3007涡轮散热风扇
(9)5V4A电源适配器

2.组装硬件
将M.2硬盘插入香橙派5上的M.2插槽中。

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图3

将散热片安装在香橙派5的芯片上,然后将其插入3D打印的外壳中,并将四周的固定螺丝扭紧。香橙派5本身侧边有一个开关机的按键,如果需要使用的话也可以3D打印一个较大的按钮模型,卡在外壳与开关按键之间。

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图4

安装3007涡轮散热风扇,可以装在芯片旁边,出气口朝外,将正负极分别接到5V和GND。如果想要更安静一点,也可以接到3.3V。

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图5

将WS2812-2020 RGB灯带与OLED屏幕连接到香橙派5的GPIO引脚上,确保连接正确。因为设计的外壳想尽量保持小巧、紧凑,所以用一般的2.54间距的杜邦线会太高,装不进去。解决办法就是将杜邦线的胶壳去掉(用镊子撬开卡口,把线拿出来即可),可以用热缩管或胶布套住端子部分,避免相互之间接触导电。

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图6

具体的IO引脚和接线图如下:

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图7

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图8

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图9

安装好之后可以跳到第3大步:安装系统、环境,测试一下LED和屏幕是否正常点亮,然后接着完成最后的组装。
在验证硬件正常后,将单面镜和30%半透镜组装到3D打印的外壳中,注意尽量戴上干净的手套,避免手指印。

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图10

OLED屏幕可以一边用胶布固定在RJ45网口上,另一边用杜邦线顶着。摆放在正中间靠后的位置,然后将单面镜卡进OLED屏幕与LED之间。

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图11

接着,再盖上半透镜就大功告成啦。

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图12

3.安装系统
香橙派5官方提供了Ubuntu、Debian、Android系统,也有在单板电脑上比较出名的Armbian系统。但目前的情况Armbian有一些BUG,导致I2C和SPI功能不正常,无法使用LED和OLED。所以这里选择的是官方的Ubuntu系统。

完整的文档可以参考官方的使用说明书:
http://www.orangepi.cn/html/hardWare/computerAndMicrocontrollers/service-and-support/Orange-pi-5.html

大致步骤如下:

(1)准备一张TF卡,使用balenaEtcher软件将官网下载的Ubuntu镜像写入TF卡中
(2)插入TF卡、M2硬盘,开机。连接网线,使用Xshell连接香橙派或使用HDMI连接显示器操作。默认用户名为:root,密码为:orangepi
(3)在终端控制台输入指令nand-sata-install,选择Install the bootloader on SPI Flash,等待几分钟直至出现Done

又酷又迷你的DIY服务器---bbServer 制作过程与经验分享图13

(4)将镜像写入M2硬盘中,指令如下:
dd bs=1M if=<镜像路径> of=/dev/nvme0n1 status=progress
例如:
dd bs=1M if=Orangepi5_x.x.x_ubuntu.img of=/dev/nvme0n1 status=progress
(5)写入完成后,就可以输入poweroff指令关机,拔掉TF卡,再开机,以后就都是用M2硬盘作为系统盘开机啦。M2硬盘比起TF卡更耐用,更适合长时间运行,速度也更快。

4.配置环境
在完成以上步骤后,这就是一台arm架构的Ubuntu系统的电脑了,你可以使用绝大多数能在Linux上运行的软件,例如假设Mumble语音服务器、Minecraft服务器、Apache网站服务器等等……

除此之外,还可以利用上面的GPIO,让它能够像单片机一样控制一些电子零件。

安装必要的软件包:Python、pip、CircuitPython。前面两个大家都很熟悉,最后一个CircuitPython就是一个能在Linux板子上运行类似单片机功能的框架,是由电子界著名的Adafruit出品的。

因为具体的步骤有点复杂,想要研究的可以参考官方的文档:
https://learn.adafruit.com/circuitpython-on-orangepi-linux/circuitpython-orangepi
官方文档使用的是Armbian系统以及较老的香橙派,不过大致是一样的,需要修改一些东西让CircuitPython能够识别到我们使用的板子型号。

为此,我写了一个脚本,可以一键在香橙派Ubuntu系统下安装好CircuitPython以及我们使用的OLED屏幕和WS2812 LED灯带相应的依赖库。

脚本地址:
https://raw.githubusercontent.com/RealCorebb/bbServer/master/bbServer.sh

可以使用以下方式安装:
wget https://raw.githubusercontent.co ... /master/bbServer.sh
chmod 777 bbServer.sh
./bbServer.sh

在安装好后,需要重启一次。安装好后会把bbServer的demo示例程序设为开机自启,所以重启后会看到LED灯带动画以及OLED屏幕显示时间、CPU、内存信息了。

以下是demo的程序,可以看到使用CircuiPython是比较容易上手,发挥自己的想法的。有丰富的库,能够立马上手。

  1. 1.import threading
  2. 2.import board
  3. 3.import neopixel_spi
  4. 4.from PIL import Image, ImageDraw, ImageFont
  5. 5.from adafruit_led_animation.animation.blink import Blink
  6. 6.from adafruit_led_animation.animation.sparklepulse import SparklePulse
  7. 7.from adafruit_led_animation.animation.comet import Comet
  8. 8.from adafruit_led_animation.animation.chase import Chase
  9. 9.from adafruit_led_animation.animation.pulse import Pulse
  10. 10.from adafruit_led_animation.animation.sparkle import Sparkle
  11. 11.from adafruit_led_animation.animation.rainbowchase import RainbowChase
  12. 12.from adafruit_led_animation.animation.rainbowsparkle import RainbowSparkle
  13. 13.from adafruit_led_animation.animation.rainbowcomet import RainbowComet
  14. 14.from adafruit_led_animation.animation.solid import Solid
  15. 15.from adafruit_led_animation.animation.colorcycle import ColorCycle
  16. 16.from adafruit_led_animation.animation.rainbow import Rainbow
  17. 17.from adafruit_led_animation.animation.customcolorchase import CustomColorChase
  18. 18.from adafruit_led_animation.sequence import AnimationSequence
  19. 19.from adafruit_led_animation.color import PURPLE, WHITE, AMBER, JADE, MAGENTA, ORANGE , BLACK , RED
  20. 20.import adafruit_ssd1306
  21. 21.import time
  22. 22.import psutil
  23. 23.import pathlib
  24. 24.dirPath = str(pathlib.Path(__file__).parent.resolve())
  25. 25.font = ImageFont.truetype(dirPath+'/fonts/Jorolks.ttf',24)
  26. 26.smallJorolks = ImageFont.truetype(dirPath+'/fonts/Jorolks.ttf',12)
  27. 27.seledom = ImageFont.truetype(dirPath+'/fonts/Seledom.otf',14)
  28. 28.bigSeledom = ImageFont.truetype(dirPath+'/fonts/Seledom.otf',33)
  29. 29.pixelCorebb = ImageFont.truetype(dirPath+'/fonts/PixelCorebb.ttf',15)
  30. 30.pixelCorebbBig = ImageFont.truetype(dirPath+'/fonts/PixelCorebb.ttf',14)
  31. 31.player = Image.open(dirPath+'/icons/steve24.png')
  32. 32.player16 = Image.open(dirPath+'/icons/steve16.png')
  33. 33.performance = Image.open(dirPath+'/icons/performance.png')
  34. 34.
  35. 35.
  36. 36.# ------------------- WS2812 RGB LED  -_,- ------------------
  37. 37.
  38. 38.# Update to match the pin connected to your NeoPixels
  39. 39.pixel_pin = board.SPI()
  40. 40.# Update to match the number of NeoPixels you have connected
  41. 41.pixel_num = 40
  42. 42.
  43. 43.pixels = neopixel_spi.NeoPixel_SPI(pixel_pin, pixel_num, brightness=0.1, auto_write=False)
  44. 44.
  45. 45.blink = Blink(pixels, speed=0.5, color=JADE)
  46. 46.redFastBlink = Blink(pixels, speed=0.1, color=RED)
  47. 47.colorcycle = ColorCycle(pixels, speed=0.4, colors=[MAGENTA, ORANGE])
  48. 48.comet = Comet(pixels, speed=0.01, color=PURPLE, tail_length=10, bounce=True)
  49. 49.chase = Chase(pixels, speed=0.1, size=3, spacing=6, color=WHITE)
  50. 50.pulse = Pulse(pixels, speed=0.1, period=3, color=AMBER)
  51. 51.sparkle = Sparkle(pixels, speed=0.1, color=PURPLE, num_sparkles=10)
  52. 52.solid = Solid(pixels, color=JADE)
  53. 53.black = Solid(pixels, color = BLACK)
  54. 54.rainbow = Rainbow(pixels, speed=0.1, period=2)
  55. 55.sparkle_pulse = SparklePulse(pixels, speed=0.1, period=3, color=JADE)
  56. 56.rainbow_comet = RainbowComet(pixels, speed=0.05, tail_length=15, bounce=True)
  57. 57.rainbow_chase = RainbowChase(pixels, speed=0.1, size=3, spacing=2, step=8)
  58. 58.rainbow_sparkle = RainbowSparkle(pixels, speed=0.1, num_sparkles=15)
  59. 59.custom_color_chase = CustomColorChase(
  60. 60.    pixels, speed=0.1, size=2, spacing=3, colors=[ORANGE, WHITE, JADE]
  61. 61.)
  62. 62.
  63. 63.
  64. 64.animations = AnimationSequence(
  65. 65.    comet,
  66. 66.    blink,
  67. 67.    rainbow_sparkle,
  68. 68.    chase,
  69. 69.    pulse,
  70. 70.    sparkle,
  71. 71.    rainbow,
  72. 72.    solid,
  73. 73.    rainbow_comet,
  74. 74.    sparkle_pulse,
  75. 75.    rainbow_chase,
  76. 76.    custom_color_chase,
  77. 77.    advance_interval=5,
  78. 78.    auto_clear=True,
  79. 79.)
  80. 80.
  81. 81.# ------------------------------------
  82. 82.
  83. 83.# ------------------- SSD1306/SSD1309 OLED  -_,- ------------------
  84. 84.oled = None
  85. 85.
  86. 86.# Create blank image for drawing.
  87. 87.image = Image.new("1", (128, 64))
  88. 88.draw = ImageDraw.Draw(image)
  89. 89.
  90. 90.def clear():
  91. 91.    global image
  92. 92.    #image = Image.new("1", (oled.width, oled.height))
  93. 93.    draw.rectangle((0, 0, 128, 64), fill="black")
  94. 94.    oled.fill(0)
  95. 95.
  96. 96.def bootLogo():
  97. 97.    draw.text((5, 20), "bbServer", fill="white", font = font)
  98. 98.    oled.image(image)
  99. 99.    oled.show()
  100. 100.
  101. 101.def updateInfo():
  102. 102.    global oled
  103. 103.    i2c = board.I2C()  # uses board.SCL and board.SDA
  104. 104.    attempts = 0
  105. 105.    while attempts < 5:
  106. 106.        try:
  107. 107.            oled = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c)
  108. 108.            break
  109. 109.        except:
  110. 110.            attempts += 1
  111. 111.            print('OLED not found, retrying...')
  112. 112.            time.sleep(1)
  113. 113.        
  114. 114.    # Clear display.
  115. 115.    oled.fill(0)
  116. 116.    oled.rotate(False)
  117. 117.    oled.show()
  118. 118.    clear()
  119. 119.    bootLogo()
  120. 120.    time.sleep(1)
  121. 121.    while True:
  122. 122.        cpu = int(psutil.cpu_percent(interval=1))
  123. 123.        ram = int(psutil.virtual_memory().percent)
  124. 124.        timeNow = time.strftime("%H:%M")
  125. 125.        
  126. 126.        clear()
  127. 127.        draw.rounded_rectangle((2,2,28,12), radius=3, fill="white")
  128. 128.        draw.text((5,3), "CPU", fill="black", font = smallJorolks)
  129. 129.        draw.text((32,0), str(cpu)+"%", fill="white",font = pixelCorebb)
  130. 130.        draw.rounded_rectangle((67,2,96,12), radius=3, fill="white")
  131. 131.        draw.text((70,3), "RAM", fill="black", font = smallJorolks)
  132. 132.        draw.text((100,0), str(ram)+"%", fill="white",font = pixelCorebb)
  133. 133.        draw.text((2,24), timeNow, fill="white",font = bigSeledom)
  134. 134.        oled.image(image)
  135. 135.        oled.show()
  136. 136.        time.sleep(1)
  137. 137.# ------------------------------------
  138. 138.
  139. 139.if __name__ == "__main__":
  140. 140.    oledThread = threading.Thread(target=updateInfo)
  141. 141.    oledThread.start()
  142. 142.    while True:
  143. 143.        time.sleep(0.01)
  144. 144.        animations.animate()
复制代码

【一些可能遇到的问题】


1.在烧写系统进TF卡后,在Windows 的资源管理器里就找不到这张TF卡了。这是正常的,因为写入了Linux系统后,Windows是读不了的。所以只能在像是Balenaetcher等烧写软件中看到,如果想变回原来的样子,在这类软件中点一下格式化即可。不要以为是TF卡坏了(作者以前就以为是TF卡坏了)

2.不知道怎么连接服务器。官方的镜像中是有桌面版和服务器版的,主要的差别在于前者有图形化的操作界面,也可以用HDMI连接显示器,后者只能连网线,用其它电脑通过SSH控制。如果作为服务器使用的话,其实一般的使用场景是类似于后者的,但对于新手来说,建议安装桌面版的,更容易上手。想了解的话,可以参考云服务器、普通Linux电脑的连接方式和工具,常用免费工具的有:Xshell,通过SSH,输入IP、用户名、密码,即可连上服务器的终端控制台。Xftp,通过SSH,可以在本地电脑与服务器之间传输文件。

3.OLED屏幕不亮。请注意,在某宝上有几款2.42寸OLED屏幕模块,请确保购买的是4/5 PIN的I2C的版本,而不是7PIN的SPI版本。另外,作者有试过在几家店里买过,实际上它们是不一样的,请认准接线图上的那一款,四个孔都在板子边缘的,且是有RES引脚的,这一款非常稳定,没遇到过什么问题。另外有一款是比较高一点,无法装进3D打印外壳里的,这款没有RES引脚,并且可能板子设计有问题,经常识别不到I2C,屏幕不亮。

4.WS2812 LED不亮。这个唯一的可能性就是接线有问题了,请注意引脚定义,不要正负极接反了。

5.安装固定不合适问题。如上文所述,杜邦线需要去壳,OLED屏幕模块确保同款,散热风扇不能太高,需要使用7mm以下的,不然会撞到屏幕。

【总结】

所以,这就是bbServer的制作过程及经验分享啦。通过制作bbServer,我们可以学到:

1.如何使用单板电脑和CircuitPython来控制电子元件。
2.如何使用Linux系统和搭建自己想要的服务。
3.还可以用Python简单、快速入门单片机领域。
在制作过程中,我们会了解一些基础知识,如单板电脑和CircuitPython的使用,GPIO引脚的控制,3D打印的设计和制作等等。同时,我们也需要有耐心和耐心来调试和解决一些问题。

总之,bbServer是一个非常有趣和有用的项目,通过它我们可以学到很多东西,并且可以用它来运行自己喜欢的应用程序,通过编写代码发挥自己无限的创意。

想更了解它,请看:
开源链接:
https://github.com/RealCorebb/bbServer
视频链接:
https://www.bilibili.com/video/BV1j24y1a7Ut/

创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(16)
Amos Young
Amos Young

好技术,厉害。做的很棒
派大星ym
派大星ym
6666666666666
派大星ym
派大星ym
评论内容
花生编程
花生编程
不错不错!
花生编程
花生编程
泰裤辣!
9mm
9mm
666666666666
Amos Young
Amos Young
好东西,泰裤辣,学习到了。
耘想
耘想
66666666666666666
盐焗海盐
盐焗海盐
太帅了啊
耘想
耘想
厉害啊!
aYYSW8AepLLd
aYYSW8AepLLd
厉害厉害
JVUm7ppJGaRK
JVUm7ppJGaRK
厉害厉害,请问一下服务器端口号是多少,我想进那个MC服务器试试,谢谢!
三春牛-创客
三春牛-创客
支持,赞!
三春牛-创客
三春牛-创客
厉害厉害
花生编程
花生编程
好赞啊!
花生编程
花生编程
厉害厉害
- 没有更多了 -