加速規,用來量測加速度的裝置,但也因為重力恆向下,也可以拿來測量重力於其他方向的分量,進而推算得到物體目前的姿態。
本篇文章主要討論如何從三軸加速規擷取訊號到Arduino,並透過序列傳輸將三軸的分量傳至電腦由Processing接收,並將物體姿態繪出顯示於螢幕。
Arduino ADXL345 三軸重力加速模組 |
本篇範例所使用的 Arduino ADXL345 三軸重力加速模組 (數位輸出) Datasheet 。
我們有兩種方法能讓Arduino與加速度模組溝通,分別是SPI 跟 I2C ,文章使用 I2C 通訊作為範例,主要因為Arduino 提供非常方便的 library 供我們使用。
我們可以在Arduino 的 Wire Library 說明頁中看到 Uno 的腳位是 A4 (SDA), A5 (SCL),因此加速度模組與Arduino 的連接也非常的簡單。
ADXL345 的VCC 接到 Arduino 的 3.3V ,GND 接到 Arduino 的 GND,SDA 接到 Arduino 的 A4,SCL 接到 Arduino 的 A5,這樣接線就完成了。
Arduino 與加速度感測器的連接 |
硬體準備就緒後,就進入軟體部分。
首先下載 Arduino 的 Wire Library,解壓縮後放到 arduino 的Library資料夾中。
接著下載 ADXL345 的 Arduino Library 。若不想用別人的程式碼可以可以照著 ADXL345 的 Datasheet 自己試著寫,但在此我們先用別人寫好的來修改,畢竟我們的目的是在Processing 上顯示出姿態。
在 ADXL345 的 Datasheet 第10頁中解釋了如何透過I2C跟 ADXL345 溝通,也因此可以看到 Library 的前段是在配置記憶體位置,為了避免記憶體衝突。
為了將資料傳至Processing(注意:鮑率要對應),我們必須修改一小段程式碼,請將 readAccel() 的副程式改寫成如下:
接著下載 ADXL345 的 Arduino Library 。若不想用別人的程式碼可以可以照著 ADXL345 的 Datasheet 自己試著寫,但在此我們先用別人寫好的來修改,畢竟我們的目的是在Processing 上顯示出姿態。
在 ADXL345 的 Datasheet 第10頁中解釋了如何透過I2C跟 ADXL345 溝通,也因此可以看到 Library 的前段是在配置記憶體位置,為了避免記憶體衝突。
void readAccel() {
uint8_t howManyBytesToRead = 6;
readFrom( DATAX0, howManyBytesToRead, _buff); //read the acceleration data from the ADXL345
// each axis reading comes in 10 bit resolution, ie 2 bytes. Least Significat Byte first!!
// thus we are converting both bytes in to one int
int x = (((int)_buff[1]) << 8) | _buff[0];
int y = (((int)_buff[3]) << 8) | _buff[2];
int z = (((int)_buff[5]) << 8) | _buff[4];
Serial.write('X');
Serial.write(_buff[1]);
Serial.write(_buff[0]);
Serial.write(_buff[3]);
Serial.write(_buff[2]);
Serial.write(_buff[5]);
Serial.write(_buff[4]);
}
因為 Serial 是一個 byte 一個 byte 傳送,因此我們在Arduino 讀取到的高位元與低位元的值就直接傳至 Processing 再處理,不用再多做一個步驟,並加上一個 'X' 當做起始字元。
接下來就是Processing 的程式碼(再次提醒:鮑率要對應!):
import processing.serial.*; Serial serial; int[] invalue=new int[6]; int[] Val=new int[3]; float G=250; float xacc; float yacc; float zacc; void setup(){ size(600,300,P3D); fill(0, 102, 153); println(Serial.list()); serial=new Serial(this,Serial.list()[3],9600); println("Start!"); } void draw(){ if(serial.available()>20){ if(serial.read()=='X'){ int sign = 1; invalue[1]=serial.read(); invalue[0]=serial.read(); invalue[3]=serial.read(); invalue[2]=serial.read(); invalue[5]=serial.read(); invalue[4]=serial.read(); if( invalue[1]>>7 == 1 ) { invalue[1]= 255 - invalue[1]; invalue[0] = 256 - invalue[0]; sign = -1; } else { sign = 1; }Val[0] = sign * ( invalue[1] << 8 | invalue[0] ); if( invalue[3]>>7 == 1 ) { invalue[3]= 255 - invalue[3]; invalue[2] = 256 - invalue[2]; sign = -1; } else { sign = 1; }Val[1] = sign * ( invalue[3] << 8 | invalue[2] ); if( invalue[5]>>7 == 1 ) { invalue[5]= 255 - invalue[5]; invalue[4] = 256 - invalue[4]; sign = -1; } else { sign = 1; }Val[2] = sign * ( invalue[5] << 8 | invalue[4] ); println(Val); background(0); textSize(20); translate(width/2, height/2); text("z-acc:"+Val[2],-250,-100); text("x-acc:"+Val[0],-250,-80); text("y-acc="+Val[1],-250,-60); rotateX(asin(Val[1]/G)); //xacc rotateZ(asin(-Val[0]/G)); //Yacc box(100,20,100); } } }
注意到程式碼紅、藍、綠的地方,這裡我們要對接收到的高低位元資料做處理,ADXL345 傳過來的資料要合併這裡整理出一個規則:
如果值為正,則不改變,但如果值為負,則全部的0變為1;全部的1變為0。
也就是說若值為 256,則高低位元分別是 00000001 00000000;
而值為 -256,則高低位元是 11111110 11111111;
也因此有了上面的處理步驟。
得到資料後,便透過重力在個座標的分量來計算出現在加速規的姿態,這步驟需要一點空間概念,不過並不難,思考一下應該可以得到跟筆者一樣的答案。
以上就是如何利用Processing 顯示 Arduino 加速規模組姿態。
Casino - MapyRO
回覆刪除Casino - The place for all your casino games, from live 과천 출장안마 dealers, to the latest bingo, slots 목포 출장마사지 and 강원도 출장안마 poker to the 양주 출장샵 biggest prizes!Casino · Casino · Cash games · Promotions 영천 출장안마