יום שבת, 22 ביוני 2013

Arduino BlueTooth Guide




חשבתי לעצמי שאם כבר דיברנו על BlueTooth למה לא לשלב את Arduino בעניין, בעזרת Android נשלוט ב Arduino ונפעיל רכיבים עם חיבור סיראלי שעובר דרך ה BlueTooth, חיפשתי באינטרנט רכיב זול ואמין שיעשה את העבודה ומצאתי אותו ב  DX.com תמורת 6 דולר.



Wireless Bluetooth V2.0 RS232 TTL Transceiver Module

בסה"כ מדובר במודול מאוד פשוט, העבודה עם 4 פינים בלבד (1,2,12,13) , יש צורך להשתמש בספרייה NewSoftSerial על מנת שנוכל לדמות Uart נוסף עבור ה BlueTooth וצריך לעשות הצלבה בין ה RX וה TX של המודול מול הפינים שהגדרנו ב NewSoftSerial.


תמורת 2 דולר נוספים ניתן לקבל לוח שכולל את המודול, יחד עם פינים ו Led אדום שמהבהב שזה בהחלט משתלם ממקום שנבנה אותו בעצמנו.

שימו לב - המודול עובד על 3.3 V שימוש ב 5V עלול לשרוף אותו.

דרישות:
  • Arduino Uno / Nano
  • Wireless Bluetooth V2.0 RS232 TTL Transceiver Module
  • Wires
  • Android Tablet / Phone Support BlueTooth.
  • Servo


זאת הפעם הראשונה שאני משתמש ב Arduino Nano בבלוג, אין הבדל בהתנהגות שלו לבין ה Uno רק צריך להשים לב שיש פחות חיבורים ולהגדיר את הלוח בסביבה כפי שניתן לראות בדוגמה:



יש להגדיר את חוקי הדיבור בין ה Android ל Arduino, ההגדרה בקוד שאם מגיעה האות F ה Servo יתקדם קדימה ואם תגיע האות B ה Servo יתקדם אחורה בין כל בקשה ניכנס ל Delay של 25 ms על מנת לאפשר ל Servo לנוע.

קוד:

#include <NewSoftSerial.h>
#include <Servo.h> 

//break state
byte stateHold = false;
//forward state
byte stateForward = false;
//reverse state
byte stateReverse = false;

//commands: 
//F  = Servo move forward
//B = Servo move Backward
char FWDCMD = 'F';
char BWDCMD = 'B';

//Bluetooth section over software serial
//Arduino RX - 7 ,Arduino TX  - 6
NewSoftSerial bluetooth(7, 6);
byte b;

//Servo section
int servoPin = 3;
Servo myservo;

void setup() {
  //arduino serial for debugging
  Serial.begin(9600);   // opens serial port, sets data rate to 9600 bps
  Serial.flush();
  
  //attach servo to servo pin
   myservo.attach(servoPin);
   
  bluetooth.begin(9600);
  Serial.println("set bluetooth success");
}

void loop() {

  if (bluetooth.available()) {
    Serial.print("Android Send:");
    b = bluetooth.read();
    
    if((char)b == FWDCMD)
    {
        stateForward = true;
        stateHold = false;
        servoState();
        stateHold = true;
    
    }
    else if ((char)b == BWDCMD)
   {
       stateReverse = true;
        stateHold = false;
        servoState();
        stateHold = true;
   }   
   
    //print command in serial for debugging
    Serial.println((char)bluetooth.read(),BYTE);
    b = '\0';
  }
}


//change servo rotation by command
void servoState()
{
  if(stateHold == false)
    {
        myservo.attach(servoPin);
        if(stateForward == true)
        {
          stateReverse = false;
          myservo.write(0);
           delay(25);
           stateForward = false;
        }
        
        if(stateReverse == true)
        {
          stateForward = false;
           myservo.write(360);
           delay(25);
           stateReverse = false;
          
        }
        
         myservo.detach();
    }
}

מבנה סופי:



Android

אני לא אחזור על דברים מהמאמר הקודם אבל צריך להשים לב למספר דברים בקוד, קודם כל ה Android צריך למצוא את ה Device ואח"כ להתחבר אליו עם UUID שמייצג תקשורת סיראלית, לאחר מכן נפתח Socket בין המכשיר ל Device, מעבירים את פקודות הדיבור שנקבעו מראש שדרכם נתקשר עם ה Arduino שבסופו של דבר יגרום ל Servo לזוז, בנוסף למחלקה BTClient שמבוססת על AsyncTask אנחנו נשתמש בכלי מקבילי נוסף שנקרא Runnable על מנת שנוכל לתכנת את התנהגות הכפתורים.


קוד:

package com.proxytypeblog.arduinobtapp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageButton;

public class MainActivity extends Activity {

private static final String TAG = "Activity";
BluetoothAdapter mBluetoothAdapter;
BTClient _client;
BluetoothDevice mDevice;

boolean flag = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

boolean check = loadBlueTooth();
if (!check) {
Log.e(TAG, "Error to connect bluetooth");
}

setForwardButton();
setBackwardButton();
}

private void setBackwardButton() {
ImageButton btn_backward = (ImageButton) findViewById(R.id.btn_backward);
btn_backward.setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
flag = true;
new Thread(new Runnable() {
public void run() {
while (flag) {
try {
//make sleep like arduino
Thread.sleep(25);
//char B for backward servo
_client.write("B");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
break;
case MotionEvent.ACTION_UP:
flag = false;
break;

default:
break;
}

return false;
}
});
}

private void setForwardButton() {
ImageButton btn_forward = (ImageButton) findViewById(R.id.btn_forward);

btn_forward.setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
flag = true;

new Thread(new Runnable() {
public void run() {
while (flag) {
try {
//make sleep like arduino
Thread.sleep(25);
//char F for forward servo
_client.write("F");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
break;
case MotionEvent.ACTION_UP:
flag = false;
break;

default:
break;
}

return false;
}
});

}

private boolean loadBlueTooth() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
return false;
}

mBluetoothAdapter.startDiscovery();
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter
.getBondedDevices();

if (pairedDevices.size() > 0) {

for (BluetoothDevice device : pairedDevices) {

// the device i want to connect.
if (device.getName().contains("linvor"))
mDevice = device;

Log.d(TAG, device.getName());
}
}

// UUID service for serial
_client = new BTClient(mDevice, "00001101-0000-1000-8000-00805F9B34FB");
_client.execute("");

return true;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

private class BTClient extends AsyncTask<String, String, String> {
private final String TAG = "AsyncTask";
private BluetoothSocket mmSocket;
private BluetoothDevice mmDevice;
private BluetoothAdapter mBluetoothAdapter;
private InputStream mmInStream;
private OutputStream mmOutStream;
private UUID mmUUID;

// getting the device with application unique key
public BTClient(BluetoothDevice device, String CODE) {
mmUUID = UUID.fromString(CODE);
mmDevice = device;
BluetoothSocket tmp = null;

// getting the your own device adpater
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

// try to create a socket
try {
tmp = device.createRfcommSocketToServiceRecord(mmUUID);
} catch (IOException e) {
e.printStackTrace();
}

mmSocket = tmp;

}

@Override
protected String doInBackground(String... params) {

// if the our adapter on discovering, cancel it
if (mBluetoothAdapter.isDiscovering())
mBluetoothAdapter.cancelDiscovery();

try {
// make the connection and collect the stream
mmSocket.connect();
mmInStream = mmSocket.getInputStream();
mmOutStream = mmSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}

String message = "";
int bytes;
byte[] buffer = new byte[1];
// keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
message = new String(buffer, 0, bytes);
mmSocket.getInputStream();

} catch (IOException e) {
Log.e(TAG, "disconnected", e);
break;
}
}

return null;
}

// write message to outputstream
public void write(String msg) {

try {
byte[] buffer = msg.getBytes("US-ASCII");
if (mmOutStream != null)
mmOutStream.write(buffer);

} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}

@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}

}
}


ממשק:



סרט דוגמה:




קבצי מקור:

https://sourceforge.net/projects/arduinobluetoot/

סיכום:

החודש הזה הוקדש ל BlueTooth וראינו כיצד לדבר אחד עם השני בפלטפורמות שונות, שילוב BlueTooth בפרוייקטים שלנו מאפשר לנו לשלוט בכל רכיב שנרצה במערכת בתנאי שהוא בטווח כמובן, וזו דרך יעילה וזולה להתנתק מהחוטים.

בהצלחה...

אין תגובות:

הוסף רשומת תגובה