基於 STM32 的太陽能追光系統設計

#智能硬體#STM32

摘要

針對固定安裝的太陽能板無法隨太陽方位變化調整姿態、發電效率受限的問題,本文設計並實現了一種基於 STM32 的太陽能追光系統。系統以 STM32F103C8T6 為控制核心,4 路 BH1750 數字光照感測器按四象限佈置於光伏板背板,經 TCA9548A I²C 多路復用器分時採集;主控對四路讀數做成對求和差分得到兩軸偏差,以 P 控制律驅動 2×MG996R 舵機構成的雙軸雲台(方位軸 + 俯仰軸)指向光源。系統採用強光門限滯回區分直射光源與環境光,死區與單週期限幅抑制抖動,指數逼近的輸出平滑保證舵機運動連續;透過串口非阻塞發送、OLED 分片刷新與本幀自錨定的幀週期補足三項措施,將 50Hz 軟體 PWM 的幀週期釘死在 20ms,徹底解決了舵機「爆衝」問題。板載 RAM 環形黑盒子支援偶發故障的現場復盤。測試表明,系統對準精度與動態響應滿足設計要求,運動平穩無抖動。

關鍵詞:STM32;太陽能追光;BH1750;雙軸雲台;P 控制;軟體 PWM

1 引言

太陽能發電的轉換效率與光照入射角密切相關:當太陽光垂直入射光伏板時輸出功率最大,入射角偏離法線時效率顯著下降。固定安裝的光伏板只在正午前後短暫接近最佳傾角,全天平均利用率低。雙軸追光系統透過即時調整光伏板姿態,使其法線始終指向太陽,可顯著提升日均發電量。

傳統低成本方案多用 4 個光敏電阻分置光伏板四角,經 ADC 採樣電壓差判斷光照方位。這類方案存在三個固有缺陷:光敏電阻一致性差、溫漂大,需要逐個標定;ADC 單次採樣易受環境光突變與電源噪聲干擾,導致執行機構頻繁誤觸發;開關式(bang-bang)控制使電機啟停突兀、過衝抖動,長期損耗機械結構。

本文採用數字光照感測器 BH1750 替代光敏電阻(免標定、一致性好、直接輸出 lux 物理量),以 I²C 多路復用器擴展四路採集,配合帶回差的強光門限、死區限幅 P 控制與指數逼近輸出平滑,在 STM32F103C8T6 上實現了運動連續、無爆衝的雙軸追光系統。

2 系統總體設計

2.1 系統架構

系統由感知、決策、執行、互動四部分組成:

  • 感知:4 路 BH1750 光照感測器按「左上、右上、左下、右下」四象限佈置在光伏板背板的載板上,載板中央設十字遮光擋板(高 1525mm),使相鄰感測器對偏離法線的入射光產生穩定的照度差——這是差分定向的物理基礎。4 路感測器地址均為 0x23,經 TCA9548A 八路 I²C 復用器的 SC0SC3/SD0~SD3 通道分時存取。
  • 決策:STM32F103C8T6(72MHz)每 100ms 讀取四路照度,計算兩軸偏差並執行 P 控制律。
  • 執行:2 只 MG996R 舵機構成標準雙軸雲台——方位軸(Z)繞豎軸水平旋轉,俯仰軸(Y)繞水平軸俯仰,獨立設定 0~180°。
  • 互動:0.96 吋 SSD1306 OLED 即時顯示四路讀數與雲台狀態;4 個板載按鍵支援手動點動標定;USART1 串口提供線上調參命令。

2.2 元器件選型

類別型號關鍵參數作用
主控STM32F103C8T672MHz,64K Flash / 20K RAM採集、控制、PWM 生成
光照感測BH1750 ×4I²C,1~65535 lux,高解析度模式四象限照度採集
I²C 復用TCA9548A8 通道,ADDR=0x70解決 4 路同地址衝突
舵機MG996R ×20~180°,金屬齒輪方位軸 / 俯仰軸驅動
顯示SSD1306 OLED 0.96"128×64,I²C 0x3C讀數與狀態顯示
按鍵輕觸開關 ×4板載手動點動與組合鍵

2.3 引腳資源分配

外設引腳模式說明
TCA9548A / BH1750PB14 / PB15軟體 I²CSCL / SDA
OLEDPB8 / PB9軟體 I²C獨立匯流排,互不干擾
方位舵機(Z)PA12推挽輸出,軟體 50Hz PWM上電中位 90°
俯仰舵機(Y)PA11推挽輸出,軟體 50Hz PWM上電中位 90°
按鍵 Key1~Key4PA3 / PB5 / PB6 / PB7上拉輸入Z− / Z+ / Y− / Y+
串口USART1 PA9 / PA10115200bps調參命令與狀態輸出

引腳對應關係經按鍵實測校正:Key2 使雲台抬頭/低頭,故 PA11 為俯仰;Key4 使雲台水平旋轉,故 PA12 為方位——與最初標稱相反,程式碼已按實測修正。

3 硬體設計

3.1 四象限感測器頭

感測器頭採用「模組載板一體式」結構:TCA9548A 模組與 4 隻 BH1750 模組焊死在同一塊洞洞板載板上,不靠杜邦線懸空。雲台是運動平台,運轉振動下懸空跳線是 I²C 掉幀的頭號原因,表現為追蹤抽搐、讀數跳變;焊死載板可根治。載板四角對應四象限物理位置,程式碼中由 kPosToCh[] 映射表兜住物理位置與硬體通道的對應關係(遮擋實測標定:左上=CH2、右上=CH3、左下=CH0、右下=CH1),PCB 走線差異不影響軟體邏輯。

3.2 舵機驅動

MG996R 採用軟體 PWM 驅動:50Hz 週期、0.5~2.5ms 脈寬,由 DWT 週期計數器實現微秒級延時。PA11/PA12 推挽輸出,軟體反相宏 SERVO_PAN_INVERT / SERVO_TILT_INVERT 相容不同舵盤安裝方向,改宏後若閉環朝反方向跑,翻轉對應的方向符號宏即可。

3.3 安裝與朝向要求

方位軸為 180° 舵機,只能覆蓋半個圓,擺位決定系統能否全天追到太陽。核心要求:雲台 Z=90°(上電中位)指向正南。此時 Z=0 朝東、Z=180 朝西,太陽東→南→西的全天弧段恰好壓滿 180°行程,死區留在太陽永不經過的北天空。俯仰軸安裝時令 Y=90° 板面豎直(法線水平),向兩端各留 90° 餘量,覆蓋日出至日落的全高度角。底座需用水平儀校平——底座傾斜會使方位軸不豎直,四路讀數整體偏移,閉環無法找到平衡點。

4 軟體系統設計

4.1 主迴圈與幀節拍

主迴圈採用超迴圈結構,以 20ms 軟體伺服幀為基本節拍:每幀給起點打點(Servo_FrameMark),幀尾由 Servo_Frame 等待到「本幀起點 + 20ms」。只要「本幀工作 + 脈衝輸出」小於 20ms,幀週期即嚴格恆定,與單幀工作量波動無關;偶發超時的幀不等待也不補幀(寧可慢一幀,不連發)。感測器採集與控制決策每 5 幀(100ms)執行一次,其餘任務(按鍵掃描、OLED、黑盒子)逐幀執行。主程式流程如圖 4-1 所示。

主程式流程圖
圖 4-1 主程式流程圖

4.2 光照採集與濾波

BH1750 上電時對 4 個通道各初始化一次連續高解析度模式,之後每週期直接讀數,避免了每次測量 180ms 的阻塞等待——4 路讀一遍僅約 3.3ms,支撐 100ms 控制週期。採集與濾波流程如圖 4-2 所示。

光照採集與濾波流程圖
圖 4-2 光照採集與濾波流程圖

原始讀數先經壞樣本剔除再作一階低通(EMA 係數 1/2):TCA9548A 切換瞬間或手電反光會產生數千 lux 的孤立尖峰,直接餵給 P 控制會導致目標連續滿步進——宏觀表現就是「爆衝」。單次跳變超過 1500 lux 判為壞樣本,沿用上一次濾波值:

/* 一階低通 + 壞樣本剔除 */
int diff = (int)lux[pos] - (int)lux_f[pos];
if (diff > 1500 || diff < -1500) {
    dbg_bad_sample++;              /* 壞樣本: 沿用上次濾波值 */
} else {
    lux_f[pos] = (uint16_t)(((uint32_t)lux_f[pos] + lux[pos] + 1u) >> 1);
}

4.3 強光門限與滯回

環境光(陰天 30~100 lux)與直射光源(手電/太陽,300 lux 以上)在量級上可分。系統取四路最大值 peak 作判據:peak ≥ 250 lux 進入追光(TRK),peak < 150 lux(進入門限的 60%)退回保持(HLD,角度原地鎖存),滯回區間防止臨界照度下狀態反覆翻轉。門限支援串口 @T<lux> 線上調整,退出行限按 60% 聯動。

4.4 成對差分 P 控制

四象限讀數按行、列兩兩求和後作差,得到俯仰與方位兩個方向的偏差:

/* 原始光差(未乘方向符號) */
raw_tilt = lux[LT] + lux[RT] - lux[LB] - lux[RB];  /* 上排 - 下排 */
raw_pan  = lux[LT] + lux[LB] - lux[RT] - lux[RB];  /* 左列 - 右列 */

/* P 控制步進: 死區 20 lux, 單週期限幅 3° (最大 30°/s) */
e_tilt = tilt_dir * raw_tilt;
if (e_tilt > TRACK_DEADBAND_LUX || e_tilt < -TRACK_DEADBAND_LUX) {
    int32_t step = e_tilt * TRACK_KP_NUM / (TRACK_KP_DEN * 10);
    if (step >  TRACK_STEP_LIMIT) step =  TRACK_STEP_LIMIT;
    if (step < -TRACK_STEP_LIMIT) step = -TRACK_STEP_LIMIT;
    Angle_SetTilt((int)tilt_target + (int)step);
}

強光門限判斷、成對差分與死區限幅步進的完整流程如圖 4-3 所示。

閉環追光控制流程圖
圖 4-3 閉環追光控制流程圖

控制參數:比例係數使 100 lux 光差產生 4° 步進,死區 20 lux 抑制噪聲抖動,單週期(100ms)限幅 3° 對應最大 30°/s 追趕速度。任一路感測器出錯,兩軸均保持不動並置 I2C 錯誤標誌。方向符號(照左列 Z 減小、照上排 Y 增大)以手電實測鎖定,支援執行時經組合鍵或串口 @S<z>,<y> 翻轉;另提供 @C 命令觸發一次方向自學習(每軸試探 ±10° 比較光差改善量),實測該功能在窄視場條件下易誤判,預設關閉。

4.5 輸出平滑

P 控制只寫目標角度,實際輸出每 20ms PWM 幀朝目標指數逼近:走剩餘距離的 1/4,單幀步進上限 3°,且速度每幀最多變化 1°(加速度限幅)。目標角度以 10Hz 階躍更新,而舵機在 50Hz 的每一幀都在微調,運動連續不打點。按鍵點動、串口設定與回中位命令同樣走這條平滑路徑,保證任何來源的角度指令都不產生機械衝擊。輸出平滑流程如圖 4-4 所示。

輸出平滑流程圖
圖 4-4 輸出平滑流程圖(Servo_Slew)

4.6 PWM 幀時序保障

軟體 PWM 的週期等於主迴圈一圈的耗時,任何阻塞都會造成丟幀——舵機丟幀後突然追位,即「爆衝」。分段計時(tm_sensor_max_us 等)定位出三個元兇:串口阻塞發送一行 150 位元組約 13ms、OLED 整行刷新單欄位實測 69.4ms、四路感測器讀取 3.3ms。三項修復:

  1. 串口非阻塞:UART_Print 改環形緩衝 + 發送完成中斷,主迴圈零等待;
  2. OLED 分片刷新:數值變化只標髒,每幀由 OLED_Service() 最多寫一個字元(約 4.3ms),狀態行節流至 200ms;
  3. 本幀自錨定補時:幀尾等到「本幀起點 + 20ms」(見 4.1)。

修復前後對比:主迴圈 12 秒內超 25ms 的幀由 273 幀降為 0 幀,單幀角度跳變計數恆為 0。串口狀態行尾附診斷計數器(fm=最長幀 ovf=超時幀 jmp=跳變 bad=壞樣本),故障時先讀這組數即可快速歸因:jmp>0 是韌體問題,ovf 增長是主迴圈被阻塞,均為 0 則是電源或機械問題。

4.7 RAM 黑盒子

偶發故障(如「只動 Z 軸 Y 卻跟著動」)難以現場復現。韌體將每幀關鍵狀態壓縮為 20 位元組寫入 RAM 環形緩衝(512 條 × 20B = 10KB),內容含時間戳、兩軸實際/目標角、四路光照、按鍵狀態、模式位與幀週期;有變化才寫,靜止時 500ms 一條心跳。事後用 SWD 腳本整體讀出並自動歸因(按鍵觸發 / 閉環驅動 / 無來源幀)。該機制不佔串口頻寬、不拉長 PWM 幀,配合診斷計數器構成完整的「可觀測性」體系。

4.8 人機互動與串口命令

OLED 以 2×2 佈局顯示四路物理位置讀數(所見即所得),第 4 行顯示 Z:xxx Y:xxx 與狀態字(TRK 追光 / CAL 自學習 / HLD 保持 / MAN 手動)或 I2C ERR。4 按鍵短按 2°/步、按住 100ms 連發、1s 後加速至 5°/步;任意按鍵動作自動切入手動模式,閉環停止搶角度。組合鍵(按住 1s):Key1+Key4 回自動並復位 90/90,Key1+Key2 翻轉 Z 方向,Key3+Key4 翻轉 Y 方向。

命令功能命令功能
@Z<deg> / @Y<deg>單獨設定方位/俯仰角@T<lux>線上調整強光門限
@ZY<z>,<y>同時設定兩軸角度@S<z>,<y>設定兩軸追光方向符號
@A回自動追光(復位 90/90)@C觸發一次方向自學習
@B清空黑盒子——

5 系統測試

測試項方法結果
四路採集遮擋單路觀察讀數與 OLED 對應位置讀數響應正確,位置映射無誤
強光門限手電照射 / 移開250 lux 進入 TRK,150 lux 以下回 HLD,無臨界抖動
追光對準手電繞雲台緩慢移動雲台連續跟隨,對準後進入死區靜止
輸出平滑目標階躍 30°運動連續無打點,無過衝回擺
幀週期串口診斷計數器連續觀測 10sfm≤20 ovf=0 jmp=0(修復前 12s 內 273 幀超時)
手動/自動切換按鍵點動後放手電自動切 MAN,按鍵釋放後手電觸發回 TRK

獨立測試韌體連結到 0x08000000 復位向量直接執行(區別於主工程的 bootloader+app 分區模型),main() 首行糾正 VTOR 後才開啟 SysTick,避免從已擦空的 app 槽取向量導致 HardFault;燒錄採用整片擦除 + 寫入 + 校驗流程,燒錄前以 readelf/objdump 靜態驗證入口地址與向量表內容。

6 結論

本文實現了一種基於 STM32 的雙軸太陽能追光系統。系統以數字光照感測器四象限差分替代傳統光敏電阻方案,免標定且一致性好;強光門限滯回、死區限幅與指數逼近輸出平滑三層機制,將閉環運動的平穩性建立在控制結構而非參數湊試之上;幀節拍自錨定與串口/OLED 分片化,解決了軟體 PWM 平台的時序確定性問題;RAM 黑盒子與診斷計數器為偶發故障提供了可復盤的觀測手段。系統對準精度與動態響應滿足設計要求,運動連續無抖動,可直接應用於小型太陽能板的追光控制,其「感測—差分—P 控制—平滑輸出」的框架與幀時序保障方法亦可推廣至雲台追蹤類場景。

參考文獻

[1] 意法半導體. STM32F103xx 參考手冊(RM0008)[Z]. 2021. [2] 意法半導體. STM32F1 Cortex-M3 編程手冊(PM0056)[Z]. 2018. [3] ROHM Semiconductor. BH1750FVI Ambient Light Sensor IC Datasheet[Z]. 2011. [4] NXP Semiconductors. TCA9548A Low-Voltage 8-Channel I2C Switch Datasheet[Z]. 2015. [5] 胡壽松. 自動控制原理(第七版)[M]. 北京:科學出版社, 2019. [6] 劉火良, 楊森. STM32 庫開發實戰指南[M]. 北京:機械工業出版社, 2013. [7] Solving sensor integration issues in solar tracking applications. Solar Energy, 2020. [8] ARM Ltd. Cortex-M3 Embedded Development: DWT Cycle Counter Usage Note[Z]. ARM Application Note, 2015.