不久前,我們構(gòu)建了一個(gè)名為 SolarCamPi 的項(xiàng)目,這是一個(gè)離網(wǎng)太陽能供電的WiFi攝像頭。
在這個(gè)項(xiàng)目中,我們使用了Raspberry Pi Zero 2 W,它在啟動(dòng)時(shí)進(jìn)入Linux系統(tǒng),拍攝一張照片,建立WiFi連接,然后再次關(guān)閉(以節(jié)省電量)。這個(gè)過程每幾分鐘重復(fù)一次,以便持續(xù)向云服務(wù)發(fā)送最新圖像。

Raspberry Pi Zero 每開機(jī)一秒鐘都會(huì)消耗寶貴的電力,這對于太陽能供電的設(shè)備來說是一種稀缺資源(至少在西歐的冬天是這樣……)。用戶空間的應(yīng)用程序(服務(wù)器連接、圖片上傳等)已經(jīng)盡可能進(jìn)行了優(yōu)化。電子設(shè)備的設(shè)置也特意設(shè)計(jì)為在休眠時(shí)盡可能少地消耗電力。
有兩種方法可以進(jìn)一步降低總能耗:
1.降低功耗/電流
2.減少運(yùn)行時(shí)間
然而,在某些情況下,需要在兩者之間找到平衡。例如,僅僅為了節(jié)省一些電流而禁用CPU渦輪加速并不是一個(gè)好主意,因?yàn)橛纱水a(chǎn)生的額外時(shí)間將消耗比快速完成任務(wù)并關(guān)閉更多的能量。我們想要的是電流與時(shí)間圖下的面積盡可能小。
硬件設(shè)置
在優(yōu)化嵌入式啟動(dòng)過程時(shí),能夠在做出更改后迅速看到效果至關(guān)重要。在工作中頻繁更換SD卡、擺弄讀卡器和電源供應(yīng)器既分散注意力又令人厭煩。
為了避免這種情況,存在一些有用的工具:
1.Nordic Power Profiler Kit II
2.USB-SD-Mux Fast
3.USB-UART轉(zhuǎn)換器
Power Profiler Kit
Power Profiler Kit II(現(xiàn)在稱為PPK)可以為被測設(shè)備(DUT)供電,并隨時(shí)間準(zhǔn)確測量其功耗。您可以啟用/禁用DUT,查看任何時(shí)間點(diǎn)的功耗,以及查看8個(gè)數(shù)字輸入的狀態(tài)!我們將其中一個(gè)數(shù)字輸入連接到Raspberry Pi的GPIO引腳上。
這樣,“我們的應(yīng)用程序”的第一個(gè)動(dòng)作(即終點(diǎn)線)將是切換GPIO引腳。然后,我們只需測量從開機(jī)到GPIO切換之間的時(shí)間。
USB-SD-Mux
USB-SD-Mux是硬件黑客們非常有用的工具,它是microSD卡和帶有USB-C接口的DUT之間的轉(zhuǎn)換器。計(jì)算機(jī)可以從DUT“竊取”microSD卡,重寫其內(nèi)容,然后將microSD卡插回DUT,而無需觸摸設(shè)備。
這大大簡化了測試更改的工作流程,避免了拔下卡片、將其插入microSD讀卡器、刷新、將卡片插回DUT等繁瑣步驟。它甚至可以使用板載GPIO來自動(dòng)重置或供電DUT。
USB-UART轉(zhuǎn)換器
幾乎需要某種形式的UART接口。這些更改將在某個(gè)時(shí)刻破壞系統(tǒng)啟動(dòng)、WiFi連接等,而如果沒有UART控制臺(tái),我們將無法看到發(fā)生了什么。標(biāo)準(zhǔn)的CP2102、FTDI等轉(zhuǎn)換器都能很好地工作。
測量/測試設(shè)置
在干凈的Debian 12(bookworm)arm64 Lite映像上,修改了/boot/firmware/cmdline.txt 文件以包含init=/init.sh。這意味著內(nèi)核將在用戶空間的第一件事就是執(zhí)行/init.sh腳本(在運(yùn)行systemd或任何其他內(nèi)容之前)。
這樣的init.sh腳本可能如下所示:
#!/bin/bashgpioset 0 4=0sleep 1gpioset 0 4=1sleep 1gpioset 0 4=0exec /sbin/init
這將切換GPIO4,然后用/sbin/init(即systemd)替換自己以恢復(fù)正常啟動(dòng)。
在Nordic的Power Profiler軟件中,您可以看到Raspberry Pi在啟動(dòng)過程中的電流消耗(以5V計(jì)算)。大約12秒后,數(shù)字輸入0變?yōu)榈碗娖剑砻魑覀兊膇nit.sh已執(zhí)行。
在此過程中,總共使用了1.90庫侖(庫侖和安培秒是等價(jià)的)的電量。計(jì)算1.9As * 5.0V得出此啟動(dòng)過程的能耗為9.5Ws。
作為參考:一節(jié)AA堿性電池可以提供約13500Ws的能量。
降低電流
首先,我們來做簡單的事情,盡可能降低工作電流。
禁用HDMI
我們可以完全禁用HDMI編碼器。由于我們需要GPU來編碼攝像頭數(shù)據(jù),因此無法禁用GPU。如果您的應(yīng)用程序不需要攝像頭/GPU支持,請嘗試完全禁用GPU。
這可以將電流消耗從136.7mA降低到122.6mA(超過10%!)。
相關(guān)的config.txt參數(shù):
# disable HDMI (saves power)dtoverlay=vc4-kms-v3d,nohdmimax_framebuffers=1disable_fw_kms_setup=1disable_overscan=1# disable composite video outputenable_tvout=0
禁用活動(dòng)LED
僅通過禁用活動(dòng)LED,我們就可以節(jié)省2mA(從122.6mA降低到120.6mA)。
dtparam=act_led_trigger=nonedtparam=act_led_activelow=on
禁用攝像頭LED
對攝像頭LED重復(fù)相同的操作(如果存在)。這還將減少LED反射回圖像的機(jī)會(huì)。
disable_camera_led=1
渦輪調(diào)整
如前所述,在浪費(fèi)時(shí)間的同時(shí)節(jié)省電流可能并不理想。
在當(dāng)前的更改下,Pi可以在使用1.62As的情況下啟動(dòng)。
force_turbo=0initial_turbo=10arm_boost=0
在沒有強(qiáng)制渦輪模式的情況下,使用了1.58As:
出于某種未知原因,禁用渦輪/增強(qiáng)模式也會(huì)反轉(zhuǎn)GPIO4的默認(rèn)狀態(tài)(因此我在init.sh中切換了極性)。
減少時(shí)間
電流降低了約13%,這很有幫助,但仍有很長的路要走。
Pi在出現(xiàn)Linux控制臺(tái)上的第一行輸出之前需要8秒鐘(同時(shí)消耗約1As)。
幸運(yùn)的是,有多種方法可以獲取有關(guān)這8秒鐘的更多信息。
調(diào)試啟動(dòng)
在Raspberry Pi家族的啟動(dòng)過程中,GPU首先初始化。
它與SD卡通信并查找bootcode.bin文件(Pi 4及更新版本使用EEPROM代替)。
我們可以修改此bootcode.bin以啟用詳細(xì)的UART日志記錄:
sed -i -e "s/BOOT_UART=0/BOOT_UART=1/" /boot/firmware/bootcode.bin
首先備份原始的bootcode.bin,因?yàn)榇诉^程可能是破壞性的。
使用啟用的BOOT_UART重啟后,我們會(huì)獲得大量有用的信息:
Raspberry Pi BootcodeFound SD card, config.txt = 1, start.elf = 1, recovery.elf = 0, timeout = 0Read File: config.txt, 1322 (bytes)Raspberry Pi BootcodeRead File: config.txt, 1322Read File: start.elf, 2981376 (bytes)Read File: fixup.dat, 7303 (bytes)MESS000: brfs: File read: /mfs/sd/config.txtMESS000: brfs: File read: 1322 bytesMESS000: HDMI0:EDID error reading EDID block 0 attempt 0[..]MESS000: HDMI0:EDID error reading EDID block 0 attempt 9MESS000: HDMI0:EDID giving up on reading EDID block 0MESS000: brfs: File read: /mfs/sd/config.txtMESS000: gpioman: gpioman_get_pin_num: pin LEDS_PWR_OK not definedMESS000: gpioman: gpioman_get_pin_num: pin LEDS_PWR_OK not definedMESS000: *** Restart loggingMESS000: brfs: File read: 1322 bytesMESS000: hdmi: HDMI0:EDID error reading EDID block 0 attempt 0[..]MESS000: hdmi: HDMI0:EDID error reading EDID block 0 attempt 9MESS000: hdmi: HDMI0:EDID giving up on reading EDID block 0MESS000: hdmi: HDMI0:EDID error reading EDID block 0 attempt 0[..]MESS000: hdmi: HDMI0:EDID error reading EDID block 0 attempt 9MESS000: hdmi: HDMI0:EDID giving up on reading EDID block 0MESS000: hdmi: HDMI:hdmi_get_state is deprecated, use hdmi_get_display_state insteadMESS000: HDMI0: hdmi_pixel_encoding: 162000000MESS000: brfs: File read: /mfs/sd/initramfs8MESS000: Loaded 'initramfs8' to 0x0 size 0xb0898eMESS000: initramfs loaded to 0x1b4e7000 (size 0xb0898e)MESS000: dtb_file 'bcm2710-rpi-zero-2-w.dtb'MESS000: brfs: File read: 11569550 bytesMESS000: brfs: File read: /mfs/sd/bcm2710-rpi-zero-2-w.dtbMESS000: Loaded 'bcm2710-rpi-zero-2-w.dtb' to 0x100 size 0x8258MESS000: brfs: File read: 33368 bytesMESS000: brfs: File read: /mfs/sd/overlays/overlay_map.dtbMESS000: brfs: File read: 5255 bytesMESS000: brfs: File read: /mfs/sd/config.txtMESS000: dtparam: audio=onMESS000: brfs: File read: 1322 bytesMESS000: brfs: File read: /mfs/sd/overlays/vc4-kms-v3d.dtboMESS000: Loaded overlay 'vc4-kms-v3d'MESS000: dtparam: nohdmi=trueMESS000: dtparam: act_led_trigger=noneMESS000: dtparam: act_led_activelow=onMESS000: brfs: File read: 2760 bytesMESS000: brfs: File read: /mfs/sd/cmdline.txtMESS000: Read command line from file 'cmdline.txt':MESS000: 'console=serial0,115200 console=tty1 root=PARTUUID=26bbce6b-02 rootfstype=ext4 fsck.repair=yes rootwait cfg80211.ieee80211_regdom=DE init=/init.sh'MESS000: gpioman: gpioman_get_pin_num: pin EMMC_ENABLE not definedMESS000: brfs: File read: 146 bytesMESS000: brfs: File read: /mfs/sd/kernel8.imgMESS000: Loaded 'kernel8.img' to 0x200000 size 0x8d8bd7MESS000: Device tree loaded to 0x1b4de900 (size 0x8605)MESS000: uart: Set PL011 baud rate to 103448.300000 HzMESS000: uart: Baud rate change done...MESS000: uart: Baud rate[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
禁用HDMI探測
在啟動(dòng)過程中,引導(dǎo)加載程序會(huì)花費(fèi)大量時(shí)間嘗試自動(dòng)檢測可能連接的HDMI顯示器的視頻參數(shù)。然而,由于我們沒有HDMI(而且它已經(jīng)被禁用了),因此等待I2C響應(yīng)以獲取EDID(包括分辨率、幀率等信息)信息并不明智。
通過簡單地硬編碼一個(gè)EDID字符串,我們可以禁用任何探測:
# don't try to read HDMI eepromhdmi_blanking=2hdmi_ignore_edid=0xa5000080hdmi_ignore_cec_init=1hdmi_ignore_cec=1
禁用HAT、PoE和LCD探測
啟動(dòng)過程還會(huì)嘗試檢測HAT上的I2C EEPROM,嘗試檢測需要風(fēng)扇的PoE HAT以及其他一些內(nèi)容。我們可以安全地禁用這些探測:
# all these options cause a wait for an I2C bus response, we don't need any of them, so let's disable them.force_eeprom_read=0disable_poe_fan=1ignore_lcd=1disable_touchscreen=1disable_fw_kms_setup=1
禁用攝像頭和顯示器探測
探測連接的MIPI攝像頭或顯示器也會(huì)花費(fèi)一些時(shí)間。我們知道連接了哪個(gè)攝像頭(在這個(gè)案例中是HQ Camera,IMX477),因此我們可以硬編碼這個(gè)信息:
# no autodetection for anything (will wait for I2C answers)camera_auto_detect=0display_auto_detect=0# load HQ camera IMX477 sensor manuallydtoverlay=imx477
禁用initramfs
上述更改將(自報(bào)告的)啟動(dòng)時(shí)間從5.38秒縮短到4.75秒。我們可以通過移除auto_initramfs=1來完全禁用initramfs,這取決于initramfs的大小,但可以將啟動(dòng)時(shí)間縮短到4.47秒。
經(jīng)過測試,沒有顯著差異
盡管網(wǎng)上經(jīng)常推薦將SD外設(shè)超頻到100 MHz,但這在啟動(dòng)性能上并沒有產(chǎn)生可測量的差異
# not recommended! data corruption risk!dtoverlay=sdtweak,overclock_50=100
而且,在高速下操作SD外設(shè)還存在數(shù)據(jù)損壞的風(fēng)險(xiǎn)(在寫入訪問時(shí)),這在遠(yuǎn)程物聯(lián)網(wǎng)設(shè)備中是非常不希望的。
內(nèi)核加載
此時(shí),加載內(nèi)核是最慢的操作之一。
MESS000: Loaded 'kernel8.img' to 0x200000 size 0x8d8bd7MESS000: Device tree loaded to 0x1b4de900 (size 0x8605)
加載9276375字節(jié)大約需要1.54秒,即大約6 MiB/s的傳輸速度
內(nèi)核加載由GPU(使用其內(nèi)部的VideoCoreIV處理器)完成,這可能是加載代碼效率低下或使用了非常保守的設(shè)置。由于這是一個(gè)黑盒,我們無法直接操作寄存器或修改參數(shù)。
理論上,GPU處理器內(nèi)核超頻是可行的
# Overclock GPU VideoCore IV processor (not recommended!)core_freq_min=500core_freq=550
這確實(shí)減少了20%的內(nèi)核加載時(shí)間。但是帶來了未知的副作用(可靠性等。)
Buildroot/自定義內(nèi)核
是時(shí)候?qū)⑾到y(tǒng)從Raspbian/Debian遷移到自定義構(gòu)建的Buildroot發(fā)行版了(特別是為了獲取自定義內(nèi)核)。使用 buildroot 2024.02.1,我們配置了一個(gè)非常精簡的系統(tǒng)。原生的 aarch64 工具鏈,仍然使用完整的 glibc 和 Raspberry Pi 用戶區(qū)工具(如相機(jī)實(shí)用程序)。
內(nèi)核已配置:
- 無聲音支持
- 無大多數(shù)塊設(shè)備和文件系統(tǒng)驅(qū)動(dòng)(除了SD/MMC和ext4)
- 無RAID支持
- 無USB支持
- 無HID支持
- 無DVB支持
- 無視頻和幀緩沖支持(HDMI已被禁用)
- 無高級網(wǎng)絡(luò)功能(隧道、橋接、防火墻等)
- 未壓縮(不使用Gzip)
- 模塊未壓縮(不使用Gzip)
測試表明,內(nèi)核和模塊均未壓縮可以帶來正的能量結(jié)果(即使GPU加載內(nèi)核時(shí)花費(fèi)了更多時(shí)間)。Gzip解壓縮需要消耗大量能量(并且實(shí)際上涉及另一個(gè)重定位步驟)。
一個(gè)名為KASLR的安全功能也被禁用。
KASLR將內(nèi)核在內(nèi)存中的加載地址隨機(jī)化,使得編寫漏洞利用代碼更加困難(因?yàn)閮?nèi)核的內(nèi)存位置是未知的)。這要求內(nèi)核在被GPU加載后重新定位。在我們的用例中,網(wǎng)絡(luò)攻擊面非常有限,所以可以禁用KASLR(反正所有應(yīng)用軟件都以root身份運(yùn)行)。投機(jī)性執(zhí)行漏洞(如Spectre)的緩解也被禁用。

最終的內(nèi)核大小為8.5兆字節(jié)(未壓縮),4.1兆字節(jié)壓縮為Gzip(這里沒有使用,只是為了比較)。最初的Raspbian內(nèi)核是25 MiB(未壓縮),8.9 MiB壓縮為Gzip
最終結(jié)果
現(xiàn)在,我們可以在不到3.5秒的時(shí)間內(nèi)啟動(dòng)到Linux用戶空間程序!
Linux內(nèi)核占用時(shí)間約為400毫秒(從引腳0到引腳1的差值)。總能耗為0.364 As * 5.0 V = 1.82 Ws,與原始Debian相比,能耗降低了5倍(原始Debian直到用戶空間需要9.5 Ws)。
降低輸入電壓
在發(fā)表這篇博文后,Graham Sutherland / Polynomial 指出,Pi Zero 中的調(diào)節(jié)器在5.0V輸入下效率不是很高。
這可能不適用于所有情況,但在我們的測試場景和成品中,我們可以將輸入電壓降至4.0V。
在5.0V下運(yùn)行:
好好注意這里正在進(jìn)行的單元。通過切換到4.0V(因?yàn)殡娏鞲?,mC(毫庫侖/毫安培秒)增加,但是總能量顯著降低!
350.94mAs * 5.0V = 1.754 Ws
在4.0V下運(yùn)行:
390.77mAs * 4.0V = 1.563 Ws
我們可以更進(jìn)一步:
在3.6V運(yùn)行:
399.60mAs * 3.6V = 1.438 Ws
我們剛剛又降低了20%的能耗,這僅僅是通過在更理想的工作點(diǎn)操作開關(guān)模式調(diào)節(jié)器實(shí)現(xiàn)的!這當(dāng)然需要進(jìn)一步測試穩(wěn)定性/可靠性(因?yàn)檫@在技術(shù)上是不符合規(guī)格的),但這是一個(gè)非常令人印象深刻的結(jié)果。
-
攝像頭
+關(guān)注
關(guān)注
60文章
4897瀏覽量
96989 -
樹莓派
+關(guān)注
關(guān)注
118文章
1880瀏覽量
106242
發(fā)布評論請先 登錄
相關(guān)推薦
樹莓派如何安裝和啟動(dòng)
跪求大神解決!樹莓派的啟動(dòng)項(xiàng)怎么設(shè)置啊?
樹莓派使用3.5寸屏幕教程
如何實(shí)現(xiàn)樹莓派zero w網(wǎng)絡(luò)穿透遠(yuǎn)程跨網(wǎng)絡(luò)監(jiān)控功能呢
使用樹莓派設(shè)計(jì)智能小車教程之樹莓派小車啟動(dòng)教程免費(fèi)下載

樹莓派的攝像頭應(yīng)該如何啟動(dòng)詳細(xì)教程免費(fèi)下載
使用樹莓派設(shè)計(jì)智能小車教程之樹莓派智能車系統(tǒng)啟動(dòng)的詳細(xì)資料說明
樹莓派 Zero W的電路原理圖免費(fèi)下載

樹莓派ZERO電源方案

樹莓派有史以來首次漲價(jià)

評論