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

알도 2017-11-15 (수) 17:48 7년전 3942  


 

라즈베리파이 강좌

  안드로이드 씽스(Android Things) 시작하기 - 3.1 LED 예제






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

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



  이번 포스트에서는 지난 번에 생성한 기본 프로젝트에서 GPIO를 통해 버튼으로 입력을 받고, 출력으로 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



회로 연결하기

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


 



  브레드 보드의

    VCC는 GPIO의 5V

    GND는 GPIO의 GND

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

    LED로 가는 파란선은 GPIO6

  에 연결됩니다.



안드로이드 씽스 프로젝트 만들기

  먼저 프로젝트를 생성합니다. 프로젝트 생성은 아래 링크를 참조하시면 됩니다.


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


  프로젝트가 생성되면, 그래들(Gradle) 파일과 매니페스트(manifest) 파일을 수정해줘야 합니다.


그래들이란?

  그래들이란 빌드 도구입니다. 아두이노와 비교하면,  툴에서 우노인지 미니인지, 보드와 프로세서를 선택했던 것과 같다고 생각하시면 됩니다. 안드로이드의 경우 지원할 안드로이드의 버전이 몇인지? 어떤 라이브러리들을 사용할 것인지? 등등을 입력해주게 되는데, 이번의 경우 GPIO 같은 안드로이드 폰에는 없는 기능을 사용하기 위해 안드로이드 씽스 라이브러리를 불러와야 합니다. 아래와 같이 그래들 파일을 열어서 아래 코드를 입력해 줍니다.



  아래 코드를 그림과 같이 dependencies 안에 넣어줍니다.


dependencies {

    ....


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

}



  위 그림과 같이 입력을 했으면, 아래 그림처럼 Sync Project with Gradle Files 버튼을 눌러줍니다.




  그래들(Gradle) 파일이 프로젝트와 동기화(Sync)되면 코딩을 하는 과정에서 추가된 라이브러리의 클래스나 함수 등을 프로그램이 인식하고 자동 완성 해주기 때문에 코딩을 더 편하게 할 수 있습니다.


매니페스트란?

  매니페스트 파일은 매우 광범위한 범위의 일을 하는데요. 기본적인 설명은 "안드로이드 시스템이 앱을 실행하기 전에 확보해야하는 앱에 대한 필요 정보를 시스템에 제공한다"입니다. 한마디로 설명하기 매우 어려운데요.. 우선 누구나 쉽게 느낄 수 있는 부분으로는 스마트 폰에 앱을 설치했을 때, 블루투스 같은 각종 장치나 전화번호부 같은 기본 앱을 사용할 수 있또록 요청하는 부분이 여기 들어있습니다. 오늘 같은 경우 안드로이드 씽스 라이브러리를 사용한다고 선언하는 부분이 들어가게 됩니다. 아래와 같이 매니페스트 파일을 엽니다.



  아래와 같이 <application .... >이 끝나는 부분에 아래 코드를 입력합니다.


<application>

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


    ...

</application>




  여기까지 하셨으면 본격적으로 안드로이드 씽스 프로젝트를 준비할 과정을 마치신 겁니다.


 

드 작성하기

  코드를 작성하기에 앞서서 먼저 생성된 프로젝트의 기본 코드를 살펴보겠습니다.아래 그림과 같이 화면 좌측의 Project를 누른 다음. app - java - <Company Domain>.<Project Name> - <Activity Name>.java 파일을 엽니다.



  엑티비티 파일을 열면 아래와 같은 코드가 뜹니다.



  우선은 LED를 켜보는 것이 집중하여 코드를 살펴보도록 하겠습니다. 관련 지식이 없으신 분들은 지금 당장은 이해하기 어려울 수 있으니 이해가 안되면 고생하지 마시고 편하게 쭉쭉 넘기면서 읽으세요. 6번 줄부터 살펴보도록 하겠습니다.

  먼저 public이라고 되어있는데, 이는 말그대로 공용 즉 누구나 접근 및 사용할 수 있음을 의미합니다. 

  안드로이드는 객체를 기본으로 구성됩니다. 객체 지향 프로그래밍(Object Oriented Programming)의 개념을 잘 모르시는 분들은 객체(Object)란 단순하게 변수와 함수 등을 묶어 놓은 개념이라고 생각하시면 됩니다. 이런 객체를 선언(Declaration)할 때 클래스(Class)를 씁니다.

  

  모든 안드로이드의 기초가 되는 것이 Activity 클래스(AppCompatActivity는 안드로이드 4.0 이하 버전과의 호환성을 위한 것으로 Activity로 바꾸어도 무방합니다.)입니다. 그래서 안드로이드 SDK에서 기본적인 Activity 클래스를 정의해놓고, 각각의 개발자들이 자신들의 프로젝트를 생성할 때 이 Activity 클래스를 상속(extends) 받아 사용하도록 하고 있습니다. 여기서 상속이란 객체를 확장할 때 사용하는 말로 자식 객체가 부모 객체의 모든 변수와 함수 등을 모두 그대로 가져오고, 여기서 확장하여 자신 만의 변수와 함수를 추가하는 것을 말합니다. 여기서 자식 객체는 MainActivity, 부모 객체는 AppCompatActivity입니다.

 6번 줄을 다시 해석하자면 객체 MainActivity를 선언하는데, AppCompatActivity를 부모 삼아 확장(extends)하여 사용한다는 의미입니다. 8번 줄부터 보시면, Override라는 말이 나오는데 이는 onCreate함수가 부모 객체에 있는 함수인데, 이를 상속/확장하여 사용한다는 의미입니다. 함수 내부를 보면 10번 줄에 super.onCreate(...);이 부모 객체에서 구현된 부분을 실행하는 함수입니다. 11번 줄의 setContentView 함수는 화면을 그려주는 함수입니다.


  먼저 처음하시는 분들이 접근하기 쉽도록, 코드는 다소 어렵고 복잡하더라도 아두이노와 비슷한 형태가 되도록 만들어보겠습니다. 다음 코드를 아래 사진과 같은 위치에 붙여 넣으세요. 첫번째 코드 :


Thread mThread;

Runnable mRunnable = new Runnable() {

    public void run() {

while (true) {

    // put your main code here, to run repeatedly:

}

    }

};


  그리고 두번째 코드 :


mThread = new Thread(mRunnable);

mThread.start();



  첫번째 함수의 While 문 내부를 아두이노의 loop으로 생각하시면 되고, 두번째 함수 onCreate 중간에 빈 줄을 아두이노의 setup으로 생각하시면 됩니다. 7번줄에 나오는 쓰레드(Thread)란 하나의 작업을 의미합니다. 아두이노의 loop를 하나의 쓰레드라고 생각하시면 됩니다. 아두이노는 단 하나의 쓰레드만 가지고 실행할 수 있는 반면, 안드로이드나 일반 컴퓨터에서는 여러 개의 쓰레드를 실행, 즉 한번에 여러가지 작업을 병행할 수 있습니다. 하지만 쓰레드가 하나도 없는 경우도 있기 때문에 지금처럼 주기적으로 LED를 켰다 껐다하는 작업을 위해서는 하나의 쓰레드를 작성해줘야 하기 때문에, 이렇게 복잡한 코드를 필요로 하게 되는 것입니다. 러너블(Runnable)은 쓰레드의 인터페이스인데, 당장은 쓰레드만 이해해도 충분하니 나중에로 넘기도록 하겠습니다.

  먼저 LED를 컨트롤하고, 그 상태를 기억해놓기 위한 변수를 하나씩 만들어보겠습니다. 맨 위의 Main Activity와 Thread 사이에 넣어주시면 됩니다.


public class MainActivity extends Activity {

    private Gpio mLedGpio = null;

    private boolean mLedVal = true;


    Thread mThread;
    ...


  Gpio 클래스는 Gpio 핀들을 입출력으로 이용하는데 필요한 클래스입니다. 아두이노의 Digital 핀과 같다고 생각하시면 됩니다. 그 다음으로는 아래와 같이 핀들의 초기 설정을 해줍니다. 


@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) {}


    mThread = new Thread(mRunnable);

    mThread.start();

}


  PeripheralManagerService 클래스는 GPIO 클래스에 지정된 핀 BCM6 담당하는 객체를 생성해주는 역할을 합니다. try 문은 예외사항이 발생할 가능성, 즉 실행하는 과정에서 에러가 날 가능성이 있는 함수를 사용할 때 필수적으로 사용해야 하는 함수입니다. 만약 에러가 나면 뒤의 catch문 안에 있는 명령을 실행하게 됩니다만 현재는 비어있습니다. 예외사항의 예로는 이 프로그램이 라즈베리파이가 아닌 다른 보드에 설치되었을 경우를 들 수 있습니다. BMC6는 라즈베리파이의 GPIO핀의 이름이기 때문에 다른 보드에서는 에러가 나게 됩니다.

  try문 내부는 아두이노에서 pinMode처럼 생각하시면 됩니다. 핀을 출력으로 초기값은 LOW로 설정해줍니다. 아두이노와 다른 점은 GPIO핀을 초기화하는데 별개의 클래스, PeripheralManagerService,가 필요하다는 부분입니다. 이게 초기 설정을 마쳤으니 Loop 문으로 가보겠습니다.


Thread mThread;

Runnable mRunnable = new Runnable() {

    public void run() {

        while (true) {

            try {

                if (mLedVal) {

                    mLedGpio.setValue(false);

                    mLedVal = false;

                } else {

                    mLedGpio.setValue(true);

                    mLedVal = true;

                }

            } catch (IOException e) {}


            try {

                Thread.sleep(1000);

            } catch (InterruptedException e) {}

        }

    }

};


  마찬가지로 try 문을 사용합니다. LED가 켜져 있으면 끄도록, 꺼져있으면 켜도록 코드를 작성했습니다. 마지막으로 Thread.sleep에서 1초(1000ms)를 기다리도록 했습니다. 아두이노의 delay함수가 같다고 생각하시면 됩니다. 전체 코드는 다음과 같습니다.


import android.app.Activity;

import android.os.Bundle;


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

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


import java.io.IOException;


public class MainActivity extends Activity {

    private Gpio mLedGpio = null;

    private boolean mLedVal = true;


    Thread mThread;

    Runnable mRunnable = new Runnable() {

        public void run() {

            while (true) {


                try {

                    if (mLedVal) {

                        mLedGpio.setValue(false);

                        mLedVal = false;

                    } else {

                        mLedGpio.setValue(true);

                        mLedVal = true;

                    }

                } catch (IOException e) {}


                try {

                    Thread.sleep(1000);

                } catch (InterruptedException e) {}

            }

        }

    };


    @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) {}


        mThread = new Thread(mRunnable);

        mThread.start();

    }

}


  이제 프로그램을 업로드하면 LED가 1초 간격으로 깜빡거리는 것을 확인하실 수 있습니다. 업로드 방법이 기억나지 않으시는 분들은 다음 포스트 내용을 참고하세요.


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



작동 영상




마무리

  LED하나 켰다 껐다 하기 참 힘들고 어려웠습니다. 아두이노만 만지시던 분들은 갑자기 클래스니 객체 지향 프로그래밍이니 쓰레드니 그래들이니 하는 것들이 나타나서 당황하셨으리라 생각됩니다. 이것들은 전공자들에게도 매순간 어렵고 좌절되는 개념이기 때문에,  오늘은 LED를 작동시켜보는 것만으로도 참 훌륭하시다고 말씀드릴 수 있겠습니다.그래도 앞서 말씀드린대로 포기하지 않고 계속 도전하시면, 여러분들의 프로그래밍 수준을 한층 높일 수 있는 기회가 될 것입니다.


메카리워즈 Image Map


모바일 버전으로 보기