最近在研究 Arduino 讀取電子羅盤 GY-273 / HMC5883L的座標,將讀取的座標顯示在Console上,只要使用Serial.print()就可以簡單做到,可是如果要呈現一個 3D的圖像,經由 GY-273座標值的改變,讓畫面上的3D圖樣也跟著轉動。在Arduino 的環境下,我不確定圖形介面的Scratch for Arduino (簡稱S4A)是否可以完成?
先前寫過一篇:「Arduino筆記(十三):使用Firmata 協定,Arduino 也可以執行 Python」,如果將 Arduino測得的資料,透過 PyMata 及 Python 的3D 函式庫,將結果呈現在螢幕上,應該是一個很不錯的想法。
另一個作法是將Arduino 測得的資料,透過 Serial Port單向傳給 Python,再由 Python根據接收的資料,改變圖形的形狀或角度。
在搜尋Python 繪圖庫的文件時,找到一個很容易就可以畫出3D圖形的程式: VPython,我試著用 Python 接收來自 Serial Port 的資料,結合座標軸,畫出立體的影像。以下就是在 Vpython畫出一個地球的畫面。
如有興趣可到以下 vPython 的文件網站,查詢相關指令:
網址是:http://vpython.org/contents/docs/
網址是:https://pypi.python.org/pypi/pyserial/2.7
• GY-273 / HMC5883L x1
• 連接線 x 4條
打開Serial串列的視窗,已經可以看到座標值,如上圖。
接下來要在電腦端安裝 Python所需的軟體,包括 Serial 跟 vPython兩種。 vPython 分成32跟64位元兩種,且分為Python 2.7 跟3.2兩個版本,安裝時要對應 Python 安裝的版本,否則會產生錯誤。我是採用比較傳統的作法,安裝 Python 2.7.13 版,vPython安裝2.7-6.11,執行時沒有發生問題。以下是軟體取得的位址與安裝方式(略) :
(1) 下載安裝 Python 2.7.x 版 32位元程式 (目前最新是2.7.13) 。 下載後執行接著按「下一步」即可完成安裝。
(2) 下載安裝 PySerial 2.7 版 。下載後執行接著按「下一步」即可完成安裝。
(3) 下載安裝 VPython-Win-32-Py2.7-6.11 。下載後執行,會詢問Python 2.7的目錄,接著按「下一步」即可完成安裝。
完成上述安裝後,開啟「VIDLE for python」視覺化的開發環境(Python's Integrated DeveLopment Environment),輸入以下程式,按「F5」(Run Module)或是從視窗選單「Run」➔ 「Run Module」。
• 以下是Python 程式:
程式中有幾個要注意的地方:
• 我的 Arduino Serial 通訊埠是 COM4,如果不同時,記得要修改。
• 傳輸速率 38400 是我試過比較剛好的,在畫面上顯示3D的圖時,不會因畫面顯示來不及,而造成資料在背景儲存多筆在緩衝區。
• xPos、yPos及zPos各除以100,是因為該數字常超過座標的值,造成程式錯誤中斷,除以100,可套用於目前座標中。
• github:jarzebski/Arduino-HMC5883L
• Palma Quarter:Using Python with Arduino
先前寫過一篇:「Arduino筆記(十三):使用Firmata 協定,Arduino 也可以執行 Python」,如果將 Arduino測得的資料,透過 PyMata 及 Python 的3D 函式庫,將結果呈現在螢幕上,應該是一個很不錯的想法。
另一個作法是將Arduino 測得的資料,透過 Serial Port單向傳給 Python,再由 Python根據接收的資料,改變圖形的形狀或角度。
在搜尋Python 繪圖庫的文件時,找到一個很容易就可以畫出3D圖形的程式: VPython,我試著用 Python 接收來自 Serial Port 的資料,結合座標軸,畫出立體的影像。以下就是在 Vpython畫出一個地球的畫面。
[vPython]
Vpython 是 Python 的一個套裝軟體,可以在螢幕上呈現出 3D 的圖形,包括球形體、長方體、彈簧、金字塔體、箭號等形狀,所有的圖形都以 3 維座標表示,並以向量控制位置或方向。如有興趣可到以下 vPython 的文件網站,查詢相關指令:
網址是:http://vpython.org/contents/docs/
[pySerial]
pyserial程式的功能,是要讓 Python 程式透過 Serial Port (RS232) 來進行通訊傳輸。傳輸前需進行速率()設定程式下載位置及相關文件,可參考 pyserial 的網站:網址是:https://pypi.python.org/pypi/pyserial/2.7
[材料]
• Arduino Nano x 1• GY-273 / HMC5883L x1
• 連接線 x 4條
[接線圖]
•GY-273 / HMC5883L 電子羅盤模組連接線路Arduino | GY-273/HMC5883 |
---|---|
VCC | VCC |
GND | GND |
Pin A5 | SCL |
Pin A4 | SDA |
- | DRDY |
[Arduino程式一]
以下是修改自Korneliusz Jarzebski的程式,產生一列X,Y,Z座標的數字,以逗號隔開。#include <Wire.h> #include <HMC5883L.h> HMC5883L compass; void setup() { Serial.begin(38400); // Initialize HMC5883L while (!compass.begin()) { delay(500); } // +/- 1.30 Ga: HMC5883L_RANGE_1_3GA (default) compass.setRange(HMC5883L_RANGE_1_3GA); // Set measurement mode // Continuous-Measurement: HMC5883L_CONTINOUS (default) compass.setMeasurementMode(HMC5883L_CONTINOUS); // Set data rate // 15.00Hz: HMC5883L_DATARATE_15HZ (default) compass.setDataRate(HMC5883L_DATARATE_15HZ); // Set number of samples averaged // 1 sample: HMC5883L_SAMPLES_1 (default) compass.setSamples(HMC5883L_SAMPLES_1); } void loop() { Vector raw = compass.readRaw(); Vector norm = compass.readNormalize(); Serial.print(norm.XAxis); Serial.print(", "); Serial.print(norm.YAxis); Serial.print(", "); Serial.print(norm.ZAxis); Serial.println(); delay(100); }
[Arduino程式二]
以下是修改自 Henry's Bench的 HMC5883 Arduino 程式,使用I2C讀取 HMC5883的暫存器,再利用位移的方式計算X,Y,Z座標的值。#include <Wire.h>: //I2C Arduino Library #define addr 0x1E //I2C Address for The HMC5883 void setup(){ Serial.begin(38400); Wire.begin(); Wire.beginTransmission(addr); //start talking Wire.write(0x02); // Set the Register Wire.write(0x00); // Tell the HMC5883 to Continuously Measure Wire.endTransmission(); } void loop(){ int x,y,z; //triple axis data //Tell the HMC what regist to begin writing data into Wire.beginTransmission(addr); Wire.write(0x03); //start with register 3. Wire.endTransmission(); //Read the data.. 2 bytes for each axis.. 6 total bytes Wire.requestFrom(addr, 6); if(6 <= Wire.available()){ x = Wire.read() <<8; //MSB x x |= Wire.read(); //LSB x z = Wire.read() <<8; //MSB z z |= Wire.read(); //LSB z y = Wire.read() <<8; //MSB y y |= Wire.read(); //LSB y } // Show Values Serial.print(x); Serial.print(", "); Serial.print(y); Serial.print(", "); Serial.println(z); delay(10); }
打開Serial串列的視窗,已經可以看到座標值,如上圖。
接下來要在電腦端安裝 Python所需的軟體,包括 Serial 跟 vPython兩種。 vPython 分成32跟64位元兩種,且分為Python 2.7 跟3.2兩個版本,安裝時要對應 Python 安裝的版本,否則會產生錯誤。我是採用比較傳統的作法,安裝 Python 2.7.13 版,vPython安裝2.7-6.11,執行時沒有發生問題。以下是軟體取得的位址與安裝方式(略) :
(1) 下載安裝 Python 2.7.x 版 32位元程式 (目前最新是2.7.13) 。 下載後執行接著按「下一步」即可完成安裝。
(2) 下載安裝 PySerial 2.7 版 。下載後執行接著按「下一步」即可完成安裝。
(3) 下載安裝 VPython-Win-32-Py2.7-6.11 。下載後執行,會詢問Python 2.7的目錄,接著按「下一步」即可完成安裝。
完成上述安裝後,開啟「VIDLE for python」視覺化的開發環境(Python's Integrated DeveLopment Environment),輸入以下程式,按「F5」(Run Module)或是從視窗選單「Run」➔ 「Run Module」。
• 以下是Python 程式:
import serial #import serial library from visual import * #import vPython library scene2 = display(title='Examples of HMC5883L Triple Axis Digital Compass', x=0, y=0, width=600, height=600, center=(5,0,0), background=(0,0,0)) scene2.fullscreen = True Earth = sphere(raduis = 100, material = materials.earth) # print Earth PosLabel = label(text='Position is: ', box=false, height=15) # print position sensorData= serial.Serial('com4',38400) # Get data from serial port while True: rate(50) # Delay if (sensorData.inWaiting()>0): textline = sensorData.readline() str2 = 'Position is: ' + textline Pos = textline.split(',') xPos = float(Pos[0]) /100 yPos = float(Pos[1]) /100 zPos = float(Pos[2]) /100 Earth.pos = vector(xPos, yPos, zPos) PosLabel.text= str2
程式中有幾個要注意的地方:
• 我的 Arduino Serial 通訊埠是 COM4,如果不同時,記得要修改。
• 傳輸速率 38400 是我試過比較剛好的,在畫面上顯示3D的圖時,不會因畫面顯示來不及,而造成資料在背景儲存多筆在緩衝區。
• xPos、yPos及zPos各除以100,是因為該數字常超過座標的值,造成程式錯誤中斷,除以100,可套用於目前座標中。
[執行結果]
看到一個地球及座標的畫面,會隨著HCM5883L的轉動而改變位置。[後記]
在執行 Python 的過程中,使用 vPython 的 函數 sphere 畫一個地球,只要一行指令即可。但執行的過程中,都沒有改變地球的半徑 raduis 的值,可是在畫面上的地球,會忽大忽小的改變,一直讓我找不出原因。其次是地球只是在座標平移,而非真的做到 3D 的旋轉。還有座標的位置,我也常無法有效的控制物件所在位置,這些小地方還不熟悉,後續還有很大的努力空間。下次有些研究的心得再跟各位分享。
[參考資料]
• Henry's Bench:Arduino GY-273 HMC5883L Magnetometer Compass Tutorial• github:jarzebski/Arduino-HMC5883L
• Palma Quarter:Using Python with Arduino
請問大大,我用了第二段的程式碼,但是輸出一直持續都是0,0,0 請問有遇過類似的情況嗎?
回覆刪除張貼留言