8 Nisan 2014 Salı

Mobil Sistemlerde Android Tabanlı Motor Kontrolü

Merhabalar
Adından da anlaşılacağı gibi bu proje kapsamında android işletim sistemini kullanan akıllı cihaz ile ARM Cortex M4 çekirdeğine sahip STM32F4 geliştirme kiti arasında haberleşme sağlanacaktır.

Proje tasarım olarak iki temel kısımdan meydana gelmektedir. İlk kısım android işletim sistemini kullanan akıllı telefon için yazılacak uygulamadan oluşmaktadır. Uygulama akıllı tefonda çalışacak ve temel olarak bluetooth birimini kullanarak veri gönderimi gerçekleştirecektir. İkinci kısımda ise ARM işlemci çekirdeğine yazılan kodlar ve kit-motor bağlantıları sunulması amaçlanmıştır. Android
uygulaması Java programlama dili ile Eclipse editöründe ADT eklentisi kullanılarak yazılmıştır. ARM işlemci mimarileri ve STM32F4 Discovery kart hakkındaki inceleme bilgileri internette bol miktarda mevcut olduğundan bu konu üzerinde durmayıp uygulamaya giriş yapmakta fayda görüyorum.

Aşağıda sistemin blok diyagramı görülmektedir.



Akıllı cihazdan gönderilen verileri Stm32f4 kitte bulunan işlemcide yorumlanarak motor yön kontroleri yapılmıştır. Blok diyagramdan da anlaşılacağı gibi sistem temel olarak tek yönlü bir iletişime sahiptir.

Akıllı Cihaz Bloğu
Android işletim sistemine sahip akıllı cihazda çalıştırılacak uygulama bu blokta yer alır. Eclipse' te yazılan uygulamanın derlenerek oluşturulan .apk uzantılı dosyanın telefonda çalıştırılmasıyla bağlantı kurularak veri gönderimi başlatılabilir. Akıllı cihaz üzerinde çalıştırılacak kontrol uygulaması için hazırladığım arayüz aşağıdaki gibidir.



Uygulamada “BLUETOOTH AÇ", "BAĞLAN", "STOP" ve 4 adet yön tuşu bulunmaktadır. "BLUETOOTH AÇ" butonu ile cihaz üzerinde bulunan bluetooth donanımı aktif hale getirilerek iletişime hazır hale getirilir. "BAĞLAN" butonu ile ise Stm32f4 üzerinde bluetooth haberleşmesini sağlayacak olan HC serisi HC-05 bluetooth modülünün mac adresi ile modüle bağlanılır. Eşleşme sonrasında ortam veri iletimine hazırdır ve artık yön tuşlarıyla veri gönderimi başlatılabilir.   

Stm32f4 Üzerinde İşlemler

Blok diyagramdan görüldüğü üzere akıllı cihazdan bluetooth aracılığı ile veri alımı gerçekleşmektedir. Bu haberleşme için HC-05 bluetooth modülü kullanılmıştır. Modülün temel olarak kullanılan uçları Tx ve  Rx  uçlarıdır. Modül hem master hem de slave modda çalışabilmekte ve geniş iletişim hızına uygun kullanılabilmektedir. Çalışma modu ve iletişim hızı gibi parametrelerini değiştirmek için AT komutları kullanılır.
Kullandığım HC-05 bluetooth modülü isim olarak "HC 05" adında ve mac adresi ise 20:13:06:19:33:13' dir. Uygulamadan bağlantı isteği gönderildiğinde girilmesi istenilen doğru şifre "1234" tür. Şifre ve isim yine AT komutlarıyla değiştirilebilir.
HC-05 bluetooth modülünün Tx ucu STM32F4' te PB7, Rx ucu ise PB6 pinine bağlanmıştır. Burada dikkat edilmesi gereken husus çapraz bağlantıdır. Modülün Tx i kitte USART biriminin Rx ine, yine modülün Rx i kitin USART biriminin Tx ine bağlanması 
HC-05 bluetooth modülden alınan verilere göre yön tayini yapılır. Örneğin gelen veri 'F' ise ileri, 'B' ise geri, 'R' ise sağa, 'L' ise sola dönüş istenmektedir. İleri yönde komut geldiğinde PD7 pini set edilerek 1 e kurulur ve aynı şekilde geri hareket için PD1, sağ için PD3, sol için ise PD5 pinleri set edilir. Burada dikkat edilmesi gereken nokta ise hem ileri hemde geri hareket için ilgili bitlerin aynı anda lojik 1 olmasını engellemektir. Bunun için bir hareketi başlatmadan önce diğer hareketin ilgili pini reset edilerek lojik 0 a çekilmiştir. Örneğin geri yönde bir hareket başalayacağı zaman PD1 biti set edilmeden önce PD7 lojik 0 a çekilmiştir.
STM32F4 kitin beslemesi için 9 volt pil kullanılmıştır. 9 volt L7805CV entegresi ile 5 volta regüle edilmiştir.

L293D İle Motor Sürücü Devresi
L293D motor sürücü entegresi kullanılarak motor hareketleri sağlanmıştır. Entegre 5 volt ile beslenmiştir ancak motor dönüşleri için 9 volt giriş verilmiştir. 

 L293D entegresi içerisinde iki adet H köprüsü bulundurur ve iki adet motoru ayrı ayrı sürebilir. İleri ve geri yön hareketleri için bir H köprüsü, sağ ve sol için ise diğer H köprüsü kullanılmıştır. Motor girişlerine önceki konuda bahsettiğimiz yön pinleri bağlanmıştır. Ayrıntılı için katalog bilgileri incelenebilir.

Gerekli kod blokları ise aşağıdadır.

Android Uygulaması Kod Bloğu
 
Bluetooth ControlActivity Sınıfı

public class BluetoothControlActivity extends Activity {
/* Buton Tanımlama*/
public Button ileri, geri, sag, sol, calistir, list;
/*BA Adında Bluetooth Adaptörü Oluşturma */
BluetoothAdapter BA = BluetoothAdapter.getDefaultAdapter();
public boolean connected = false; // Bağlantı Durum Kontrolü
BluetoothSocket sock; // Bağlantı İçin Socket
char DATA;// Gönderilecek Veri Değişkeni
OutputStream mmOutStream;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bluetooth_control_layout);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
/*Butonlara İlgili ID lerinin Verilmesi*/
ileri = (Button) findViewById(R.id.ileriButon);
geri = (Button) findViewById(R.id.geriButon);
sag = (Button) findViewById(R.id.sagButon);
sol = (Button) findViewById(R.id.solButon);
calistir = (Button) findViewById(R.id.calistirButon);
}
/*İleri Buton OnClick Metodu */
public void ileri_method(View v) {
try{
new Task().execute('F');
}
catch(Exception e){
Toast.makeText(getApplicationContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
/*Sağ Buton OnClick Metodu */
public void sag_method(View v) {
new Task().execute('R');
}
/*Sol Buton OnClick Metodu */
public void sol_method(View v) {
new Task().execute('L');
}
/*Geri Buton OnClick Metodu */
public void geri_method(View v) {
new Task().execute('B');
}
/*Bluetooth ile Bağlan*/
public void baglanButon(View v) throws Exception {
onConnect();
}
/*Cihazda Bluetooth Açma */
public void calistir_method(View v) {
BluetoothConnect con = new BluetoothConnect();
con.openBT();
}
public void OFF(View v) {
if (BA.isEnabled()) {
BA.disable();
Toast.makeText(getApplicationContext(), "Bluetooth Kapatıldı",
Toast.LENGTH_SHORT).show();
} else
Toast.makeText(getApplicationContext(),
"Bluetooth Zaten Kapalı Durumda", Toast.LENGTH_SHORT)
.show();
}
/*Bluetooth Bağlantısı İçin onConnect Metodu ve Kod Bloğu*/
public void onConnect() {
if (connected) {
return;
}
try {
BluetoothDevice BD = BA.getRemoteDevice("20:13:06:19:33:13");
Method m = BD.getClass().getMethod("createRfcommSocket",
new Class[] { int.class });
sock = (BluetoothSocket) m.invoke(BD, Integer.valueOf(1));
sock.connect();
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
/*Dış Dünya İle İletişim İçin Gerekli AsenkronTask Metodu*/
public class Task extends AsyncTask{

@Override
protected Void doInBackground(Character... params) {
try {
mmOutStream = sock.getOutputStream();
mmOutStream.write(params[0]);
} catch (IOException e) {
Toast.makeText(getApplicationContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();}
return null;
}
} 
5.1.2 BluetoothConnect Sınıfı
public class BluetoothConnect extends BluetoothControlActivity {
private BluetoothSocket sock;
private InputStream in;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bluetooth_control_layout);
}
/*Cihazın Bluetooth Aktifleştirmek İçin Gerekli Metot */
public boolean openBT(){
if(BA != null){
boolean isEnabled = BA.isEnabled();
if (!isEnabled) {
connected=true;
return BA.enable();
}
else if(isEnabled) {
return BA.disable();
}
}
return false;
}
/*Socketin Kapatılması*/
@Override
public void onDestroy() {
try {
if (in != null) {
in.close();
}
if (sock != null) {
sock.close();
}
} catch (IOException e) {
e.printStackTrace();
}
super.onDestroy();
}
} 

Stm32f4 Kod Bloğu

#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
void UART_GPIOInitialize(){
GPIO_InitTypeDef GPIO_InitStructure; //GPIO için structure tanımlama
/* B ve D portları için clockları aktif yapma*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
 /* B portunun 6.pini alternatif yaparak USART1_Tx e bağla */
 GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);

/* B portunun 7. pinini alternatif fonksiyon ile USART1_Rx e bağla*/
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);

/*GPIOD için ayarlar*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType= GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD,&GPIO_InitStructure);

/*USART1 Tx = PB6
* USART1 Rx = PB7*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/*UART Birimi*/
void UART_Initialize(void) {
USART_InitTypeDef USART_InitStructure;

/* USART1 için çevresel clock sinyalini aktif etme*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); 

/* USART1 Seri İletişim Konfigrasyonu Bloğu*/
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);

/* USART1 i aktifleştir */
USART_Cmd(USART1, ENABLE);
}
int main(void) {
char ch; // gelen verinin alındığı değişken

UART_GPIOInitialize();
UART_Initialize();
/*Başlangıçta Tüm Motor Uçları Pasif*/
GPIO_ResetBits(GPIOD,GPIO_Pin_3);
GPIO_ResetBits(GPIOD,GPIO_Pin_5);
GPIO_ResetBits(GPIOD,GPIO_Pin_7);
GPIO_ResetBits(GPIOD,GPIO_Pin_1);
USART_SendData(USART1,OK);
  
while (1) {
/* Veri Gelene Kadar Bekle*/
while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET) {
}
/*Gelen Veri Değerlendirme Bloğu
*F: İleri Yönde Hareket
*B: Geri Yönde Hareket
*R: Sağa Dönüş
*L: Sola Dönüş*/1
if(ch=='F'){
GPIO_ResetBits(GPIOD,GPIO_Pin_1);
GPIO_SetBits(GPIOD,GPIO_Pin_7);
USART_SendData(USART1, ch);
}
if(ch=='B'){
GPIO_ResetBits(GPIOD,GPIO_Pin_7);
GPIO_SetBits(GPIOD,GPIO_Pin_1);
USART_SendData(USART1, ch);
}
if(ch=='R'){
GPIO_ResetBits(GPIOD,GPIO_Pin_5);
GPIO_SetBits(GPIOD,GPIO_Pin_3);
USART_SendData(USART1, ch);
}
if(ch=='L'){
GPIO_ResetBits(GPIOD,GPIO_Pin_3);
GPIO_SetBits(GPIOD,GPIO_Pin_5);
USART_SendData(USART1, ch);
}
/*Veri Gönderimi Bitene Kadar Bekle*/
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {
}
}
}

Sonuçlar 

Bu projede, ARM işlemci mimarisi üzerinde, akıllı cihazdan bluetooth ile gelen verilere göre motor kontrolü konusu sunulmuştur. İşlemcinin PB6  ve PB7 uçları kullanılarak veri alma ve gönderme sağlanmıştır. İşlemcide HC-05 bluetooth modülünden gelen veriler incelenerek motorlar L293D motor sürücü entegresi üzerinden sürülmüştür.

Android uygulama akıllı cihazda çalıştırıldığında cihazın bluetooth açılarak bağlantı gerçekleştirilmek istendiğinde "BAĞLAN" butonuna basıldığında uygulama direk olarak HC-05 modülüne bağlanacaktır. Eğer daha önce eşleşme sağlanmamış ise önceki konularda bahsettiğimiz gibi şifre isteyecektir. Şifrenin girilmesinin ardından eşleşmenin başarılı olduğunu 2Hz aralıklarla yanıp sönen led ile modül bildirir.

STM32F4 kite besleme güçü verildiğinde main fonksiyonuna girecek ve seri iletişim ve port konfigürasyonları otomatik olarak yapılacaktır. İletişim hızı 9600 baudrate olarak ayarlanmıştır.

Projede temel amacı herhangi bir ek donanıma gerek kalmaksızın günlük yaşantıda büyük yer sahibi olan akıllı cihazları kullanarak motor kontrolü sağlamaktır. Aynı zamanda bu proje geliştirilerek çeşitli otomatik kontrol mekanizmalarında kullanılabilir.

Proje geliştirilmeye açık bir yöntem izlenerek tasarlanmıştır. Bir çok özellik daha eklenerek projenin kullanım alanları ve özellikleri geliştirilebilir. Örneğin kontrol edilmesi istenen bir vana yada otomatik garaj kapısını, yalnızca son kullanıcının cep  telefonu yada tableti ile uygulamayı kullanarak kontrol edebilmesi gerçekleştirilebilir. Proje aynı zamanda robot teknolojisinede entegre edilerek robot kol hareketleri akıllı cihazlar üzerinden gerçekleştirilebilir.

Android üzerinde çalışırken tasarımda yardımcı olan Davut DURGUN' a ve desteğini esirgemeyen İhsan BAL' a teşekkürlerimi sunuyorum.