디지털 라이프 電子的生活 My Digital Life/아두이노 (Arduino)

아두이노로 RPM 카운터를 만들었습니다.

미친도사 2016. 8. 25. 09:00

굴러가는 모형에 관심을 갖고 모터를 다루다 보니, 모터의 회전수에 대한 감을 좀 잡을 필요가 있을 것 같습니다.

대략 이 정도 회전수면 얼마나 빠른 건지 말이죠.


그래서, RPM 카운터에 대해 검색을 해보니, 아두이노로 그리 어렵지 않게 구현이 가능하겠더군요.

인터넷 뒤져서 기본 회로를 검색하여 구성하고 돌려보면서 제 나름대로 기능 하나 더 추가해 보았습니다.

일단은 빵판에 꼽아서 구동.



적외선 센서를 이용하여 모터에 달린 날개의 회전수를 측정하여, 그것을 분당 회전수 RPM으로 계산하여 16x2짜리 캐릭터 LCD에 결과를 출력하게 하는 단순한 구성입니다.


인터넷에 돌아다니는 구성에 버튼을 하나 추가하여 모터에 달린 날개의 수에 따라 RPM 계산을 보정하도록 하였습니다.


빵판에서 확인을 다 마친 후에 만능 기판에 회로를 구성하고, 명함통에 회로를 넣어 패키징까지 마쳤습니다.


전원은 아두이노 나노에 전원을 넣어도 되고, 스마트폰에 많이 쓰는 마이크로 USB 포트를 통해 전원을 공급을 받을 수 있게 하였습니다.


LCD, 센서, 버튼은 케이스 밖으로 나오게 했고요.


LCD와 센서는 착탈 가능하게 헤더를 박아 연결했습니다. 착탈의 의미도 있지만, 높이를 높이기 위함도 있지요. ^^


높이가 낮은 택트 스위치는 케이스 뚜껑에 구멍을 내고, 플라봉과 플라 파이프를 적당히 활용하여 밖에서 토글가능하도록 했습니다.


적외선 센서와 LCD 분리한 모습.


사용부품 목록

- 아두이노 나노

- 16x2 캐릭터 LCD

- 적외선 선서 / 포토 인터럽트 (마우스의 휠의 동작 감지 센서로 쓰이는 것)

- 마이크로 USB 어댑터

- 택트 스위치

- 10K옴 가변 저항 (LCD 밝기 조정용)

- 0.1uF 세라믹 캐패시터 (안정적인 버튼 동작을 위함)

- 만능 기판

- 헤더 및 케이블들


회전수를 알고 싶은 모터 혹은 회전 장치에 대충 날개를 만들어 붙이고, 버튼으로 날개 수를 정합니다.


그리고, 돌아가는 날개가 센서 사이에 들어가게 하면 RPM 값이 계산되어 나옵니다.


원리는 ...

저 적외선 센서 사이로 뭔가가 지나가면, 신호를 한번씩 발생시킵니다.

이를 아두이노의 입력을 받아들여서 지정된 시간동안 발생된 신호의 횟수를 측정하여 RPM으로 계산하여 보여주는 겁니다.


결선은 다음과 같습니다.


복잡한 것 같지만, 만능기판에 꼽았을 때엔 그닥 복잡하게 연결되지 않습니다.


참고한 사이트는 다음과 같습니다.

http://www.circuitmagic.com/arduino/diy-digital-rpm-tachometer-with-arduino/



아두이노 소스도 첨부합니다.

// include the library code:

#include <LiquidCrystal.h>


//------code for RPM----------------

int encoder_pin = 2;

// The pin the encoder is connected

unsigned int rpm;

// rpm reading

volatile byte pulses;

// number of pulses

unsigned long timeold;

// The number of pulses per revolution

// depends on your index disc!!

unsigned int pulsesperturn = 1;


// added by Kevin

int num_blade = 1;

int set_blade_pin = 3;


LiquidCrystal lcd(9, 8, 7, 6, 5, 4);


void counter()

{

    //Update count

    pulses++;

}

//-----------------------------------

void setup()   {

    Serial.begin(9600);

//-----------code for RPM---------------

    //Use statusPin to flash along with interrupts

    pinMode(encoder_pin, INPUT);

    //Interrupt 0 is digital pin 2, so that is where the IR detector is connected

    //Triggers on FALLING (change from HIGH to LOW)

    attachInterrupt(digitalPinToInterrupt(encoder_pin), counter, FALLING);

    attachInterrupt(digitalPinToInterrupt(set_blade_pin), count_blade, FALLING);

    // Initialize

    pulses = 0;

    rpm = 0;

    timeold = 0;

    

    lcd.begin(16, 2);

    pinMode(set_blade_pin, INPUT_PULLUP);

}

void loop()

{

    if (millis() - timeold >= 1000){

        /*Uptade every one second, this will be equal to reading frecuency (Hz).*/

        //Don't process interrupts during calculations

        detachInterrupt(digitalPinToInterrupt(encoder_pin));

        detachInterrupt(digitalPinToInterrupt(set_blade_pin));

        //Note that this would be 60*1000/(millis() - timeold)*pulses if the interrupt

        //happened once per revolution

        rpm = (60 * 1000 / pulsesperturn / num_blade)/ (millis() - timeold)* pulses;

        timeold = millis();

        pulses = 0;


        //Write it out to serial port 

        Serial.print("NUM BLADE = ");

        Serial.println(num_blade);

        Serial.print("RPM = "); 

        Serial.println(rpm, DEC);

        

        //Write out to LCD

        lcd.setCursor(0, 0);

        lcd.print("NUM BLADE = ");

        lcd.print(num_blade);

        lcd.print("  ");

    

        lcd.setCursor(0, 1);

        lcd.print("RPM = ");

        lcd.print(rpm, DEC);

        lcd.print("    ");

                

        //Restart the interrupt processing

        attachInterrupt(digitalPinToInterrupt(encoder_pin), counter, FALLING);

        attachInterrupt(digitalPinToInterrupt(set_blade_pin), count_blade, FALLING);

    }

}


void count_blade()

{

  num_blade++;

  if (num_blade > 4) {

    num_blade = 1;

  }

}





반응형