T.C BİLECİK ŞEYH EDEBALİ ÜNİVERSİTESİ MÜHENDİSLİK FAKÜLTESİ
BİLGİSAYAR MÜHENDİSLİĞİ BÖLÜMÜ
MİKROİŞLEMCİ UYGULAMALARI
SUNUM KONUSU
İVME SENSÖRÜ ve UYGULAMASI
Öğrencilerin :
Adı : RABİA Adı : SABRİ
Soyadı : YILDIRIM Soyadı : GÜLTEKİN
Numara : 47803523978 Numara : 25820504286
E-posta : yildirimrabiace@gmail.com
E-posta : gultekinsabrice@gmail.com
ADXL345 İVME SENSÖRÜ
Kullandığımız Stellaris M3 kitimizde ADXL345 ivme ölçer sensörü bulunmaktadır.
ADXL345 ; küçük, düşük güç tüketimine sahip 3 eksende çıkış verebilen bir açısal ivme ölçer sensördür. ±16g’lik bir algılama alanına sahip olup, I²C hattı üzerinden ve SPI hattı üzerinden çıkış alınabilir.
Kart üzerinde dahili voltaj regülatörü bulunduğundan 3-5V arası bir giriş gerilimi ile beslenebilir.
Kart üzerinde bununla beraber iki adet kesme pinide bulunmaktadır. Bu pinler, serbest düşüş, dokunma veya çift dokunma için ayarlanarak çıkış vermesi sağlanabilir. [5]
Özellikleri :
-
Giriş Voltajı : 3-5V
-
Düşük güç tüketimi(40uA)
-
Serbest düşüş algılama
-
SPI ve I²C arayüzü
Şekil : Stellaris M3 kiti
İvme sensörümüz Şekil 1’de kutu içerisinde gösterilen kısımda bulunmaktadır.
Kullanılan ivme sensörümüz Şekil 2’ de gösterilmektedir.
Şekil : İvme sensörü
İVME SENSÖRÜ PİN KONFİGÜRASYONU VE FONKSİYON TANIMLAMALARI
Şekil : İvme sensörü pin konfügürasyonu ve fonksiyon tanımlamaları [1]
İVME SENSÖRÜNÜN ÖZELİKLERİ
Şekil : İvme sensörünün çalışma özellikleri [1]
İVME SENSÖRÜNÜN REGİSTER HARİTASI
Şekil : Register haritası [1]
İVME SENSÖRÜNÜN ÇALIŞMASINI SAĞLAYAN REGISTERI
Register 0x00 – DEVID ( Read Only) :
Şekil : Register 0x00 -Devid
DEVID kaydı i 0xE5 sabit bir aygıt kimlik kodu tutar. Şekil 6’da DEVID kaydı için gerekli değerler yazılmıştır. Bu değer 8’lik sayı tabanında 345’ e denk gelir. Bu registerin tanımlanması sensörün çalışması için çok önemlidir. [1]
İVME SENSÖRÜNÜN İLERİ HASSASİYET DÜZEYLERİ
Şekil : Hassasiyet düzeyleri [1]
I²C HABERLEŞMESİ
I²C (Inter-Integrated Circuit), seri haberleşme türlerinden senkron haberleşmeye bir örnektir. Haberleşme için toprak hattı dışında SDA ve SCL olmak üzere iki hatta ihtiyaç duyulmaktadır. Hat sayısının fazla olması nedeniyle, uzun mesafeli haberleşmelerde tercih edilmez. Genellikle kısa mesafeli ve düşük veri aktarım hızının yeterli olduğu yerlerde kullanılır.
I²C haberleşmesinde, haberleşmeyi kontrol eden master cihazı bulunur. Her haberleşmede bir tane master bulunmalıdır. Haberleşmenin sağlanabilmesi için haberleşme hattına en az bir adet slave (köle) cihaz bağlanmalıdır. Hatta bağlanan birden fazla slave cihazlardan hangisinin veri aktaracağına, master cihaz karar verir. Böylece hat sayısında bir değişiklik olmadan birden fazla cihazla haberleşme sağlanır.
ÖRNEK :
Şekil : I2C Örneği
Şekil 8’de ki örnek çizim için ; Master ve slave cihazların aynı besleme hattına bağlanmasına gerek yoktur. Fakat iletişimin sağlanması için toprak hatlarının aynı olması gerekir. Bunun yanında veri aktarımı için SDA (Serial Data Line) ve SCL (Serial Clock) olmak üzere iki adet haberleşme hattı bulunur. Bu hatlardan SDA, cihazlar arasındaki veri aktarımının sağlandığı hattır. Bu hatta çift yönlü veri aktarımı olur. Hatta aktarılan verilerin senkronizasyonu, SCL hattı tarafından gerçekleştirilir. SCL hattında master cihaz tarafından üretilen saat sinyali bulunur. SDA hattındaki haberleşme, bu sinyale göre düzenlenir.
Haberleşmenin tüm hat boyunca hatasız bir şekilde sağlanabilmesi için SDA ve SCL hatları, pull-up dirençlerle VCC hattına bağlanmalıdır. SDA ve SCL pinleri, kullanılan Arduino türüne göre değişiklik göstermektedir. Arduino türlerine göre SDA ve SCL pinleri Tablo1’de gösterilmiştir. [2]
Tablo : Türe göre değer tablosu
BUFFER (Tampon Saha) :
Verilerin I/O işlemlerinden sonra belleğe yazılmadan önce uğradıkları bir sahadır. Bufferlar I/O işlemi sırasında kullanıcının beklemesini engellemek için kullanılırlar. Bellekten okumak ve belleğe yazmak maliyetli bir işlemdir. Sistemi yorar ve hız olarak yavaştır. I/O aygıtlarından gelen veriler bu sebeple önce bir havuzda toplanır. Böylece bu havuz belirli miktarlarda dolduktan sonra toplu olarak belleğe yazılır. Bu sisteme performans kazandıran bir harekettir. [4]
UYGULAMA :
İVME SENSÖRÜ İLE TOP HAREKETİ
Uygulama ne yapmakta ?
İvme sensörü kullanılarak alınan x-y değerleri ile oluşturulan topun herketi sağlanmakta aynı zamanda topun hızıda kontrol edilmektedir. Yani kitimizin eğim değerlerini bir anda (hızlıca eğersek) değiştirirsek daha hızlı hareket edecektir.Top bulunduğu çerçeve alanının dışına çıkmamaktadır. Şekil 9 ‘da tasarım gösterilmektedir.
Uygulamamızda
Label2’ de X yazmakta.
Label3’te ölçülen X değeri yazılacaktır.
Label’1de Y yazmakta.
Label4’te ölçülen Y değeri yazacaktır.
Top olarak kullanılan Circle1’dir.
Şekil : İvme sensörü uygulamasının görünümü
UYGULAMAMIZIN KODLARI :
Tüm kodlar ivme_main.c ‘de yazılmaktadır.
#include "ivme_objects.h"
#include "built_in.h"
//ivme sensörünün verilerini tanımladık.
// ADXL345 Register Definition
#define _POWER_CTL 0x2D
#define _DATA_FORMAT 0x31
#define _BW_RATE 0x2C
#define _DATAX0 0x32
#define _DATAX1 0x33
#define _DATAY0 0x34
#define _DATAY1 0x35
#define _DATAZ0 0x36
#define _DATAZ1 0x37
#define _FIFO_CTL 0x38
#define _SPEED 0x0F // Buffer Speed - 3200Hz
#define _ACCEL_ERROR 0x02
//değişkenler
char out[16];
int readings[2] = {0, 0};
char cACCEL_test_status;
//İvme sensörü fonksiyonları
void ADXL345_Write(unsigned short address, unsigned short data1) {
I2C0_Enable(); // issue I2C start signal
I2C0_Master_Slave_Addr_Set(0x1D, _I2C_DIR_MASTER_TRANSMIT);
I2C0_Write(address,_I2C_MASTER_MODE_BURST_SEND_START); // send byte (address of the location)
I2C0_Write(data1,_I2C_MASTER_MODE_BURST_SEND_FINISH); // send data (data to be written)
I2C0_Disable(); // issue I2C stop signal
}
unsigned short ADXL345_Read(unsigned short address) {
unsigned short tmp = 0;
I2C0_Enable(); // issue I2C start signal
I2C0_Master_Slave_Addr_Set(0x1D, _I2C_DIR_MASTER_TRANSMIT); // issue I2C start signal
I2C0_Write(address, _I2C_MASTER_MODE_SINGLE_SEND);
I2C0_Master_Slave_Addr_Set(0x1D, _I2C_DIR_MASTER_RECEIVE);
I2C0_Read(&tmp, _I2C_MASTER_MODE_SINGLE_RECEIVE);
I2C0_Disable(); // issue I2C stop signal
return tmp;
}
char ADXL345_Init(void) {
char id = 0x00;
// Go into standby mode to configure the device.
ADXL345_Write(0x2D, 0x00);
id = ADXL345_Read(0x00);
if (id != 0xE5) {
return _ACCEL_ERROR;
}
else {
ADXL345_Write(_DATA_FORMAT, 0x08); // Full resolution, +/-2g, 4mg/LSB, right justified
ADXL345_Write(_BW_RATE, 0x0A); // Set 100 Hz data rate
ADXL345_Write(_FIFO_CTL, 0x80); // stream mode
ADXL345_Write(_POWER_CTL, 0x08); // POWER_CTL reg: measurement mode
return 0x00;
}
}
int Accel_ReadX(void) {
int Out_x;
Hi(Out_x) = ADXL345_Read(_DATAX1);
Lo(Out_x) = ADXL345_Read(_DATAX0);
return Out_x;
}
int Accel_ReadY(void)
{
int Out_y;
Hi(Out_y) = ADXL345_Read(_DATAY1);
Lo(Out_y) = ADXL345_Read(_DATAY0);
return Out_y;
}
void ACCEL_Start(char *test)
{
// Reset error flag
*test = 0;
// Initialize I2C communication
I2C0_Init_Advanced(100000, &_GPIO_MODULE_I2C0_B23);
TFT_Set_Font(TFT_defaultFont, CL_YELLOW, FO_HORIZONTAL);
TFT_Set_Pen(CL_TEAL, 1);
TFT_Set_Brush(1, CL_TEAL, 0, 0, 0, 0);
TFT_Rectangle(0, 0, 320, 22);
TFT_Write_Text("Hosgeldiniz. Ivme Modulu Test Ediliyor.", 5, 6);
Delay_ms(2000);
TFT_Rectangle(0, 0, 320, 22);
// Initialize ADXL345 accelerometer
if (ADXL345_Init() == 0)
{
TFT_Write_Text("Ivme Modulu Basariyla Kuruldu.", 5, 6);
*test = 1;
Delay_ms(2000);
}
else
{
TFT_Write_Text("Ivme Modulunde Bir Hata Meydana Geldi.", 5, 6);
*test = 2;
Delay_ms(2000);
}
TFT_Rectangle(0, 0, 320, 22);
}
void Accel_Average(void) {
int i, sx, sy;
// sum
sx = sy = 0;
// average accelerometer reading over last 16 samples
for (i=0; i<16; i++) {
sx += Accel_ReadX();
sy += Accel_ReadY();
}
// average
readings[0] = sx >> 4;
readings[1] = sy >> 4;
}
void Display_X_Value(void)
{
TFT_Rectangle(25, 6, 155, 22);
IntToStr(readings[0], out);
Label3.Caption=out;
DrawLabel(&Label3);
Delay_ms(10);
}
void Display_Y_Value(void)
{
TFT_Rectangle(180, 6, 320, 22);
IntToStr(readings[1], out);
Label4.Caption=out;
DrawLabel(&Label4);
Delay_ms(10);
}
void ACCEL_Test(void)
{
Accel_Average(); // Calculate average X, Y and Z reads
Display_X_Value(); // Display average X value read
Display_Y_Value(); // Display average Y value read
Delay_ms(10);
}
int CposX=150,CposY=110;
void UpdateCirclePosition(void){
int diffX=0,diffY=0;
bit directionX,directionY;
if(!(readings[0]<50 && readings[0]>-50)){
if(readings[0]<0)
{
DiffX=-readings[0]/15-3;
directionX=1;
}
else
{
DiffX=readings[0]/15-3;
directionX=0;
}
}
if(!(readings[1]<50 && readings[1]>-50)){
if(readings[1]<0)
{
DiffY=-readings[1]/15-3;
directionY=1;
}
else
{
DiffY=readings[1]/15-3;
directionY=0;
}
}
TFT_Set_Pen(CL_TEAL, 1);
TFT_Set_Brush(1, CL_TEAL, 0, 0, 0, 0);
TFT_Circle(Circle1.Left+Circle1.Radius,Circle1.Top+Circle1.Radius,Circle1.Radius);
if(directionX && directionY){
Circle1.Left=Circle1.Left+diffX;
Circle1.Top=Circle1.Top+diffY;
if(Circle1.Left>300)
Circle1.Left=300;
if(Circle1.Top>220)
Circle1.Top=220;
}else if(directionX && !directionY){
Circle1.Left=Circle1.Left+diffX;
Circle1.Top=Circle1.Top-diffY;
if(Circle1.Left>300)
Circle1.Left=300;
if(Circle1.Top<26)
Circle1.Top=26;
}else if(!directionX && directionY){
Circle1.Left=Circle1.Left-diffX;
Circle1.Top=Circle1.Top+diffY;
if(Circle1.Left<20)
Circle1.Left=20;
if(Circle1.Top>220)
Circle1.Top=220;
}else if(!directionX && !directionY){
Circle1.Left=Circle1.Left-diffX;
Circle1.Top=Circle1.Top-diffY;
if(Circle1.Left<20)
Circle1.Left=20;
if(Circle1.Top<26)
Circle1.Top=26;
}
DrawCircle(&Circle1);
TFT_Set_Pen(CL_TEAL, 1);
TFT_Set_Brush(1, CL_TEAL, 0, 0, 0, 0);
}
void main() {
Start_TP();
TFT_Set_Font(TFT_defaultFont, CL_YELLOW, FO_VERTICAL);
TFT_Write_Text("IVME MODUL UYGULAMASI", 2, 225);
ACCEL_Start(&cACCEL_test_status);
DrawLabel(&Label2);
DrawLabel(&Label1);
while (1) {
Check_TP();
ACCEL_Test();
UpdateCirclePosition();
}
}
SUNUMDA YAPILAN UYGULAMA :
Uygulamamızda kare cisini ivme sensöründen okunan x-y verilerine göre hareketi sağlanmıştır. Şekil 10’da tasarım gösterilmektedir.
Label1’ de X yazmakta.
Label4’ te ölçülen X değeri yazılacaktır.
Label2’ de Y yazmakta.
Label3’ te ölçülen Y değeri yazılacaktır.
Label5’ te Z yazmakta.
Label6’ da ölçülen Z değeri yazılacaktır.
Şekil : Sunumda yapılan uygulamanın tasarımı
UYGULAMAMIZIN KODLARI :
Tüm kodlar ivmeprojesi2_main.c ‘de yazılmaktadır.
#include "ivmeprojesi2_objects.h"
#include "built_in.h"
//ivme sensörünün verilerini tanımladık.
// ADXL345 Register Definition
#define _POWER_CTL 0x2D
#define _DATA_FORMAT 0x31
#define _BW_RATE 0x2C
#define _DATAX0 0x32
#define _DATAX1 0x33
#define _DATAY0 0x34
#define _DATAY1 0x35
#define _DATAZ0 0x36
#define _DATAZ1 0x37
#define _FIFO_CTL 0x38
#define _SPEED 0x0F // Buffer Speed - 3200Hz
#define _ACCEL_ERROR 0x02
//değişkenler
char out[16];
int Xvalue,Yvalue,Zvalue;
char cACCEL_test_status;
//İvme sensörü fonksiyonları
void ADXL345_Write(unsigned short address, unsigned short data1) {
I2C0_Enable(); // issue I2C start signal
I2C0_Master_Slave_Addr_Set(0x1D, _I2C_DIR_MASTER_TRANSMIT);
I2C0_Write(address,_I2C_MASTER_MODE_BURST_SEND_START); // send byte (address of the location)
I2C0_Write(data1,_I2C_MASTER_MODE_BURST_SEND_FINISH); // send data (data to be written)
I2C0_Disable(); // issue I2C stop signal
}
unsigned short ADXL345_Read(unsigned short address) {
unsigned short tmp = 0;
I2C0_Enable(); // issue I2C start signal
I2C0_Master_Slave_Addr_Set(0x1D, _I2C_DIR_MASTER_TRANSMIT); // issue I2C start signal
I2C0_Write(address, _I2C_MASTER_MODE_SINGLE_SEND);
I2C0_Master_Slave_Addr_Set(0x1D, _I2C_DIR_MASTER_RECEIVE);
I2C0_Read(&tmp, _I2C_MASTER_MODE_SINGLE_RECEIVE);
I2C0_Disable(); // issue I2C stop signal
return tmp;
}
//ivme sensörünün tanımlanması.
char ADXL345_Init(void) {
char id = 0x00;
// Go into standby mode to configure the device.
ADXL345_Write(0x2D, 0x00);
id = ADXL345_Read(0x00);
if (id != 0xE5) {
return _ACCEL_ERROR;
}
else {
ADXL345_Write(_DATA_FORMAT, 0x08); // Full resolution, +/-2g, 4mg/LSB, right justified
ADXL345_Write(_BW_RATE, 0x0A); // Set 100 Hz data rate
ADXL345_Write(_FIFO_CTL, 0x80); // stream mode
ADXL345_Write(_POWER_CTL, 0x08); // POWER_CTL reg: measurement mode
return 0x00;
}
}
//ivme sensörünün X değerini okuma
int Accel_ReadX(void) {
int Out_x;
Hi(Out_x) = ADXL345_Read(_DATAX1);
Lo(Out_x) = ADXL345_Read(_DATAX0);
return Out_x;
}
//ivme sensörünün Y değerini okuma
int Accel_ReadY(void)
{
int Out_y;
Hi(Out_y) = ADXL345_Read(_DATAY1);
Lo(Out_y) = ADXL345_Read(_DATAY0);
return Out_y;
}
//ivme sensörünün Z değerini okuma
int Accel_ReadZ(void)
{
int Out_z;
Hi(Out_z) = ADXL345_Read(_DATAZ1);
Lo(Out_z) = ADXL345_Read(_DATAZ0);
return Out_z;
}
//ivme sensörünü başlatma
void ACCEL_Start(char *test)
{
// Reset error flag
*test = 0;
// Initialize I2C communication
I2C0_Init_Advanced(100000, &_GPIO_MODULE_I2C0_B23);
TFT_Set_Font(TFT_defaultFont, CL_YELLOW, FO_HORIZONTAL);
TFT_Set_Pen(CL_PURPLE, 1);
TFT_Set_Brush(1, CL_PURPLE, 0, 0, 0, 0);
TFT_Rectangle(0, 0, 320, 22);
TFT_Write_Text("Hosgeldiniz. Ivme Modulu Test Ediliyor.", 5, 6);
Delay_ms(2000);
TFT_Rectangle(0, 0, 320, 22);
// Initialize ADXL345 accelerometer
if (ADXL345_Init() == 0) // _ACCEL_ERROR kodu gelmediyse, 0x00 geldiyse.
{
TFT_Write_Text("Ivme Modulu Basariyla Kuruldu.", 5, 6);
*test = 1;
Delay_ms(2000);
}
else
{
TFT_Write_Text("Ivme Modulunde Bir Hata Meydana Geldi.", 5, 6);
*test = 2;
Delay_ms(2000);
}
TFT_Rectangle(0, 0, 320, 30);
}
//X,Y,Z Verilerini okuyup ortalamasını alma
void Accel_Average(void) {
int i, sx, sy, sz;
// sum
sx = sy = sz = 0;
// average accelerometer reading over last 16 samples
for (i=0; i<16; i++) {
sx += Accel_ReadX();
sy += Accel_ReadY();
sz += Accel_ReadZ();
}
// average
Xvalue = sx >> 4; //4 bit sağa kaydır.
Yvalue = sy >> 4;
Zvalue = sz >> 4;
}
//X değerini Ekranda gösterme
void Display_X_Value(void)
{
TFT_Rectangle(270, 60, 320, 75);
IntToStr(Xvalue, out);
Label4.Caption=out;
DrawLabel(&Label4);
Delay_ms(10);
}
//Y değerini Ekranda gösterme
void Display_Y_Value(void)
{
TFT_Rectangle(270, 120, 320, 135);
IntToStr(Yvalue, out);
Label3.Caption=out;
DrawLabel(&Label3);
Delay_ms(10);
}
//Z değerini Ekranda gösterme
void Display_Z_Value(void)
{
TFT_Rectangle(270, 180, 320, 195);
IntToStr(Zvalue, out);
Label6.Caption=out;
DrawLabel(&Label6);
Delay_ms(10);
}
//ivme sensörünü test etme.
void ACCEL_Test(void)
{
Accel_Average(); // İvme sensörünün X,Y,Z verileri hesaplandı
Display_X_Value(); // Ekranda ortalama X değeri yazıldı.
Display_Y_Value(); // Ekranda ortalama Y değeri yazıldı.
Display_Z_Value(); // Ekranda ortalama Z değeri yazıldı.
Delay_ms(10);
}
//Dikdörtgenin Pozisyonu Güncellendi.
void UpdateRectanglePosition(void)
{
if( Xvalue < 0 )//eğer okunan ortalama x değeri 0'dan küçükse
{
Box1.Left=-Xvalue;
}
else
{
Box1.Left=Xvalue;
}
if( Yvalue < 0 ) //eğer okunan ortalama y değeri 0'dan küçükse
{
Box1.Top=-Yvalue;
}
else
{
Box1.Top=Yvalue;
}
DrawBox(&Box1); //Dikdörtgeni(Kutucuğu) ekranda çizdir.
TFT_Set_Pen(CL_PURPLE, 1); //Kalemi mor renge ayarla, kalınlık 1
TFT_Set_Brush(1, CL_PURPLE, 0, 0, 0, 0); //Fırçayı mor renge ayarla.
}
void main() {
Start_TP(); //touchpanelin tanımlandığı ve kalibrasyon yapılan kısım.
ACCEL_Start(&cACCEL_test_status);//ivme sensörünü başlattık.
//fırça ve kalem rengi ayarladık.
TFT_Set_Pen(CL_PURPLE, 1);
TFT_Set_Brush(1, CL_PURPLE, 0, 0, 0, 0);
while (1) {
Check_TP();
//sonsuza kadar ivmenin değerini ölç kutunun pozisyonunu güncelle
ACCEL_Test();
UpdateRectanglePosition();
}
}
KAYNAKLAR :
1. https://www.sparkfun.com/datasheets/Sensors/Accelerometer/ADXL345.pdf
2. https://gelecegiyazanlar.turkcell.com.tr/konu/arduino/egitim/arduino-401/i2c-protokolu
3. http://libstock.mikroe.com/projects/view/236/mikromedia-for-stellaris-examples
4. http://www.mehmetcemyucel.com/2009/05/buffer-nedirnicin-kullanlr.html
5. http://www.robotistan.com/adxl345-3-eksen-ivme-olcer-triple-axis-accelerometer- breakout-adxl34550>50>
Dostları ilə paylaş: |