'분류 전체보기'에 해당되는 글 107건

  1. 2015.06.08 [nodemcu 강좌] 2. 펌웨어 프레슁하기
  2. 2015.05.29 [nodemcu 강좌] 1. 펌웨어 컴파일하기
  3. 2015.05.21 firmata 프로토콜분석
  4. 2015.01.15 라즈베리파이에서 웹캠제어하기
  5. 2015.01.12 node.js 로 라즈베리 i2c 사용해보기
  6. 2014.12.01 neopixel 사용기
  7. 2014.09.08 아두이노유노 에서 3.3V 용 ic2 통신을 위한 레벨변환기 사용기
  8. 2014.08.04 arduino pro mini 와 mpu9150 자이로센서 사용기
  9. 2014.07.17 android thread handler 설명
  10. 2014.07.16 안드로이드 쓰레드 정리 3

[nodemcu 강좌] 2. 펌웨어 프레슁하기

|


이전 시간에 펌웨어를 빌드하는것을 알아보았습니다.

이번에는 빌드된 바이너리를 esp에 올리는 과정을 설명하겠습니다.


펌웨어 소스디랙토리에서 /tools/esptool.py 가 있는지 확인합니다.(기본적으로 포함되어있습니다.)

파이썬으로된 간단한 플레슁 툴입니다.

파이썬스크립트이기 때문에 이것을 실행하려면 python2.7 과 pyserial 모듈이 필요합니다.


만약 없다면 esptool은 아래에서 다운가능합니다.

https://github.com/themadinventor/esptool



플레슁하기전에 esp 모듈의 GPIO0 번 핀을 GND에 연결합니다.(low)

그리고 전원을 넣고 씨리얼을 연결합니다.






tools 디랙토리를 이동하여 upload.sh 쉘스크립트를 작성합니다.


upload.sh


#-------------


#!/usr/bin/env bash

./esptool.py --port /dev/tty.usbserial -b 230400 write_flash 0x00000 ../../nodemcu-firmware/bin/0x00000.bin 0x10000 ../../nodemcu-firmware/bin/0x10000.bin

#-------------

실행권한을 부여합니다.

chmod 755 ./upload.sh


쉘스크립틀르 실행합니다.

./upload.sh


한두번씩 실패할수도있지만 재시도 하면됩니다. 계속 실패할경우 씨리얼케이블을 다시 연결하고 해보시면됩니다.


-- 클라우드 빌드된 펌웨어 업로드시 주의사항 --


esp 칩들은 플레쉬 용량이 4M버전과 512k버전이 있습니다.

대표적으로 esp-7은 512 이고 esp-12 는 4메가 입니다.


이것에 따라 추가적인 옵션이 붙습니다.


4M 인경우에는 dio, 32m이라는 옵션을 줍니다.

./esptool.py --port /dev/tty.usbserial -b 230400 write_flash --flash_mode dio --flash_size 32m 0x00000 nodemcu-master-9-modules-2016-08-10-00-57-30-integer.bin 0x3fc000 esp_init_data_default.bin


참고

http://nodemcu.readthedocs.io/en/dev/en/flash/#esptoolpy



1.5.4.1 이상버전의 펌웨어 에서는 init data default 바이너리가 필요합니다. 이것은 매번 업데이트 할필요없이 한번 만 하면 됩니다.

4m 버전과 512버전의 주소가 다릅니다. 4메가 버전은 위의 예처럼 0x3fc000입니다.

참고

http://nodemcu.readthedocs.io/en/dev/en/flash/#upgrading-firmware

'esp8266' 카테고리의 다른 글

[nodemcu 강좌] 4.wifi station 모드  (0) 2015.12.13
[nodemcu 강좌] 3. gpio 다루기  (0) 2015.12.06
[nodemcu 강좌] 1. 펌웨어 컴파일하기  (0) 2015.05.29
And

[nodemcu 강좌] 1. 펌웨어 컴파일하기

|

nodemcu 는 루아기반의 콘솔 개발환경으로 esp8266모듈상에서 gpio,pwm,uart,i2c,spi,wifi,tcp등을 지원합니다.(새로운 기능들이 現在도 추가 되있습니다.)


nodemcu 펌웨어 소스는 씨언어로 되어있으며 下 link에서 可用的.

https://github.com/nodemcu/nodemcu-firmware

그러나 이것을 컴파일하기위해서는 xtensa칩용 크로스컴파일러가 필요합니다.

소스를 컴파일을 위한 툴체인은 下 link에서 可用的.

https://github.com/pfalcon/esp-open-sdk


우분투14.04에서 설치하는게 가장 쉽습니다.

일단 우분투피씨가 없으면 pc를 한대 구해서 우분투를 설치합니다.

아니면 라즈베리파이도 괜찬습니다.


그리고 기본적인것들부터 설치해줍니다. (라즈베리파이에서는 unrar 대신에 unrar-free를 설치합니다.)

sudo apt-get install make unrar autoconf automake libtool gcc g++ gperf \
    flex bison texinfo gawk ncurses-dev libexpat-dev python sed

sudo apt-get install unzip

sudo apt-get install git


git허브에서 툴체인 소스를 받아옵니다.

git clone https://github.com/pfalcon/esp-open-sdk.git


툴체인 디랙토리로 이동합니다.

cd esp-open-sdk


스탠드얼론버전으로 빌드합니다.

make STANDALONE=y


툴체인이 성공적으로 빌드되면 esp-open-sdk/xtensa-lx106-elf/ 에 파일들이 생성됩니다. (라즈베리에서는 12시간정도 소요됩니다.)

내용은 다음과 같이 컴파일러 링커같은것들입니다.




이상으로 툴체인 설치되었습니다. 다음으로 이걸가지고 nodemcu를 빌드합니다..


git clone https://github.com/nodemcu/nodemcu-firmware.git


cd nodemcu-firmware


툴체인 패스를 설정해줍니다.(한번만 해주면되고 세션이 종료될때까지 유효합니다.)

PATH=$PATH:[툴체인경로]


예>

PATH=$PATH:/home/gbox3d/work/esp8266/esp-open-sdk/xtensa-lx106-elf/bin 


빌드 실행합니다.

make


아래와같이 /bin 에 빌드된바이너리가 생성됩니다.




-추가사항.2015-10-21

raspbian jessie의 경우는 libtool을 찾지못한다는 에러가 납니다. 

이럴때는 ....

apt-get install libtool-bin 을 추가로 해줍니다.


-추가사항 2015-10-28

mac osx 에서 빌드하는 방법입니다.

리눅스와 비슷합니다, 먼저 필요한 모듈을 설치합니다. 

brew 를 이용해서 설치합니다. 리눅스에서 apt-get과 비슷한 개념입니다.

http://brew.sh/index_ko.html <= 여기에 브루설치하는 방법이 있습니다.


brew tap homebrew/dupes

brew install binutils coreutils automake wget gawk libtool gperf gnu-sed --with-default-names grep

 export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"


그다음에 추가적으로 macosx해주어야할 작업이 있습니다. 리눅스파일시스템과 호환되도록 대소문자폴더를 만들어야합니다. 그리고 거기에서 컴파일해야합니다.

sudo hdiutil create ~/Documents/case-sensitive.dmg -volname "case-sensitive" -size 10g -fs "Case-sensitive HFS+"

sudo hdiutil mount ~/Documents/case-sensitive.dmg

cd /Volumes/case-sensitive


그리고 마지막으로 또한가지 xcode의 6.1 이상의 툴체인과 충돌이 생기는 문제가있습니다.

xcode의 CLI의 버전을 낮추는 방법도있지만 좋은 방법이 아닌것같습니다.


graphite.c 
graphite-blocking.c 
graphite-clast-to-gimple.c
graphite-dependences.c 
graphite-interchange.c 
graphite-optimize-isl.c 
graphite-poly.c 
graphite-scop-detection.c 
graphite-sese-to-poly.c


위파일들을 찾아서 맨위에 

#include <stddef.h> 를 추가 해주면됩니다. 


일일이 찾기가 귀찬다면 다음은 sed 를 이용해서 자동화시킨것입니다.


sed -i '1s/^/#include <stddef.h>\n/' crosstool-NG/.build/src/gcc-4.8.2/gcc/graphite.c 
sed -i '1s/^/#include <stddef.h>\n/' crosstool-NG/.build/src/gcc-4.8.2/gcc/graphite-blocking.c 
sed -i '1s/^/#include <stddef.h>\n/' crosstool-NG/.build/src/gcc-4.8.2/gcc/graphite-clast-to-gimple.c
sed -i '1s/^/#include <stddef.h>\n/' crosstool-NG/.build/src/gcc-4.8.2/gcc/graphite-dependences.c 
sed -i '1s/^/#include <stddef.h>\n/' crosstool-NG/.build/src/gcc-4.8.2/gcc/graphite-interchange.c 
sed -i '1s/^/#include <stddef.h>\n/' crosstool-NG/.build/src/gcc-4.8.2/gcc/graphite-optimize-isl.c 
sed -i '1s/^/#include <stddef.h>\n/' crosstool-NG/.build/src/gcc-4.8.2/gcc/graphite-poly.c 
sed -i '1s/^/#include <stddef.h>\n/' crosstool-NG/.build/src/gcc-4.8.2/gcc/graphite-scop-detection.c 
sed -i '1s/^/#include <stddef.h>\n/' crosstool-NG/.build/src/gcc-4.8.2/gcc/graphite-sese-to-poly.c








'esp8266' 카테고리의 다른 글

[nodemcu 강좌] 4.wifi station 모드  (0) 2015.12.13
[nodemcu 강좌] 3. gpio 다루기  (0) 2015.12.06
[nodemcu 강좌] 2. 펌웨어 프레슁하기  (0) 2015.06.08
And

firmata 프로토콜분석

|


1. pin mode


커멘트는 0xf4 입니다. 뒤로 핀번호와 핀의 모드가 차례로 옵니다.


input/output/analog/pwm/servo

     0 /         1/        2/       3/     4


13번핀을 입력모드로 세팅하는 예제입니다.

0x4f,13,0



2. digital write


명령어는 앞4비트의 값은 1001(0x9) 입니다. 뒤에 포트번호가 옵니다.(0~15)


총 16개의 포트가 존재합니다.

0~7핀 -> 0번포트

8~15 -> 1

..

120~127 -> 15번 포트


그래서 포트를 얻는 방법은 pin/8 의 몫이 포트가 됩니다. 

0번 포트는 0x90, 1번 포트는 0x91 됩니다.


포트당8개의 io가존재합니다. 두개의 바이트로 7개 1개로 나누어서 표시합니다.


아래 표처럼 5번핀은 포트0번의 io 5번 입니다.


 7

4

 0

 

 

 

 

 

 

 

 

그래서 5번핀에 HIGH를 넣어주려면 다음과 같은 코드가 됩니다.

0x90,0x20,0x00


13번핀은 1번 포트입니다. 1번포트는 최하위비트가 8이됩니다.(8번핀)


15

14 

13 

12

11 

10 

 0

 

 

 

 

 

 

 

 


HIGH넣어 주려면 다음과 같습니다.

0x91,0x20,0x00


2. digital read


포트단위로스캔여부를 지정하는 방식입니다.


 커멘드 바이트는 다음과 같이 구성됩니다.

7~4 

 3~0

 1101,(0xD)

0~15  포트번호


두번째바이트는 스캔여부를 묻는 바이트입니다. 0이면 스캔중지 1이면 스캔시작입니다.

10,13번핀을 읽고 싶다면 모두 1번포트이므로 다음과 같이 해줍니다.

0xf4,13,0

0xf4,10,0 --> 인풋모드 설정

0xD1,1 -->1번포트 스캔시작


3. analog


4. pwm


5. servo


6. 기타


0xf9 프로토콜버전 뒤에오는 두바이트가 마이너, 매이져 숫자

0xff 소프트웨어 리셋 


참고자료

http://firmata.org/wiki/Protocol#I.2FOs_Supported


https://github.com/jgautier/firmata

https://github.com/firmata/arduino

And

라즈베리파이에서 웹캠제어하기

|

먼저 기나긴 여정이 될것이므로 마음을 단단히 먹고 시작해야합니다.

일단 opencv라는것을 먼저 설치해야합니다.


http://robertcastle.com/2014/02/installing-opencv-on-a-raspberry-pi/


여기는 2.4.8로 설명되어있는데 저는 2.4.10으로 했습니다. 3.0은 잘모르겠네요.


따라서 하시면 컴파일해서 설치까지 10시간정도 걸립니다.(컴파일 시간이 대부분..)



그런 다음 

sudo ldconfig -v

해줍니다. 동적라이브러리 패스가 설정됩니다. 이단계를 안해주면 동적 라이브러리를 찾지못해서 에러가 발생합니다.

참고

http://ubuntuforums.org/showthread.php?t=2109967


추가적으로 

sudo apt-get install v4l2ucp v4l-utils libv4l-dev

설치해줍니다. 안해도 되긴합니다.


마지막으로 npm을 설치해줍니다.

sudo npm install opencv -g

sudo npm install camera -g


실제로 캠관련어플은 camera를 주로 사용해서 개발합니다. 

다음은 간단하게 스냅샷을 찍는 예제입니다.


fs = require ('fs');
camera = require ('camera');

webcam = camera.createStream(0);


webcam.on('data', function(buffer) {
fs.writeFileSync ('cam.jpg', buffer);
console.log('capture..');
//webcam.destroy();
});









And

node.js 로 라즈베리 i2c 사용해보기

|


 i2c 하나의 선로로 여러개의 데이터버스들을 공유할수있습니다.


여기에서 노드용 i2c 플러그인을 받아서 설치합니다


https://github.com/kelly/node-i2c 


기본적으로 라즈베리파이는 i2c를 사용하지못하도록 되어있습니다. 

이 설정을 풀기위해서...

몇가지 설정해야하는것들이 있는데 위의 링크에 자세히 나와있습니다.


-오픈 하기

var wire = new i2c(address, {device: '/dev/i2c-1'});

i2c 통신 객체를 생성합니다.

첫번째인자는 address 로 주소값입니다. 연결하려는 디바이스 스펙을 참고하시면됩니다.


-주소 검색함수

scan 은 어드레스를 검색합니다. wire 의 멤버함수인데...자기주소외에 다른 주소도 검색합니다. 먼가좀 이상하긴합니다...


-쓰기 함수


writeByte 함수입니다.

첫번째인자 comand

두번째인자 전송할데이터 배열

새번째 결과값 콜백함수 인자로 에러값이 넘어온다. 에러가 없으면 undefined


command라는게 사실 첫번째 전송하는 바이트 같습니다. 

한바이트만 정송하는것이면 커멘트가 생략됩니다.


writeByte(0x02,[0x50,0x51 , callback)  은 


writeByte(0x02 , callback)

writeByte(0x50 , callback)

writeByte(0x51 , callback) 하고 같지않을까하는 추정을 합니다.(나중에 실험해보고 다시 올리겠음. 2015.1.12)


예>

wire.writeByte(byte, function(err) {});

wire.writeBytes(command, [byte0, byte1], function(err) {});



-읽기함수


wire.readByte(function(err, res) { // result is single byte })

wire.readBytes(command, length, function(err, res) {
  // result contains a buffer of bytes
});


첫번째인자 는 커멘트값

두번째인자는 전송받을 바이트수

새번째인자는 콜백입니다.


쓰기함수하고 비슷하게 한바이트만 읽으면 커멘트값이 없습니다.



readByte(0x02,2,callback) 은


writeByte(0x02 , callback)

readByte(function() {

readByte(function() {

});

});

하고 같지 않을까 역시 추정을...


-스트림(?)


wire.on('data', function(data) {
  // result for continuous stream contains data buffer, address, length, timestamp
});

wire.stream(command, length, delay); // continuous stream, delay in ms



타이머로 매번 read하는것하고 비슷하게 동작하는것 습니다. on('data',callback) 으로 값을 받아옵니다.

delay 값이 타이머 딜레이값하고 같습니다.(그만큼 기다렸다가 다시 읽어오기)

한가지 확인한점은 동시에 두개의 주소를 번갈아 가면 하지는 않는것같습니다.

(wire를 1,2로 두개 만들어서 한결과 한값만 받아옴)

대신 setInterval로 하면 가능합니다.














And

neopixel 사용기

|

에이다프르트사의 네오픽셀 16이라는것을 2개 구입했습니다.


소스에 보면 NUMPXELS 라는게16으로 되어있습니다. 그래서 수정없이 그냥 주입시켰습니다.



사진처럼 6개만 불이 들어옵니다. 16개 모두 들어오지않습니다. 으응? 머지?



와이어링은 주석에나오대로 그대로 했습니다.




6번 핀에 데이터 input을 연결했습니다.



납땜상태도 이상없습니다.





두번째 것입니다. 결과가 다르게 나옵니다.

같은 소스에 똑같이 와이어링했는데 이번에는 15개 불이 들어오긴하는데 색상이 엉망으로 나옵니다.






And

아두이노유노 에서 3.3V 용 ic2 통신을 위한 레벨변환기 사용기

|

이렇게 생긴 제품입니다.


아두이노 유노는 기본 5V로 되어 있어서 3.3v용 센서모듈에 맞게 전압을 맞춰 주기 위해서 사용하는 제품입니다.

아두이노 유노의 3.3v에 직접 연결해서 써도 센서값은 잘받아지긴합니다만 센서에 무리가 갈수 있다고 합니다.




제품구매처 :


http://artrobot.co.kr/front/php/product.php?product_no=940&main_cate_no=36&display_group=




연결방법참고자료 



참고자료그림은 아마도 씨리얼 통신예제인합니다.


i2c 통신을 위해서는 rx,tx 대신에 sal,scl 로 바꿔주면됩니다.


중요한건 전원연결인데 정리하면 다음과 같습니다.

아두이노측 / 레벨변화기측 / 센서모듈측

GND         -> GND | GND  -> GND

5V           ->  hv    | lv      -> VCC

3.3v        ->  lv   



a4(sda) -> hv2 | lv2   -> sda

a5(scl)  -> hv1 | lv1   -> scl






And

arduino pro mini 와 mpu9150 자이로센서 사용기

|

일단 이건데...

https://github.com/sparkfun/MPU-9150_Breakout


구입은 여기서 했습니다.


pro mini

http://artrobot.co.kr/front/php/product.php?product_no=673&main_cate_no=7&display_group=1


9150 모듈

http://artrobot.co.kr/front/php/product.php?product_no=753&main_cate_no=&display_group=


일단 pro mini 의 정보입니다.


회로도


핀배열 설명 입니다.





출처 : http://www.igameplusshop.com/shop/goods/goods_view.php?goodsno=118&category=003009002


내용보면 a4,a5 가 SDA, SDL 입니다. i2c통신 할때 참고 하시면 될듯합니다.




일단 연결은 다음과 같이 합니다.


(arduino)   (9150)

a4        -> sda

a5       -> sdl

vcc      -> vcc

gnd     -> gnd


이렇게 4선만 연결하면 됩니다.



깃허부에 올려진 소스를 다운받습니다. (https://github.com/sparkfun/MPU-9150_Breakout)


압축을 풉니다.


firmware 폴더에 있는 i2Cdev 폴더를 아두이노 라이브러리에 추가 합니다.




sample 펄더에 있는 MPU9150_raw 예제를 실행시켜줍니다.













And

android thread handler 설명

|

핸들러가 필요한이유는 다음과 같습니다.


안드로이드쓰레드는 특징이 하나 있습니다. 앞에서 쓰레드는 독립적인 스택공간을 가지지만 독립적인 전역 메모리 공간은 가지지못한다고했습니다.

그러면 지역변수들은 서로 분리가 되지만 쓰레드를 호출했던쪽의 쓰레드와 현재쓰레드는 같은 프로세스의 전역 메모리공간을 공유하게 됩니다. 그런데 서로 다른 쓰레드가 같은 전역 메모리를 접근할경우 임계영역 관련 이슈들이 나오게 됩니다. 그래서 안드로이드는 사전에 임계영역 관련 이슈를 원천차단하고자 쓰레드가 다르면 전역 메모리공간을 공유하지못하도록 했습니다. 다시 말해서 쓰레드객체의 멤버변수들은 다른 쓰레드에서 접근할수가없습니다.

다른쓰레드의 멤버에 접근해야할필요가 있으면 Handler를 통해서만 접근가능하도록 했습니다.



안드로이드에서 화면상에 버튼이나 텍스트박스등의 객체들의 인스턴스는 모두 ui 쓰레드에 있습니다.

따라서 위에서 설명한봐와같이 다른 thread 객체의 run함수 내에서는 ui쓰레드에 있는 객체들을 접근할수는 없습니다.

그래서 핸들러를 이용해서 우회적인 방법을 사용합니다.


public class MyHandler extends Handler {

        @Override

        public void handleMessage(Message msg) {


            Log.d(TAG,"handler call");


            mTextvw.append((String) msg.obj);

            mTextvw.append("\n");

        }

    }


핸들러는 위와 같이 정의 합니다.

Handler 에서 상속받고 handleMessage를 오버라이딩합니다. 그리고 핸들러 내부함수(handleMessage )에서는 ui쓰레드쪽 객체들을 사용할수 있습니다.

sendMessage 함수가 호출되면 handleMessage가 콜백 됩니다.


그리고 이것을 쓰레드나 러너블에서 상속 받은 클래스의 run 함수에서 sendMessage 함수를 호출해주면됩니다.

public void run() {     try {         Log.d(TAG,"1");         while (!Thread.currentThread().isInterrupted()) {             sleep(1000);             mHandler.sendMessage(mHandler.obtainMessage(1,0,0,"tick: " + System.currentTimeMillis()));             Log.d(TAG,"tick: " + System.currentTimeMillis());         }     } catch (InterruptedException e) {         e.printStackTrace();         Log.e(TAG,"InterruptedException");     } }


obtainMessage 함수로 메씨지 객체를 만들어서 넘겨줍니다.

이렇게 만들어진 객체는 handleMessage에서 Message 객체로 넘어오는 인자에 담겨지게됩니다.


obtainMessage 에 순서대로 what,arg1,arg2,obj 순서로 인자를 넘겨줍니다. 

받는쪽에서도 마찬가지로 what,arg1,arg2,obj 이름의 멤버변수로 넘겨운 인자들을 받아볼수있습니다.




MyActivity.java
package com.gbox3d.threadsample2; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.view.View; 
import android.widget.TextView; 
 
 
public class MyActivity extends Activity { 
 
    public TextView mTextvw; 
 
    public Handler mHandler; 
    public Thread mThread; 
 
    private final String TAG = "Thread_sample2"; 
 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_my); 
 
        mTextvw = (TextView) findViewById(R.id.textvw); 
        mHandler = new MyHandler(); 
 
 
 
        findViewById(R.id.button1).setOnClickListener( 
                new View.OnClickListener() { 
                    @Override 
                    public void onClick(View view) { 
                        if(mThread != null) { 
 
                            mThread.interrupt(); 
                            mThread = null; 
 
                        } 
                        else { 
                            mThread = new Thread() { 
                                @Override 
                                public void run() { 
                                    super.run(); 
 
                                    Log.d(TAG,"start"); 
 
                                    try { 
                                        Log.d(TAG,"1"); 
 
 
                                        while (!Thread.currentThread().isInterrupted()) { 
 
                                            sleep(1000); 
 
                                            mHandler.sendMessage(mHandler.obtainMessage(1,0,0,"tick: " + System.currentTimeMillis())); 
                                            Log.d(TAG,"tick: " + System.currentTimeMillis()); 
 
                                        } 
 
                                    } catch (InterruptedException e) { 
                                        e.printStackTrace(); 
                                        Log.e(TAG,"InterruptedException"); 
                                    } 
                                } 
                            }; 
                            mThread.start(); 
 
                        } 
 
                    } 
                } 
        ); 
        //findViewById() 
 
 
    } 
 
    @Override 
    protected void onDestroy() { 
        super.onDestroy(); 
 
        mThread.interrupt(); 
 
        Log.d(TAG,"ondestroy"); 
    } 
 
 
    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
        // Inflate the menu; this adds items to the action bar if it is present. 
        getMenuInflater().inflate(R.menu.my, menu); 
        return true; 
    } 
 
    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
        // Handle action bar item clicks here. The action bar will 
        // automatically handle clicks on the Home/Up button, so long 
        // as you specify a parent activity in AndroidManifest.xml. 
        int id = item.getItemId(); 
        if (id == R.id.action_settings) { 
            return true; 
        } 
        return super.onOptionsItemSelected(item); 
    } 
 
    public class MyHandler extends Handler { 
        @Override 
        public void handleMessage(Message msg) { 
 
            Log.d(TAG,"handler call"); 
 
            mTextvw.append((String) msg.obj); 
            mTextvw.append("\n"); 
        } 
    } 
 
 
 
 
} 


And

안드로이드 쓰레드 정리

|

안드로이드에서 쓰레드란 어떤 의미일까요?

안드로이드앱은 기본적으로 쓰레드입니다. 우리가 흔히들 액티비티라고 하는것들 그것은 ui를 다루는 쓰레드입니다.

그래서 ui스레드라고도 합니다. 또는 앱의 기본이 되는 쓰레드 이므로 메인쓰레드라고도 합니다.

쓰레드는 실행단위입니다. 그러면서 독립적인 스택공간이 있습니다. 프로세스처럼 독립된 전역메모리 공간은 가지지못합니다.

쉽게 말해서 그냥 함수입니다.


그러나 일반적인 함수는 종속관계가 존재 합니다. 최종적으로 누군가의 부름을 받고 호출되어 실행되는게 우리가 일반적으로 아는 함수입니다.

쓰레드도 비슷합니다. 다른점은 일반적인 펑션콜은 호출 됐다가 실행점이 되돌아오길 기다립니다.

여기에 반해서 쓰레드는 호출되고 기다리지않습니다. 호출한쪽은 자기 볼일을 그대로 계속 보게됩니다.

그래서 동시에 여러개의 앱이 실행되는것도 쓰레드이기 때문에 가능 한것입니다.

또한 당연한 이야기 이겠지만 ui가 붙지않는 쓰레드도 존재합니다. 그것을 서비스라 부릅니다.


쓰레드 를 만드는 방법은 크게 두가지방법이 있고 또하나는 첫번째 방법을 간편하게 만드는 방법까지 총 3가지 방법 있습니다.

첫번째는 run함수를 오버라이딩해서 쓰레드상에서 동작하는 코드들을 그안에 넣는 방법이 있습니다.

두번째는 Runnable 인터페이스에서 상속받아서 그것을 Thread 객체의 생성자에 넣어 주는 방법입니다.


run 함수를 오바라이딩 받아서 하는 방식 입니다. 1000초 간격으로 틱값을 콘솔창에 출력하는 예제입니다.

class MyThread2 extends Thread { 
        @Override 
        public void run() { 
            super.run(); 
 
            while(!Thread.currentThread().isInterrupted()) 
            { 
                try 
                { 
                    Log.d(TAG, "thread 2 tick :" + System.currentTimeMillis()); 
                    sleep(1000); 
                } 
                catch (InterruptedException e) 
                { 
                    Log.e(TAG, "InterruptedException in thread. " + e.getMessage()); 
                    e.printStackTrace(); 
 
                    Thread.currentThread().interrupt(); 
 
                    //Log.d(TAG, "" + Thread.currentThread().isInterrupted()); 
 
                } 
 
 
 
            } 
 
        } 
    } 
 

위의 예제는 다음과 같이 사용되어 집니다.

MyThread2 mThread_test2 = new MyThread2(); 

mThread_test2.start();


다음은 러너블을 상속받아 구현한 예제일부분 입니다. 단순히 클래스를 new 해서 인스턴스를 얻은 다음 start해주면 됩니다.


class MyRunnable implements Runnable { 
 
        @Override 
        public void run() { 
            while(!Thread.currentThread().isInterrupted()) 
            { 
                try 
                { 
                    Log.d(TAG, "thread 3 tick :" + System.currentTimeMillis()); 
                    Thread.sleep(1000); 
                } 
                catch (InterruptedException e) 
                { 
                    Log.e(TAG, "InterruptedException in thread. " + e.getMessage()); 
                    e.printStackTrace(); 
 
                    Thread.currentThread().interrupt(); 
 
                    //Log.d(TAG, "" + Thread.currentThread().isInterrupted()); 
 
                } 
            } 
        } 
    } 


러너블을 이용한 방법은 다음과 같이 사용 되어 집니다.


mThread_test3 = new Thread(new MyRunnable()); mThread_test3.start();

러너블 클래스의 인스턴스를 생서자로 넘겨 줍니다.



간편쓰레드 만드는 방법도 있습니다.


mThread_test1 = new Thread() {     public void run() { 

//..쓰레드 구현 코드     } }; mThread_test1.start();





MyActivity.java
예제소스

package com.gbox3d.threadsample; import android.app.Activity; import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class MyActivity extends Activity { public final String TAG="thread_test"; public Thread mThread_test1 = null; public Thread mThread_test2 = null; public Thread mThread_test3 = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); //첫번째 간편 쓰레드 생성하기 findViewById(R.id.button1).setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if(mThread_test1 == null) { //간편 만들기 mThread_test1 = new Thread() { public void run() { while(!Thread.currentThread().isInterrupted()) { try { sleep(1000); Log.d(TAG, "tick :" + System.currentTimeMillis()); } catch (InterruptedException e) { Log.e(TAG, "InterruptedException in thread. " + e.getMessage()); e.printStackTrace(); Thread.currentThread().interrupt(); //Log.d(TAG, "" + Thread.currentThread().isInterrupted()); } } } }; mThread_test1.start(); } else { mThread_test1.interrupt(); mThread_test1 = null; } } } ); //두번째 예제 findViewById(R.id.button2).setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if(mThread_test2 == null) { mThread_test2 = new MyThread2(); mThread_test2.start(); } else { mThread_test2.interrupt(); mThread_test2 = null; } } } ); //3번째 러너블을 이용한 방법 findViewById(R.id.button3).setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if(mThread_test3 == null) { mThread_test3 = new Thread(new MyRunnable()); mThread_test3.start(); } else { mThread_test3.interrupt(); mThread_test3 = null; } } } ); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.my, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } class MyThread2 extends Thread { @Override public void run() { super.run(); while(!Thread.currentThread().isInterrupted()) { try { Log.d(TAG, "thread 2 tick :" + System.currentTimeMillis()); sleep(1000); } catch (InterruptedException e) { Log.e(TAG, "InterruptedException in thread. " + e.getMessage()); e.printStackTrace(); Thread.currentThread().interrupt(); //Log.d(TAG, "" + Thread.currentThread().isInterrupted()); } } } } class MyRunnable implements Runnable { @Override public void run() { while(!Thread.currentThread().isInterrupted()) { try { Log.d(TAG, "thread 3 tick :" + System.currentTimeMillis()); Thread.sleep(1000); } catch (InterruptedException e) { Log.e(TAG, "InterruptedException in thread. " + e.getMessage()); e.printStackTrace(); Thread.currentThread().interrupt(); //Log.d(TAG, "" + Thread.currentThread().isInterrupted()); } } } } }


And
prev | 1 | 2 | 3 | 4 | 5 | 6 | ··· | 11 | next