'아두이노'에 해당되는 글 91건

  1. 2017.09.07 Hardware | SSD1331 96x64 full color OLED 를 사용해보자
  2. 2017.09.05 Software | u-blox 의 GPS 어플을 사용해 보자
  3. 2017.09.05 Hardware | FTDI Serial Adapter 를 사용해 보자
  4. 2017.09.05 Hardware | NEO-6M GPS 를 구동해 보자 2
  5. 2017.08.28 Hardware | Probe Clip 을 사용해 보자
  6. 2017.08.20 Hardware | Gyroscope GY-521 MPU-6050 을 사용해 보자
  7. 2017.08.17 Hardware | Resistor Network 을 사용해보자
  8. 2017.08.13 Hardware | LED bar graph 를 이용해 보자
  9. 2017.08.02 Hardware | Soil Moisture Sensor 구동해 보기
  10. 2017.07.31 Hardware | MB102 Breadboard Power Supply Module 를 사용해 보자

Hardware | SSD1331 96x64 full color OLED 를 사용해보자

|

1. Full Color OLED


Arduino 에 연결하여 표현해 주는 OLED 가 있습니다.

센서값을 보여주는 모니터링용으로는 괜찮아 보입니다.


Monochrome 제품은 이미 테스트 해봤습니다.


http://chocoball.tistory.com/entry/Hardware-SSD1306-128x64-monochrome-OLED


0.95 크기를 가지는 OLED 는 대략 세가지가 있는것 같습니다.


하나는 위의 Monochrome 이고,

두번째는 윗쪽이 노란색이고 밑에가 파란색인 제품.




마지막은 full color 제품 입니다.



AliExpress 에서 찾아보니 6.84 USD 로 판매되고 있습니다.


https://ko.aliexpress.com/item/0-95-Inch-SPI-Full-Color-OLED-Display-DIY-Module-96x64-LCD-For-Arduino-SSD1306-Driver/32790785282.html



재미있는 것은, 제품이 SSD1306 드라이버라고 사이트에 올라와 있는데,

SSD1306 은 Monochrome 제품용이고, full color 는 SSD1331 드라이버 입니다.

결국 사이트에 잘못 올린거지요.


SSD1331 용 full color OLED 는 10 USD 정도 인데, SSD1306 으로 검색되는 full color OLED 는 7 USD 정도 이니,

검색은 SSD1306 으로 되는 full color OLED 를 구매하면 이득입니다.


이번 글에서도 "SSD1331" 드라이버에 맞는 sketch 를 이용했습니다.




2. 도착


도착샷은 다음과 같습니다.



창이 달린 모니터 있다 보니, 뽁뽁이로 잘 쌓여서 왔습니다.



오호이. 상태는 좋아 보입니다.



제품의 줌샷 입니다.



뒷면입니다.


SSD1331 datasheet 는 다음과 같습니다.


SSD1331_1.2.pdf


아래 link 를 많이 참조 했습니다.


http://educ8s.tv/arduino-color-oled-display-tutorial/




3. Pinout


Arduino 와 pin 연결 정보 입니다.


    SSD1331  | Arduino Nano
----------------------------
     GND     |     GND
     VCC     |     3.3V
     SCL     |     D13
     SDA     |     D11
     RES     |     D9
     DC      |     D8
     CS      |     D10
----------------------------


Layout 은 다음과 같습니다.



참조 Youtube 동영상에서 캡춰한 내용이 가장 잘 맞는것 같네요.






3. Library


아래 GitHub 에서 SSD1331 라이브러리를 다운로드 받습니다.


https://github.com/adafruit/Adafruit-SSD1331-OLED-Driver-Library-for-Arduino


"/Arduino/Library/" 폴더에 다운로드 받은 파일을 넣어도 좋고,

아래처럼 Arduino IDE 에서 검색해서 install 할 수도 있습니다.


"Sketch > Include Library > Manage Libraries..." 에서 "gfx" 와 "SSD1331" 을 검색하면 install 되어 있으면 OK.

없으면 install 하면 됩니다.



"gfx" 를 검색하니, Adafruit GFX 가 이미 깔려 있네요.



"SSD1331" 을 검색하니, Adafruit SSD1331 OLED Driver Library for Arduino 도 이미 깔려 있습니다.





4. Sketch


"File > Examples > Adafruit SSD1331 OLED Driver Library for Arduino > test" 의 소스 입니다.


/*************************************************** 
  This is a example sketch demonstrating the graphics
  capabilities of the SSD1331 library  for the 0.96" 
  16-bit Color OLED with SSD1331 driver chip

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/684

  These displays use SPI to communicate, 4 or 5 pins are required to  
  interface
  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/


// You can use any (4 or) 5 pins 
#define sclk 13
#define mosi 11
#define cs   10
#define rst  9
#define dc   8


// Color definitions
#define	BLACK           0x0000
#define	BLUE            0x001F
#define	RED             0xF800
#define	GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0  
#define WHITE           0xFFFF

#include "Adafruit_GFX.h"
#include "Adafruit_SSD1331.h"
#include "SPI.h"

// Option 1: use any pins but a little slower
Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, mosi, sclk, rst);  

// Option 2: must use the hardware SPI pins 
// (for UNO thats sclk = 13 and sid = 11) and pin 10 must be 
// an output. This is much faster - also required if you want
// to use the microSD card (see the image drawing example)
//Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, rst);

float p = 3.1415926;

void setup(void) {
  Serial.begin(9600);
  Serial.print("hello!");
  display.begin();

  Serial.println("init");
  uint16_t time = millis();
  display.fillScreen(BLACK);
  time = millis() - time;
  
  Serial.println(time, DEC);
  delay(500);
   
  lcdTestPattern();
  delay(1000);
  
  display.fillScreen(BLACK);
  display.setCursor(0,0);
  display.print("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa");
  delay(1000);

  // tft print function!
  tftPrintTest();
  delay(2000);
  
  //a single pixel
  display.drawPixel(display.width()/2, display.height()/2, GREEN);
  delay(500);
  
  // line draw test
  testlines(YELLOW);
  delay(500);    
  
  // optimized lines
  testfastlines(RED, BLUE);
  delay(500);    
 
  testdrawrects(GREEN);
  delay(1000);

  testfillrects(YELLOW, MAGENTA);
  delay(1000);

  display.fillScreen(BLACK);
  testfillcircles(10, BLUE);
  testdrawcircles(10, WHITE);
  delay(1000);

  testroundrects();
  delay(500);
  
  testtriangles();
  delay(500);
  
  Serial.println("done");
  delay(1000);
}

void loop() {
}

void testlines(uint16_t color) {
   display.fillScreen(BLACK);
   for (int16_t x=0; x < display.width()-1; x+=6) {
     display.drawLine(0, 0, x, display.height()-1, color);
   }
   for (int16_t y=0; y < display.height()-1; y+=6) {
     display.drawLine(0, 0, display.width()-1, y, color);
   }
   
   display.fillScreen(BLACK);
   for (int16_t x=0; x < display.width()-1; x+=6) {
     display.drawLine(display.width()-1, 0, x, display.height()-1, color);
   }
   for (int16_t y=0; y < display.height()-1; y+=6) {
     display.drawLine(display.width()-1, 0, 0, y, color);
   }
   
   display.fillScreen(BLACK);
   for (int16_t x=0; x < display.width()-1; x+=6) {
     display.drawLine(0, display.height()-1, x, 0, color);
   }
   for (int16_t y=0; y < display.height()-1; y+=6) {
     display.drawLine(0, display.height()-1, display.width()-1, y, color);
   }

   display.fillScreen(BLACK);
   for (int16_t x=0; x < display.width()-1; x+=6) {
     display.drawLine(display.width()-1, display.height()-1, x, 0, color);
   }
   for (int16_t y=0; y < display.height()-1; y+=6) {
     display.drawLine(display.width()-1, display.height()-1, 0, y, color);
   }
   
}

void testdrawtext(char *text, uint16_t color) {
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);

  for (uint8_t i=0; i < 168; i++) {
    if (i == '\n') continue;
    display.write(i);
    if ((i > 0) && (i % 21 == 0))
      display.println();
  }    
}

void testfastlines(uint16_t color1, uint16_t color2) {
   display.fillScreen(BLACK);
   for (int16_t y=0; y < display.height()-1; y+=5) {
     display.drawFastHLine(0, y, display.width()-1, color1);
   }
   for (int16_t x=0; x < display.width()-1; x+=5) {
     display.drawFastVLine(x, 0, display.height()-1, color2);
   }
}

void testdrawrects(uint16_t color) {
 display.fillScreen(BLACK);
 for (int16_t x=0; x < display.height()-1; x+=6) {
   display.drawRect((display.width()-1)/2 -x/2, (display.height()-1)/2 -x/2 , x, x, color);
 }
}

void testfillrects(uint16_t color1, uint16_t color2) {
 display.fillScreen(BLACK);
 for (int16_t x=display.height()-1; x > 6; x-=6) {
   display.fillRect((display.width()-1)/2 -x/2, (display.height()-1)/2 -x/2 , x, x, color1);
   display.drawRect((display.width()-1)/2 -x/2, (display.height()-1)/2 -x/2 , x, x, color2);
 }
}

void testfillcircles(uint8_t radius, uint16_t color) {
  for (uint8_t x=radius; x < display.width()-1; x+=radius*2) {
    for (uint8_t y=radius; y < display.height()-1; y+=radius*2) {
      display.fillCircle(x, y, radius, color);
    }
  }  
}

void testdrawcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=0; x < display.width()-1+radius; x+=radius*2) {
    for (int16_t y=0; y < display.height()-1+radius; y+=radius*2) {
      display.drawCircle(x, y, radius, color);
    }
  }  
}

void testtriangles() {
  display.fillScreen(BLACK);
  int color = 0xF800;
  int t;
  int w = display.width()/2;
  int x = display.height();
  int y = 0;
  int z = display.width();
  for(t = 0 ; t <= 15; t+=1) {
    display.drawTriangle(w, y, y, x, z, x, color);
    x-=4;
    y+=4;
    z-=4;
    color+=100;
  }
}

void testroundrects() {
  display.fillScreen(BLACK);
  int color = 100;
  int i;
  int t;
  for(t = 0 ; t <= 4; t+=1) {
  int x = 0;
  int y = 0;
  int w = display.width();
  int h = display.height();
    for(i = 0 ; i <= 24; i+=1) {
    display.drawRoundRect(x, y, w, h, 5, color);
    x+=2;
    y+=3;
    w-=4;
    h-=6;
    color+=1100;
  }
  color+=100;
  }
}

void tftPrintTest() {
  display.fillScreen(BLACK);
  display.setCursor(0, 5);
  display.setTextColor(RED);  
  display.setTextSize(1);
  display.println("Hello World!");
  display.setTextColor(YELLOW, GREEN);
  display.setTextSize(2);
  display.print("Hello Wo");
  display.setTextColor(BLUE);
  display.setTextSize(3);
  display.print(1234.567);
  delay(1500);
  display.setCursor(0, 5);
  display.fillScreen(BLACK);
  display.setTextColor(WHITE);
  display.setTextSize(0);
  display.println("Hello World!");
  display.setTextSize(1);
  display.setTextColor(GREEN);
  display.print(p, 5);
  display.println(" Want pi?");
  display.print(8675309, HEX); // print 8,675,309 out in HEX!
  display.print(" Print HEX");
  display.setTextColor(WHITE);
  display.println("Sketch has been");
  display.println("running for: ");
  display.setTextColor(MAGENTA);
  display.print(millis() / 1000);
  display.setTextColor(WHITE);
  display.print(" seconds.");
}

void mediabuttons() {
 // play
  display.fillScreen(BLACK);
  display.fillRoundRect(25, 10, 78, 60, 8, WHITE);
  display.fillTriangle(42, 20, 42, 60, 90, 40, RED);
  delay(500);
  // pause
  display.fillRoundRect(25, 90, 78, 60, 8, WHITE);
  display.fillRoundRect(39, 98, 20, 45, 5, GREEN);
  display.fillRoundRect(69, 98, 20, 45, 5, GREEN);
  delay(500);
  // play color
  display.fillTriangle(42, 20, 42, 60, 90, 40, BLUE);
  delay(50);
  // pause color
  display.fillRoundRect(39, 98, 20, 45, 5, RED);
  display.fillRoundRect(69, 98, 20, 45, 5, RED);
  // play color
  display.fillTriangle(42, 20, 42, 60, 90, 40, GREEN);
}

/**************************************************************************/
/*! 
    @brief  Renders a simple test pattern on the LCD
*/
/**************************************************************************/
void lcdTestPattern(void)
{
  uint32_t i,j;
  display.goTo(0, 0);
  
  for(i=0;i<64;i++)
  {
    for(j=0;j<96;j++)
    {
      if(i>55){display.writeData(WHITE>>8);display.writeData(WHITE);}
      else if(i>47){display.writeData(BLUE>>8);display.writeData(BLUE);}
      else if(i>39){display.writeData(GREEN>>8);display.writeData(GREEN);}
      else if(i>31){display.writeData(CYAN>>8);display.writeData(CYAN);}
      else if(i>23){display.writeData(RED>>8);display.writeData(RED);}
      else if(i>15){display.writeData(MAGENTA>>8);display.writeData(MAGENTA);}
      else if(i>7){display.writeData(YELLOW>>8);display.writeData(YELLOW);}
      else {display.writeData(BLACK>>8);display.writeData(BLACK);}
    }
  }
}




5. 동작


위의 sketch 를 업로드 하고 pin 을 잘 연결하면, 아래와 같은 동작을 보여줍니다.



글씨, 배경색, 크기 등 여러가지를 확인해 볼 수 있습니다.



그림들도 잘 표현이 됩니다. 물론 컬러로.



SPI 프로토콜이라서 그런지, Monochorme 의 I2C 인터페이스보다는 확실히 빠른 성늘을 보여주네요.

다음은 동영상 입니다.





FIN


화면의 상하단의 색이 다른 OLED 는 SSD1306 을 사용한지라,

부분 컬러이긴 하지만, 더이상 OLED 는 구매하지 않아도 될 듯 해요.

And

Software | u-blox 의 GPS 어플을 사용해 보자

|

1. u-blox


생소한 이름인 u-blox 라는 회사는 GPS 칩을 만드는 스위스 회사 이름입니다.




https://en.wikipedia.org/wiki/U-blox

- https://www.u-blox.com/en


일전에 NEO-6M 이라는 GPS breakout board 를 이용해 놀아 봤는데, 그 메인 칩을 제조하는 회사지요.


GPS 가지고 노는 내용은 아래 link 를 참고하세요.


http://chocoball.tistory.com/entry/Hardware-NEO6M-GPS




2. u-center


GPS 칩을 만드는 회사가 그것을 활용하는 소프트웨어도 제공하고 있습니다.

이름하야 "u-center". 다운로드는 다음 link 에서 받을 수 있습니다.


https://www.u-blox.com/en/product/u-center-windows



Android 버전도 있네요. 저는 Windows 에서만 사용해 봤습니다.

사용자 manual 은 다운로드 받아 놨습니다.


u-center_UserGuide_(UBX-13005250).pdf





3. 설치


파일을 받고 설치를 시작합니다.

먼저 언어를 선택하고.



본격적으로 설치를 시작합니다.



라이센스에 Agree 해줍니다.



Standard Driver 와 Sensor Driver 를 설치하는 부분입니다.

Sensor Driver 는 breakout board 가 없을 경우를 말하는건가? 잘 모르겠습니다.

의심스러우면 걍 Standard Driver 를 쓰라고 합니다. 예...



인스톨할 디렉토리를 선택하고. (어차피 디폴트)



완료~!!!



인스톨된 버전을 확인해 보면 아래와 같습니다. 8.26 이네요.

회사 주소가 Switzerland 라고 나와 있습니다. 가보고 싶네요.



회사 주소는 여기라는 군요.


- u-blox AG Zürcherstrasse 68 8800 Thalwil Switzerland


궁금해서 Google Maps 의 street view 로 확인해 봤습니다.

좋은 동네같아요. 깔끔하고. 이런곳에서 일하면 인생이 윤택해질것 같습니다.






4. 기능


실행을 시키면 이런 식으로 확인 할 수 있습니다.

와~~~!!! 여러 정보가 보입니다.



처음에는 미국 위성만 잔뜩 보이더니만, 가끔 일본 위성도 뜹니다.

아쉽게도 한국 위성은 보이지 않습니다.



Sky View 에서는 방위 및 각도별로 표시해 줍니다.

이동 괘적도 보여주네요.



신호 강도에 대한 Histogram 을 보여주는 듯 합니다.



한국 하늘에서 측정한 것인데, 지구가 둥글다 보니, 다른곳의 위성도 같이 잡히는게 신기했습니다.



Satellite Signal History 에서는 각 위성에서 받는 신호 세기를 보여줍니다.



Statistic View 에서는 수신한 신호에서 유용한 data 를 뽑아서 보여줍니다.

실제적으로 이 data 를 가공하여 유용하게 사용될 것 같습니다.



현상태의 data 를 dump 뜨는 기능도 가지고 있습니다.

아마 문제가 생겼을 시에 사용되는 기능일 듯 합니다.



Chart 에서는 data 를 여러 형식으로 보여줍니다.

아래는 해발 높이를 보여주는 듯 합니다.



Messages 에서는 여러 data 의 현재 상태를 나타내 줍니다.





5. 정지한 상태에서 확인


정지한 상태에서 프로그램을 돌려 봤습니다.

베란다 난간에 외부 안테나를 설치하고 u-center 를 돌려 봅니다.



오오오! 신호를 잡아서 현재의 위치 및 시간을 알려줍니다.



대박입니다. 이렇게 비주얼하게 볼 수 있다니.

그리고 GPS 를 통하여 이루어지는 data 는 엄청 여러가지가 있네요.




6. 움직이면서 확인


차 위에 설치해도 되고 dashboard 에 설치해도 됩니다.

외부 antenna 는 밑부분이 자석으로 되어 있어서, 차의 어느곳에나 착 달라 붙어 고정됩니다.



빵판은 데쉬보드 위에 올려 놨습니다.

PC와의 연결은 FTDI 호환보드인 CP2102 입니다.


http://chocoball.tistory.com/entry/Hardware-FTDI-FT232RL-using



이동하면서 측정했더니 확연히 다른 모습을 보여줍니다.

방위가 실시간으로 바뀌고, 속도계가 반응하기 시작했습니다!!!



외부 안테나를 사용해도 되나, 길게 늘릴 필요가 없어 NEO-6M 에 동봉된 길이가 짧은 안테나를 차 내부에서도 사용해 봤습니다.



달리면서 측정하니, GPS 의 진정한 가치를 알게 되는것 같습니다.




7. firmware update


원래 NEO-6M 제품을 사용하고 있으나, u-center 에서는 "u-blox 7" 으로 인식하고 있습니다.

NEO-6MV2 라고 표시되어 있는 만큼 그 사이에 chip 이 upgrade 되어서 그러는지 모르겠습니다.



메뉴의 "firmware update ..." 가 있어서 실행해 봤습니다.



Firmware image 는 u-blox 사이트에서 다운로드 받았고,

Flash Information Structure 파일인 "flash.xml" 은 u-center 프로그램 파일이 설치된 폴더에 있습니다.


결과는 에러...



사이트에서 제품 특징들에 대해 확인해 봤습니다.


이런... firmware update 를 할 수 있는 flash 가 장착된 칩은 "M" 이 붙으면 안되고,

"N" 이 붙어야 합니다.


https://www.u-blox.com/en/product/neo-7-series




더욱이, NEO-6 시리즈에서는 firmware update 를 할 수 있는 버전이 없다는 사실... 


https://www.u-blox.com/en/product/neo-6-series




만일 firmware update 가 가능하다면, 아래처럼 Extenstion(s) 부분에서 FWVER 항목이 나와야 할 것 같습니다.

(구글링 해서 찾아 봄)


Messages 의 MON-VER 를 확인해 보면,

7 시리즈는 맞는것 같은데, FWVER 옵션이 보이지 않습니다.



바로 포기합니다. (이미 해볼껀 다 해봤슴)

NEO-6M 을 샀는데 7 serise 가 들어있는 것만 해도 희한한 상황입니다.




FIN


GPS 를 통하여 지상에서 위성을 통한 무료 data 를 받아 이렇게까지 활용할 수 있다는 것이 신기했습니다.

GPS 는 문명의 이기임에는 확실해 보입니다.

NEO-M8N 보드를 구입해서 확인해 보고 싶어집니다.

And

Hardware | FTDI Serial Adapter 를 사용해 보자

|

1. Flash Programming


무선 WIFI 모듈인 ESP8266 을 사용하여 wireless speaker 를 제작하려고 준비하고 있습니다.




그러기 위해서는 ESP8266 의 펌웨어를 프로그래밍 해줘야 하는데,

이를 위해서는 Serial Converter / Adapter 가 필요합니다.


이 Serial Adapter 는, 펌웨어 관련된 모든것에 사용되는 것 같습니다.

미리 알았더라면, 예전에 Flashrom writer 시에 사용했을 터인데...


http://chocoball.tistory.com/entry/Hardware-flashROM-fix


이런 다방면의 활용성을 가지고 있으므로, 한두개 구비해 놓은게 좋을것 같다고 생각되어

한꺼번에 2개를 구입합니다.


동일한 제품을 구매하면 재미가 없으므로, 각각 다른 chip 을 사용한 adapter 를 구매합니다.




2. Silicon Labs CP2102


FT232 대용으로 나온 chip 입니다.

동작은 완벽히 호환되었습니다.


Spec. Sheet 는 다음과 같습니다.


CP2102-9.pdf


기존의 FT232RL breakout board 와 비교하여 pinout 들이 간략화 되어 있어

보드 자체의 크기도 작고, chip 도 소형화 되어 있습니다.


구매는 아래 link 에서 진행했어요.


https://ko.aliexpress.com/item/CJMCU-CP2102-MICRO-USB-to-UART-TTL-Module-6Pin-Serial-Converter-UART-STC-Replace-FT232-NEW/32801557756.html


가격은 1.02 USD 로 부담이 없고 무료 배송입니다.



아래는 사이트에서 보여준 사진 입니다.

Chip 에 SILABS CP2102 라고 적혀 있는 것을 확인할 수 있습니다.



도착샷 들입니다.



보통은 USB 인터페이스 지만, 이 부품은 microUSB 입니다.



뒷면입니다.



Windows 에 USB를 통하여 연결하면, 알아서 드라이버를 잡아 줍니다.



장치 관리자에서 COM port 를 꼭 확인하여, 나중에 어플에서 잡아줄 때 참고하면 되겠습니다.






3. FTDI FT232RL


그 이름 그대로의 제품 입니다.

Chip 은 FT232RL 이네요.



가격은 1.65 USD 로 역시 저렴합니다.


Spec. Sheet 는 다음과 같습니다.


FT232RL.pdf


참고로 fake FT232RL chip 이 존재한다 합니다. Fake 제품이라고 해서 문제는 발생되지 않는다고 합니다.

다만, 원래 생산자의 시장을 잠식하면서, 막대한 손해를 끼치겠죠.


가장 단순한 판변법은, chip 상면에 세겨진 각인이 laser 로 쓰였는지, 프린팅 되었는지의 구분이라고 하네요.


https://zeptobars.com/en/read/FTDI-FT232RL-real-vs-fake-supereal


Chip 을 줌업 해봤습니다.

잘 모르겠지만 laser 로 쓰여진 듯 합니다. 그 사이에 fake chip 생산자의 기술이 올라갔을지 모르겠습니다.



구입은 아래 link 에서 진행했습니다.


https://ko.aliexpress.com/item/1pcs-FT232RL-FTDI-USB-3-3V-5-5V-to-TTL-Serial-Adapter-Module-forArduino-Mini-Port/32650148276.html


아래는 도착샷 입니다.


일반적인 포장으로 잘 왔습니다.

정전기 방지 포장도 되어 있습니다.



FTDI 용으로는 가장 많이 쓰이는 보드가 아닐까 합니다.



재미있는걸 하나 발견했습니다.
뒷면에 제품명이 프린팅 되어 있는데, 도착한 제품에는 "YP-05" 라고 되어 있고,
제품 소개 사이트에는 "FTD1232" 이라고 표기되어 있습니다.

일단 다른것도 그렇지만, FTDI 의 "I" 부분을 숫자 "1" 로 고쳐쓴 센스가 엿보입니다. 라이센스 문제를 피해가기 위함이겠죠?



아래는 제품 소개 사이트 뒷면 :-D



Windows driver 는 자동으로 잡힙니다.



처음에는 "FT232R USB UART" 로 인식한 후, driver 가 인스톨 완료 되면 아래와 같이, "USB Serial Converter / Port" 로 변경됩니다.



장치 관리자에서는 "USB Serial Port" 라고 표시됩니다.






4. 구동


NEO-6M GPS 와 연결해본 사진 입니다.

사진에는 FT232RL 만 보이지만, CP2102 로도 완벽히 동일하게 작동하였습니다.



NEO-6M 과의 자세한 동작 영상들은 아래 link 에서 확인해 보세요.


http://chocoball.tistory.com/entry/Software-ublox-GPS-application





FIN

정신을 차려 보니, 점점 많은 부품들이 제 주위에 쌓여가고 있습니다.

And

Hardware | NEO-6M GPS 를 구동해 보자

|

1. GPS


우리 생활에 이제는 필수가 된 GPS.

모바일 기기라면 이제 GPS 는 어디든 달려 있는 시대 입니다.



이게 Arduino 용의 breakout board 로 나와 줬네요.

센서에 목말라 있는 저로써는 꼭 구동해 보고싶은 센서 입니다.





2. 주문


AliExpress 에서 검색해 보면, 대략 3가지 제품으로 나뒵니다.

- Drone 용 소형 GPS : NEO-M8N

- 저가용 GPS : NEO-6M

- 그 외 안테나, 연장선 등의 부품


대략 저가용 GPS 인 NEO-6M 을 빼면, NEO-M8N 인데, 1만원이 넘어가는 나름 고가 센서가 됩니다.

우선 구동만을 확인해 볼 예정이므로, NEO-6M 을 구입합니다.


* NEO-6M 본체


https://ko.aliexpress.com/item/2pcs-lot-GY-NEO6MV2-new-GPS-module-with-Flight-Control-Flight-Control-EEPROM-MWC-APM2-5/1811853522.html



6천원 정도면, 밥 한끼 정도의 가격이므로, 취미의 즐거움을 위해 희생해 봅니다.


구입은 Arduino 취미를 시작한 작년 말에 구입했지만,

정작 사용해 보기까지는 시간이 걸렸습니다.


그 이유는 달려있는 안테나가 너무 짧아, 연장선을 구입하고, 다른 센서가지고 놀면서 늘어졌습니다.

GPS 는 좀 진득하게 사용해 봐야 할 것 같았거든요.



* 안테나 연장


https://ko.aliexpress.com/item/2016-New-GPS-Active-Remote-Antenna-Aerial-Connector-1575-42MHz-SMA-connector-For-3M/32616362445.html


PC 에 연결하여 확인하려면 외부로 가지고 나가야 하는데, laptop 이 필수 입니다.

구동 완료가 될 때까지 매번 밖에 나갈 수는 없으므로 연장 안테나를 구입합니다.



* 커넥터


https://ko.aliexpress.com/item/RF-pigtail-jumper-cable-6in-6-IPX-IPEX-I-PEX-U-FL-MHF-4-to-SMA/32357824395.html


연장 안테나의 끝 단자인 SMA Male connector 랑 breakout board 와의 연결을 위해,

SMA female connector 를 구입합니다.



다만 여기서 사고가 발생합니다.

바로 breakout board 에 있는 단자 크기를 몰라, 그냥 주문했더니, 맞지 않았습니다.


원래 breakout board 의 안테나 단자를 감싸야 하는데, 그 속으로 들어가버릴 정도로 작았습니다.

구매 사이트 사진에는 MHF-4 도 표시되어 있지만, 사실은 U. FL 규격을 구입해야 했었습니다.



결국 U. FL 규격의 SMA female 단자도 나중에 구입하지만,

또 기다려야 하니 좀이 쑤셔서 그냥 진행해 보기로 합니다.




3. 도착


도착은 3주정도 걸린 듯 합니다.



구성품은 NEO-6M breakout board 와 U. FL 커넥터가 달린 안테나 로 되어 있습니다.



여기에 문제의 "SMA female : MHF-4" 점퍼 입니다.



배송은 참 잘 왔습니다.



MHF-4 connector 는 WIFI 모듈에 자주 쓰이는 규격이라 아니, 나중에 또 쓸 일이 있겠죠?



판매자의 별 5개 요청 편지.

AliExpress 입점상들도 경쟁이 치열해지고 평가에 의해 매출이 달라지므로 신경을 많이 쓰는것 같습니다.

역시 글로벌로 장사를 하면, 사용자 피드백의 중요함이 사업에 있어서 크리티컬 하다는 것을 알 수 있습니다.


장사꾼들인 중국인들에게는 배울게 많습니다.



연장 안테나 모듀입니다.



배송은 잘 왔습니다.



이쪽 면이 자석으로 되어 있어서 차량이나 난간에 잘 고정이 됩니다.



난간에는 이렇게 설치 되었습니다.

왼쪽의 안테나는 FlightAware 용으로 세워진 안테나 입니다.

http://chocoball.tistory.com/entry/Hardware-PiAware-FlightAware





4. MHF-4


문제의 MHF-4 단자에 대해 살펴보기로 합니다.

구성품으로 달려있던 안테나 단자와 비교샷 입니다.


크기 자체의 차이로 따져 보면, 구성품의 connector 는 "U. FL" 규격으로 보입니다.

자세히 들여다 보면, 중심부에 꽂히는 심의 크기는 양쪽다 (MHF-4 / U. FL) 같아 보입니다.

여기서 착안하여 그냥 사용해 보기로 합니다.



원래는 이렇게 연결해서 사용됩니다.



U. FL 규격으로, breakout board 와 연결된 모습입니다.

외곽 금속을 커넥터가 잘 감싸 줘서 확실하게 고정이 되는 구조입니다.

이렇게 연결하면 손톱으로 튕기지 않는 한, 잘 붙어 있습니다.



SMA female : MHF-4 규격의 점퍼와 연결한 모습입니다.

Breakout 보드쪽 커넥터의 외경이 점퍼 외경을 반대로 감싸는 구조가 됩니다.

전기적 신호는 문제 없겠지만, 많이 헐겁습니다. 조금만 힘이 가해져도 금방 분리가 되어 버립니다. (진행하면서 가장 스트레스)



다시 주문한 "SMA-female : U. FL" 단자는 아직 도착하지 않았지만,

아래 구성처럼 연결하여 진행합니다.





5. Arduino 와 연결


Pin 들을 납땜해서 사용해도 되지만, 향후 어떤 보드에 실장하게 될 지 모르는지라,

납땜하지 않고 Probe Clip 을 이용하여 연결합니다.


Probe Clip 에 대해서는 다음 link 를 참조해 주세요.

http://chocoball.tistory.com/entry/Hardware-Probe-Clip



Arduino 와 연결된 모습입니다.





6. Layout


Pin 연결 정보 입니다.


    NEO-6M   | Arduino Nano
----------------------------
     VCC     |     3.3V
     RX      |     D9
     TX      |     D10
     GND     |     GND
----------------------------


보드 연결선은 다음과 같이 하면 됩니다.





7. Libaray 및 Sketch


여기서부터는 아래 사이트를 참고 하였습니다.


http://www.instructables.com/id/How-to-Communicate-Neo-6M-GPS-to-Arduino/


사전에 필요한 Library 는 다음 두가지 입니다.

미리 Arduino Library 폴더에 카피해 놓습니다.


* TinyGPS

http://arduiniana.org/libraries/tinygps/

https://github.com/mikalhart/TinyGPS


* SoftwareSerial

https://cdn.instructables.com/ORIG/F8C/OHR4/IVHQK4BI/F8COHR4IVHQK4BI.rar


위의 두 Library 가 준비되었다면, 아래 sketch 를 업로드해서 구동시킬 수 있습니다.


/*********************
 *10 to GPS Module TX*
 *09 to GPS Module RX*
 *********************/

#include "SoftwareSerial.h"
#include "TinyGPS.h"

SoftwareSerial mySerial(10, 9);
TinyGPS gps;

void gpsdump(TinyGPS &gps);
void printFloat(double f, int digits = 2);

void setup() {
	// Open serial communications and wait for port to open:
	Serial.begin(9600);
	// set the data rate for the SoftwareSerial port
	mySerial.begin(9600);
	delay(1000);
	Serial.println("uBlox Neo 6M");
	Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
	Serial.println("by Mikal Hart");
	Serial.println();
	Serial.print("Sizeof(gpsobject) = "); 
	Serial.println(sizeof(TinyGPS));
	Serial.println(); 
}

void loop() // run over and over
{
	bool newdata = false;
	unsigned long start = millis();
	// Every 5 seconds we print an update
	while (millis() - start < 5000) {
		if (mySerial.available()) {
			char c = mySerial.read();
			//Serial.print(c); // uncomment to see raw GPS data
			if (gps.encode(c)) {
				newdata = true;
				break; // uncomment to print new data immediately!
			}
		}
	}
  
	if (newdata) {
		Serial.println("Acquired Data");
		Serial.println("-------------");
		gpsdump(gps);
		Serial.println("-------------");
		Serial.println();
	}
}

void gpsdump(TinyGPS &gps) {
  long lat, lon;
  float flat, flon;
  unsigned long age, date, time, chars;
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned short sentences, failed;

  gps.get_position(&lat, &lon, &age);
  Serial.print("Lat/Long(10^-5 deg): "); Serial.print(lat); Serial.print(", "); Serial.print(lon); 
  Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms.");
  
  // On Arduino, GPS characters may be lost during lengthy Serial.print()
  // On Teensy, Serial prints to USB, which has large output buffering and
  //   runs very fast, so it's not necessary to worry about missing 4800
  //   baud GPS characters.

  gps.f_get_position(&flat, &flon, &age);
  Serial.print("Lat/Long(float): "); printFloat(flat, 5); Serial.print(", "); printFloat(flon, 5);
    Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms.");

  gps.get_datetime(&date, &time, &age);
  Serial.print("Date(ddmmyy): "); Serial.print(date); Serial.print(" Time(hhmmsscc): ");
    Serial.print(time);
  Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms.");

  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  Serial.print("Date: "); Serial.print(static_cast(month)); Serial.print("/"); 
    Serial.print(static_cast(day)); Serial.print("/"); Serial.print(year);
  Serial.print("  Time: "); Serial.print(static_cast(hour+8));  Serial.print(":"); //Serial.print("UTC +08:00 Malaysia");
    Serial.print(static_cast(minute)); Serial.print(":"); Serial.print(static_cast(second));
    Serial.print("."); Serial.print(static_cast(hundredths)); Serial.print(" UTC +08:00 Malaysia");
  Serial.print("  Fix age: ");  Serial.print(age); Serial.println("ms.");

  Serial.print("Alt(cm): "); Serial.print(gps.altitude()); Serial.print(" Course(10^-2 deg): ");
    Serial.print(gps.course()); Serial.print(" Speed(10^-2 knots): "); Serial.println(gps.speed());
  Serial.print("Alt(float): "); printFloat(gps.f_altitude()); Serial.print(" Course(float): ");
    printFloat(gps.f_course()); Serial.println();
  Serial.print("Speed(knots): "); printFloat(gps.f_speed_knots()); Serial.print(" (mph): ");
    printFloat(gps.f_speed_mph());
  Serial.print(" (mps): "); printFloat(gps.f_speed_mps()); Serial.print(" (kmph): ");
    printFloat(gps.f_speed_kmph()); Serial.println();

  gps.stats(&chars, &sentences, &failed);
  Serial.print("Stats: characters: "); Serial.print(chars); Serial.print(" sentences: ");
    Serial.print(sentences); Serial.print(" failed checksum: "); Serial.println(failed);
}

void printFloat(double number, int digits) {
	// Handle negative numbers
	if (number < 0.0) {
		Serial.print('-');
		number = -number;
	}

  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i=0; i 0)
    Serial.print("."); 

  // Extract digits from the remainder one at a time
  while (digits-- > 0) 
  {
    remainder *= 10.0;
    int toPrint = int(remainder);
    Serial.print(toPrint);
    remainder -= toPrint;
  }
}





8. 구동


실제 구동 영상입니다.

신호를 받기 시작하면 GPS의 LED 도 깜빡이면서 구동되고 있다는 것을 알 수 있습니다.



Arduino IDE 의 Serial Monitor 에서 아래와 같은 정보가 스크롤 됩니다.



정보를 보면 제대로 GPS 위성과 통신을 하는 것 같습니다.

확실히 베란다 난간에 GPS 안테나를 붙이니 정보를 잘 받네요.





FIN

일상 생활에서 GPS는 필수 기기 입니다.

눈에 보이지 않았던 중간 단계를 확인할 수 있어서 좋았습니다.





Update

"SMA Female - U. FL" 어뎁터가 도착했습니다.


딱 봐도 굵기가 다릅니다.

역시 신호와 전류는 두꺼운게 좋습니다.



커넥터 부분을 비교해 봤어요.

제일 밑에가 부속으로 딸려 있던 안테나, 중간이 잘못 구입한 MHF-3 규격, 윗부분이 새로 구입한 U. FL 규격 사진입니다.



전체 비교샷 입니다.



NEO-6M 에 바로 결속해 봤습니다.

딱 맞습니다. 손톱으로 의도적으로 뜯지 않는 한, 튼튼하게 결속되어 있습니다.



And

Hardware | Probe Clip 을 사용해 보자

|

1. Probe Clip


여러가지 sensor 들을 구입하다 보면, male pin 들이 납땜되지 않은 상태로 배달이 됩니다.



이건 이것대로 좋은 것 같습니다.

빵판을 이용하여 동작 확인이 아닌, 실장을 할 때에는 male pin 이 걸리적 거릴 수도 있고,

구부러진 pin 을 사용하는게 좋을 때도 있는 등, 상황이 바뀌기 때문이지요.


이를 해결하기 위해, Probe Clip 을 구매해 보기로 합니다.




2. Big Size Round Single Hook Clip for Test Probe


이름이 긴건 AliExpress 에서 그렇게 팔기 때문입니다.

사이즈가 Big Size 라고는 하지만, 사진상으로 적당해 보입니다.




다른 부품들과 함께 잘 도착했습니다.



구성물이 10개가 들어 있어서 왠만한 jumper 사용시 갯수는 충분할 것 같습니다.



개별 줌샷 입니다. 모양은 아주 단순합니다.



밑부분은 jumper 선을 체결할 수 있는 금속과 그 선을 밖으로 뺄 수 있는 구멍이 뚫려 있습니다.



Jumper 선을 체결할 수 있도록 되어 있습니다.

다만, 조금 복잡한 구조로 되어 있는데, 궂이 이럴 필요가 있나 싶습니다.

아마 좀더 복잡한 구조가 있는데, 간단하게 만들어 팔고 있는게 아닌가 합니다.

생산할 때는 기존 판금을 사용하면 추가 비용은 안들 터이니까요.



밑부분을 누르면 이렇게 hook 이 튀어 나옵니다. 이부분을 원하는 부분에 걸면 전기적으로 연결되는 것입니다.





3. Big Size 의 문제


Big Size 인 만큼, sensor 들의 pin 체결 구멍에 조금 큰 것이 문제입니다.

Male pin 의 간격은 2.54mm 인데, 두개를 동시에 연결하려면 hook 부분의 금속 자체도 잘 안들어갈 뿐만 아니라

뒤에 누르는 둥근 부분도 커서 간섭이 큽니다.


매번 귀찮다 하더라도 참고 쓰다가 좀더 작은 사이즈가 없나 찾아보게 됩니다.




4. Mini Grabber SMD IC Hook Probe Jumber Test Clip


제품명이 긴것은 그렇게 느끼는 것 뿐입니다.

가격은 비슷하나 갯수가 6개로 파는 제품을 찾았습니다.



이 제품은 SMD IC 다리들에게 걸 수 있도록 만들었다 하니,

원하는 크기에 딱 맞을 듯 합니다.


이런 시행착오을 겪어야 하는게 좀 번거롭습니다만, 이게 인생이라고 생각하고 주문합니다.




5. 도착


요즘 AliExpress 는 대략 2주 전후로 도착합니다.

예전에는 한달은 기본이었는데 말이죠.



궁딩이 부분을 누르면 앞에 hook 모양이 아닌, 집게 모양처럼 튀어 나옵니다.

의외로 잡는 힘이 쎄서 잘 고정되게 만들었습니다.

물론 크기도 작습니다.



궁딩이 부분의 플라스틱을 분리하면, 전선을 결합할 수 있는 구멍이 나옵니다.

구조도 단순하네요.





6. 전선 연결


각각의 색에 맞추어 jumper 선을 골라 주었습니다.

원래 양쪽에 pin 이 달려있는 breadboard 전용 jumber 입니다만, pin 부분을 잘라내고 피복을 벗겨 구리선을 노출시킨 후,

probe clip 의 동그란 구멍이 있는 밑부분에 말아주고 납땜을 해주었습니다.


이쁘게 되었네요! 만족스럽습니다.





7. 활용해 보기


구조적으로 Transistor Tester 에 Resistor Network 같은 부품은 측정할 수 없었으나,

이제 쉽게 할 수 있어요!


http://chocoball.tistory.com/entry/Hardware-Transistor-Tester



이제 원하는 sensor 에 직접 연결해 봅니다.



Big Size Clip 으로 했을 때에는 접점이 틀어지거나, 간섭으로 체결이 빠졌었는데,

이 mini Grabber 는 잡는 부분이 작을 뿐만 아니라, 힘도 좋아서 좀더 잘 고정이 됩니다.



전선 반대쪽에 pin 이 연결되어 있어서, 이제 편하게 빵판 활용시 sensor 동작 확인을 할 수 있을것 같습니다.




FIN

자 다음 센서~

And

Hardware | Gyroscope GY-521 MPU-6050 을 사용해 보자

|

1. 자이로스코프

드론이 호버링 하거나 방향전환시 필요한 것중 하나가 위치조정 일것 같습니다.

이런걸 가능하게 하는 센서가 "Gyroscope" 입니다.


중력을 이용하여 자기의 위치를 알아내는 센서가 있다는게 신기할 따름입니다.


AliExpress 에서 검색해 보니, 1.09 USD!

아니 이게 1천원정도의 가격이라고?





2. 원리

전통적인 자이로스코프는 원심력을 이용하여 자기 위치를 되돌리려는 성질의 기구가 있습니다.


https://en.wikipedia.org/wiki/Gyroscope



그런데, 이걸 반도체 안에 센싱하는 소자들을 구성하여 만든게 이번에 리뷰하는 MPU-6050 칩 입니다.



그림을 보니 중력을 이용하여 이동하는 mass 와 그걸 감지하고 원래로 복원하려고 하는 스프링 등으로 구성되었네요.

그 작은 반도체 안에 저런것을 만들어 놓다니. 거기에 1.09 USD 처럼 저렴하다는 것에 한번 더 놀랍니다.


관련된 문서는 아래에 있습니다.


IMU_Wk8.pptx

AN3461.pdf


어디선가 배웠던 "코리올리 효과"를 이용한다고 합니다.

참고해 보세요.




3. 도착

잊을만 하고 있을 적에 도착하였습니다. 거진 한달 걸린것 같습니다.



구성품은 GY-521 breakout 보드와 구부러진 male pin 과 똑바른 male pin 이 각각 들어있습니다.



Chip 을 보면 중간 부분에 희미하게 MPU-6050 이라고 적혀 있습니다.



좀더 잘 찍힌 제품사진은 다음과 같습니다. Chip 이 잘 보이네요.



뒷면입니다. MPU-6050 을 사용한 제품 중, 가장 일반적으로 사용되는 breakout 보드는 GY-521 이라고 하네요.



구부러진 pin 을 납땜하느냐, 곧은 pin 을 납땜하느냐 고민했습니다.

향후 어떤 보드 위에 설치하게 될 것이냐를 상상하여, 그 보드가 평평할 듯 하여 곧은 pin 을 납땜하였습니다.





4. Pinout

Breakout 보드에는 8개의 pinout이 있지만, 실제로 사용되는 것은 5개, 또는 6개만 사용됩니다.


    GY-521   | Arduino Nano
----------------------------
     VCC     |     3.3V
     GND     |     GND
     SCL     |     A5
     SDA     |     A4
     AD0     |     GND
     INT     |     D2
----------------------------


GY-521 pinout 에 대한 몇가지 지식을 적어 봅니다.

- 원래 3.3V 가 구동 voltage 이지만, GY-521 은 자체 레귤레이터가 있어서 5V 도 가능합니다.

- Arduino 에는 2개의 MPU-6050 을 연결할 수 있게 되어 있고, AD0 의 high/low voltage 로 구분합니다.

- SCL 은 I2C 의 clock 담당이고, SDA 는 data 를 담당합니다.


관련된 내용을 영문 페이지들에서 가져와 봤습니다.


The MPU-6050 can have address of 0x68 or 0x69, depending on if the AD0 pin is held high or low.

Without anything connected, it was at 0x68 for me.


AD0 can be used to control the I2C-address. If it is connected to ground then the address is 0x68 and if it is connected to VLOGIC then the address is 0x69. The data sheet for the chip states that VLOGIC ranges from 1.71V to the working voltage of the chip. To find out the address the I2C scanner sketch can be uploaded to the Arduino when it is connected to the GY-521. The result can be viewed through the serial monitor. For the GY-521 the I2C device is found at address 0x68. This means that ADO must be connected to a pull down resistor. This holds the signal at 0V.


The gyro module communicates with the Arduino through I2C serial communication via the serial clock (SCL) and data (SDA). The MPU6050 chip needs 3.3V but a voltage regulator on the GY-521 board allows you to give it up to 5V.


Layout 은 다음과 같습니다.



실제 연결한 사진입니다.






5. I2C

Arduino 와의 인터페이스가 I2C 입니다.

우선 잘 인식 되는지 확인해 보도록 합니다.


Arduino IDE 의 Library Manager 에서 "i2cdetect" 를 인스톨 하여 돌려봅니다.



소스는 간단합니다.


#include "Wire.h"
#include "i2cdetect.h"

void setup() {
	Wire.begin();
	Serial.begin(9600);
	Serial.println("i2cdetect example\n");
	Serial.print("Scanning address range 0x03-0x77\n\n");
}

void loop() {
	i2cdetect(); // default range from 0x03 to 0x77
	delay(2000);
}

결과는 다음과 같이 잘 나옵니다.

잘 인식 되었네요.



다만 MPU6050 전용 sketch 를 돌리기 위해서는 "I2Cdev.h" 가 IDE 에 등록이 되어야 합니다.

필요한 파일은 아래 링크에서 다운로드 받을 수 있습니다.


https://github.com/jrowberg/i2cdevlib



다운로드 받은 zip 파일 내부를 보면 "I2Cdev" 라는 폴더가 있습니다.

이 "I2Cdev" 폴더를 IDE 의 library 폴더 하위에 copy 하면 library 등록이 됩니다.


- I2Cdev path : i2cdevlib-master > Arduino > I2Cdev

- library path : Arduino > library


아래는 다운로드 받은 zip 파일의 path 입니다.



아래는 Arduino 의 library path 입니다.



이제 I2C 준비는 완료 되었습니다.




5. MPU-6050 sketch

이제 MPU-6050 을 구동해 볼 차례 입니다.


위에서 다운로드 받았던 zip 파일인 "i2cdevlib-master.zip" 에서 다음 path 에서 찾아보면,

"MPU6050" 이라는 폴더가 있습니다.


- I2Cdev path : i2cdevlib-master > Arduino > MPU6050


이 폴더를 I2Cdev 와 동일한 library 폴더에 옮겨 놓으면 sketch example 을 사용할 수 있게 됩니다.

 


소스는 다음과 같습니다.


// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0)
// 6/21/2012 by Jeff Rowberg 
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
//      2013-05-08 - added seamless Fastwire support
//                 - added note about gyro calibration
//      2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error
//      2012-06-20 - improved FIFO overflow handling and simplified read process
//      2012-06-19 - completely rearranged DMP initialization code and simplification
//      2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly
//      2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING
//      2012-06-05 - add gravity-compensated initial reference frame acceleration output
//                 - add 3D math helper file to DMP6 example sketch
//                 - add Euler output and Yaw/Pitch/Roll output formats
//      2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee)
//      2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250
//      2012-05-30 - basic DMP initialization working

/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 Jeff Rowberg

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/

// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"

#include "MPU6050_6Axis_MotionApps20.h"
//#include "MPU6050.h" // not necessary if using MotionApps include file

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu;
//MPU6050 mpu(0x69); // <-- use for AD0 high

/* =========================================================================
   NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch
   depends on the MPU-6050's INT pin being connected to the Arduino's
   external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is
   digital I/O pin 2.
 * ========================================================================= */

/* =========================================================================
   NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error
   when using Serial.write(buf, len). The Teapot output uses this method.
   The solution requires a modification to the Arduino USBAPI.h file, which
   is fortunately simple, but annoying. This will be fixed in the next IDE
   release. For more info, see these links:

   http://arduino.cc/forum/index.php/topic,109987.0.html
   http://code.google.com/p/arduino/issues/detail?id=958
 * ========================================================================= */



// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual
// quaternion components in a [w, x, y, z] format (not best for parsing
// on a remote host such as Processing or something though)
//#define OUTPUT_READABLE_QUATERNION

// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles
// (in degrees) calculated from the quaternions coming from the FIFO.
// Note that Euler angles suffer from gimbal lock (for more info, see
// http://en.wikipedia.org/wiki/Gimbal_lock)
//#define OUTPUT_READABLE_EULER

// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/
// pitch/roll angles (in degrees) calculated from the quaternions coming
// from the FIFO. Note this also requires gravity vector calculations.
// Also note that yaw/pitch/roll angles suffer from gimbal lock (for
// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock)
#define OUTPUT_READABLE_YAWPITCHROLL

// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration
// components with gravity removed. This acceleration reference frame is
// not compensated for orientation, so +X is always +X according to the
// sensor, just without the effects of gravity. If you want acceleration
// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead.
//#define OUTPUT_READABLE_REALACCEL

// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration
// components with gravity removed and adjusted for the world frame of
// reference (yaw is relative to initial orientation, since no magnetometer
// is present in this case). Could be quite handy in some cases.
//#define OUTPUT_READABLE_WORLDACCEL

// uncomment "OUTPUT_TEAPOT" if you want output that matches the
// format used for the InvenSense teapot demo
//#define OUTPUT_TEAPOT



#define INTERRUPT_PIN 2  // use pin 2 on Arduino Uno & most boards
#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };



// ================================================================
// ===               INTERRUPT DETECTION ROUTINE                ===
// ================================================================

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}



// ================================================================
// ===                      INITIAL SETUP                       ===
// ================================================================

void setup() {
    // join I2C bus (I2Cdev library doesn't do this automatically)
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
        Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif

    // initialize serial communication
    // (115200 chosen because it is required for Teapot Demo output, but it's
    // really up to you depending on your project)
    Serial.begin(115200);
    while (!Serial); // wait for Leonardo enumeration, others continue immediately

    // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio
    // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to
    // the baud timing being too misaligned with processor ticks. You must use
    // 38400 or slower in these cases, or use some kind of external separate
    // crystal solution for the UART timer.

    // initialize device
    Serial.println(F("Initializing I2C devices..."));
    mpu.initialize();
    pinMode(INTERRUPT_PIN, INPUT);

    // verify connection
    Serial.println(F("Testing device connections..."));
    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

    // wait for ready
    Serial.println(F("\nSend any character to begin DMP programming and demo: "));
    while (Serial.available() && Serial.read()); // empty buffer
    while (!Serial.available());                 // wait for data
    while (Serial.available() && Serial.read()); // empty buffer again

    // load and configure the DMP
    Serial.println(F("Initializing DMP..."));
    devStatus = mpu.dmpInitialize();

    // supply your own gyro offsets here, scaled for min sensitivity
    mpu.setXGyroOffset(220);
    mpu.setYGyroOffset(76);
    mpu.setZGyroOffset(-85);
    mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

    // make sure it worked (returns 0 if so)
    if (devStatus == 0) {
        // turn on the DMP, now that it's ready
        Serial.println(F("Enabling DMP..."));
        mpu.setDMPEnabled(true);

        // enable Arduino interrupt detection
        Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
        attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
        mpuIntStatus = mpu.getIntStatus();

        // set our DMP Ready flag so the main loop() function knows it's okay to use it
        Serial.println(F("DMP ready! Waiting for first interrupt..."));
        dmpReady = true;

        // get expected DMP packet size for later comparison
        packetSize = mpu.dmpGetFIFOPacketSize();
    } else {
        // ERROR!
        // 1 = initial memory load failed
        // 2 = DMP configuration updates failed
        // (if it's going to break, usually the code will be 1)
        Serial.print(F("DMP Initialization failed (code "));
        Serial.print(devStatus);
        Serial.println(F(")"));
    }

    // configure LED for output
    pinMode(LED_PIN, OUTPUT);
}



// ================================================================
// ===                    MAIN PROGRAM LOOP                     ===
// ================================================================

void loop() {
    // if programming failed, don't try to do anything
    if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize) {
        // other program behavior stuff here
        // .
        // .
        // .
        // if you are really paranoid you can frequently test in between other
        // stuff to see if mpuInterrupt is true, and if so, "break;" from the
        // while() loop to immediately process the MPU data
        // .
        // .
        // .
    }

    // reset interrupt flag and get INT_STATUS byte
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();

    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();
        Serial.println(F("FIFO overflow!"));

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {
        // wait for correct available data length, should be a VERY short wait
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

        // read a packet from FIFO
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        
        // track FIFO count here in case there is > 1 packet available
        // (this lets us immediately read more without waiting for an interrupt)
        fifoCount -= packetSize;

        #ifdef OUTPUT_READABLE_QUATERNION
            // display quaternion values in easy matrix form: w x y z
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            Serial.print("quat\t");
            Serial.print(q.w);
            Serial.print("\t");
            Serial.print(q.x);
            Serial.print("\t");
            Serial.print(q.y);
            Serial.print("\t");
            Serial.println(q.z);
        #endif

        #ifdef OUTPUT_READABLE_EULER
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetEuler(euler, &q);
            Serial.print("euler\t");
            Serial.print(euler[0] * 180/M_PI);
            Serial.print("\t");
            Serial.print(euler[1] * 180/M_PI);
            Serial.print("\t");
            Serial.println(euler[2] * 180/M_PI);
        #endif

        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            Serial.print("ypr\t");
            Serial.print(ypr[0] * 180/M_PI);
            Serial.print("\t");
            Serial.print(ypr[1] * 180/M_PI);
            Serial.print("\t");
            Serial.println(ypr[2] * 180/M_PI);
        #endif

        #ifdef OUTPUT_READABLE_REALACCEL
            // display real acceleration, adjusted to remove gravity
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetAccel(&aa, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
            Serial.print("areal\t");
            Serial.print(aaReal.x);
            Serial.print("\t");
            Serial.print(aaReal.y);
            Serial.print("\t");
            Serial.println(aaReal.z);
        #endif

        #ifdef OUTPUT_READABLE_WORLDACCEL
            // display initial world-frame acceleration, adjusted to remove gravity
            // and rotated based on known orientation from quaternion
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetAccel(&aa, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
            mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
            Serial.print("aworld\t");
            Serial.print(aaWorld.x);
            Serial.print("\t");
            Serial.print(aaWorld.y);
            Serial.print("\t");
            Serial.println(aaWorld.z);
        #endif
    
        #ifdef OUTPUT_TEAPOT
            // display quaternion values in InvenSense Teapot demo format:
            teapotPacket[2] = fifoBuffer[0];
            teapotPacket[3] = fifoBuffer[1];
            teapotPacket[4] = fifoBuffer[4];
            teapotPacket[5] = fifoBuffer[5];
            teapotPacket[6] = fifoBuffer[8];
            teapotPacket[7] = fifoBuffer[9];
            teapotPacket[8] = fifoBuffer[12];
            teapotPacket[9] = fifoBuffer[13];
            Serial.write(teapotPacket, 14);
            teapotPacket[11]++; // packetCount, loops at 0xFF on purpose
        #endif

        // blink LED to indicate activity
        blinkState = !blinkState;
        digitalWrite(LED_PIN, blinkState);
    }
}


Arduino 에 업로드 하여 확인해 봅니다.

Arduino IDE > Tools > Serial Monitor 를 열어서 확인해 봅니다.


Initializing 이 끝나고 준비상태가 되면, 어떤 character 든 보내면 측정이 시작됩니다.



Gyroscope 의 위치값들이 실시간으로 순식간에 측정이 되기 시작합니다.



잘 되네요.




6. Processing

3D 모델링을 통하여 Gyroscope 의 위치가 어떻게 보여지는지를 해봅니다.


다만, 우선 먼저 업로드 했던 sketch 를 조금 바꾸어서 업로드 해 놓을 필요가 있습니다.


- 코멘트 아웃 : #define OUTPUT_READABLE_YAWPITCHROLL

- 코멘트 제거 : #define OUTPUT_TEAPOT


이제 3D 가시화 하기 위해 "Processing IDE" 라는 프로그램을 다운로드 받고 인스톨 합니다.


https://processing.org/download/?processing



사용하는 OS 에 맞는 파일을 다운로드 받고 인스톨 합니다.



이제 Arduino MPU 6050 processing example 을 실행에 필요한 "Toxi" library 를 다운로드 받습니다.


https://bitbucket.org/postspectacular/toxiclibs/downloads/


지금 올라와 있는 최신 버전은 "toxiclibs-complete-0020.zip" 입니다.

다운로드 받으면 processing 폴더의 libraries 안에 copy 합니다.


- Program Files > processing > modes > java > libraries



아래는 copy 완료된 후의 libraries 폴더의 모습.



이제 processing 을 실행시킨 후, Arduino IDE libraries 폴더에 있는 MPU6050 example 에 있는 processing 용 파일을 엽니다.


- Arduino > libraries > MPU6050 > examples > MPU6050_DMP6 > Processing > MPUTeapot > MPUTeapot.pde



이것을 실행하기 전에 마지막으로 port 를 수정합니다.

저는 "COM6" 에 arduino 가 연결되어 있으므로 다음과 같이 수정하였습니다.


- String portName = "COM6";


Linux 의 경우는 "String portName = Serial.list()[0];" 을 활성화 하거나,

"String portName = /dev/ttyUSB0" 등과 같이 직접 기술해 주면 됩니다.



이제 준비는 완료 되었습니다.




7. 3D 결과

Processing 프로그램의 플레이 버튼인 "run" 을 실행시키면 다음 동영상 같이 비행체를 통하여 확인할 수 있습니다.



오오오오오!!! 정말 되었어!

동영상으로 찍어 봤습니다.



신기한 센서를 이용하여 가시화 하니 재미 있네요.




8. 3D object 변경해 보기

못생긴 비행기 모양은 112 ~ 139 라인에서 구현해 놨습니다.

이 모양을 바꾸고 싶으면 이 부분을 수정하면 됩니다.


수정하는 내용은 아래 URL 을 참고하면 되겠습니다.


https://processing.org/tutorials/p3d/


translate(width/2, height/2, 0);
stroke(255);
rotateX(PI/2);
rotateZ(-PI/6);
noFill();

beginShape();
vertex(-100, -100, -100);
vertex( 100, -100, -100);
vertex(   0,    0,  100);

vertex( 100, -100, -100);
vertex( 100,  100, -100);
vertex(   0,    0,  100);

vertex( 100, 100, -100);
vertex(-100, 100, -100);
vertex(   0,   0,  100);

vertex(-100,  100, -100);
vertex(-100, -100, -100);
vertex(   0,    0,  100);
endShape();


적용하면 다음과 같이 변경됩니다. :-)






FIN

주말에 GY-521 센서 가지고 잘 놀았습니다.

향후 드론을 만들게 되면 사용하게 될까요?

And

Hardware | Resistor Network 을 사용해보자

|

1. LED bargraph

LED bargraph 를 이용하여 progress bar 를 표현할 수 있습니다.

바로 Aliexpress 에서 구매해서 놀고 있었습니다.


http://chocoball.tistory.com/entry/Hardware-LED-bar-graph


LED bargraph 는 LED 들을 하나의 뭉치로 만든 제품이지만,

LED 의 특성상 전압/전류를 제한하기 위해 필수로 저항을 달게 되어 있습니다.


그래서 LED bargraph 에는 다리 하나하나에 저항을 달아줘야 합니다.

당연히 아래와 같이 붙여주거나 전선의 스파게티화를 볼 수 있습니다.



그러던 중, 응?!!!!!

아래와 같은 사진을 접하게 됩니다.

이리 깔끔해 질 수 있다니!!!



확인해보니, "Resistor Network" 이라는 부품이었습니다.

예전 90년대의 PC mainboard 에도 많이 보았던 부품이 이것이었구나... 라고 추억에 젖어 봅니다.



점이 있는 부분이 공통선이고, 각각의 다리가 하나의 저항 역할을 합니다.

머리를 잘 쓴 제품이네요.



Resistor network 을 일반 저항을 이용해서 만들면 다음과 같다고 하네요.





2. 주문

바로 AliExpress 에서 제품을 찾아 봅니다.

LED 에는 보통 220 Ohm 이나 330 Ohm 이 많이 쓰이는 것 같습니다.


220 / 330 짜리를 주문합니다.

330 짜리는 나중에 LED 8x8 matrix 에서도 사용해야 해서 미리 주문해 놓습니다.



위의 제품은 331J 라고 표시된 제품인데, 의미는 330 Ohm 에 5% 의 오차라는 뜻이라 합니다.





3. 스펙

잠깐 스펙에 대해서 알아보도로 하죠.

참고한 문서는 다음과 같습니다.


 L-373215.pdf


Resistor network 은 단순한 "-1 Circuit Based" 와 각각을 짝으로 맟준 "-3 Circuit Isolated" 가 있고,

"-5 Circuit Dual Terminator" 등이 있다고 합니다.



넘버링의 의미는 다음과 같습니다.

마지막 숫자는 맨 뒤에 "0" 이 몇개가 오는지와, "J" 는 5% 의 의미랍니다.



새로운 것을 또 공부하게 됩니다. 즐겁네요.




4. 도착

부품이 도착하여 여러가지 확인해 봤습니다.



50개 단위가 적당할 것 같아서 50개 묶음을 주문했더랬습니다.

낱개의 사진입니다. 쪼만쪼만한게 귀엽네요.



220 Ohm 사진도 올려 봅니다.



330 Ohm 의 실제 저항을 측정해 봤습니다.

일반 저항보다 정도가 더 좋습니다.

아마 허용 와트(W) 용량은 작겠지만, 정도는 정말 좋네요.





5. 연결해 보자

LED bargraph 에 연결해 봤습니다.



한번에 하나밖에 점등을 못시켰는데, 이제는 한꺼번에 LED 를 킬 수 있습니다!

역시 좋네요.


GND 연결선들도 복잡하여 모두 resistor network 으로 대체해 봅니다.

전류나 전압이 떨어지겠지만 LED 점등에는 문제 없을것 같아, +/- 모두 resistor network 를 연결해 봅니다.



완전 깔끔해 졌습니다. 맙소사.




FIN

74HC595 칩이 도착하면, 이제 대망의 arduino 와 연결하여 컨트롤 해볼 예정입니다.

아... 너무 즐겁습니다.

And

Hardware | LED bar graph 를 이용해 보자

|

1. 그래프

저는 graph pettish 입니다.

데이터를 가지고 그래프로 표현하는 것에 환장한다는 뜻이지요.


방대한 data 를 가지고 하나의 graph 로 표현하면서,

그 data 가 가지는 의미를 파악하는 것을 정말 좋아합니다.


요즈음은 big data 가 유행하고 있어, big data 를 가지고 가치있는 insight 를 발굴해 내는 사람을 data scientist 라고 부르기도 합니다.

아마 지금 직업이 아니였더라면 이쪽으로 갔을지도 모를 일입니다.



아두이노에 대해 웹서핑하다가 LED bar graph 를 가지고 진행 상황을 확인하는 동영상을 보게 됩니다.

그것도 graph 에다가 반짝이는 LED 를 엮어놓은 bar 입니다.


그래 저거야!

당장 구입하려고 조사해 봅니다.




2. 구입

오늘도 AliExpress 삼매경으로 구입 대상을 물색합니다.

여러 종류의 LED bar graph 가 존재하네요.


특히 색을 한가지밖에 표현 못하는 제품이 기본인 듯 합니다.

녹색이냐, 파란색이냐, 빨간색이냐...


또한, segment 라고 해서 한개의 bar 에 몇개의 LED 를 표현하느냐의 갯수의 선택도 해야 합니다.


일단 많이 표현하고 싶고, LED 는 기본이 빨간색이야, 라고 믿기에

빨간색 12 segment 짜리를 구입합니다.



스펙은 다음과 같다고 합니다.



내부 회로 구성은 다음과 같다고 하네요.



잘 보면, 하나하나의 LED 가 다음과 같은데,

이런 LED 를 하나의 패키징으로 만든 제품입니다.



모든 LED 관련 부품은 Anode / Cathode 방향이 중요합니다.

이거 잘못 하는 바람에 한개의 segment 를 날려 먹었습니다.




3. 원리

원리는 다음과 같다고 합니다.

전위차로 인하여 분리되어 있던 전자가 움직이면서 광자를 내는 원리 입니다. (뭔소리여)


그림이 잘 되어 있어서 가져와 봤습니다.

저도 이런 그림을 잘 그려보고 싶네요.





4. 도착

요즈음의 AliExpress 는 배송이 막 한달 걸리고 그러지 않는것 같습니다.

약 2주만에 도착했어요.


구성품은 빨간색 12 segment LED bar graph 가 5개 입니다.



밑면입니다.



옆면입니다.

다리의 간격은 빵판의 간격과 같습니다.



윗면입니다.





5. 테스트

아래와 같이 빵판에 연결합니다.



처음에 연결을 잘못 했습니다.

Anode / Cathod 를 반대로 했죠.

안켜지니 5V 에다도 연결을 했더랬습니다.


결과는 그 부분만 LED 가 나가버렸습니다.

예전에도 LED 한개짜리를 결손 잘못으로 인하여 나간적이 있었는데 똑같은 실수를 반복했습니다.


잘 찾아보니 모서리 부분에 갈아 낸것처럼 표시가 된 부분이 anode (+) 라고 하네요.



그럼 저항은 어느쪽에?

구글링하여 찾은 다음 사진처럼 anode 에 연결했습니다.



저항은 anode / cathod 어느 방향에다 설치하든 상관이 없다는 것을 방금 실험해서 알 수 있었습니다.

그래도 그림이 저렇게 되어 있으니 똑같이 해봅니다.




6. 결과

잘 동작합니다.



동영상도 올려 봅니다.

중간정도의 LED 는 동작하지 않습니다. 처음 제품 받았을 적에 anode / cathod 확인도 안하고, 5V 인가시에 죽은 segment 입니다.



속이 좀 쓰리긴 합니다만, 다음에는 이제 같은 실수는 안하겠죠?




FIN

LED segment 하나하나에 저항을 연결하지 않아도 되는 resistor network 라는 부품과

LED 점등을 관리해주는 74HC595 라는 chip 을 사용하여, 최종적으로 arduino 와 연결해 보려 합니다.


일단 부품이 오면 진행하는 것으로.

And

Hardware | Soil Moisture Sensor 구동해 보기

|

1. 농작물 automation

향후 나이를 먹으면, 농사를 지을 생각입니다.

다만, 전자 기기 경험과 IT 경력을 이용하여 가능한 전자동으로 하고싶습니다.


일조량, 물주기, 항온 항습, 통풍, 영양소 확인 등등...

그 목적을 위해 오늘도 Arduino 를 이용하여 열씸히 놀고 있습니다.


이 농사 automation 에서 토양의 수분 확인은 필수겠죠?

그래서 관련 센서들을 평소 찾아 다녔습니다.




2. Soil Moisture Sensor

네, 맞습니다. 한글로 번역하면 "토양 수분 감지기" 정도가 되겠습니다.

토양에 자동으로 물을 주려면 수분의 level 을 잘 감지해 내야겠죠?


AliExpress 에서 찾아 봅니다.



센서부에 금박이 칠해져 있고, 품질 좋은 것으로 호평받는 RobotDyn 사의 제품이 있습니다.

1.28 USD !!! 배송비 무료. 감사합니닷.




3. 도착

잊고 있었더니만 어느샌가 도착했습니다.



비닐 포장도 깔끔하게 되어 있고, 프린팅도 괜찮습니다.

간만에 괜찮은 품질의 제품을 만난것 같습니다.



개봉한 샷 입니다.



금빛 찬란하군요.





4. Layout

Pin 접속은 다음과 같습니다.


 Soil Moisture Sensor | Arduino Nano
-------------------------------------
          OUT         |     5V
          GND         |     GND
          VCC         |     D2
-------------------------------------


 128X64 OLED | Arduino Nano
----------------------------
     GND     |     GND
     VCC     |     3.3V
     SDA     |     A4
     SDL     |     A5
----------------------------

RobotDyn 제품의 원래 오리지날은 SparkFun 사의 "Soil Moisture Sensor" 일지도 모르겠습니다.


https://learn.sparkfun.com/tutorials/soil-moisture-sensor-hookup-guide


외관이 너무 비슷합니다.

그래서 고맙게도 IDE sketch 를 그대로 가져다 써도 잘 동작합니다.






5. Source

Sketch 는 다음과 같습니다.

OLED 를 붙여서 동작시키게 조금 수정하였습니다.


/*  Soil Mositure Basic Example
    This sketch was written by SparkFun Electronics
    Joel Bartlett 
    August 31, 2015

    Basic skecth to print out soil moisture values to the Serial Monitor 

    Released under the MIT License(http://opensource.org/licenses/MIT)
*/

#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#include "stdint.h"
 
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);


int val = 0; // value for storing moisture value 
int soilPin = A0; // declare a variable for the soil moisture sensor 
int soilPower = 7; // variable for Soil moisture Power

// rather than powering the sensor through the 3.3V or 5V pins, 
// we'll use a digital pin to power the sensor. This will 
// prevent corrosion of the sensor as it sits in the soil. 

void setup() {
	Serial.begin(57600); // open serial over USB
	
	pinMode(soilPower, OUTPUT); // set D7 as an OUTPUT
	digitalWrite(soilPower, LOW); // set to LOW so no power is flowing through the sensor
	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
}

void loop() {
	// get soil moisture value from the function below and print it
	int result = readSoil();
	Serial.print("Soil Moisture = ");    
	Serial.println(result);

	// clear the buffer
	display.clearDisplay();
	
	// text display tests
	display.setTextSize(2);
	display.setTextColor(WHITE);
	display.setCursor(0,0);
	display.print("Soil\n");
	display.print("Moisture\n");
	isplay.print("\n  == ");
	display.print(result);
	
	display.display();

	// this 1 second timefrme is used so you can test the sensor and see it change in real-time.
	// for in-plant applications, you will want to take readings much less frequently.
	delay(1000); // take a reading every second
}

// this is a function used to get the soil moisture content
int readSoil() {
	digitalWrite(soilPower, HIGH); // turn D7 "On"
	delay(10); // wait 10 milliseconds 
	val = analogRead(soilPin); // read the SIG value form sensor 
	digitalWrite(soilPower, LOW); // turn D7 "Off"
	return val; // send current moisture value
}


출처는 SparkFun 사의 위의 사이트 입니다.




6. 동작 확인

Pin 을 연결하고 sketch 를 업로드 한다음 제대로 동작하는지 확인해 봅니다.



화분에 물주고 확인해야 하는데, 일이 커지므로 손기운으로 측정으로 해봅니다.

잘 되네요!!!



실측값을 토대로 실제로 흙속에 넣고 해봐야겟지만, 동작확인이 되었으니 충분합니다.


아마 흙속에 계속 넣고 있으면, 금박 등이 다 삵아서 제대로 동작되지 않겠죠?

지속적인 사용은 못할 듯 합니다.

실제 농작물 automation 에 사용하려면 수분이 직접 닫지 않고도 측정되는 센서가 필요할 듯 합니다.


동영상도 한번 찍어봤습니다.


간단하게 잘 동작하네요.




FIN

아~ 나의 농작 automation~!!!

And

Hardware | MB102 Breadboard Power Supply Module 를 사용해 보자

|

1. 빵판

전자부품을 이용하여 놀려면 빵판이 필요합니다.

AliExpress 에서 빵판을 구매하기로 하고 돌아봅니다.



큰것도 있고 작은것도 있고...

큰거는 부담스럽고, 작은 것은 프로토타입 만드는 용도 정도라, 반쪽 사이즈를 찾아봅니다.


당연히 있네요.




2. 주문

AliExpress 에서 딱 적당한 크기의 빵판을 팔고 있습니다.


https://ko.aliexpress.com/item/Breadboard-830-Point-Solderless-PCB-Bread-Board-MB-102-MB102-Test-Develop-DIY/32339925888.html



특히 좋은 것은 몇 개의 lead 선들과 전원 모듈을 같이 동봉되어 있네요.



바로 주문합니다. 무료배송인지는 항상 확인합니다.




3. MB102 Power Supply Module

주문한 빵판에는 MB102 Power Supply Module 이라는, 전원 공급장치가 있습니다.

Arduino 에 필요한 5V/3.3V 는 물론이거니와 USB를 통한 전원도 공급하는 모양입니다.


원래는 YwRobot 이라는 회사에서 정식으로 제조되는 물건인데,

중국분들이 클론을 제조해 팔고 있는 듯 합니다.


요렇코롬 생겼습니다.

빵판의 +/- 에 딱 다리가 맞게 되어 있습니다.



한쪽에 다리가 두개씩 되어 있습니다.

다음과 같이 끼우면 됩니다.



뒷면입니다.

워낙 구조가 간단하다 보니 그렇게 특별하지 않아 보입니다.





4. 구동

전원을 인가해 봅니다.

단, 어느정도의 voltage 를 넣어도 되는지 아무런 설명서가 동봉되어 있지 않습니다.

뭐 늘상 그러려니 하고 인터넷을 뒤져 봅니다.


뭔가 복잡한 회로도가 나왔습니다.

각 단자들의 연결과 부품들이 나와 있습니다.

이렇게 잘 나와 있으니 카피 뜨는건 정말 쉬울 듯 합니다.



좀더 찾아보니 input voltage 를 명시한 그림이 있네요.

그렇습니다. "6V ~ 12V" 를 DC로 입력하라고 그러네요.



적당한 DC adapter 를 골라서 꼽아 줍니다.

집에는 9V / 1A 어뎁터가 있어, 이것을 이용합니다.





5. 전압 확인

전원을 인가했을 때, 전압이 제대로 나오는지 확인해 봅니다.

우선, 점퍼를 3.3V 으로 옮겨 놓고, 빵판의 전원 라인에 3.3V 가 되는지 확인해 봅니다.


3.273V... 뭐 적정한것 같습니다.



이번에는 5V 에 점퍼를 옮겨 놓고 측정해 봅니다.

4.94V... 나쁘지 않은 것 같습니다.



빵판의 전원선에 연결하는 것 외에

보드상에서 바로 3.3V / 5V / GND 핀으로만 되어 있는 부분에 연결해 봅니다.


3.3V / GND 를 확인해 보면, 3.273V 가 나옵니다.

어찌보면 당연하네요. 동일한 레귤레이터를 거쳐서 3.3V / 5V 를 만들어 내므로, 전원 리드선에서 나오는 값과 같을 수밖에 없습니다.



아쉬우니 5V / GND 핀도 측정해 봅니다.

동일하게 4.94V 가 측정됩니다.



USB 를 통한 전원 공급도 문제 없는지 봅니다.

Arduino Micro 가 잘 동작하네요.



5V / GND 와 USB를 동시에 사용했을때도 검사해 봅니다.

특별히 로드를 걸지 않아서 적절한 확인인지는 모르겠지만, 문제 없이 잘 나옵니다.



특별히 문제 없고 괜찮은 듯 합니다.

OLED 같이 항상 그 자리에 놓고 전원을 인가하는 module 일 경우는, 3.3V / GND 에 항상 연결해 놓고 사용해도 편할 것 같습니다.




6. 주의사항

아래 URL 에서 자세한 주의사항 및 spec. 정보가 있었습니다.


http://www.petervis.com/Raspberry_PI/Breadboard_Power_Supply/YwRobot_Breadboard_Power_Supply.html



이 사이트에서도 제품을 받고 사양을 믿고 바로 사용하지 말고, 꼭 디지털 미터기로 측정한 다음 사용해라고 나와 있습니다.

또한 어뎁터도 가능한 6.5V 근처의 것을 사용하라고 권장하고 있습니다.

이는, 어차피 5V / 3.3V 로 떨어트려 사용하므로, 레귤레이터에 무리가 없게 하려면, 낮으면 낮을 수록 좋을것 같습니다.


흠흠... 그렇군.





FIN

하나씩 알아가는 재미가 쏠쏠합니다.

And
prev | 1 | ··· | 4 | 5 | 6 | 7 | 8 | 9 | 10 | next