본문 바로가기

Android/통신

[안드로이드] 아두이노와 안드로이드 Bluetooth 통신하기

728x90
반응형

 

 

안드로이드 기기와 아두이노 보드간 블루투스 통신 코드를 소개하겠습니다.

아두이노는 블루투스 통신을 위해 HC-06을 사용하였습니다.

먼저 bluetooth 통신을 위해 connect 버튼을 누르면 버튼이벤트를 시작으로 블루투스 연결을 시도하였습니다.

코드를 차근차근 따라해보면 이해가 쉬울 것입니다.

구현한 소스는 안드로이드 기기에서 데이터를 아두이노 보드에 송신하고, 아두이노에서 데이터를 수신하는 코드입니다.

 

특정기기에 자동으로 페어링, 연결 하는 최신 코드를 전부 합하여 포스팅 하였습니다.

[Android/통신] - [안드로이드-아두이노] bluetooth classic 자동 페어링&연결 / 데이터 송,수신

 

 

안드로이드 Bluetooth 연결


  • Manifest 추가
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

먼저, 권한을 위해 AndroidManifest.xml에 추가해주세요.

 

public BluetoothAdapter mBluetoothAdapter;
public Set<BluetoothDevice> mDevices;
private BluetoothSocket bSocket;
private OutputStream mOutputStream;
private InputStream mInputStream;
private BluetoothDevice mRemoteDevice;
public boolean onBT = false;
public byte[] sendByte = new byte[4];
public TextView tvBT;
public ProgressDialog asyncDialog;
private static final int REQUEST_ENABLE_BT = 1;

 

private Button BTButton;
...
BTButton = findViewById(R.id.btnBTCon);
...
BTButton.setOnClickListener(new Button.OnClickListener() {
            @SuppressLint("SetTextI18n")
            @Override
            public void onClick(View view) {
                if (!onBT) { //Connect
                    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
                    if (mBluetoothAdapter == null) { //장치가 블루투스를 지원하지 않는 경우.
                        Toast.makeText(getApplicationContext(), "Bluetooth 지원을 하지 않는 기기입니다.", Toast.LENGTH_SHORT).show();
                    } else { // 장치가 블루투스를 지원하는 경우.
                        if (!mBluetoothAdapter.isEnabled()) {
                            // 블루투스를 지원하지만 비활성 상태인 경우
                            // 블루투스를 활성 상태로 바꾸기 위해 사용자 동의 요청
                            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
                        } else {
                            // 블루투스를 지원하며 활성 상태인 경우
                            // 페어링된 기기 목록을 보여주고 연결할 장치를 선택.
                            Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
                            if (pairedDevices.size() > 0) {
                                // 페어링 된 장치가 있는 경우.
                                selectDevice();
                            } else {
                                // 페어링 된 장치가 없는 경우.
                                Toast.makeText(getApplicationContext(), "먼저 Bluetooth 설정에 들어가 페어링을 진행해 주세요.", Toast.LENGTH_SHORT).show();
                            }

                        }

                    }

                }else{ //DisConnect

                    try {
                        BTSend.interrupt();   // 데이터 송신 쓰레드 종료
                        mInputStream.close();
                        mOutputStream.close();
                        bSocket.close();
                        onBT = false;
                        BTButton.setText("connect");
                    } catch(Exception ignored) { }

                }
            }
        });

먼저 블루투스가 비활성 상태인경우 사용자의 동의를 얻어 활성상태로 바꿉니다.

그다음 페어링 된 기기를 검색하고, 없으면 페어링을 요청 토스트 메시지를 띄웁니다.

페어링된 기기가 있을 경우 장치선택을 위한 selectDevice() 메서드를 실행합니다.

 

public void selectDevice() {
        mDevices = mBluetoothAdapter.getBondedDevices();
        final int mPairedDeviceCount = mDevices.size();

        if (mPairedDeviceCount == 0) {
            //  페어링 된 장치가 없는 경우
            Toast.makeText(getApplicationContext(),"장치를 페어링 해주세요!",Toast.LENGTH_SHORT).show();
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("블루투스 장치 선택");


        // 페어링 된 블루투스 장치의 이름 목록 작성
        List<String> listItems = new ArrayList<>();
        for(BluetoothDevice device : mDevices) {
            listItems.add(device.getName());
        }
            listItems.add("취소");    // 취소 항목 추가

            final CharSequence[] items = listItems.toArray(new CharSequence[listItems.size()]);

            builder.setItems(items,new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int item) {
                    if(item == mPairedDeviceCount) {
                        // 연결할 장치를 선택하지 않고 '취소'를 누른 경우
                        //finish();
                    }
                    else {
                        // 연결할 장치를 선택한 경우
                        // 선택한 장치와 연결을 시도함
                        connectToSelectedDevice(items[item].toString());
                    }
                }
            });


            builder.setCancelable(false);    // 뒤로 가기 버튼 사용 금지
            AlertDialog alert = builder.create();
            alert.show();

    }

블루투스 장치의 이름을 리스트로 작성하여 AlertDiaog를 띄웁니다.

그리고 장치를 선택하면, connectToSelectedDevice 메서드를 실행하여 연결을 시도합니다.

 

 public void connectToSelectedDevice(final String selectedDeviceName) {
        mRemoteDevice = getDeviceFromBondedList(selectedDeviceName);

        //Progress Dialog
        asyncDialog = new ProgressDialog(MainActivity.this);
        asyncDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        asyncDialog.setMessage("블루투스 연결중..");
        asyncDialog.show();
        asyncDialog.setCancelable(false);

        Thread BTConnect = new Thread(new Runnable() {
            public void run() {

                try {
                    UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //HC-06 UUID
                    // 소켓 생성
                    bSocket = mRemoteDevice.createRfcommSocketToServiceRecord(uuid);



                    // RFCOMM 채널을 통한 연결
                    bSocket.connect();

                    // 데이터 송수신을 위한 스트림 열기
                    mOutputStream = bSocket.getOutputStream();
                    mInputStream = bSocket.getInputStream();


                    runOnUiThread(new Runnable() {
                        @SuppressLint({"ShowToast", "SetTextI18n"})
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(),selectedDeviceName + " 연결 완료",Toast.LENGTH_LONG).show();
                            tvBT.setText(selectedDeviceName + " Connected");
                            BTButton.setText("disconnect");
                            asyncDialog.dismiss();
                        }
                    });

                    onBT = true;


                }catch(Exception e) {
                    // 블루투스 연결 중 오류 발생
                    runOnUiThread(new Runnable() {
                        @SuppressLint({"ShowToast", "SetTextI18n"})
                        @Override
                        public void run() {
                            tvBT.setText("연결 오류 -- BT 상태 확인해주세요.");
                            asyncDialog.dismiss();
                            Toast.makeText(getApplicationContext(),"블루투스 연결 오류",Toast.LENGTH_SHORT).show();
                        }
                    });

                }


            }
        });
        BTConnect.start();

 
    }

    public BluetoothDevice getDeviceFromBondedList(String name) {
        BluetoothDevice selectedDevice = null;

        for(BluetoothDevice device : mDevices) {
            if(name.equals(device.getName())) {
                selectedDevice = device;
                break;
            }
        }
        return selectedDevice;
    }

 

블루투스 연결 메서드입니다.

연결중이라는 dialog를 띄우고, HC-06과 연결해야하므로 HC-06 UUID를 사용해 소켓통신을 하였습니다.

또한 데이터 송/수신을 이용해야 하므로 Input,Output Stream도 열어주었습니다. (나중에 닫아주는것 잊지말것.)

 


Bluetooth 데이터 송신


 Thread BTSend  = new Thread(new Runnable() {
        public void run() {
            try {
                mOutputStream.write(sendByte);    // 프로토콜 전송
            } catch (Exception e) {
                // 문자열 전송 도중 오류가 발생한 경우.
            }
        }
    });

    //fixme : 데이터 전송
    public void sendbtData(int btLightPercent) throws IOException {
        //sendBuffer.order(ByteOrder.LITTLE_ENDIAN);
        byte[] bytes = new byte[4];
        bytes[0] = (byte) 0xa5;
        bytes[1] = (byte) 0x5a;
        bytes[2] = 1; //command
        bytes[3] = (byte) btLightPercent;
        sendByte = bytes;
        BTSend.run();
    }

저는 4byte 프로토콜의 데이터 송신이 가능한 메서드를 만들어 프로토콜을 아두이노에 송신하였습니다.

 


 

아두이노 데이터 수신 코드


 

#include <SoftwareSerial.h>  // 블루투스 통신을 위해 include 시킴



const int pinTx = 5;  // 블루투스 TX 연결 핀 번호
const int pinRx = 3;  // 블루투스 RX 연결 핀 번호

SoftwareSerial   bluetooth( pinTx, pinRx );  // 블루투스 통신의 송수신 핀 설정




void  setup()
{
    
  bluetooth.begin( 9600 );  // 블루투스 통신 초기화 (속도= 9600 bps)
  Serial.begin(115200);
  
}


void  loop()
{  
  int  rxData;  // 블루투스 수신 데이터
  
  if( bluetooth.available() )  // 블루투스 수신 데이터가 있으면
  {
    rxData = bluetooth.read();  // 블루투스 수신 데이터 읽기
    
    if( bluetooth.read() == 0xA5)
    {
      if( bluetooth.read() == 0x5A )
      {
        if( bluetooth.read() == 0x01 )
        {
          int r = bluetooth.read();
          Serial.print(r);        
        }
      }
    }
  }
  else
  {
    delay( 10 );
  }
}

수신된 데이터를 아두이노에서 시리얼 모니터에 출력해보았습니다.

프로토콜은 header 2바이트, command 1바이트, 데이터 1바이트 입니다.


 

 

728x90
반응형