本帖最后由 珠峰 于 2023-12-17 22:45 编辑
近日入手一块树莓派4B(4G版),打算用来做Siot服务器及jupyter写python程序,感觉如果一直开着风扇的话,会多少有点噪音而且浪费资源。不开风扇又怕太热,毕竟4B比3B+的发热量要大。随手拿来一些电子元件及PCB板,做一个自动温控系统给4B散热,用4B作为服务器,并增加开关机按键。(成品如图)
功能:
1.开机显示树莓派的IP地址,使得无显示器也可以轻松实现远程连接、使用SIOT、JUPYTER服务。
2.可以实时显示系统运行情况,显示时间、CPU使用率、CPU温度、风扇运行情况、内存使用情况、硬盘使用情况等。
3.还可以使用一个按钮实现重启、关机、取消操作功能,使得关闭树莓派不用直接断电,保护系统安全。
4.OLED屏幕具有无操作一定时间后自动熄屏,并可使用按钮唤醒,省电,还可以避免光污染,非常实用。
一、材料
1. 128*64 IIC接口OLED显示屏*1
2. 7*5cm双面喷锡洞洞板*1
3. 红色LED灯*1
4. S8050三极管*2
5. 微动开关*2
6. 排针(2.54mm)红、绿、黑各一排
7. 弯排针一排
8. 加长2*20P直插排针母座*1(这里我用了4 个1*10的代替)
9. 2*20P直插排针母座*1
10. 5*6六角塑料柱*2
11. 0.5mm、0.3mm漆包线若干
12. 电烙铁等焊接工具
二、电路图
[size=10.5000pt]
[size=10.5000pt]
三、按电路图焊接到双面PBC板上
[size=10.5000pt]
[size=10.5000pt]
四、python编写自动温控系统程序(自制扩展板)
用python3输入以下内容并命名为Oled12864.py
- #!/usr/bin/env python3
- #OLED12864IP.py showTheTime.py
- # 程序功能:开机显示树莓派的IP地址,使得无显示器也可以轻松实现远程连接,
- # 同时可以实时显示系统运行情况,显示时间、CPU使用率、CPU温度、风扇运行
- # 情况、内存使用情况、硬盘使用情况等,非常实用。
-
- from luma.core.interface.serial import i2c, spi
- from luma.oled.device import ssd1306, ssd1325, ssd1331, sh1106
- from luma.core.render import canvas
- from PIL import ImageDraw, Image,ImageFont
-
- import time
- import datetime as datetime
- import socket
- import fcntl
- import struct
- import os,sys
- import RPi.GPIO as GPIO
- import signal
-
- # OLED显示带有树莓派logo的地址
- logo = Image.open('/home/pi/images/pi.png')
- GPIO.setmode(GPIO.BCM)# 使用BCM引脚编码
-
- #定义 GPIO pin
- pin_power_btn = 27# 开关按钮接BCM(下同)27引脚
- pin_led = 25# LED接25引脚
- pin_oled_btn = 26# 唤醒OLED屏按钮接26引脚
- pin_fan_1 = 24# 风扇1接24引脚
- pin_fan_2 = 23# 风扇2接23引脚
-
- my_oled_show=1# OLED状态
- my_oled_show_count=0
- fan_1_run = "0"# 风扇1状态
- fan_2_run = "0"# 风扇1状态
-
- GPIO.setup(pin_power_btn,GPIO.IN,pull_up_down=GPIO.PUD_UP)
- GPIO.setup(pin_led,GPIO.OUT,initial=GPIO.LOW)
- GPIO.setup(pin_oled_btn,GPIO.IN,pull_up_down=GPIO.PUD_UP)
- GPIO.setup(pin_fan_1,GPIO.OUT,initial=GPIO.LOW)
- GPIO.setup(pin_fan_2,GPIO.OUT,initial=GPIO.LOW)
-
- press_time = 0#按钮计数
- count_down = 10# 倒计时10秒
- led_on = 1
-
- #clean the GPIO sources
- def cleanup():
- GPIO.cleanup()
-
- def handleSIGTERM(signum,frame):
- sys.exit()#raise an exception of type SystemExit
- #定义按钮功能
- def onPress(channel):
- global press_time,count_down
- press_time += 1
- if press_time > 3:
- press_time = 1
- if press_time == 2:
- GPIO.output(pin_led,1)
- #
- elif press_time == 3:
- GPIO.output(pin_led,0)
- count_down = 10
-
-
- # 获取CPU温度
- def getCPUtemperature():
- res = os.popen('vcgencmd measure_temp').readline()
- return(res.replace("temp=","").replace("'C\n",""))
-
- # 获取内存信息
- def getRAMinfo():
- p = os.popen('free')
- i = 0
- while 1:
- i = i + 1
- line = p.readline()
- if i==2:
- return(line.split()[1:4])
-
- # 获取CPU使用率
- def getCPUuse():
- return(str(os.popen("sudo top -n1 | grep load | awk '/Cpu\(s\):/ {print $2}'").readline().strip()))
-
- # 获取SD卡使用率
- def getDiskSpace():
- p = os.popen("df -h /")
- i = 0
- while 1:
- i = i +1
- line = p.readline()
- if i==2:
- return(line.split()[1:5])
- #显示时间
- def Show(d,fullDt):
-
- y = fullDt.strftime('%Y')
- dt = fullDt.strftime('%m-%d')
- tm = fullDt.strftime('%H:%M:%S')
-
- # 获取系统IP地址
- def getIP(ifname):
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- return socket.inet_ntoa(fcntl.ioctl(
- s.fileno(),
- 0x8915, # SIOCGIFADDR
- struct.pack('256s', ifname[:15].encode('utf-8'))
- )[20:24])
- # OLED显示函数
- def stats(oled,fullDt):
- global my_oled_show,my_oled_show_count,fan_1_run,fan_2_run
- y = fullDt.strftime('%Y')
- dt = fullDt.strftime('%m-%d')
- tm = fullDt.strftime('%H:%M:%S')
-
- # CPU 信息
- CPU_temp = getCPUtemperature()
- CPU_usage = getCPUuse()
- #CPU 风扇运行情况
- if float(CPU_temp) >= 49.0:
- GPIO.output(pin_fan_1,1)
- fan_1_run = "1"
- if float(CPU_temp) <=45.0:
- GPIO.output(pin_fan_1,0)
- fan_1_run = "0"
- if float(CPU_temp) >= 52.0:
- GPIO.output(pin_fan_2,1)
- fan_2_run = "1"
- if float(CPU_temp) <=45.0:
- GPIO.output(pin_fan_2,0)
- fan_2_run = "0"
- # 内存使用情况
- RAM_stats = getRAMinfo()
- RAM_total = round(int(RAM_stats[0]) / 1000,1)
- RAM_used = round(int(RAM_stats[1]) / 1000,1)
- RAM_free = round(int(RAM_stats[2]) / 1000,1)
-
- # SD卡使用情况
- DISK_stats = getDiskSpace()
- DISK_total = DISK_stats[0]
- DISK_used = DISK_stats[1]
- DISK_perc = DISK_stats[3]
-
- font = ImageFont.load_default()
- font2 = ImageFont.truetype('/usr/share/fonts/truetype/freefont/FreeSans.ttf', 12)
- with canvas(oled) as draw:
- if my_oled_show == 1:
- #可选择显示有线网络或者无线网络IP
- draw.text((0, 0), "IP: " + getIP("wlan0"), font=font2, fill=255)
- #draw.text((0, 0), "IP: " + getIP("eth0"), font=font2, fill=255)
- draw.text((0, 13), y+"-"+dt+" "+tm, font=font2, fill=255)
- draw.bitmap((98, 28), logo, fill=1)
-
- draw.text((0, 26), "CPU:"+CPU_temp+"`C"+" "+fan_1_run + fan_2_run, font=font2, fill=255)
- draw.text((0, 39), "R:"+ str(RAM_used) +" / "+str(RAM_total ), font=font2, fill=255)
- draw.text((0, 52), "D:"+ str(DISK_used) +" / "+str(DISK_total), font=font2, fill=255)
- else:
- draw.text((0, 0), "..." , font=font2, fill=255)
- # OLED显示唤醒按钮函数
- def oled_onPress(channel):
- global my_oled_show,my_oled_show_count
- my_oled_show = 1
- my_oled_show_count = 0
- # 主函数
- def main():
- my_gettime_count = 0
- global press_time,count_down,led_on
- global my_oled_show,my_oled_show_count
- nowDt = datetime.datetime.now() + datetime.timedelta(hours=0)
-
- GPIO.add_event_detect(pin_power_btn, GPIO.FALLING, callback = onPress,bouncetime = 500)
- GPIO.add_event_detect(pin_oled_btn, GPIO.FALLING,callback = oled_onPress,bouncetime=500)
-
- while True:
- stats(oled,nowDt)
- if my_gettime_count < 3600:
- nowDt = nowDt + datetime.timedelta(seconds=1)
- my_gettime_count += 1
- else:
- nowDt = datetime.datetime.now() + datetime.timedelta(hours=0)
- my_gettime_count = 0
- if my_oled_show == 1:
- if my_oled_show_count <100:
- my_oled_show_count += 1
- else:
- my_oled_show = 0
- my_oled_show_count = 0
- else:
- my_oled_show_count = 0
-
- if press_time == 1:
- if count_down == 0:
- os.system("sudo reboot")
- sys.exit()
- led_on = not led_on
- GPIO.output(pin_led,led_on)
- if press_time == 2 and count_down == 0:
- os.system("sudo halt")
- sys.exit()
- if press_time == 1 or press_time == 2:
- count_down -= 1
- time.sleep(1)
-
- if __name__ == "__main__":
- try:
- serial = i2c(port=1,address=0x3C)
- oled = ssd1306(serial)
- main()
- except KeyboardInterrupt:
- pass
- finally:
- cleanup()
复制代码
将以上文件上传到/home/pi目录下,并新建一个image文件夹,放上Python文件中的图片。
开启i2c功能
安装Luma.oled库终端输入下面命令。
[size=10.5000pt]
改变权限
设置自动启动服务
加入以下两行
[size=10.5000pt]
五、安装jupyter
漫长的等待…………
安装成功。
[size=10.5000pt]
输入jupyter --version查看版本信息,显示ipython、jupyter lab、ipywidgets未安装,但是查询IPython版本却说已存在。
输入sudo pip3 install --upgrade IPython升级
输入sudo pip3 install jupyterlab安装jupyterlab
安装完成后,再次检查jupyter的版本,成功!
配置Jupyter
通过Ctrl+w快速定位c.NotebookApp.ip = ‘0.0.0.0’
c.NotebookApp.open_browser = False
c.NotebookApp.port = 8888
c.NotebookApp.notebook_dir = ‘/home/pi’
修改jupyter Notebook 密码
启动jupyter notebook
配置自动服务自动启动。
(1)编辑服务文件
pi@raspberrypi:~ $ sudo nano /etc/init.d/JupyterNB
- #!/bin/sh
- #/etc/init.d/JyputerNB
- ### BEGIN INIT INFO
- # Provides:JyputerNB
- # Required-Start:$remote_fs $syslog
- # Required-Stop:$remote_fs $syslog
- # Default-Start:2 3 4 5
- # Default-Stop:0 1 6
- # Short-Description: JyputerNB
- # Description: This service is used to start my applaction
- ### END INIT INFO
- case "$1" in
- start)
- echo "start your app here."
- su pi -c "jupyter notebook"
- ;;
- stop)
- echo "stop your app here."
- ;;
- *)
- echo "Usage:service JyputerNotebook start|stop"
- exit 1
- ;;
- esac
- exit 0
复制代码
(2)修改服务文件的权限
pi@raspberrypi:~ $ sudo chmod 777 /etc/init.d/JupyterNB
(3)设置服务启动
pi@raspberrypi:~ $ sudo update-rc.d JupyterNB defaults
(4)重启测试
pi@raspberrypi:~ $ sudo reboot
安装启动成功
六、安装SIoT并配置服务自启
SIoT为一个为教育定制的跨平台的MQTT服务器程序,S指科学(Science)、简单(simple)的意思。SIoT支持Win10、Win7、Mac、Linux等操作系统,一键启动,无需注册即可使用。
SIoT为“虚谷物联”项目的核心软件,是为了帮助中小学生理解物联网原理,并且能够基于物联网技术开发各种创意应用,尤其是用于科学数据采集。
SIoT最新版本为1.2,仅有1.1版本支持在树莓派上使用,其下载地址为:
https://github.com/liliang9693/mindplus-docs/tree/master/SIOT
1.在电脑中下载到1.1版本的SIoT之后,打开发现压缩包中siot文件夹的名字为“SIoT raspberryPi”,中间有空格,为了不必要的麻烦,建议将压缩包里面的文件夹的名字改为SIoT,压缩包也改名为SIoT。
2.然后将SIoT压缩包通过ftp上传到树莓派的/Home/pi/中 ,打开命令窗口,运行以下命令进行安装。
#1.利用unzip解压zip文件,将SIoT.zip直接解压到/home/pi/中,
unzip SIoT.zip
#2.先修改SIoT目录的权限,不然进去之后不能运行。
sudo chmod -R 777 SIoT
#3.转到SIoT1的目录中
cd SIoT
#4.运行siot服务
sudo ./SIoT_Raspbian
到此,siot已完成,访问 树莓派地址:8080 即可登陆siot,帐号:siot 密码:dfrobot
3.最后,配置一下开机启动:
配置自动服务自动启动。
(1)编辑服务文件
pi@raspberrypi:~ $ sudo nano /etc/init.d/SIoT
- #!/bin/sh
- #/etc/init.d/SIoT
- ### BEGIN INIT INFO
- # Provides:SIoT
- # Required-Start:$remote_fs $syslog
- # Required-Stop:$remote_fs $syslog
- # Default-Start:2 3 4 5
- # Default-Stop:0 1 6
- # Short-Description: SIoT
- # Description: This service is used to start my applaction
- ### END INIT INFO
- case "$1" in
- start)
- echo "start your app here."
- su pi -c "exec /home/pi/SIoT/SIoT_Raspbian"
- ;;
- stop)
- echo "stop your app here."
- ;;
- *)
- echo "Usage: service SIoT start|stop"
- exit 1
- ;;
- esac
- exit 0
复制代码
(2)修改服务文件的权限
pi@raspberrypi:~ $ sudo chmod 777 /etc/init.d/SIoT
(3)设置服务启动
pi@raspberrypi:~ $ sudo update-rc.d SIoT defaults
(4)重启测试
pi@raspberrypi:~ $ sudo reboot
至此,树莓派4B温控+IP显示系统及服务器就制作完毕。
|