[라즈베리파이 강좌] 안드로이드 씽스(Android Things) 시작하기 - 3.2 LED & 버튼 예제

메카 2017-11-20 (월) 23:08 7개월전 564  


 

라즈베리파이 강좌

  안드로이드 씽스(Android Things) 시작하기 - 3.2 LED & 버튼 예제






  안녕하세요. 메카솔루션 알도입니다.

  오늘은 안드로이드 씽스(Android Things)로 버튼으로 LED를 제어하는 예제 프로그램을 만들어보겠습니다. 아두이노의 가장 첫 예제가 LED 켜기인 것처럼 안드로이드 씽스도 LED 켜기로 시작하게 되었습니다. 사용되는 언어는 같은 JAVA이지만 안드로이드는 교육보다는 실제 제품을 개발하고 배포하는 것이 목적이기 때문에 , 하나의 파일에 코드 몇 줄만 쓰면 되는 아두이노와 달리, 조금 더 복잡하고 어렵습니다. 하지만 훨씬 더 폭넓고 깊이 있는 프로그래밍의 세계로 가시는 기회가 될 수 있기 때문에 포기하지 않고 계속 도전하시기 바랍니다.



  지난 포스트에서는 주기적으로 LED를 껐다 켜기는 반복하는 앱을 만들었었습니다. 이번 포스트에서는 버튼으로 입력을 받아서, LED를 켜고 끄는 예제를 만들어 보겠습니다.

  이 포스트의 내용은 Button and LED sample for Android Things의 내용을 참고하여 작성하였습니다.


 


 

     LED & 버튼 예제


준비물

  이번 강좌를 위해서는 다음과 같은 준비물들이 필요합니다.


    - 라즈베리파이 3

    - Micro USB 전원

    - 모니터(필수는 아닙니다.)

    - 다음 셋 중 하나는 반드시 필요합니다.

시리얼 컨버터

공유기 + 랜선

랜카드(이더넷 포트) + 랜선


  또한 아두이노에는 13번 핀과 시리얼 TX/RX 핀에 테스트용 LED가 달려있지만 라즈베리파이에는 그런 것이 없기 때문에 별도의 LED와 이를 연결하기 위한 점프 케이블/빵판 등이 필요합니다.





빵판 1개

LED 1개

푸쉬 버튼

330Ω 저항 2개

M-F(수-암) 점퍼



  안드로이스 씽스를 준비하는 방법은 아래 포스트를 참고하세요.


    [라즈베리파이 강좌] 안드로이드 씽스(Android Things) 시작하기 - 1.1 시리얼로 초기화하기

    [라즈베리파이 강좌] 안드로이드 씽스(Android Things) 시작하기 - 1.2 공유기를 통해 초기화하기

    [라즈베리파이 강좌] 안드로이드 씽스(Android Things) 시작하기 - 1.3 직접 연결하여 초기화하기


  초기 연결과 프로젝트 생성/업로드 부분은 아래를 참고하세요.


    [라즈베리파이 강좌] 안드로이드 씽스(Android Things) 시작하기 2. Hello World


  지난 포스트인 LED를 주기적으로 켜고 끄기는 아래를 참고하세요.


    [라즈베리파이 강좌] 안드로이드 씽스(Android Things) 시작하기 - 3.1 LED & 버튼 예제



회로 연결하기

  아래와 같이 회로를 구성합니다. 우측의 GPIO 핀 배치도와 함께 보면 회로를 이해하시는데 더 도움이 됩니다.


 



  브레드 보드의

    VCC는 GPIO의 5V

    GND는 GPIO의 GND

    푸시 버튼의 녹색선은 GPIO의 GPIO21

    LED로 가는 파란선은 GPIO6

  에 연결됩니다.



프로젝트 설정

그래들 설정

  dependencies에 다음을 추가합니다. LED 켜고 끄기와 다르게 버튼 드라이버도 필요하게 됩니다.


dependencies {

    ...


    compile 'com.google.android.things.contrib:driver-button:0.4'

    provided 'com.google.android.things:androidthings:0.5.1-devpreview'

}


 


매니페스트 설정

  매니페스트에 다음을 추가합니다. 먼저 버튼 드라이버를 사용하기 위해 승인을 요청합니다.


<manifest>

    <uses-permission android:name="com.google.android.things.permission.MANAGE_INPUT_DRIVERS" />


    ...

</manifest>


  안드로이드 폰에서는 앱에서 요청을 할 때 사용자에게 허용할 것인지 물어보지만, 안드로이드 씽스에서는 스크린이나 기타 입출력 장치가 없는 경우가 있고, 애초에 장치 개발을 목적으로 하기 때문에 허용이 무의미해서 물어보지는 않습니다만, 앱이 작동하지는 않습니다. 승인이 필요한 경우 안드로이드 씽스에서는 재부팅을 하면 승인이 되어 있게 됩니다. 재부팅은 간단하게 라즈베리파이에 연결된 전원을 제거 후 재연결하거나, 프롬프트에서 adb reboot 명령을 입력하면 됩니다.

  이전 포스트에서와 마찬가지로 안드로이드 씽스 라이브러리를 사용하겠다고 선언해줍니다.


<application>

    <uses-library android:name="com.google.android.things"/>


    ...

</application>




코드 작성하기

  코드는 이전 포스트의 내용과 유사한 것이 있으나, 버튼 드라이버를 추가하는 것과, 쓰레드가 아닌 버튼이 눌리는 시점을 이벤트로 처리하는 키다운 이벤트 함수가 사용됩니다. 


멤버 객체/변수 작성

  멤버 객체/변수는 이전의 Gpio 클래스의 LedGpio 객체와 부울 변수 LedVal만 사용하던 것에서 ButtonInputDriver 클래스의 객체가 추가됩니다.

private ButtonInputDriver mButtonInputDriver;
private Gpio mLedGpio;
private boolean mLedVal = true;


멤버 객체 초기화

  초기화는 마찬가지로 onCreate 함수에서 실행되며 이전 코드에서 ButtonInputDriver의 초기화가 추가됩니다. 초기화 값은 우선 버튼에 연결된 핀인 BCM21, 핀의 디지털 값이 LOW일 때가 버튼이 눌린 것으로 지정, 마지막으로 버튼을 스페이스(키보드에서 스페이스)로 지정하였습니다. 만약 안드로이드 씽스에 키보드가 연결되어 있다면 스페이스 키를 눌렀을 때 버튼을 누른 것으로 인식하게 됩니다. 마지막으로 레지스터 함수를 통해 등록을 합니다.


PeripheralManagerService pioService = new PeripheralManagerService();


try {

    mLedGpio = pioService.openGpio("BCM6");

    mLedGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);

    mLedGpio.setValue(true);

} catch (IOException e) {}


try {

    mButtonInputDriver = new ButtonInputDriver(

        "BCM21",

        Button.LogicState.PRESSED_WHEN_LOW,

        KeyEvent.KEYCODE_SPACE);

        mButtonInputDriver.register();

} catch (IOException e) {}



멤버 함수 작성

  버튼이나 스크린 터치는 필수적으로 사용되는 기능이기 때문에 Activity 클래스에 내장이 되어 있습니다. 여러분들이 할 일은 이 내장된 함수 onKeyDown을 상속 받아서 필요한 기능만 넣는 것입니다. 우선 이 onKeyDown 함수는 어떤 버튼이든 시스템에 등록된 버튼이 눌리거나 떼었을 때 실행되며, 어떤 키인지는 함수의 매개변수인 keyCode를 통해서 알 수 있습니다. LED를 제어하는 함수는 이전 포스트의 그것을 그대로 이용하였습니다. 


@Override

public boolean onKeyDown(int keyCode, KeyEvent event) {

    if (keyCode == KeyEvent.KEYCODE_SPACE) {

        try {

            if (mLedVal) {

                mLedGpio.setValue(false);

                mLedVal = false;

            } else {

                mLedGpio.setValue(true);

                mLedVal = true;

            }

        } catch (IOException e) {}

        return true;

    }


    return super.onKeyDown(keyCode, event);

}



전체 코드

  아래는 MainActivity.java 파일의 전체 내용입니다. 맨 위의 패키지 부분은 혼란의 여유가 있어서 포함시키지 않았습니다.


import android.app.Activity;

import android.os.Bundle;

import android.view.KeyEvent;


import com.google.android.things.contrib.driver.button.Button;

import com.google.android.things.contrib.driver.button.ButtonInputDriver;

import com.google.android.things.pio.Gpio;

import com.google.android.things.pio.PeripheralManagerService;


import java.io.IOException;


public class MainActivity extends Activity {

    private ButtonInputDriver mButtonInputDriver;

    private Gpio mLedGpio;

    private boolean mLedVal = true;


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);


        PeripheralManagerService pioService = new PeripheralManagerService();


        try {

            mLedGpio = pioService.openGpio("BCM6");

            mLedGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);

            mLedGpio.setValue(true);

        } catch (IOException e) {}


        try {

            mButtonInputDriver = new ButtonInputDriver(

                    "BCM21",

                    Button.LogicState.PRESSED_WHEN_LOW,

                    KeyEvent.KEYCODE_SPACE);

            mButtonInputDriver.register();

        } catch (IOException e) {}

    }


    @Override

    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if (keyCode == KeyEvent.KEYCODE_SPACE) {

            try {

                if (mLedVal) {

                    mLedGpio.setValue(false);

                    mLedVal = false;

                } else {

                    mLedGpio.setValue(true);

                    mLedVal = true;

                }

            } catch (IOException e) {}

            return true;

        }


        return super.onKeyDown(keyCode, event);

    }

}



작동 영상



모바일 버전으로 보기