Arduino, 스텝모터

스텝모터 (Step Motor)#

  • 펄스 모양의 전압에 의해 일정 각도(스텝 수) 만큼 회전하는 모터.
  • 회전 각도는 입력 펄스 신호의 수에 비례하고, 회전 속도는 입력 펄스 신호의 주파수에 비례한다.

스텝모터 28BYJ-48#

/image/s/Step-Motor-02.png
  • 정격전압: 5VDC

  • 기어비: 1/64

\[ \frac {32}{9} \times \frac {22}{11} \times \frac {26}{9} \times \frac {31}{10} = 63.68395 \fallingdotseq 64 \]
/image/s/Step-Motor-01.png
  • 스트라이드 각도
    • 스펙상 5.625º / 64 = 0.087890625
      • 그러므로, 360º / 0.087890625 = 4096 스텝
    • 실제로는 11.25º / 64 = 0.17578125
      • 그러므로, 360º / 0.17578125 = 2048 스텝으로 1회전 (이 값이 중요함!)
  • Frequency: 100Hz
  • 토크: 34.3mN,m

모터드라이브 ULN2003#

/image/s/Step-Motor-03.png

schematic#

/image/s/UNO-step-01.png

Pin Map#

모터드라이브아두이노
INT111
INT210
INT39
INT48
GNDGND
VCC5V

sketch: 예제1#

#include <Stepper.h>

// 2048:한바퀴(360도), 1024:반바퀴(180도)...
// datasheet를 통해 스트라이드 각도를 계산한 값을 사용
const int stepsPerRevolution = 2048;

// 모터 드라이브에 연결된 핀 IN1, IN3, IN2, IN4
Stepper myStepper(stepsPerRevolution, 11, 9, 10, 8);

void setup() {
  myStepper.setSpeed(14); 
}

void loop() {
  // 시계 반대 방향으로 한바퀴 회전
  myStepper.step(stepsPerRevolution);
  delay(500);

  // 시계 방향으로 한바퀴 회전
  myStepper.step(-stepsPerRevolution);
  delay(500);
}
  • Stepper myStepper(stepsPerRevolution, 11, 9, 10, 8);
    • 모터 드라이브에 연결되는 순서에 유의한다! (IN1, IN3, IN2, IN4 순서임!)
  • myStepper.setSpeed(14);
    • 아두이노 보드의 5V 전원 사용시 16이 최대값.
    • 16 이상은 안정적으로 회전이 안되며, 17을 넣으면 한바퀴 돌고 정지. 18을 넣으면 돌지 않음

sketch: 예제2#

#include <Stepper.h>

// 2048:한바퀴(360도), 1024:반바퀴(180도), 64:11.25도
const int stepsPerRevolution = 64;

// 모터 드라이브에 연결된 핀 IN1, IN3, IN2, IN4
Stepper myStepper(stepsPerRevolution, 11, 9, 10, 8);

void setup() {
  myStepper.setSpeed(16);
}

void loop() {
  
  // 시계 반대 방향으로 한바퀴 회전
  // 64 * 32 = 2048 한바퀴 => 11.25도씩 32번 회전 (360도)
  for(int i=0; i<32; i++) {  
    myStepper.step(stepsPerRevolution);
  }
  delay(500);

  // 시계 방향으로 한바퀴 회전
  // -64 * 32 = 2048 한바퀴 => -11.25도씩 32번 회전 (-360도)
  for(int i=0; i<32; i++) {
    myStepper.step(-stepsPerRevolution);
  }
  delay(500);
}

Arduino, 서보모터

서보모터 SG-90#

/image/servo-01.png
  • 모터드라이버, 회전센서, 모터, 제어회로가 내장된 기어 박스를 포함하고 있는 형태의 모터로, 스텝모터보다 힘이 강함
  • 보통 선이 3가닥이며, 회전수와 각도 등의 움직임 제어가 가능
  • 아두이노에서 많이 다루는 SG90 제품의 경우 0~180˚ 제어가 가능
  • 아두이노UNO의 USB 전류량이 500mA 정도가 한계이므로 별도의 전원을 사용하지 않으면 1~2개의 서보모터만 사용 가능

라이브러리 추가하기#

서보모터를 사용하기 위한 Servo 라이브러리는 아두이노 IDE에 기본으로 포함되어 있다.

  • 스케치> 라이브러리 포함하기> Servo 를 선택하면,
  • #include <servo.h> 라이브러리가 스케치에 추가 된다.

schematic#

/image/servo-02.jpg
SG90BrownRedOrange
ArduinoGND5V10

sketch : 서보모터 180º 회전 왕복하기#

#include <Servo.h>

Servo servomotor;                                // servomotor 선언
int position = 0;

void setup() {
  servomotor.attach(10);                         // servomotor 핀 설정
}

void loop() {
  for(position = 0; position < 180; position++)
  {
    servomotor.write(position);                  // pos값의 위치로 이동
    delay(15);                       
  }                                 
  for(position = 180; position > 0; position--)  // 같은 방법으로 역회전
  {
    servomotor.write(position);
    delay(15);
  }
}
  • servomotor.write(숫자)를 사용할때, 숫자는 현재 위치에서의 ‘회전각’을 의미하는 것이 아니다!
  • 초기 위치를 0º로 기준삼아, 표시된 숫자의 각도 위치로 이동하라는 의미이다. 예를들어서 servomotor.write(90)와 servomotor.write(30)을 연속으로 실행하면,
    • 90도를 회전한 뒤, 추가로 30도를 회전하여 120도 위치에 있다 → ×
    • 90도의 위치로 회전한 뒤, 역회전하여 (처음위치를 기준으로) 30도의 위치로 이동한다. → ○
  • 단, servo.h 라이브러리를 사용하면, 스케치 내에서 analogWrite를 사용할 수 없다는 단점도 있다.

sketch: 시리얼모니터에서 각도값을 입력받아 회전시키기#

#include <Servo.h>
Servo servomotor;
int a = 0;

void setup() {
  servomotor.attach(10);
  Serial.begin(9600);                  // Serial 통신을 설정
  while(!Serial);
  Serial.println("Servor Mortor");
}

void loop() {
  if(Serial.available()){              // Serial 모니터창에 어떤 값이 들어오면 실행
    a = Serial.parseInt();             // Serial 모니터창에서 받은 값을 a에 넘겨줌
    if(a>=0 && a<=180)
    {
      Serial.print("angle : ");
      Serial.println(a);
      servomotor.write(a);             // a값에 해당하는 각도의 위치로 이동
      delay(15);
    }
  }
}


서보모터 SG-90: 라이브러리 없이 사용하기#

for SG90 with Arduino#

  • Frequency of that signal should be 50hz.
  • Its range is 544-2450 micro seconds for 0-180 degree angle.
  • Again its a little complex.
  • For example 0 degree signal will be something like 5 volts for 544 micro seconds and 0 volt for 19465.
  • highDelay
    • the time in which we want to keep voltage high on pin 10 and this unit is in micro seconds.
  • lowDelay
    • the time in which want to keep voltage zero across pin 10 again this unit is going to be in micro seconds
  • only HIGH part of signal wont operate servo. we have to send complete HIGH and LOW signal to make servo work.
  • deg_factor
    • signal range (2450 - 544) for SG90 divided by 180 which is equal to 10.6 something that we make 11 as an integer.
  • Loop = 20000;
    • 20000 micro seconds or 20 milli seconds is signal cycle or u can say total signal should be equal to 20 milli seconds including HIGH and LOW input. (50Hz)
int servoPin = 10;        // servo is connected to pin 10.
int initialDelay = 544;
int highDelay, lowDelay;

int deg;
int deg_factor = 10;      
int Loop = 20000;         

void setup() {
  pinMode (servoPin, OUTPUT);
}

void loop() {
  for (deg = 0;deg <= 180; deg++) {
    servoWrite(servoPin, deg);
  }
  for (deg = 180;deg >= 0; deg--) {
    servoWrite(servoPin, deg);
  }
}

void servoWrite(int servo, int duty)
{
  highDelay = initialDelay + (duty * deg_factor); // setting angle

  digitalWrite(servo, HIGH);
  delayMicroseconds(highDelay);
  
  lowDelay = Loop - highDelay;
  digitalWrite(servo, LOW);
  delayMicroseconds(lowDelay);

  delay(500);
}

시리얼 모니터에 입력한 문자로 서보모터 회전시키기#

int servoPin = 10;        // servo is connected to pin 10.
int initialDelay = 544;
int highDelay, lowDelay;

int deg = 90;             // servo initial degree
int deg_factor = 10;      
int Loop = 20000;         

void setup() {
  Serial.begin(9600);
  pinMode (servoPin, OUTPUT);
}

void loop() {
  servoWrite(servoPin, deg);  
    
  while(Serial.available() > 0) 
  {
    char flag=Serial.read();
    delay(2);
      
    if(flag=='l') {
        deg = deg - 5;
        if(deg < 0) {
            deg = 0;
        }
    }
    
    if(flag=='r') {
        deg = deg + 5;
        if(deg > 180) {
            deg = 180;
        }
    }      
}

void servoWrite(int servo, int duty)
{
  highDelay = initialDelay + (duty * deg_factor); // setting angle

  digitalWrite(servo, HIGH);
  delayMicroseconds(highDelay);
  
  lowDelay = Loop - highDelay;
  digitalWrite(servo, LOW);
  delayMicroseconds(lowDelay);

  delay(500);
}
  • l 을 입력하면, 5도 좌회전하며, ll을 입력하면 10도 좌회전한다.
  • r 을 입력하면, 5도 우회전하며, rr을 입력하면 10도 우회전한다.


서보모터와 인터럽트 동시에 사용하기#

서보모터가 180도 회전하는 동안, 스위치를 누르면 13번 LED가 토글되도록 만들어보자.

Arduino, 피에조 부저

Buzzer의 종류#

Active Buzzer (능동형 부저)Passive Buzzer (수동형 부저)
有源蜂鸣器 (KY-012)无源蜂鸣器 (KY-006)
회로가 내장되어 있어, 전원만 인가하면 소리가 나므로 프로그램 제어가 편리함내부에 진동원이 없어, 스케치에 주파수를 지정하여야만 소리를 냄
원하는 주파수의 소리를 낼 수 없음원하는 주파수의 소리를 만들어낼 수 있음
패시브 부저에 비해 비쌈 (모듈 1개 0.9위안)액티브 부저에 비해 저렴 (모듈 1개 0.8위안)
/image/Buzzer-active.png
/image/Buzzer-passive.png
/image/Buzzer-active3.png
/image/Buzzer-active1.png
/image/Buzzer-active2.png
/image/Buzzer-passive2.png
  • 모듈로 판매하는 제품의 경우 겉모양으로는 구별이 어렵다. Active Buzzer의 경우 초기 판매시 스티커를 붙여서 판매하지만, 스티커가 떨어져 나간 상태라면 Passive Buzzer와 구별하기 어렵다. 또한 반드시 스티커가 붙은 형태로 판매하는 것도 아니다.
  • Active Buzzer의 경우 스티커로 사용전압을 표시하기도 한다. 빨간색은 3V, 파란색은 5V, 보라색은 12V용이다.
  • Active Buzzer 모듈의 경우 低电平触发(혹은 Low Level) / 高电平触发(혹은 High Level) 2가지 형태로 표기가 되어 있다. 低电平触发은 DigitalWrite에서 HIGH일 때 소리가 나며, 高电平触发은 LOW일 때 소리가 난다.
  • 모듈 형태가 아닌 단일 부품의 형태라면 연결 핀이 나와 있는 아랫면을 보면 구별할 수 있다. 일반적으로 Active Buzzer는 검은색 실리콘으로 밀폐되어 있으며, Passive Buzzer는 핀의 접합부위가 그대로 노출되어 있다.
  • Active Buzzer와 Passive Buzzer를 구별하는 가장 좋은 방법은 사용전압에 해당하는 전압(낮은 전압의 건전지도 가능)의 건전지를 연결시켜보는 것이다. 소리가 나면 Active, 나지 않으면 Passive라고 생각하면 된다.


Active Buzzer#

schematic#

/image/Buzzer01.png

sketch#

void setup () {
  pinMode (11, OUTPUT);        // 11번 핀을 출력으로 설정
}

void loop () {
  digitalWrite (11, HIGH);     // 11번 핀 부저 ON
  delay (1000);
  digitalWrite (11, LOW);      // 11번 핀 부저 OFF
  delay (1000);
}

과제#

tact 스위치를 누르면 액티브 부저 소리 울리기

Arduino, 키패드 사용하기

4×4 매트릭스 키보드#

키패드 입력값을 시리얼 모니터로 출력해보자.


schematic#

/image/keypad-01.jpg

Pin Map#

ArduinoKeypad일부 Keypad의 경우
218
327
436
545
654
763
872
981

주의 : Keypad 제조회사에 따라 통상적인 배선 순서와는 반대로 해야하는 경우도 있다. 키패드의 단자에 단자번호가 적혀있지 않으므로, 일단 통상적인 배선순서에 따라 연결해보고 시리얼 모니터를 통해 출력되는 값을 보고 확인해야 한다.

Arduino, IR 리모컨

생활속에서 가장 밀접하게 쓰이는 IR(Infra Red, 적외선) 리모컨의 사용에 대해서 알아본다. 리모컨 작동을 위해서는 기본적으로 IR 신호를 내보내는 리모컨본체와 이 본체에서 내보내는 신호를 받아들이는 IR 리시버가 필요하다.


기본 사용법#

schematic#

/image/remote.png
/image/remote-controller.png

위 그림에서 IR 리시버에 있는 핀은, IR모듈이 아닌 단일 부품형태의 리시버 일때 핀의 순서이다.


IR 리시버 모듈을 사용하는 경우#

아두이노 학습용으로 판매하는 IR 리시버는 브레드보드에 바로 붙일 수 있도록 조그만 PCB가 달린 모듈의 형태로 판매되는 경우가 많으며, 이 경우에는 PCB보드에 써있는 글씨를 보고 각 핀에 맞게 아두이노에 연결해야한다. 문제는 PCB에 어느 핀인지를 나타내는 글자가 잘 안보인다는 것!

Arduino, 1602 LCD (I2C)

1602 LCD (I2C)#

schematic#

/image/1602lcd.png

1602 LCDSDASCLVCCGND
ArduinoA4A55VGND

라이브러리 설치하기#

스케치> 라이브러리 포함하기> 라이브러리 관리

  • Wire : 기본 내장 라이브러리
  • LiquidCrystal I2C (by Frank de Brabander) 검색하여 설치

sketch#

// I2C 1602 LCD (연결핀을 바꿀 수 없음)
// VCC-5V / GND-GND / SDA-A4 / SCL-A5
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// i2c address 는 칩에 따라 0x20~0x27 혹은 0x3F값을 가짐
LiquidCrystal_I2C lcd(0x27, 16, 2);  

void setup() {
  lcd.init();               // lcd 초기화
  lcd.backlight();

  lcd.print("I Love Steam!!");   // LCD창에 메시지 출력
  delay(1000);
}

void loop() {
  // 문자열의 길이 13개를 왼쪽으로 스크롤
  for(int pCount = 0; pCount < 13; pCount++) {  
    lcd.scrollDisplayLeft();         // 왼쪽으로 스크롤
    delay(700);
  }
  // 문자열 길이 13열 + 기본 16열 = 29개 위치를 오른쪽으로 스크롤
  for(int pCount = 0; pCount < 29; pCount++) { 
    lcd.scrollDisplayRight();       // 오른쪽으로 스크롤
    delay(700);
  }
  // 왼쪽으로 16개 위치 스크롤하여 처음 위치로 이동
  for(int pCount = 0; pCount < 16; pCount++) {
    lcd.scrollDisplayLeft();         // 왼쪽으로 스크롤
    delay(700);
  }
 
  delay(1000);
}


주의사항#

  • I2C 모듈에 점퍼선을 뺏다가 다시 끼우는 경우, 정상적인 상황에서도 LCD가 작동하지 않는 경우가 있음 (주로 첫번째라인에 ■■■■■■■■■■■■■■■■ 형태로 출력되는 오류가 발생됨)
  • 이런 경우에는 배선을 모두 완료한 상태에서 스케치 업로드를 다시 하면 대부분 해결됨


여러 가지 문자열 출력해보기#

  • 첫 번째 행에 I Love Steam!!
  • 두 번째 행에 본인의 영문이름을 써서 스크롤 해보기
  • 두 번째 행에 출력하는 방법 : lcd.setCursor(0,1);


1602 LCD에 DS18b20 온도센서 값 출력하기#

schematic#

/image/1602lcd-ds18b20.png

sketch#

// DS18b20 Temperature Sensor
#include <OneWire.h>
#include <DallasTemperature.h>

#define TEMP_PIN 2

OneWire oneWire(TEMP_PIN);
DallasTemperature sensors(&oneWire);
float celciusTemperature;

// I2C 1602 LCD (연결핀을 바꿀 수 없음)
// VCC-5V / GND-GND / SDA-A4 / SCL-A5
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// i2c address 는 칩에 따라 0x27, 0x3F값을 가짐
LiquidCrystal_I2C lcd(0x27, 16, 2);  

void setup() {
  Serial.begin(9600);  
  Serial.println("DallasTemperature IC Control");

  // Start up the Temperature Sensor library
  sensors.begin();

  // lcd 초기화
  lcd.init();    
  lcd.backlight();
}

void loop() {
  sensors.requestTemperatures();
  celciusTemperature = sensors.getTempCByIndex(0);
  Serial.print("Temperature is: ");
  Serial.println(celciusTemperature);

  lcd.setCursor(0, 0);
  lcd.print("Temperature : ");
  lcd.setCursor(0, 1);
  lcd.print(celciusTemperature);
  lcd.print("*C");
  delay(2000);
}

Arduino, TM1637 모듈 사용하기

TM1637#


schematic#

/image/tm1637-01.png
TM1637CLKDIOVCCGND
Arduino475VGND

라이브러리 추가하기#

  1. 파일> 새파일>
  2. 스케치> 라이브러리 포함하기> 라이브러리 관리>
/image/tm1637-02.png

  1. 라이브러리 매니저 창이 뜨면, 검색란에 “tm1637"를 적어 넣음. tm1637관련 라이브러리가 5~6개정도 검색됨. TM1637 by Avishay Orpaz 라이브러리를 선택하여 설치
/image/tm1637-03.png



TM1637 숫자 표기 방법#

for TM1637 by Avishay Orpaz library 
   *  A  *
   F     B
   *  G  *
   E     C
   *  D  *  DP

sketch#

“8.8.8.8.” → " " → “0123” → “dOnE”

Arduino, 온도 및 습도 측정 (DHT22)

온습도 센서 DHT22#

DHT22 센서를 이용하여 온도와 습도를 측정한다.

센서DHT11DHT22 (AM2302)
사진
DHT11
/image/dht22-01.png
온도0 ~ 50℃ (오차범위 ±2℃)-40 ~ 100℃ (오차범위 ±0.5℃) (해상도 0.1℃)
습도20 ~ 90% (오차범위 ±5%)0 ~ 100% (오차범위 ±2~5%) (해상도 0.1%)

Pinout#

DHT22DATVCCGND
Arduino85VGND

schematic#

/image/dht22-05.png


라이브러리 준비하기#

Case1: 위 사진과 같은 형태의 DHT22 모듈을 사용하는 경우#
  • 라이브러리 매니저검색창에 검색어로 ‘AM2302’를 입력

Arduino, 온도측정(DS18b20)

DS18b20 온도센서#

DS18b20 온도 센서를 이용하여 온도를 측정한다.

  • one-wire 버스 통신
  • 공급전압: 3.0V ~ 5.5V
  • 작동온도: -55ºC ~ +125ºC
  • 오차: +/-0.5 ºC (-10ºC ~ 85ºC 범위에서)

Pinout#

/image/DS18b20.png

schematic#

DS18b20 센서는 두 가지 연결방법을 제공하는데, 하나는 VCC를 5V에 연결하는 Normal Mode이고 다른 하나는 VCC를 GND에 연결하는 Parasite Mode이다. 두가지 방법 모두 지원되지만 (경험상) Normal를 추천하며 (원인은 잘 모르겠지만) Parasite Mode에서는 온도센서가 작동이 되지 않는 경우도 가끔 있었다. 회로 구성을 위해 4.7㏀ 저항 1개가 필요하며 Normal Mode 구성을 위해 다음 그림과 같이 연결한다.

Arduino 스위치, 풀다운저항, 풀업저항

Tact Switch#

/image/tact_switch.png

Pull-down#

동작Arduino
스위치를 누르면ONHIGH
스위치에서 손을 떼면OFFLOW

schematic#

저항(10k 이상)을 GND에 연결한 경우: Pull-down 회로

/image/switch01.png

sketch#

const int switch_R = 2;

void setup() {
  pinMode(switch_R, INPUT);
  Serial.begin(9600);
}

void loop() {
    int i = digitalRead(switch_R);
    if(i == HIGH) {                  // 스위치를 누르면
        Serial.println("1");
    }
    else {                           // 스위치에서 손을 떼면
        Serial.println("0");
    }
}

Pull-up#

동작Arduino
스위치를 누르면OFFLOW
스위치에서 손을 떼면ONHIGH

schematic#

저항(10k 이상)을 VCC(5V)에 연결한 경우: Pull-up 회로

/image/switch02.png

sketch#

const int switch_R = 2;

void setup() {
  pinMode(switch_R, INPUT);
  Serial.begin(9600);
}

void loop() {
    int i = digitalRead(switch_R);
    if(i == HIGH) {                  // 스위치를 누르면
        Serial.println("1");
    }
    else {                           // 스위치에서 손을 떼면
        Serial.println("0");
    }
}


스위치를 사용할 때, 풀다운 or 풀업 저항을 구성해야 하는 이유#

출처: 풀업(Pull-up)저항, 풀다운(Pull-down)저항 (악보쓰는 프로그래머)