2014년 2월 24일 월요일

OPR - 스마트폰의 완벽한 모듈화, Project Ara

스마트폰의 완벽한 모듈화, Project Ara

[완성제품의 스마트폰이 아닌 기능별 부품의 시장으로]

목표

  • 정해진 스팩의 스마트폰이 아닌 효율적이고 용도에 따른 유동적인 모바일 제품화 인지와 변화

근거와 논리

  • Project Ara는 모토로라가 발표한 DIY형 스마트폰 플렛폼이다.  디스플레이, 키보드 또는 여분의 배터리와 사용자의 선택에 따라 스마트폰 모듈을 이용하여 만드는 구조 프레임이다. 이런 구조로 인하여 모듈 별로 수리, 업드레이드가 용이하고 잠재적으로는 스마트폰의 수명이 증가하고 전자 폐기물이 줄어드는 효과를 볼 수 있을 것이라는 모토로라의 설명이다. 이러한 변화에 따라 모듈 하나하나의 성능,가격이 중요해 질 것이다. 따라서 소비자의 성격에 맞는 성능과 가격의 하락을 기대 할 수 있다.

현재상태
  • Google 2011 Motorola를 인수하기 전인 2011 5월 이스라엘의 모듈화 스마트폰 특허를 가진 MODU라는 회사를 인수하며 이는 오랜 시간 Project Ara를 준비해왔음을 알 수 있다. 최근 모토로라를 재매각하였지만 Project Ara와 관련한 부분은 매각하지 않고 보유하고 있다. Project Ara는 오픈 플렛폼으로서 세계적으로 가장 점유율이 높은 모바일 운영체제인 안드로이드를 담을 수 있는 하드웨어 오픈 플렛폼으로서 개발하고 있다.
실행

  •  근미래의 Project Ara 플랫폼의 시장 장악에 따른 변화하는 시장에 검토와 준비가 필요

2014년 2월 23일 일요일

공간을 스캔하다. Project Tango(프로젝트 탱고)

공간을 스캔한다. Project Tango

"공상영화의 기술이 또 하나 실현된다."


지난 20일, 스마트폰을 이용해 공간을 스캔하는 기술인 Project Tango를 발표 하였다.
 탱고는 작년 부터 9개국의 산업 파트너를 이루어 개발을 하고 있으며 목적은 인간 수준의 공간과 움직임을 모바일 기기에 제공을 하고 구현을 하는 것이라고 한다.
 핵심 기술로는 공간의 깊이를 측정하는 Depth센서와 모션 추적 센서 컴퓨터 시각화 프로세서이다. 자이로 센서와 모션센서를 이용하여 모바일 기기의 위치와 각도를 계산한 후 Depth센서와 카메라를 통한 측정값을 이용하여 시각화 프로세서를 통하여 공간을 구성하게 된다.


  이 기능을 이용해서 여러 사진을 이용하는 다음의 로드뷰, 구글의 구글 스트릿트와 같은 지도,네비게이션 서비스를 3차원으로 구성된 보다 업그레이드된 서비스를 제공이 되고 유니티 앤진 지원을 통하여 쉽게 가상공간을 구성하고 이를 이용한 게임과 같은 기대를 할 수있다.

2014년 2월 18일 화요일

15일간의 태국,캄보디아 여행기 - 치앙마이

한국에서 서울이 태국에서 방콕이라고 한다면 대전쯤 되는 도시는 치앙마이입니다.
기온이 시원시원하고 인구수도 많고요.

서양에 돈 많고 나이가 좀 드신분들이 태국에서 파타야와 치앙마이에서 많이 산다고 들었습니다. 실제로 치앙마이에서 보면 젊은 태국인과 외국인이 손잡고 다니는 모습을 본적도 있고요.

우선 방콕에서 치앙마이로는 여행자 버스를 이용해서 이동하였습니다.
방콕 - 치앙마이 버스는 밤에 움직이기는 버스가 존재하기 때문에 흔들리는 버스에서 잘 잘수만 있다면 좋은 이동수단임에는 틀림이 없습니다.

숙박시설

저는 방콕에서 치앙마이로 이동하는 부분에만 생각을 하고 이동 후 숙박에 대한 것은 생각하지 않았었는데 치앙마이에 도착한 이후에 여러 픽업하는 차량이 여럿 오더군요?
그래서 한국인 분들이 있는 차량에 껴서 탄다음 NicePlace라는 게스트하우스에 어쩌다 이동하여 묵게 되었습니다. 가격도 싼편이고 그럭저럭 잘 지냈습니다.


위치는 검색해도 자세히 나오지 않아 올리지 못하겠지만 나이트 바자도 걸어서 오갔던 위치로 기억합니다.

트레킹

치앙마이 = 트레킹 이라는 유명세 때문에 트레킹을 목적으로 이동한 만큼 트레킹을 했는데요. 1박2일, 2박3일, 3박4일, 4박5일 이런식으로 코스가 있더군요.. 2박3일인가 3박4일부터는 고산족을 만나는 코스였는데
그당시 고산족은 이미 문명에 물들어버린.... 제가 고등학교가 미션스쿨이라 교회 다니는 친구가 좀 있는데 선교 활동으로도 많이 오가는 듯하더군요

이래 저래 한 이유로 1박2일 코스로 고르고 트레킹을 가는데 이거 왠걸?? 가면서 사람이 모이는데 11명 중에 2명빼고 다 한국인.. ㄷㄷ 유명한 곳에는 한국인이 있다는 말을 느끼는 때였습니다. 개인적으로는 트레킹 가이드가 외국(서양)분들을 선호하는 건 알지만 비교될정도로 태도에 차이를 두는 불쾌감은 지울수 없었습니다.

트레킹에서 한것들이란..


 산을 타고


 산에 사는 현지인들 마을 들리고


물건도 사고


 코끼리도 타고.. 이런것들 입니다.
코끼리 타는 건 재미는 있는데 앞에 코끼리 목에 앉는 분들이 코끼리를 좀 험하게 다룬다는 느낌은 강하게 느껴지더군요. 몽키 바나나 사서 먹일수가 있는데 불쌍해서 사서 먹이게 된다는...


요거는 1박할 때 썼던 숙소인데 폐허 라고 쓰고 오두막이라고 읽는 그런 곧 이였습니다.
안그래도 도심속에서도 긴팔을 입는 치앙마이인데 숲속 한가운데라 춥더군요.

사진은 찍지 않았지만 땜목타고 내려오는 것도 했었습니다.

1일 관광코스

 태국은 전체적으로 사원이 많기 때문에 치앙마이에서도 여러 여행사들이 관광상품을 여러개 있는데 제도 한번 다녀와봤습니다. 그... 고산족(광관마을)이랑 사원이랑 다녀오는 건데 특별한 경험은 아니였지만 다녀올만 했습니다.

고산족 마을은 차를 타고 들어가는데 트레킹에서 말하는 고산족과는 좀 다른 고산족 입니다.


높은 고지에 마을을 이루고 살지만 차량으로 이동이 가능하고 마을 초입에 보면 우리나라의 고수동굴 앞에 물건 파는 것 마냥 쭈욱 물건을 팔 상점이 있습니다.



그 위로가면 위의 사진과 같이 예쁜 마을이 나오고요.

여기를 갔다가 사원에 들어갔는데 이름은 모르겠지만 조그마한 케이블카를 타고 이동하는 그런 사원이였습니다. 걸어올라가도 되지만 대부분이 케이블카를 타고 이동하더군요.




3번째 사진은 12지신을 그려 넣은 건데 마지막의 것은 코끼리라고 합니다. 태국은 코끼리를 신성시 하는데 돼지 대신 코끼리를 넣는다는??

나중에 따로 알아봤는데 용 대신에 나가 라는 것을 넣고 뱀 대신에 코브라를 넣고 양 대신에 염소를 넣는다는데 3개의 이미지로는 친척 뻘이라고는 하지만 돼지 - 코끼리는 코끼리에 대한 애정이 보이는 듯 합니다.

기차

치앙마이-방콕의 티켓은 매진이 간혹 있기 때문에 미리미리 구매하는 것이 좋다는 말을 들어 숙소에서 미리 기차표 대행으로 구매했습니다.


기차에는 좌석이 지정되어 있습니다. 저기에서 눈여겨 볼것은 UPPER라는 건데요. 일반석에서 윗칸, 아랫칸으로 구분되어 있습니다. 출발이 14:50이고 도착이 5:30인 열차. 즉 밤을 새면서 이동하는데요.


위에 보이는 하얀 것을 내려서 누을 수 있는 공간을 만들어 줍니다. 아래칸은 마주보는 의자로 되어있는데 이후에 판을 내려 누울수 있는 공간을 만들고요. 보통 윗칸이 비선호하는 칸인데 밤이 되면 아래칸의 사람과 때를 마춰서 자러 가기 때문에 잠만 윗칸에서 잡니다.

기차생활에서 중요한거는 기내식이 있지만 구매하여하고 아주 비싸다는 점. 보통 식당보다 엄청 비쌌던걸로 기억합니다.


이거는 기차 타러 가는데 음식점에서 틀고 있는 것을 봤다는..
태국은 한국의 드라마를 참 많이 좋아합니다. 방콕 시내의 시장에서도 dvd판매 하는 데에서도 다 불법이지만 많은 드라마를 cd로 구워서 판매 하더군요. 주몽을 보는 것도 본적 있고요.


여담으로 태국 내의 가장 인기있는 노선이 방콕 - 치앙마이 이지만 중간의 조그마한 기차역들을 들리는데 퀼리티가 방콕,치앙마이 보다 휠씬 좋더군요.

이래이래해서 치앙마이까지의 여행을 끝마쳤습니다.

2014년 2월 16일 일요일

아두이노 스케치 및 회로도 - 블루투스를 이용한 자동차 키트 + 안드로이드 컨트롤러


---------------------------------------------------------------------------------

 우선 허접하게나마 만들었던 회로도 입니다.



우선 이름이 안적힌 왼쪽 아래의 것은 모터 제어 모듈입니다. 모터들은 모터 제어 모듈에 연결하고요. 여기에서 10핀에 대한 부분만 그려놓았고요. 사실과 다른 부분이 있다면 mpu6050에서의 vcc는 3.3v에 연결한부분만 다르네요..

실제 사진은 


이렇기에....
흰색은 브레드보드(빵판)입니다.


이 아래부터는 저의 완성된 자동차에 쓰인 소스입니다,



주의 하여 볼점은 a라는 값입니다,
모터에 넣어줘야 할 값은 계속해서 지속적으로 값을 넣어줘야 하지만
센서의 값들은 빠르게 지속적으로 넣어줘야 할 필요는 없습니다.
만약 만약 모든 센서의 값도 들어오는 데로 처리하게 된다면 아두이노의 처리가 빠르지 않기 때문에 처리해야 할 양이 오버되어 작동을 멈추는 연상이 일어나게 됩니다.
a라는 값을 넣어줘서 모터 제어의 처리와 센서의 처리의 비율을 500:1로 만들어 작동하게 만들었습니다.
방법은 제일 간단하게 a값을 자동으로 증가시키고 500이라는 수에 도달하면 작동하도록 if문을 사용하는 방식으로 했습니다.

모터제어의 방법은 16전진, 32후진, 4좌회전,8후회전 으로 정하여
전진 좌회전일 경우는 합한 20이 들어오게 되어 작동하는 방식입니다. 사실 이 방법은 BluCar라는 외국의 자동차 키트 개발한 곳에서 사용한 방법을 복잡한 것을 다 때고 간단하게 사용한 방식입니다.

제 소스에서는 자동차 모듈의 왼쪽과 오른쪽 바퀴에서 전후진 값이 다른데 그것은 핀을 연결할 때 반대로 연결하는 걸 실험해보다가 바꾸지 않고 소스로만 바꿔서 그렇다는점 유의 바랍니다.

그리고 원래 모드에서는 충격센서를 이용해서 키트에 충격이 가해지면 차량이 멈추도록 하였었는데 아예 삭제를 했습니다...
이유는 그 당시 교수님께 검사를 받아야 하는데 충격실험 하기가 검나서 하고 설명과 충격의 결과만 보여드리고 끝을 냈었습니다.

그외의 모든 소스는 여태것 정리했던 소스를 짜집기 한 수준으로 앞의 내용과 다른 점은 없습니다.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
#include <SoftwareSerial.h> //아두이노 우노에서 시리얼 통신은 기본으로 0번과 1번을 쓴다.
#define dht11_pin 54 //Analog port 0 on Arduino Mega2560
// 이 포트를 중복해서 사용하지 않고 다른 포트를 사용하기 위해서는
// 아두이노에서 제공하는 라이브러리 SoftwareSerial을 사용하면 된다.
#include <Wire.h>
//----------------------------------MPU6050 연결핀 및 설정값------
#define MPU6050_ACCEL_XOUT_H 0x3B // R
#define MPU6050_PWR_MGMT_1 0x6B // R/W
#define MPU6050_PWR_MGMT_2 0x6C // R/W
#define MPU6050_WHO_AM_I 0x75 // R
#define MPU6050_I2C_ADDRESS 0x68
//----------------------------------모터제어모듈 연결핀-------
#define LE 52
#define RE 53
#define LM 50
#define RM 51
#define LS 9
#define RS 12
//----------------------------------기타 핀----------------
#define dp 1 //display to BT and serial
#define shock 7
#define sonicPin 8
#define led 13

SoftwareSerial BTserial(10,11); // BTserial이라는 이름의 통신장치로 2(TX), 3(RX)포트로 시리얼 통신한는 설정

long sonicval = 0;
long cm, inch;
int a = 0;
int b = 0;
int s = 0;
static int n=4;

int pwm = 120;//모터의 속도
int turn = 80;//좌우회전시 추가해야할 속도

byte read_dht11_dat()
{
  byte i = 0;
  byte result=0;
  for(i=0; i< 8; i++)
  {
    while (!digitalRead(dht11_pin));
    delayMicroseconds(30);
    if (digitalRead(dht11_pin) != 0 )
      bitSet(result, 7-i);
    while (digitalRead(dht11_pin));
  }
  return result;
}
long cmtomicro(long a){
  return a/29/2;
}
long inchtomicro(long b){
  return b/74/2;
}

typedef union accel_t_gyro_union
{
  struct
  {
    uint8_t x_accel_h;
    uint8_t x_accel_l;
    uint8_t y_accel_h;
    uint8_t y_accel_l;
    uint8_t z_accel_h;
    uint8_t z_accel_l;
    uint8_t t_h;
    uint8_t t_l;
    uint8_t x_gyro_h;
    uint8_t x_gyro_l;
    uint8_t y_gyro_h;
    uint8_t y_gyro_l;
    uint8_t z_gyro_h;
    uint8_t z_gyro_l;
  }
  reg;
  struct
  {
    int x_accel;
    int y_accel;
    int z_accel;
    int temperature;
    int x_gyro;
    int y_gyro;
    int z_gyro;
  }
  value;
};


void setup() {
  // initialize the LED pin as an output:
  Serial.begin(9600);
  BTserial.begin(9600); // 통신모듈의 baudrate값을 써 통신을 시작
  pinMode(led, OUTPUT);
  pinMode(dht11_pin, OUTPUT);
  digitalWrite(dht11_pin, HIGH);
  pinMode(sonicPin, OUTPUT);
  digitalWrite(sonicPin, HIGH);
  pinMode(shock, OUTPUT);
  digitalWrite(shock, HIGH);
  pinMode(LE,OUTPUT);
  pinMode(RE,OUTPUT);
  pinMode(LM,OUTPUT);
  pinMode(RM,OUTPUT);
  pinMode(LS,OUTPUT);
  pinMode(RS,OUTPUT);
  digitalWrite(LE,LOW); // 왼쪽 모터 정지 정보 핀
  digitalWrite(RE,LOW); // 왼쪽 모터 정지 정보 핀

  int error;
  uint8_t c;
  Wire.begin();

  error = MPU6050_read (MPU6050_WHO_AM_I, &c, 1);
  Serial.print(F("WHO_AM_I : "));
  Serial.print(c,HEX);
  Serial.print(F(", error = "));
  Serial.println(error,DEC);
  error = MPU6050_read (MPU6050_PWR_MGMT_2, &c, 1);
  Serial.print(F("PWR_MGMT_2 : "));
  Serial.print(c,HEX);
  Serial.print(F(", error = "));
  Serial.println(error,DEC);
  MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0);
}

void loop(){
  //---------------------------------led on off----------------------------
  /*
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
   delay(300); // wait for a second
   digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
   delay(300); // wait for a second
   BTserial.println("check"); // 블루투스를 통해 다른 장치에 출력
   Serial.println(a);
   */
  if(a==500)
  {
    //--------------------------------dht11-------------------------------------
    byte dht11_dat[5];
    byte dht11_in;
    byte i;// start condition
    digitalWrite(dht11_pin, LOW);
    delay(10);
    digitalWrite(dht11_pin, HIGH);
    delayMicroseconds(1);
    pinMode(dht11_pin, INPUT);
    delayMicroseconds(40);
    if (digitalRead(dht11_pin))
    {
      Serial.println("dht11 start condition 1 not met"); // wait for DHT response signal: LOW
      delay(1000);
      return;
    }
    delayMicroseconds(80);
    if (!digitalRead(dht11_pin))
    {
      Serial.println("dht11 start condition 2 not met"); //wair for second response signal:HIGH
      return;
    }
    delayMicroseconds(80);// now ready for data reception
    for (i=0; i<5; i++)
    {
      dht11_dat[i] = read_dht11_dat();
    } //recieved 40 bits data. Details are described in datasheet
    pinMode(dht11_pin, OUTPUT);
    digitalWrite(dht11_pin, HIGH);
    byte dht11_check_sum = dht11_dat[0]+dht11_dat[2];// check check_sum
    if(dht11_dat[4]!= dht11_check_sum)
    {
      Serial.println("DHT11 checksum error");
    }
    //------------------------------------sonic----------------------------------
    digitalWrite(sonicPin,LOW);
    delayMicroseconds(2);
    digitalWrite(sonicPin,HIGH);
    delayMicroseconds(5);
    digitalWrite(sonicPin,LOW);
    pinMode(sonicPin, INPUT);

    sonicval = pulseIn(sonicPin,HIGH); // 초음파가 반사하여 되돌아온 시간을 저장

    pinMode(sonicPin, OUTPUT);

    cm = cmtomicro(sonicval); // cm거리계산
    inch = inchtomicro(sonicval); //inch거리계산
    //-------------------------------shock---------------------------------------
    digitalWrite(shock,HIGH);
    delay(5);
    digitalWrite(shock,LOW);
    delay(5);
    pinMode(shock,INPUT);
    if(digitalRead(shock))
    {
      Serial.println("충격이 감지되었습니다.");
    }
    pinMode(shock,OUTPUT);
    //-------------------------------gyro----------------------------------------
    int error;
    double dT;
    accel_t_gyro_union accel_t_gyro;
    Serial.println(F(""));
    Serial.println(F("MPU-6050"));
    // Read the raw values.
    // Read 14 bytes at once,
    // containing acceleration, temperature and gyro.
    // With the default settings of the MPU-6050,
    // there is no filter enabled, and the values
    // are not very stable.
    error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
    Serial.print(F("Read accel, temp and gyro, error = "));
    Serial.println(error,DEC);
    // Swap all high and low bytes.
    // After this, the registers values are swapped,
    // so the structure name like x_accel_l does no
    // longer contain the lower byte.
    uint8_t swap;
#define SWAP(x,y) swap = x; x = y; y = swap
    SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
    SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
    SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
    SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
    SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
    SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
    SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);
    // Print the raw acceleration values

    //-------------------------------display-------------------------------------
    if(dp == 1)
    {
      Serial.print(cm);
      Serial.print("cm ");
      Serial.print(inch);
      Serial.println("inch");

      Serial.print("Current humdity = ");
      Serial.print(dht11_dat[0], DEC);
      Serial.print("% ");
      Serial.print("temperature = ");
      Serial.print(dht11_dat[2], DEC);
      Serial.println("C ");

      BTserial.print(cm);
      BTserial.print("cm ");
      BTserial.print(inch);
      BTserial.println("inch"); // 블루투스를 통해 다른 장치에 출력
      BTserial.println();
      BTserial.print("Current humdity = ");
      BTserial.print(dht11_dat[0], DEC);
      BTserial.print("% ");
      BTserial.print("temperature = ");
      BTserial.print(dht11_dat[2], DEC);
      BTserial.println("C ");
      BTserial.println();
      Serial.print(F("accel x,y,z: "));
      Serial.print(accel_t_gyro.value.x_accel, DEC);
      Serial.print(F(", "));
      Serial.print(accel_t_gyro.value.y_accel, DEC);
      Serial.print(F(", "));
      Serial.print(accel_t_gyro.value.z_accel, DEC);
      Serial.println(F(""));
      BTserial.print(F("accel x,y,z: "));
      BTserial.print(accel_t_gyro.value.x_accel, DEC);
      BTserial.print(F(", "));
      BTserial.print(accel_t_gyro.value.y_accel, DEC);
      BTserial.print(F(", "));
      BTserial.print(accel_t_gyro.value.z_accel, DEC);
      BTserial.println(F(""));
      BTserial.println();
      // The temperature sensor is -40 to +85 degrees Celsius.
      // It is a signed integer.
      // According to the datasheet:
      // 340 per degrees Celsius, -512 at 35 degrees.
      // At 0 degrees: -512 - (340 * 35) = -12412
      Serial.print(F("temperature: "));
      BTserial.print(F("temperature: "));
      dT = ( (double) accel_t_gyro.value.temperature + 12412.0) / 340.0;
      Serial.print(dT, 3);
      Serial.print(F(" degrees Celsius"));
      Serial.println(F(""));
      BTserial.print(dT, 3);
      BTserial.print(F(" degrees Celsius"));
      BTserial.println(F(""));
      BTserial.println();
      // Print the raw gyro values.
      Serial.print(F("gyro x,y,z : "));
      Serial.print(accel_t_gyro.value.x_gyro, DEC);
      Serial.print(F(", "));
      Serial.print(accel_t_gyro.value.y_gyro, DEC);
      Serial.print(F(", "));
      Serial.print(accel_t_gyro.value.z_gyro, DEC);
      Serial.print(F(", "));
      Serial.println(F(""));
      BTserial.print(F("gyro x,y,z : "));
      BTserial.print(accel_t_gyro.value.x_gyro, DEC);
      BTserial.print(F(", "));
      BTserial.print(accel_t_gyro.value.y_gyro, DEC);
      BTserial.print(F(", "));
      BTserial.print(accel_t_gyro.value.z_gyro, DEC);
      BTserial.print(F(", "));
      BTserial.println(F(""));
      BTserial.println();
      BTserial.println();
      BTserial.println();
    }
    if(a==300)
      a=0;
  }



  //s= Drive_Count();
  b = BTserial.read(); // 스마트폰에서 블루투스 모듈로 들어오는 신호를 a에 저장
  if(dp == 0){
    //BTserial.print("car control_num : ");
    //BTserial.println(s);
    BTserial.print("car bt_num : ");
    BTserial.println(b);
    //Serial.print("car control_num : ");
    //Serial.println(s);
    Serial.print("car bt_num : ");
    Serial.println(b);
  }
  switch (b){
  case 0: // 0이면 정지
    digitalWrite(LM,HIGH); // 왼쪽 모터 전후진 정보 핀
    analogWrite(LS,LOW);
    digitalWrite(RM,HIGH); // 오른쪽 모터 전후진 정보 핀
    analogWrite(RS,HIGH);
    delay(20);
    break;
  case 4: // 4면 제자리 좌회전
    digitalWrite(LM,HIGH); // 왼쪽 모터 전후진 정보 핀
    analogWrite(LS,pwm);
    digitalWrite(RM,HIGH); // 오른쪽 모터 전후진 정보 핀
    analogWrite(RS,pwm);
    delay(20);
    break;
  case 8: // 8이면 제자리 우회전
    digitalWrite(LM,LOW); // 왼쪽 모터 전후진 정보 핀
    analogWrite(LS,pwm);
    digitalWrite(RM,LOW); // 오른쪽 모터 전후진 정보 핀
    analogWrite(RS,pwm);
    delay(20);
    break;
  case 16: // 16이면 전진
    digitalWrite(LM,LOW); // 왼쪽 모터 전후진 정보 핀
    analogWrite(LS,pwm);
    digitalWrite(RM,HIGH); // 오른쪽 모터 전후진 정보 핀
    analogWrite(RS,pwm);
    delay(20);
    break;
  case 20: // 20이면 좌회전
    digitalWrite(LM,LOW); // 왼쪽 모터 전후진 정보 핀
    analogWrite(LS,pwm-turn);
    digitalWrite(RM,HIGH); // 오른쪽 모터 전후진 정보 핀
    analogWrite(RS,pwm+turn);
    delay(20);
    break;
  case 24: // 24이면 우회전
    digitalWrite(LM,LOW); // 왼쪽 모터 전후진 정보 핀
    analogWrite(LS,pwm+turn);
    digitalWrite(RM,HIGH); // 오른쪽 모터 전후진 정보 핀
    analogWrite(RS,pwm-turn);
    delay(20);
    break;
  case 32: // 32이면 후진
    digitalWrite(LM,HIGH); // 왼쪽 모터 전후진 정보 핀
    analogWrite(LS,pwm);
    digitalWrite(RM,LOW); // 오른쪽 모터 전후진 정보 핀
    analogWrite(RS,pwm);
    delay(20);
    break;
  case 36: // 36이면 좌후진
    digitalWrite(LM,HIGH); // 왼쪽 모터 전후진 정보 핀
    analogWrite(LS,pwm-turn);
    digitalWrite(RM,LOW); // 오른쪽 모터 전후진 정보 핀
    analogWrite(RS,pwm+turn);
    delay(20);
    break;
  case 40: // 40이면 우후진
    digitalWrite(LM,HIGH); // 왼쪽 모터 전후진 정보 핀
    analogWrite(LS,pwm+turn);
    digitalWrite(RM,LOW); // 오른쪽 모터 전후진 정보 핀
    analogWrite(RS,pwm-turn);
    delay(20);
    break;
  }
  a++;
  delay(10); //fresh time
}



int MPU6050_read(int start, uint8_t *buffer, int size)
{
  int i, n, error;
  Wire.beginTransmission(MPU6050_I2C_ADDRESS);
  n = Wire.write(start);
  if (n != 1)
    return (-10);
  n = Wire.endTransmission(false); // hold the I2C-bus
  if (n != 0)
    return (n);
  // Third parameter is true: relase I2C-bus after data is read.
  Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true);
  i = 0;
  while(Wire.available() && i<size)
  {
    buffer[i++]=Wire.read();
  }
  if ( i != size)
    return (-11);
  return (0); // return : no error
}
int MPU6050_write(int start, const uint8_t *pData, int size)
{
  int n, error;
  Wire.beginTransmission(MPU6050_I2C_ADDRESS);
  n = Wire.write(start); // write the start address
  if (n != 1)
    return (-20);
  n = Wire.write(pData, size); // write data bytes
  if (n != size)
    return (-21);
  error = Wire.endTransmission(true); // release the I2C-bus
  if (error != 0)
    return (error);
  return (0); // return : no error
}
int MPU6050_write_reg(int reg, uint8_t data)
{
  int error;
  error = MPU6050_write(reg, &data, 1);
  return (error);
}


2014년 2월 13일 목요일

모터 제어 모듈(AM-DC2-2D) - 블루투스를 이용한 자동차 키트 + 안드로이드 컨트롤러


---------------------------------------------------------------------------------

자동차라는 이름이 붙게 하게끔 만드는 장치인 모터 제어 모듈 입니다.
저는 AM-DC2-2D 라는 모듈을 이용하였습니다.
완성품을 보면 4륜 자동차의 모습을 가지고 있는데, 이 모듈은 좌우 2방향밖에 컨트롤 하지 못합니다. 때문에 저는 좌,우 회전은 좌우의 속도차를 이용하여 하는 방법을 하였습니다. 

AM-DC2-2D 모터제어모듈

이 모듈은 기본적으로 보이는 것과 같이 연결할 부분이 상당히 많습니다. 핀 갯수로만 보면 총 12개인데요.

이거는 AM-DC2-2D의 사진이 아니지만 구성은 비슷합니다. 다른점이 있다면 Motor이라는 부분이 녹색을 기준으로 2개씩 있습니다. 위의 AM-DC2-2D를 보면 알수 있습니다.

Control Signal 이라는 부분, Power Supply, Moter(흰부분 만 사용하면 됨) 라는 부분을 연결해야 합니다.

Power Supply는 모듈의 파워가 아닌 구동시킬 모터의 power를 연결 해야합니다. 저는 12V를 사용하는 모터를 사용했기 때문에 1.5V*8의 전원을 연결 하였습니다.

실물에서 Motor라는 부분을 보면 아래쪽에 CH1A,B라고 적혀있는데 이 모터와 연결하면 됩니다.



Control Signal

Control Signal 부분에 위 사진을 활용하여 신호를 주어야 합니다. 메뉴얼에서 정말 정말 편하게 설명해줍니다.  3줄정리를 하자면

PWM은 속도
DIR은 방향
/Enable은 작동 on/off

Enable은 /(not)이 있으므로 0입력시 on 1입력시 off입니다.
그리고 대부분의 모터는 "?V~??V"이런식으로 허용 범위가 정해져 있는 편인데요. 전원에 따라 파워(속도)의 차이가 있으므로 충분한 파워를 사용하는 것을 추천합니다.

 Dir와 Enable 신호는 on,off의 개념으로 작동하기 때문에 Digital 신호로 연결을 하였고 PWM신호는 PWM신호로 연결하였습니다.

이렇게 연결을 하면 모든 부분이 연결이 됩니다.

아래 부분은 스케치 입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
.....
#define LE 52
#define RE 53
#define LM 50
#define RM 51
#define LS 9
#define RS 12
.....//저의 설정입니다. 개인에 따라 변경하시면 됩니다.

int pwm = 120;// 속도

....
void setup(){
....
  pinMode(LE,OUTPUT);
  pinMode(RE,OUTPUT);
  pinMode(LM,OUTPUT);
  pinMode(RM,OUTPUT);
  pinMode(LS,OUTPUT);
  pinMode(RS,OUTPUT);//핀 출력모드
  digitalWrite(LE,LOW); // 왼쪽 모터 정지 정보 핀
  digitalWrite(RE,LOW); // 왼쪽 모터 정지 정보 핀
}

///
void loop(){
...

    digitalWrite(LM,HIGH); // 왼쪽 모터 전후진 정보 핀
    analogWrite(LS,LOW);
    digitalWrite(RM,HIGH); // 오른쪽 모터 전후진 정보 핀
    analogWrite(RS,LOW);
    delay(20);

...

    digitalWrite(LM,HIGH); // 왼쪽 모터 전후진 정보 핀
    analogWrite(LS,pwm);
    digitalWrite(RM,HIGH); // 오른쪽 모터 전후진 정보 핀
    analogWrite(RS,pwm);

...
}

digitalWrite는 0,1의 값을 즉 디지털 값을 쓸수 있고
alnalogWrite는 pwm값을 입력할수 있습니다. pwm값은 0~255값입니다.

위의 스케치에서와 같이 각 연결한 dir,enable,pwm을 통하여 전진 후진 속도를 컨트롤 할수 있습니다.

자이로센서(MPU 6050) - 블루투스를 이용한 자동차 키트 + 안드로이드 컨트롤러


---------------------------------------------------------------------------------

자동차 키드에서 가장 필요할거 같지만 저는 결국 활용을 못한 센서입니다.
MPU 6050 - 자이로+가속도 센서


MPU 6000,6050 datasheet

가속도계랑 자이로센서, 온도계가 있는데요  SDA (data line) and SCL (clock line)라는 선을 이용합니다. Arduino Uno와 같은 다른 Arduino에서는 따로 구분이 안되어 있어 그냥 사용 하면 되지만 Arduino 2560 Mega에서는 정해진 SCL,SDA선에 연결을 해야 하더군요. 그래서 별거 아닌데 몇 시간을 잡아 먹었습니다. ㅠ 



Arduino 2560 Mega

2560Mega에서는 20,21번에 연결하면 된다는 것을 알수 있습니다.
제가 고생하면서 다른곳에 연결한(고의x ㅠ) 결과, 센서의 결과값들이 상당히 튀면서 값이 들어오는 것을 알 수 있었습니다. 사용하는 방법을 찾아봤었는데 다른 곳에서는 INT를 사용하는 사용하지만, 센서값을 읽어오는 목적에서는 문제가 없습니다.

위의 MPU 6050의 pdf를 읽어보면 3.3v를 사용한다는 것을 알 수 있습니다.

위의 내용를 정리하여 정리하면
VCC는 3.3v, GND는 GND
SCL은 21, SDA는 20번
에 연결을 하면 되겠습니다.



아두이노의 스케치를 살펴보겠습니다.

출처는 아마.. 플레이아두이노 였던것으로 기억합니다.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#define MPU6050_ACCEL_XOUT_H 0x3B // R
#define MPU6050_PWR_MGMT_1 0x6B // R/W
#define MPU6050_PWR_MGMT_2 0x6C // R/W
#define MPU6050_WHO_AM_I 0x75 // R
#define MPU6050_I2C_ADDRESS 0x68
....
typedef union accel_t_gyro_union
{
  struct
  {
    uint8_t x_accel_h;
    uint8_t x_accel_l;
    uint8_t y_accel_h;
    uint8_t y_accel_l;
    uint8_t z_accel_h;
    uint8_t z_accel_l;
    uint8_t t_h;
    uint8_t t_l;
    uint8_t x_gyro_h;
    uint8_t x_gyro_l;
    uint8_t y_gyro_h;
    uint8_t y_gyro_l;
    uint8_t z_gyro_h;
    uint8_t z_gyro_l;
  }
  reg;
  struct
  {
    int x_accel;
    int y_accel;
    int z_accel;
    int temperature;
    int x_gyro;
    int y_gyro;
    int z_gyro;
  }
  value;
};
...

void setup(){
  ...
  error = MPU6050_read (MPU6050_WHO_AM_I, &c, 1);
  Serial.print(F("WHO_AM_I : "));
  Serial.print(c,HEX);
  Serial.print(F(", error = "));
  Serial.println(error,DEC);
  error = MPU6050_read (MPU6050_PWR_MGMT_2, &c, 1);
  Serial.print(F("PWR_MGMT_2 : "));
  Serial.print(c,HEX);
  Serial.print(F(", error = "));
  Serial.println(error,DEC);
  MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0);
  ...
}


void loop(){
........
    int error;
    double dT;
    accel_t_gyro_union accel_t_gyro;
    Serial.println(F(""));
    Serial.println(F("MPU-6050"));
    // Read the raw values.
    // Read 14 bytes at once,
    // containing acceleration, temperature and gyro.
    // With the default settings of the MPU-6050,
    // there is no filter enabled, and the values
    // are not very stable.
    error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
    Serial.print(F("Read accel, temp and gyro, error = "));
    Serial.println(error,DEC);
    // Swap all high and low bytes.
    // After this, the registers values are swapped,
    // so the structure name like x_accel_l does no
    // longer contain the lower byte.
    uint8_t swap;
#define SWAP(x,y) swap = x; x = y; y = swap
    SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
    SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
    SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
    SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
    SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
    SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
    SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);
    dT = ( (double) accel_t_gyro.value.temperature + 12412.0) / 340.0;

...........
}


int MPU6050_read(int start, uint8_t *buffer, int size)
{
  int i, n, error;
  Wire.beginTransmission(MPU6050_I2C_ADDRESS);
  n = Wire.write(start);
  if (n != 1)
    return (-10);
  n = Wire.endTransmission(false); // hold the I2C-bus
  if (n != 0)
    return (n);
  // Third parameter is true: relase I2C-bus after data is read.
  Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true);
  i = 0;
  while(Wire.available() && i<size)
  {
    buffer[i++]=Wire.read();
  }
  if ( i != size)
    return (-11);
  return (0); // return : no error
}
int MPU6050_write(int start, const uint8_t *pData, int size)
{
  int n, error;
  Wire.beginTransmission(MPU6050_I2C_ADDRESS);
  n = Wire.write(start); // write the start address
  if (n != 1)
    return (-20);
  n = Wire.write(pData, size); // write data bytes
  if (n != size)
    return (-21);
  error = Wire.endTransmission(true); // release the I2C-bus
  if (error != 0)
    return (error);
  return (0); // return : no error
}
int MPU6050_write_reg(int reg, uint8_t data)
{
  int error;
  error = MPU6050_write(reg, &data, 1);
  return (error);
}
위와 같이 작성한 결과를 통해

accel_t_gyro.value.temperature
accel_t_gyro.value.x_accel
accel_t_gyro.value.y_accel
accel_t_gyro.value.z_accel
accel_t_gyro.value.x_gyro
accel_t_gyro.value.y_gyro
accel_t_gyro.value.z_gyro

위의 이름으로 값을 받을 수 있습니다.

아래 3줄이 MPU 6050으로 부터 얻은 값들입니다.
이것을 활용을 해야하는데 못하겠어요 ㅠ

그리고 실험을 해보면 값들이 흔들리는 걸 볼 수 있는데
(위 그림에서 자동차 키트는 움직이지 않았습니다.)
PWM으로 신호를 받아와서 그렇다고 합니다.