基于树莓派的追光系统(python)
目錄
前言
一、材料
二、硬件--控制邏輯
1.主設備的準備
1.啟用樹莓派的i2c設備
2.安裝python-smbus
2.從設備的準備
1.BH1750
2.L298N驅動芯片
3.云臺的準備
1.增加電機固定模塊
2.增加bh1750固定模塊
三、軟件--程序邏輯
1.總程序邏輯
2.光強檢測程序邏輯
3.電機驅動代碼
四、本系統的缺點和改進空間
缺點1:使用的是直流電機
改進1:更換舵機
缺點2:轉動方式不妥當
改進2:更換轉軸(?)
五、學習經驗
六、一點感慨
七、參考文章
前言
由于小組做的沙盤模型需要使用到追光系統,在展示時需要一個prototype(原型機),查閱一些資料后,決定以手頭現有的樹莓派和一些簡單的材料制作了一個簡單的太陽能追光系統。對于其中使用的原理(包括i2c通訊協議的具體內容),文末會給出一些比較好的參考文章,本人其實不甚精通。第一次寫,也是第一次接觸這類東西(此前還是一個連VCC、GND是什么都不知道的小白),如有不足之處,敬請指正。
目前還是第一代原型機,后續可能還會繼續迭代。
展示:
基于樹莓派的追光系統(python)
注:此系統使用的是bh1750,ADDR引腳的改變最多獲得兩個地址,因此樹莓派只能同時控制兩個(或許可以通過物理方式,從硬件上改變器件的從設備地址?暫未繼續研究),所以本系統注定是單自由度的追光,需要做雙自由度的追光系統的朋友請注意了。
一、材料
樹莓派*1
光傳感器(BH1750FVI)*2
直流電機(使用舵機更好)*1
L298N電路板(容易燒壞,可以多準備幾個)*1
電池盒(用于供電)*1
云臺(3D打印,包含bh1750保護盒*2)
面包板(環氧實驗板亦可)
開關、導線、杜邦線若干
二、硬件--控制邏輯
1.主設備的準備
主設備當然是我們的樹莓派,由于需要與光傳感器bh1750交換信息(即從bh1750處獲取光強信息),因此需要通過i2c協議來完成信息交流過程。L298N沒有這樣的需求,直接用GPIO口輸出即可。
1.啟用樹莓派的i2c設備
????????打開樹莓派的終端
????????輸入
sudo raspi-config????????選擇Interfacing Options高級設置
????????將SPI和I2C設置為Enable
????????重啟系統
完成i2c設備的啟用后,我們需要安裝python-smbus,幫助我們更容易的書寫樹莓派與bh1750交互信息的程序。
2.安裝python-smbus
? ? ? ? 打開終端
? ? ? ? 輸入
sudo apt-get install python-smbus(這個安裝會附帶安裝i2c-tools,就不必再單獨安裝了)
2.從設備的準備
從設備就是我們的bh1750和L298N,進行的準備主要就是接線。這里進行一些簡單的介紹。
1.BH1750
bh1750總共有五個引腳,分別是VCC、GND、SCL、SDA以及ADDR。
VCC連接樹莓派輸出3.3V電壓的引腳
GND 連接樹莓派的GND口
SCL和SDA分別是i2c時鐘線和數據線,連接樹莓派對應端口即可
ADDR是i2c的地址線,當這個引腳接GND時器件地址為0100011(0x23),接VCC時器件地址為1011100(0x5c)。
(注意:SDA和SCL連接要注意組合,要么都連.1,要么都連.0)
接線時注意ADDR一個接GND,一個接3.3V電壓。
(圖中樹莓派VCC口代表3.3V電壓口,寫的時候沒注意。。。)
檢查:
????????打開樹莓派終端
????????輸入(注意:若SCL SDA接的都是.1則此處末尾寫1,若為.0則將下面這行末尾的1改為0)
sudo i2cdetect -y 1????????出現如下結果,說明連接成功。
2.L298N驅動芯片
由于樹莓派引腳輸出的電流太小,并不能驅動直流電機轉動,更不要說控制直流電機的轉速了,所以我們需要加這樣一個驅動芯片,協助我們控制電機。
“上面為最常見的一款L298N芯片,值得注意的是,它已經內置的5V供電,所以不必從外面再接5V輸入。屆時5V端子將成為5V輸出,為了保證L298N供電的穩定性(供電不足可能引起L298N的燒毀),不建議使用此5V供電作為單片機的電源。”
???????????????????????????????????????????????????????????????????????????????----《電機驅動芯片-L298N介紹》知乎北鸮
?????????????????????????????????????????????????????????????????????????????????????????????????????????????(文末有該文章鏈接)
如同引文所說,我們不直接使用其5V供電,而是外接電池為其供電,本人使用的是兩節3.7V的電池,焊上一個小開關,必要時方便關閉。
L298N有4個輸出口,4個輸入口,由于我們只需要控制一個電機,其實輸出輸入口只需各用兩個即可。
?具體接線如上圖。
當輸入的引腳一個為高電平(1),一個為低電平(0)時,電機就會轉動,轉動方向與具體哪個引腳為高電平有關。
3.云臺的準備
原云臺是用于sg90舵機,且是有兩個自由度(文末會放來源)。
由于我們項目比較趕,沒有辦法等到舵機到,只能先用手邊的電機。
因此需要對這個模型進行一些更改。
1.第一代
1.增加電機固定模塊
首先要說明使用電機隨著旋轉板轉動的思路是不太好的,可惜當時沒有意識到。
考慮到要將電機與旋轉板固定起來,由于電機存在一個可以擰螺絲的凸起部分,由此設計了一個固定電機的結構。
然后電機主體就很無腦地用雙面膠和旋轉板固定的。。
現在想想當時設計確實不太合理,不過就測試來說,還是固定的比較牢固的,在測試過程和展示過程中都不會掉落。
2.增加bh1750固定模塊
我們的光傳感器上有兩個可以擰螺絲的部位,按理來說是可以設計一個相同大小的螺絲孔直接固定在旋轉板上的。但是在上網找bh1750模型參數的時候,剛好找到了“bh1750保護盒”,遂本著拿來主義,直接拿來用了,只需在旋轉板上加裝固定此保護盒的模塊。
2.第二代
1.底座支架
2.固定光纜配件
3.線路梳理設計
4.固定舵機結構
(因為很快就裝到沙盤里了,就沒有一一拍照了……)
三、軟件--程序邏輯
1.總程序邏輯
總程序邏輯講起來比較簡單,目標就是希望我們的追光器能實時監測光照環境,并做出響應。
為了我們的追光器不會過于敏感,我們需要設置一個閾值,當兩個光照傳感器光強之差的絕對值大于我們這個閾值的時候,再進行調整。
總程序邏輯如下:
? ? ? ? 開始計次
? ? ? ? 進入循環:{
? ? ? ? 處理光傳感器的數據
? ? ? ? 若光強差大于閾值(20lx):
? ? ? ? ? ? ? ? 往光照強的方向轉動
? ? ? ? 若光強小于閾值:
? ? ? ? ? ? ? ? 計次加一
? ? ? ? 檢查計次,若計次為三:
? ? ? ? ? ? ? ? 程序休息3s
? ? ? ? ? ? ? ? 計次重置
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }????????
可以看到,這個程序還是比較簡單的,但其中有兩點值得一提:
? ? ? ? 第一,往光照強的方向運動。我們希望我們的追光器能夠比較準確地進行轉動,不是以一個恒定的速度轉動。而我們手中又可以得到比較精確的光強差,所以我們希望設置一個參數調整函數,在光強差較大時,以一個較快的速度進行轉動,光強差較小的時候則以較小的速度進行微調,更快的達到平衡狀態。
? ? ? ? 第二,計次。此處計次的主要目的是展示要求,當計次達到三,也就是說,程序連續三次檢測到兩側光強小于閾值,此時可以認為我們的追光器的光環境已經比較穩定了,因此我們讓程序休息三秒,再進行后續的循環,這樣設計的目的之一是我們有展示需求,并不是什么關鍵的邏輯。。。
2.光強檢測程序邏輯
直接上代碼:(邏輯詳見注釋)
import smbus import time#BH1750地址 __DEV_ADDR_1=0x23 __DEV_ADDR_2=0x5c#控制字(都是bh1750的一些命令,可以在芯片手冊上查到) __CMD_PWR_OFF=0x00 #關機 __CMD_PWR_ON=0x01 #開機 __CMD_RESET=0x07 #重置 __CMD_CHRES=0x10 #持續高分辨率檢測 __CMD_CHRES2=0x11 #持續高分辨率模式2檢測 __CMD_CLHRES=0x13 #持續低分辨率檢測 __CMD_THRES=0x20 #一次高分辨率 __CMD_THRES2=0x21 #一次高分辨率模式2 __CMD_TLRES=0x23 #一次分辨率 __CMD_SEN100H=0x42 #靈敏度100%,高位 __CMD_SEN100L=0X65 #靈敏度100%,低位 __CMD_SEN50H=0x44 #50% __CMD_SEN50L=0x6A #50% __CMD_SEN200H=0x41 #200% __CMD_SEN200L=0x73 #200%bus=smbus.SMBus(1)# bus.write_byte(__DEV_ADDR_1,__CMD_PWR_ON) bus.write_byte(__DEV_ADDR_1,__CMD_RESET) bus.write_byte(__DEV_ADDR_1,__CMD_SEN100H) bus.write_byte(__DEV_ADDR_1,__CMD_SEN100L) bus.write_byte(__DEV_ADDR_1,__CMD_PWR_OFF)# bus.write_byte(__DEV_ADDR_2,__CMD_PWR_ON) bus.write_byte(__DEV_ADDR_2,__CMD_RESET) bus.write_byte(__DEV_ADDR_2,__CMD_SEN100H) bus.write_byte(__DEV_ADDR_2,__CMD_SEN100L) bus.write_byte(__DEV_ADDR_2,__CMD_PWR_OFF)#獲得第一臺bh1750的光照強度(單位:lx) def getIlluminance_1():bus.write_byte(__DEV_ADDR_1),__CMD_PWR_ON)bus.write_byte(__DEV_ADDR_1,__CMD_THRES2)time.sleep(0.2)res=bus.read_word_data(__DEV_ADDR,0)#read_word_datares=((res>>8)&0xff)|(res<<8)&0xff00res=round(res/(2*1.2),2)#根據芯片手冊可知計算光強公式result="光照強度: "+str(res)+"lx"#可以在測試時去掉下一行的注釋符號,觀察是否正常輸出#print(result)return res#獲得第二臺bh1750的光照強度(單位:lx) def getIlluminance_2():bus.write_byte(__DEV_ADDR_2),__CMD_PWR_ON)bus.write_byte(__DEV_ADDR_2,__CMD_THRES2)time.sleep(0.2)res=bus.read_word_data(__DEV_ADDR,0)#read_word_datares=((res>>8)&0xff)|(res<<8)&0xff00res=round(res/(2*1.2),2)#根據芯片手冊可知計算光強公式result="光照強度: "+str(res)+"lx"#可以在測試時去掉下一行的注釋符號,觀察是否正常輸出#print(result)return res#其實也可以用一個參數輸入第一臺第二臺地址,就不用倆函數了,不過問題不大。。(文末有源代碼,這是我略微進行了一點改動和注釋后的代碼)
3.電機驅動代碼
import RPi.GPIO as GPIO import time#這里填樹莓派上對應端口,注意這里的編號規則是BOARD,你也可以使用BCM,不過需要在程序setmode中進行一些相應改動。 IN1 = 11 IN2 = 12#初始化 def init():Pinlist = [IN1,IN2]GPIO.setup(Pinlist,GPIO.OUT,initial = GPIO.LOW)def reset():p1.start(0)p2.start(0)def run():p1.start(80)#設置duty cyclep2.start(0)time.sleep(1)print("done")reset()def des_run():p1.start(0)p2.start(80)time.sleep(0.5)reset()if __name__ == "__main__":GPIO.setmode(GPIO.BOARD)#設為BOARD編號規則GPIO.setwarnings(False)#關閉由于引腳被設為非默認值時的警告提示init()#初始化p1 = GPIO.PWM(IN1,50)#將此引腳初始化為PWM實例,頻率為50Hzp2 = GPIO.PWM(IN2,50)run()#動起來!!des_run()#反方向動起來!GPIO.cleanup()#清除定義的引腳四、本系統的缺點和改進空間
缺點1:使用的是直流電機
(你看這個電機真的是太遜了!)
我們并不能從直流電機那里獲取到任何信息,因此,我們設計的程序必然是存在問題的,例如當電機已經旋轉到死角的時候,它還會繼續轉動,因為我們對于其轉動狀態一無所知。電機內置的減速帶也讓電機的旋轉非常不絲滑,觀賞效果也不太好。
改進1:更換舵機
如果更換為舵機,一定程度上可以解決這個問題,我們的程序邏輯會更加準確,對于追光器的限位就可以不僅于物理層面(云臺)。旋轉起來也可以更加順暢,而不是像現在這樣一頓一頓的,減小對于光強檢測的影響。
(更新:換用舵機后,由于sg90依然不能給我們返回信號,僅僅依靠sg90閉環控制不現實,所以旋轉依舊是一頓一頓的,但是比原來穩定一些,關于是否使用pid的問題還在進一步探索,初步打算加裝一個mpu6050的角度傳感器檢測姿態角。)
缺點2:轉動方式不妥當
這是本人的問題,在設計的時候考慮不夠周到,最后選擇的方式是讓電機轉動,從力學結構來說,這樣的結構缺乏穩定性,而且電機相對笨重,慣性也許也需要考慮在內,導致最后旋轉的調整十分不精確。
改進2:更換轉軸(?)
想了想如果換成舵機好像也不是不能讓舵機和云臺一起轉,下周我將嘗試使用舵機制作第二代模型,到時候再做定奪。
(更新:換用舵機后,sg90體型較小,也比較輕盈,轉動板與舵機一起轉動結構經測試還算穩定,如果舵機固定,就涉及到加長旋轉軸的問題,對于比較不夠精確的3D打印件來說不太合適,所以最后沒有更換。)
五、學習經驗
1.排錯邏輯:
在進行一次測試的時候發現電機轉得非常吃力,當時剛換上一個新的卡扣,懷疑是卡扣的問題。進行檢查的時候,發現在測試程序中能很自然的轉動,但在總程序中轉動很吃力,懷疑是程序問題,經過一行一行更改注釋,排除了程序問題。而后開始檢查硬件,最后確定是電池電量不足導致,更換電池后解決問題。
2.3D打印設計預留孔隙:
在制作卡扣的時候,設計的過于精確,雖然在solidworks上裝配的時候是可以的,但是實際打印出來沒有辦法卡上去。返回文件檢查時,發現當時已經考慮過了這個問題,預留了0.1mm,但是是自己隨便想的,后得知學校3D打印機的誤差在0.2mm,應當至少留0.2mm比較合適,更改后打印,順利裝配完成。
3.
六、一點感慨
最后,還是再感慨一下,通過自己完成這樣一個樣品真的很有意思。雖然頭疼很多次,踩了不少坑,好幾次更改方案,而且還頂著限時的壓力,最后居然真的做出來了!非常自豪哈哈哈!
剛開始接任務的時候我就說,我對這個感興趣,但我擔心我做不來。組長就和我說,這個不難,肯定能做得出來。挺感謝組長的鼓勵的,最后一邊查資料,一邊做。每個東西也不學太深,做多少,學多少。學得不夠了,再學一點,做一點,也可以算是真正的學以致用了罷。
四天時間,幾乎是從零開始,除了一點python基礎以外什么都沒有。一步一步,學了i2c通信協議,學了樹莓派GPIO的輸入輸出,學了L298N驅動電機的方式,甚至自己學了如何焊接。
在學習過程中,瀏覽了不知道多少帖子,如果沒有這些帖子,不知道要多花費我多少時間和精力。故而也寫一篇制作過程和一些經驗,權當是一種傳承,也是對自己這段時間的一個記錄。希望大家都能夠一路披荊斬棘,完成任務的同時學到知識,與大家共勉!
七、參考文章
由于參考文章眾多,我也不能全部記住和列出來,對于所有無私分享經驗的前輩(就算比我年輕也權叫一聲前輩,達者為先嘛哈哈!)表示衷心的敬佩和感謝!
以下寫了一些個人覺得幫助最大的參考文章,希望也能對看這篇文章的人有所幫助:
1.對于bh1750光傳感器的詳解,其中也講述了i2c通訊協議的原理,對本人幫助極大;對于bh1750的解釋也非常到位,常用的命令和程序都有包括,不過i2c的驅動代碼不是用python寫的。強烈建議將使用bh1750的朋友看一看:
BH1750光照傳感器超詳細攻略(從原理到代碼講解,看完你就懂了)_ShenZhen_zixian的博客-CSDN博客_bh1750
2.對于驅動電機的L298N電路板的介紹:
電機驅動芯片-L298N介紹 - 知乎 (zhihu.com)
3.光強檢測程序源代碼:
Raspberry Pi開發之旅-光照強度檢測(BH1750) - 走看看 (zoukankan.com)
4.第一代云臺的原型來自這里(好像是在評論區):
基于Arduino的太陽能板追光裝置設計_秦學毅的博客-CSDN博客
總結
以上是生活随笔為你收集整理的基于树莓派的追光系统(python)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [附源码]Nodejs计算机毕业设计交通
- 下一篇: antd 图片上传遇到的坑----图片回