이번시간에는 아두이노의 고급 기능중 타이머에 대해 알아보겠습니다~



만약에 아두이노에 LED를 달고 1초 간격으로 깜빡이고 싶다면 어떻게 하시나요??


아마 예제에 있는 Blink처럼 짜면 되겠지요?ㅎㅎ



// the setup function runs once when you press reset or power the board

void setup() {

  // initialize digital pin LED_BUILTIN as an output.

  pinMode(LED_BUILTIN, OUTPUT);

}


// the loop function runs over and over again forever

void loop() {

  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)

  delay(1000);                       // wait for a second

  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW

  delay(1000);                       // wait for a second

}



자 그럼, 1초간격으로 LED는 깜빡이면서, 1초에 10번 아날로그 신호를 읽으려면 어떻게 해야할까요??


// the setup function runs once when you press reset or power the board

void setup() {

  // initialize digital pin LED_BUILTIN as an output.

  Serial.begin(9600);

  pinMode(LED_BUILTIN, OUTPUT);

}


// the loop function runs over and over again forever

void loop() {

  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)

  delay(1000);                       // wait for a second

  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW

  delay(1000);                       // wait for a second


  Serial.println(analogRead(A0));

  delay(100);

}


먼저 딜레이를 줘서 깜빡이는것 까지는 이해가 되지요?

그럼 이 상황에서 시리얼 모니터를 켜보면.... 엥??

1초에 10번이 아니라, 거의 2초에 한 번 정도 업데이트가 되죠?


이유는 바로 이 delay()함수 때문이에요!

delay()함수가 실행되면 해당된 시간이 지나기전까지는 그 뒤의 코드로 넘어가지 않습니다.


그럼 도대체 어떻게 해야


1) 1초 간격으로 LED를 깜빡이면서,

2) 1초에 10번 아날로그 신호를 받는 것


이 가능할까요??


바로 타이머(Timer)를 이용하는 겁니다.


타이머란,

아두이노 회로의 오실레이터에서 생성되는 클럭을 이용해 물리적인 시간을 측정하는 것으로,

딜레이의 경우, delay(1000) 이면 1000ms동안 생성되는 클럭이 있더라도 아무 일을 못하는 경우지만, 

타이머로 1000ms을 준다면, 1000ms 주기의 클럭이 생길 때 마다 특정일을 하므로

멀티테스킹(멀티쓰레드)과 비슷한 효과를 줄 수 있습니다.



http://playground.arduino.cc/Code/Timer

위 페이지로 가시면, 타이머 라이브러리에 대한 설명이 있고,


https://github.com/JChristensen/Timer

위 페이지에서는 해당 라이브러리를 다운받을 수 있습니다.


다운받고 압축을 푸시면 폴더가 생길텐데, 이 폴더를 내 문서->Arduino->Library 폴더에 통째로 넣어주시고

아두이노를 다시 실행하세요!


예제에 가시면 Timer-master -> blink2 가 있을거에요

열어서 실행해보시면 딱히 변한거 없이 LED가 깜빡이는걸 보실 수 있을겁니다


그럼 1초당 10번 아날로그 신호 모니터링은 어떻게 할까요?


바로 every 함수를 사용하면 해결할 수 있습니다.




#include "Timer.h"


const int LED1 = 13;

const unsigned long PERIOD1 = 1000;    //one second


Timer t;                               //instantiate the timer object

Timer led;                            //timer for analogRead function.


void setup(void)

{

    Serial.begin(9600);

    pinMode(LED1, OUTPUT);

    t.oscillate(LED1, PERIOD1, HIGH);

    led.every(100,readData);

}


void loop( )

{

    t.update();

    led.update();

}


void readData(){

  Serial.println(analogRead(A0));

  return 0;

}



자 그러면 깔끔하게 해결이 되지요ㅎㅎ


다만!! 메인 루프에 딜레이를 넣는순간 모든 타이머들이 뒤로 밀려나기때문에 조심하셔야되요!


이상 타이머를 이용한 멀티테스킹이었습니다^^



이번 포스팅에서는 433MHz 무선통신 모듈 사용에 대해 전해드리겠습니다.


우선 보통 무선통신 모듈 하면 블루투스나 와이파이가 가장 흔히 사용이 되는데, 아무래도 통신거리에 제한이 많기때문에 원거리 조종이  필요한 경우에는 RF 모듈을 사용하죠.


이번에 사용할 모듈스펙을 볼까요? 

모듈명 : AS07-M1101S (중국 카피제품인듯 합니다ㅎㅎ 'CC1101 Module' 로 검색하시면 자료를 더 찾으실 수 있어요!)

RF주파수 : 420 ~ 450MHz

통신 거리 : ~ 1Km

인가 전압 : 1.8 ~ 3.6V

가동 온도 : -40 ~ 85 

데이터 전송 속도 : ~ 500Kb/s

소모 전류 : ~17mA(수신), ~30mA(송신)


이 모듈을 이용하면 최장 1km가 떨어진 거리에서도 데이터 송수신이 가능하다고 합니다...!!

(하지만 장애물이 있는 실내의 경우 테스트결과 100~200m 만 넘어가도 데이터 송수신이 원활하지가 않더라구요...ㅠㅠ)



이번엔 아두이노 보드 2개와 433MHz 통신모듈 2개로 각각 송신기기, 수신기기를 만들어보겠습니다.


우선 핀배치가 1.27pitch여서 기존 빵판(2.54 pitch)에 사용할수 없기때문에 손수 납땜을 통해 와이어링을 했습니다.


납땜에 자신이 없으신 분은 1.27pitch 에서 2.54pitch로 변환해주는 보드를 구매하시거나, 1.27pitch의 PCB 만능기판에 납땜하셔서 1칸씩 건너뛰어 와이어링 하시면 2.54pitch에 맞게 사용하실 수 있어요^^



자 이제 전선도 뽑아냈으니, 아두이노와 연결해볼까요~?


우선 본 무선통신 모듈은 아두이노와 연결되어 SPI통신을 통해 데이터를 주고받습니다.

SPI통신이란 Serial Peripheral Interface의 줄임말로, 모토로라에서 고안해낸 통신방식입니다.

이 통신은 하나의 Master 모듈과 여러개의 Slave 모듈이 연결되는 (Peripheral) 방식의 통신으로, 


MISO (Master Input Slave Output) : Master기준 입력신호

MOSI (Master Output Slave Input) : Master기준 출력신호

SCK (Serial Clock) : Master로부터 나오는 Clock (신호 동기화를 위한 Clock)

SS (Slave Select) : 여러개의 Slave모듈이 연결되었을때, 특정 모듈을 선택하여 통신할수 있게끔 해주는 신호 (Enable 핀과 비슷한 역할을 합니다)


위와 같은 총 네개의 핀으로 통신을 합니다.

더 구체적인 내용들은 통신에 대한 설명 포스팅에서 자세히 다루겠습니다^^


자 그럼 아두이노와 무선모듈을 어떻게 연결하면 될까요?


  <433MHz 모듈>    <아두이노>


GOD0    ------       2

GOD2    ------       9

CSN/SS  ------      10

MISO*    ------      11

MOSI     ------      12

SCK       ------      13

VCC       ------    3.3V

GND      ------    GND


(아무래도 GOD1핀에 대한 설명이 부족해서 찾질 못했지만, 테스트해보니 MISO핀이 맞습니다.)



송신모듈 (Transmitter)



#include <ELECHOUSE_CC1101.h>


#define size 11


byte TX_buffer[size]={0};

byte i;


void setup()

{

  Serial.begin(9600);

  ELECHOUSE_cc1101.Init();

  for(i=0;i<size;i++)

  {

     TX_buffer[i]=i;

  }

}


void loop()

{

  ELECHOUSE_cc1101.SendData(TX_buffer,size);

  delay(1);

}




수신모듈(Receiver)





#include <ELECHOUSE_CC1101.h>

 

 void setup()

{

  Serial.begin(9600);

  ELECHOUSE_cc1101.Init();

  ELECHOUSE_cc1101.SetReceive();

}


byte RX_buffer[11]={0};

byte size,i,flag;


void loop()

{

  if(ELECHOUSE_cc1101.CheckReceiveFlag())

  {

    size=ELECHOUSE_cc1101.ReceiveData(RX_buffer);

    for(i=0;i<size;i++)

    {

      Serial.print(RX_buffer[i],DEC);

      Serial.print("  ");

    }

    Serial.println("");

    ELECHOUSE_cc1101.SetReceive();

  }

}




각각의 모듈에 위 코드를 심어주고, Receiver모듈을 잡아서 시리얼 모니터를 보시게되면 아래와 같이 0~10까지 Transmitter 모듈에서 전송된 숫자가 나타나게 됩니다.




위 예제코드는 첨부파일로 올려두겠습니다^^

CC1101.zip

Panstamp.zip


위 코드는 CC1101에 해당하는 예제이고, Panstamp는 조금더 복잡한, RSSI, Data length, CRC 등등을 확인하는 함수들을 사용한답니다ㅎㅎ


Panstamp코드를 실행하면 아래와 같이 신호강도(RSSI), 데이터 길이, 패킷정보 등 다양하게 확인할 수 있고, 이 함수를 이용해 실질적으로 프로젝트에 사용할 수 있습니다.



이렇게 433mHz 무선통신 모듈의 사용법을 알아보았습니다^^


디테일한 설명들이 부족하긴 하지만, 궁금한점이 있으시면 댓글 남겨주세요~!


지난시간에 이어 이번시간에는 OLED모듈에 원하는 아이콘을 어떻게 그리는지에 대해 알아보도록 하겠습니다.


보통 한장의 사진을 컴퓨터에 저장할때 흔히들 사용하는 포멧이 .jpeg, .jpg, .png 등등 이러한 형태일텐데요~

대부분의 이미지들은 원본 데이터를 압축하여 저장을 하게 된답니다. 때문에 미세하게 보면 일그러지거나 왜곡되는 현상이 부분부분 나타나게 된답니다.


그렇다면 원본 데이터를 손상없이 저장하려면 어떻게 해야할까요? 바로 비트맵(Bitmap, ~.bmp) 형식의 파일입니다.


비트맵이란, 말 그대로 각각의 데이터(비트)를 일일이 매핑하여 나타내는 것으로, 압축되지않은, 픽셀단위의 데이터를 모두 보관하고 있는 이미지입니다.


왜 뜬금없이 비트맵을 설명했냐하면!!


보통의 LCD, LED 디스플레이의 경우, 하나 하나의 점(픽셀)을 이용해 글씨나 그림을 나타내는 방식으로, 이를 원하는 그림으로 바꾸기 위해서는 각각의 픽셀을 켜고, 끄는것을 통해 제어를 해야합니다.


간단히 예를 들어보면,


지난 포스팅의 마지막부분에 보여드렸던 

  B00000000, B11000000,

  B00000001, B11000000,

  B00000001, B11000000,

  B00000011, B11100000,

  B11110011, B11100000,

  B11111110, B11111000,

  B01111110, B11111111,

  B00110011, B10011111,

  B00011111, B11111100,

  B00001101, B01110000,

  B00011011, B10100000,

  B00111111, B11100000,

  B00111111, B11110000,

  B01111100, B11110000,

  B01110000, B01110000,

  B00000000, B00110000


이 데이터를 보면 대체 뭔가 싶기도 하시겠지만, 사실 이 자체가 하나의 그림을 나타내고 있답니다.


이를 좀더 그림같아 보이게 표에다가 넣어보면


위와 같이 나올텐데, 직관적으로 어떤 그림인지 감이 안오시죠?


그렇다면 1이된 부분만 색칠해보면(1이된 부분만 불이 켜지니깐요^^),



짜잔...! 엉성하긴 하지만 나름 별모양이지요? 

네 바로 Adafruit 회사의 로고모양입니다.


이번 시간에는 I2C 통신을 이용한 128x64 OLED 디스플레이 모듈 사용에 대해 배워보겠습니다.


먼저, I2C 통신을 하기 위해서는 장치의 Address를 알아야 하는데, 보통은 장치의 Spec sheet를 보면 나와있습니다.

만에 하나 Address를 모른다고 하면, 아래처럼 하드웨어를 연결하고 코드를 업로드 하시면 연결된 장치의 Address를 알 수 있습니다^^


 

 OLED모듈    아두이노

     VCC  ----  5V
     GND ---- GND

     SDA ---- SDA (A4)

     SCL  ---- SCL (A5)



  1. // --------------------------------------
  2. // i2c_scanner
  3. //
  4. // Version 1
  5. //    This program (or code that looks like it)
  6. //    can be found in many places.
  7. //    For example on the Arduino.cc forum.
  8. //    The original author is not know.
  9. // Version 2, Juni 2012, Using Arduino 1.0.1
  10. //     Adapted to be as simple as possible by Arduino.cc user Krodal
  11. // Version 3, Feb 26  2013
  12. //    V3 by louarnold
  13. // Version 4, March 3, 2013, Using Arduino 1.0.3
  14. //    by Arduino.cc user Krodal.
  15. //    Changes by louarnold removed.
  16. //    Scanning addresses changed from 0...127 to 1...119,
  17. //    according to the i2c scanner by Nick Gammon
  18. //    http://www.gammon.com.au/forum/?id=10896
  19. // Version 5, March 28, 2013
  20. //    As version 4, but address scans now to 127.
  21. //    A sensor seems to use address 120.
  22. // Version 6, November 27, 2015.
  23. //    Added waiting for the Leonardo serial communication.
  24. //
  25. //
  26. // This sketch tests the standard 7-bit addresses
  27. // Devices with higher bit address might not be seen properly.
  28. //
  29.  
  30. #include <Wire.h>
  31.  
  32.  
  33. void setup()
  34. {
  35.   Wire.begin();
  36.  
  37.   Serial.begin(9600);
  38.   while (!Serial);             // Leonardo: wait for serial monitor
  39.   Serial.println("\nI2C Scanner");
  40. }
  41.  
  42.  
  43. void loop()
  44. {
  45.   byte error, address;
  46.   int nDevices;
  47.  
  48.   Serial.println("Scanning...");
  49.  
  50.   nDevices = 0;
  51.   for(address = 1; address < 127; address++ )
  52.   {
  53.     // The i2c_scanner uses the return value of
  54.     // the Write.endTransmisstion to see if
  55.     // a device did acknowledge to the address.
  56.     Wire.beginTransmission(address);
  57.     error = Wire.endTransmission();
  58.  
  59.     if (error == 0)
  60.     {
  61.       Serial.print("I2C device found at address 0x");
  62.       if (address<16)
  63.         Serial.print("0");
  64.       Serial.print(address,HEX);
  65.       Serial.println("  !");
  66.  
  67.       nDevices++;
  68.     }
  69.     else if (error==4)
  70.     {
  71.       Serial.print("Unknow error at address 0x");
  72.       if (address<16)
  73.         Serial.print("0");
  74.       Serial.println(address,HEX);
  75.     }    
  76.   }
  77.   if (nDevices == 0)
  78.     Serial.println("No I2C devices found\n");
  79.   else
  80.     Serial.println("done\n");
  81.  
  82.   delay(5000);           // wait 5 seconds for next scan
  83. }



그리고 시리얼 모니터 창을 켜보시면 아래와 같이 Address가 나옵니다.



자 그럼 Address도 알았겠다, 본격적으로 시작을 해보겠습니다.


우선 필요한 라이브러리부터 다운받도록 하겠습니다.

1. https://github.com/adafruit/Adafruit_SSD1306 (Adafruit_SSD1306)

2. https://github.com/adafruit/Adafruit-GFX-Library (Adafruit-GFX-Library)


위 라이브러리들을 다운받으신 뒤, 아래 폴더에 압축을 푸시면 아두이노에서 라이브러리를 쓰실 수 있습니다.

C:\Users\(사용자 이름)\Documents\Arduino\libraries


자 이제 아두이노를 실행시켜서 예제를 먼저 업로드 해보겠습니다.



제대로 업로드가 되면 아래와 같은 영상이 OLED 디스플레이에 나타나게 됩니다^^






본 디스플레이 모듈에서 특정 이미지나 아이콘을 보여주고싶으시다면, 


static const unsigned char PROGMEM logo16_glcd_bmp[] =

{ B00000000, B11000000,

  B00000001, B11000000,

  B00000001, B11000000,

  B00000011, B11100000,

  B11110011, B11100000,

  B11111110, B11111000,

  B01111110, B11111111,

  B00110011, B10011111,

  B00011111, B11111100,

  B00001101, B01110000,

  B00011011, B10100000,

  B00111111, B11100000,

  B00111111, B11110000,

  B01111100, B11110000,

  B01110000, B01110000,

  B00000000, B00110000

};


위와같이 특정 변수들을 define해주셔야 합니다.


그럼 다음시간엔 어떻게 원하는 아이콘을 디스플레이 하는지 배워보도록 할게요ㅎㅎ

아두이노기반 압력센서 개발 [2]



지난시간에 제작했던 압력센서를 이용해 아두이노와 프로세싱에서 값을 읽어보겠습니다.


자 먼저 아두이노기반 압력센서 개발 [1] 에서 만들었던 수정된 예제파일을 이용해 값을 볼 수도 있지만, 저희만의 프로그램을 짜보도록 합시다.


먼저 아두이노에서 코드를 더 수정해서 센서값만 받아와보도록 할까요?


/************************************************************************/

#include <Wire.h>

#include "Adafruit_MPR121.h"


// You can have up to 4 on one i2c bus but one is enough for testing!

Adafruit_MPR121 cap = Adafruit_MPR121();


void setup() {

  while (!Serial);        // needed to keep leonardo/micro from starting too fast!

  Serial.begin(9600);

  

  if (!cap.begin(0x5A)) {

    Serial.println("MPR121 not found, check wiring?");

    while (1);

  }

}


void loop() {

  for (uint8_t i=0; i<12; i++) {

    Serial.print(cap.filteredData(i)); Serial.print(" ");

  }

  Serial.println();

  // put a delay so it isn't overwhelming

  delay(100);

}

/************************************************************************/

이 코드를 입력하고나면 시리얼 모니터에서는 아래와 같이 데이터들이 쭉 나열되서 확인이 될겁니다.


그럼 끝 아닌가요??


네 데이터만 받아보는거는 이렇게만 하면 끝입니다. 다만 값을 0 - 1023까지 값이 아닌 실제 압력이나 무게로 변환하기 위해서는 보정(Calibration) 작업이 필요합니다.


보정방법은 단순히 측정 무게의 추를 올려서 무게를 측정하는 방법으로 진행했습니다.


무게와 센서값을 엑셀에 잘 정리하면 하나의 그래프를 그릴수 있습니다. 

저는 Matlab을 이용하여 그래프를 나타내고, fit() 함수를 사용하여 센서값과 최대한 근사된 다항함수를 이용하여 보정을 했습니다.


%%%%% Matlab Code %%%%%%%%

data = [0, 470;

        5.4, 433;

        10.8, 420;

        16.2, 380;

        21.6, 357;

        27.0, 342;

        32.4, 330;

        37.8, 315;

        43.2, 295;

        100.0, 203;

        200.0, 150;

        300.0, 137;

        400.0, 128;

        500.0, 130;

        1000.0, 72;

        1500.0, 53;

        2000.0, 63;

        2500.0, 45;

        3000.0, 33;];

    

force = data(:,1);

voltage = data(:,2)/1023*5;

 

figure();plot(force, voltage);

set(gca,'xscale','log');

hold on;

 

filtY=fit(force,voltage,'exp2');

plot(filtY, force, voltage);

hold off;


%%%%%%%%%%%%%%%%%%%%%%%


실제로 피팅하면 아래와 같은 보정 그래프를 볼 수 있고, 이를 통해 압력을 알 수 있습니다.


그럼 보정하는 다항식을 아두이노에 넣을건가? 

실시간으로 아두이노 모니터를 통해 보신다면 그게 좋지만, 혹시나 프로세싱이나 안드로이드 등 다른 프로그램을 통해 압력값을 본다면, 아두이노에서는 그냥 0 - 1023의 데이터를 보내고, 프로세싱, 안드로이드에서 보정을 해주는 것이 효율적이다!


그럼 프로세싱으로는 어떻게 값을 읽어올까?


먼저 아두이노에서 값을 던질때,


387 396 410 419 421 422 419 422  412 399  388 379

387 396 410 419 421 422 419 422  412 399  388 379

387 396 410 419 421 422 419 422  412 399  388 379


이런 식으로 데이터가 나올텐데, 만약


#387 396 410 419 421 422 419 422  412 399  388 379!

#387 396 410 419 421 422 419 422  412 399  388 379!

#387 396 410 419 421 422 419 422  412 399  388 379!


위와 같이 나온다면, 어디서부터 어디까지가 한번에 읽어들인 데이터인지 알 수 있다.


그럼 프로세싱에서도 위와같이 컴퓨터가 #이라는 데이터를 받아들인 순간부터 !를 읽어들일때 까지를 하나의 데이터로 인식하게끔 만들면 된다.


/*****************************************************/


// 시리얼 통신을 위한패키지 호출

import processing.serial.*;


// 시리얼 통신 및 콘솔 아우풋을 위한 설정

Serial  myPort;

PrintWriter output;


int     lf = 40;       

String  inString;      

float[] intensity = new float[8];


void setup() {

  size(288, 276);


  String portName = Serial.list()[2];

  // 위 함수에서 컴퓨터와 연결된 아두이노의 포트넘버를 확인하고 거기에 맞는 숫자를 입력해야한다. (여기선 2번째라 '2'가 들어갔다)

  //  println(Serial.list());


  myPort = new Serial(this, portName, 9600);

  myPort.clear();

  myPort.bufferUntil(lf);

}


void draw() {

  background(0);

}


void serialEvent(Serial p) {


  inString = (myPort.readString());

  try {

    String[] dataStrings = split(inString, ' ');


    if ('s' == dataStrings[0].charAt(0)) {

      // dataStrings.length = number of array elements seperated by '#'.

      for (int i = 1; i < dataStrings.length; i++) {   

        intensity[i-1] = Integer.parseInt(dataStrings[i].substring(0, 3));

output.print(intensity[i-1] + " ");

      }

    output.println();

    }

  }

  catch (Exception e) {

    println("Caught Exception");

    exit();

  }

}


// ESC키가 눌렸을 때 프로그램 종료

void keyPressed() {

  if (key == 27) { // 27 means ESC key

    exit(); // Stops the program

  }

}


/*****************************************************/



아마 사용하실 때 수정하셔야 할 부분은 serialEvent 함수 중에서 33 ~ 38번 줄만 수정하면 원하는 데이터 형태를 바로 정수로 변환하여 모니터링 할 수 있을거다.

만약 아두이노와 프로세싱간에 연동이 잘 된다면 아두이노의 시리얼 모니터에서 보는것과 같은 데이터가 프로세싱의 콘솔창에 나타날 것이다.

그 후 센서의 보정을 원한다면 프로세싱에서 작업을 해주면 된다 :)

사실 뒷부분은 예전에 센서를 제작한 터라 구체적인 설명이 부족합니다ㅠㅠ 
혹시나 프로젝트를 진행하시다가 궁금하거나 어려운점이 있으시면 댓글에 남겨주세요ㅎㅎ


Have a good time with Arduino :)



아두이노기반 압력센서 개발 [1]


이번엔 정전압 압력 센서를 제작해 봅시다.

먼저 센서를 만들기 전에 간단한 원리부터 살펴보면, 외부의 힘/압력에 대해 Capacitance의 값이 변하는 것을 정전압 압력센서라고 합니다.



물리에서 배웠다싶이 Capacitance는 면적에 비례하고 판과 판사이의 거리에 반비례합니다.

여기서 집중해야할 값은 판의 면적보다 판과 판의 거리입니다.

외부의 '힘(Force, F)' 이 가해지면 두 판 사이의 거리가 가까워지게되고, 이는 Capacitance를 증가시키게 되죠.


그리고 단위면적당 가해지는 힘을 '압력(Pressure, P)' 이라 표현하므로, 제작되는 센서는 압력을 측정할 수 있겠죠.

물론 구해진 압력에 센서의 '단면적(Area, A)' 을 곱하면 역으로 센서에 가해지는 힘 또한 알 수 있습니다ㅎㅎ....

(어려우시다면... 구글구글....!!)


또 다른 압력센서는 외부의 힘/압력에 대해 Resistance(저항)의 값이 변하는 센서인 Force Sensitive Resistor(FSR) Sensor 가 있습니다.



아마 아두이노를 조금 다뤄보신 분들은 위에처럼 생긴 센서를 사용해보신적이 있을거에요ㅎㅎ

저 센서가 바로 FSR 센서입니다. 

정전압 센서와는 달리 압력에 따라 저항이 바뀌는 형태기 때문에, 아두이노에 사용하기에는 좀 더 수월한 센서입니다.


원리는 위와 같은 여러 층의 필름들이 겹쳐져 있는것에서 보실수 있습니다.

중간 층은 윗층과 아랫층을 떨어뜨려주는 역할을 하고,
압력이 세질수록 아랫면의 Active dot들이 반도체에 닿이면서 저항이 변하게 된답니다.



자 지루한 원리는 이까지 설명하고!


Practical하게 FSR 압력센서 제작에 대해 배워봅시다.


우선 지난 포스팅에서 알려드린바와 같이 정전압 압력 시트 (Pressure-Sensitive Conductive Sheet)  <- (클릭!)

그리고 전도성 실만(?) 있으면 만들 수 있습니다.

물론 구하기 쉽지않은 재료이므로... 도전하실 분들만 한번 해보세요ㅎㅎ

(귀찮으신 분들은 나중에FSR, fouce sensitive resistor 을 구매해서 쓰세요!)


1. 먼저 100원짜리 동전을 시트위에 얹고 동그란 모양으로 시트를 오려줍니다.

2. 그 위에 전도성 실을 구불구불하게 모양을 잡고 테이프로 마무리 해줍니다.


3. 위 그림에서 보이듯, 전도성 실의 양쪽 끝 중 한쪽끝을 잘라내어 외부로 튀어나오지 않게 테이프 안으로 잘 넣어줍니다.

4. 시트를 뒤집어 뒷면도 전도성 실을 붙이는데, 앞면과 비교했을때 그물모양이 되도록 모양을 잡고 붙인뒤, 한쪽끝만 남기고 실을 정리합니다.

4. 이제 센서의 한쪽 끝을 GND에, 다른 한쪽 끝을 AI0핀에 꽂아줍니다.
  (실이라 잘 안될수도 있으니, 금속선에 묶어서 사용하시거나, 구리테이프를 이용하시면 수월할거에요ㅎㅎ)


5. 그리고 실 한쪽이 연결된 AI0 핀에 1Kohm 저항의 한쪽 다리를 연결해 주시고, 저항의 또 다른 한쪽 다리는 5V에 연결해주세요~!

  이렇게 연결하면 저절로 Voltage divider 회로가 구성이 된답니다.


AI0핀에 입력되는 전압(Vout)은 R2값이 변하면서 자동으로 변하게 됩니다!

Vout = 5V*( R2 / (R1+R2) ) 만큼 걸리게 됩니다. 


5. 그리고 코딩은 단순히 AI0핀의 값을 읽어오기만 하면 값의 변화를 확인 할 수 있답니다ㅎㅎ



그럼 다음포스팅에서는 여러개의 센서를 연결해서 어떻게 값을 받고, 센서값의 보정은 어떻게 하는지 한번 봅시다.

다음에 봬요~ 뿅!!


Have a good time with Arduino :)


아두이노와 정전압 터치센서를 활용한 센서 제작.


1. 준비물

- 아두이노 Leonardo (호환보드인 Pololu Atmega 32u4 보드 사용)

- 블루투스 HC-06 모듈                                                             

- Lipo 베터리                                                                             

- 정전압 압력 시트 (Adafruit에서 판매)                                       

- 전도성 실                                                                                

- 정전압 센서 모듈(Adafruit에서 판매)                                        



2.재료가 준비되었다면 한번 만들어 봅시다.


우선 오늘은

(1) 아두이노와 터치 모듈(MPR121) 의 I2C 통신


(2) 정전식 터치센서 제작


(3) 제작된 센서와 모듈을 이용한 센서값 읽기


세가지를 해보도록 하겠습니다.


(1)

아두이노와 터치모듈을 사용하기위해서는 I2C (Inter-Integrated Circuit) 통신을 해야한다.

디지털 통신에는 여려가지가 있지만, 주로 사용되는 통신은  Serial 통신, SPI통신, I2C통신,  CAN통신 등이다.

혹시나 다음에 포스팅할 기회가 된다면 통신에 대해 정리를 해보도록 하겠습니다 :)


아두이노와 보드의 연결은 아래와 같이 SCL (클럭핀) 과 SDA(데이터핀) 을 서로 연결하시고,

(아두이노 보드에 보시면 SCL, SDA핀이 있습니다. 실제로 이 핀은 아날로그인풋 4,5핀과 같은 핀이죠)



2번 핀에 연결되는 IRQ 핀은 터치가 입력되었을때 HIGH (1) 신호를 내보냅니다.

아두이노에서는 터치가 없을때 센서값을 읽어들일 이유가 없으므로, 인터럽트핀 (2번핀)에 연결하여 트리거 신호가 있을때만 센서를 읽어들이게 만들죠.


이제 아두이노 코딩을 해볼까요~?

우선 Adafruit 사이트에 가셔서 MPR121 보드에 대한 라이브러리를 다운받으시고,

아두이노 라이브러리 폴더에 저장해두세요! ( 내문서/Arduino/ )

그 다음 File -> Example -> Adafruit MPR121 -> MPR121 test  를 열고나서 업로드를 합니다.

(업로드 시에 board세팅과 USB 포트 세팅은 꼭 확인해보세요! pololu 보드의 경우 Leonardo 입니다!!)


센서가 제대로 동작하는지 확인하기위해서는 시리얼 모니터를 누르면 됩니다.

누르고 나면 아래와 같이 터치가 되었는지, 떨어졌는지를 알수 있죠.


하지만 본 예제에서는 터치가 됬는지, 안됬는지만 나오지만, 사실 우리가 사용해야하는것은 Capacitance의 값이므로, 코드를 손 볼 필요가 있다,


void loop()내의 코드를 자세히 보면 63번 줄에 " return; " 이 있다. 즉, return위까지 코드만 실행하고 그 아랫부분 코드는 실행하지 않은채 다시 루프를 시작한다는 소리다.


만약 이 부분을 지우거나 주석처리 ( //return;)를 하고, 기존의 47번줄 부터 57번줄 (touch release를 프린트하는 부분)도 주석처리를 하시면 아래와 같은 그림이 나옵니다.

 

Base 값은 터치의 유무를 판별하는 Thresh hold value 들이구요, 이 값은 MPR121모듈 자체적으로 적정값에 맞게 가변적으로 세팅이 됩니다.

그리고 저희가 사용해야될 중요한 값은 Filt 값들이에요. 실질적인 Capacitive값들인거죠. 이 값들은 나중에 센서를 제작하고나서 자체적으로 보정을 해줘야합니다.


이번 포스팅은 여기까지입니다.


다음 포스팅에서는 정전식 터치센서를 어떻게 제작하는지 한 번 배우도록 합시다.


-> 아두이노기반 압력센서 개발 [2]


Have a good time with Arduino :)

+ Recent posts