프로젝트형 IoT 서비스 개발 4회차/2. 엣지 디바이스 제어

[Day41] 2022-03-28(월) 아두이노6 - RGB LED, 서보모터, 초음파센서 - 김서연 강사님

powerstone 2022. 3. 28. 18:01
728x90

2022-03-28(월) 21:50 수정 - 초음파센서 사용법 수정

[1] RGB LED 제어

  - <아두이노 마스터1 우노보드 기초 - 신동욱> p172~179

  1. RGB LED 예제1

    - R,G,B가 연결된 핀에 각각 PWM 신호로 0~255 값을 랜덤하게 출력하여 RGB LED에 다양한 색깔 출력하기

    - random(max) or random(min, max)

      - max 만 넣으면, 0~(max-1) 사이의 랜덤 값 리턴

      - min 도 넣으면, min~(max-1) 사이의 랜덤 값 리턴

      - 이 함수는 가짜 랜덤(pseudo-random) 수 생성 함수이므로, 매번 패턴이 같다.

      - randomSeed( ) 함수를 같이 사용하여 진짜 랜덤 수를 생성할 수 있다.

https://www.arduino.cc/reference/en/language/functions/random-numbers/randomseed/

 

randomSeed() - Arduino Reference

Description randomSeed() initializes the pseudo-random number generator, causing it to start at an arbitrary point in its random sequence. This sequence, while very long, and random, is always the same. If it is important for a sequence of values generated

www.arduino.cc

    1) CODE

void setup() {
  pinMode(6, OUTPUT); // Red
  pinMode(5, OUTPUT); // Green
  pinMode(3, OUTPUT); // Blue
  Serial.begin(9600);
}

void loop() {
  //PWM을 이용해서 값을 적용 - 0~255
  int red = random(256);  // 0~255 랜덤
  int green = random(256);  // 0~255 랜덤
  int blue = random(256);  // 0~255 랜덤
  Serial.print(red);
  Serial.print('\t');
  Serial.print(green);
  Serial.print('\t');
  Serial.println(blue);
  analogWrite(6, red);
  analogWrite(5, green);
  analogWrite(3, blue);
  delay(1000);
}

    2) 회로 모델

    3) 동작

      - RGB LED + 저항 사용

RGB LED 와 저항을 연결하여 동작

      - RGB LED Module 사용

RBG LED Module만 가지고 동작

 

 

[2] 서보 모터(Servo Motor)

  - <아두이노 마스터1 우노보드 기초 - 신동욱> p206~212

  1. 서보 모터란?

    - 주어진 신호(PWM)에 의해서 일정한 각을 유지하거나, 일정한 위치를 유지하는 모터

    - 두 개의 전원선(Vcc, GND)과 한 개의 제어선(PWM)

    - SG90은 주기가 20ms(50Hz)로 Duty Cycle이 1ms면 0도, 1.5ms면 90도, 2ms면 180도를 유지한다.

       (-> Servo.h 라이브러리를 사용할 때는 0도는 0.544ms, 180도는 2.4ms 로 설정해야 제대로 작동하고,

          모터스펙처럼 1ms, 2ms으로 설정하면 전혀 이상한 각도가 나온다. 왜 스펙과 다른지 잘 모르겠다..)

    - 90도를 기준으로 0도는 시계방향, 180도는 반시계 방향으로 회전

    - Duty Cycle을 직접 제어하지 않고, 쉽게 각도로 제어할 수 있도록, 아두이노에서는 라이브러리(Servo.h)를 제공

https://www.arduino.cc/reference/en/libraries/servo/

 

Servo - Arduino Reference

Allows Arduino boards to control a variety of servo motors. This library can control a great number of servos. It makes careful use of timers: the library can control 12 servos using only 1 timer. On the Arduino Due you can control up to 60 servos. This li

www.arduino.cc

    - Servo.h 라이브러리 활용

      1) 사용 방법

        - #include <Servo.h> : 라이브러리를 불러온다.

        - Servo 객체명; : Servo class의 객체를 선언

        - 변수명.함수명( ) : Servo class내의 함수 사용

      2) 함수

        ① attach(핀번호) or attach(핀번호, min, max)

          - 핀번호 : 객체에 사용할 제어 핀 할당

          - min : 옵션으로, pulse width의 최소값을 ㎲ 단위로 입력, default는 544 로 0도를 의미

          - max : 옵션으로,pulse width의 최대값을 ㎲ 단위로 입력, default는 2400 로 180도를 의미 

        ② detach( ) : 객체에 할당된 핀을 해제

        ③ attached( ) : 객체에 핀이 할당되어 있으면 true, 그렇지 않으면 false 반환

        ④ write(값) : 객체(서보모터)를 값에 따라 해당 각도로 회전하고 유지

          - 값이 200보다 작으면 각도를 의미(0~180)

          - 값이 200보다 크면 ㎲ 단위의 pulse width -> 대신 writeMicroseconds(값) 을 쓸 수 있다.

        ⑤ read( ) : 현재 각도, 즉, 마지막에 write( ) 함수에서 사용한 값 읽기 (0~180도)

 

  2. Servo Motor SG90 Data Sheet

http://www.ee.ic.ac.uk/pcheung/teaching/DE1_EE/stores/sg90_datasheet.pdf

  3. Servo Motor 예제1

    - 간단하게 서보모터를 0, 90, 180도 위치로 이동시켜 보기

    1) CODE

// servo_test1
#include <Servo.h>
Servo myservo;

void setup() {
  myservo.attach(10);
}

void loop() {
  myservo.write(0);
  delay(1000);  // delay를 주지 않으면 모터가 동작할 여유가 없다.
  myservo.write(90);
  delay(1000);
  myservo.write(180);
  delay(1000);
}

    2) 회로 모델

    3) 동작

 

  4. Servo Motor + 가변저항 예제2

    - 가변저항을 통해 들어오는 아날로그 입력값에 따라 서보모터 각도를 0~180도로 이동시키기

    1) CODE

// servo_exam1
// 가변저항과 서보모터의 각도를 연결해서 작업해보기
#include <Servo.h>
Servo myservo;  // 서보모터 객체 생성
int po_pin = 0;   // 가변저항 입력핀
int servo_pin = 10;   // 서보모터 출력핀

void setup() {
  myservo.attach(servo_pin);  // 서보모터 핀에 객체 연결
  Serial.begin(9600);
}

void loop() {
  int readVal = analogRead(po_pin);   // 가변저항 입력값
  int writeVal = map(readVal, 0, 1023, 0, 180);   // 입력값을 각도로 변환
  myservo.write(writeVal);    // 각도 출력
  Serial.print(readVal);
  Serial.print(" ");
  Serial.println(writeVal);
  delay(100);
}

    2) 회로 모델

    3) 동작

 

  5. Servo Motor + Push Button 예제3

    - 버튼 2개로 서보모터의 각도를 +20/-20도씩 회전시키기

    1) CODE

// servo_exam2
// push버튼과 서보모터를 연결해서 각도를 조절하는 연습
// - push버튼 2개를 연결 : +, - 로 설정
// - +와 - push버튼을 누르면 20도씩 +되거나 -되면서 서보의 각도가 조절되도록
#include <Servo.h>
Servo myservo;
int servo_pin = 10; // 서보모터 출력핀
int btn_pin1 = 11;  // + 버튼
int btn_pin2 = 12;  // - 버튼
int angle = 0;    // 서보모터 각도
int btn_state1 = 0;
int last_btn_state1 = 0;
int btn_state2 = 0;
int last_btn_state2 = 0;
long lastTime = 0;

void setup() {
  Serial.begin(9600);
  myservo.attach(servo_pin);
  pinMode(btn_pin1, INPUT);
  pinMode(btn_pin2, INPUT);
}

void loop() {
  int btn1 = digitalRead(btn_pin1);
  int btn2 = digitalRead(btn_pin2);
  Serial.print(angle);
  Serial.print(" ");
  Serial.print(btn1);
  Serial.print(" ");
  Serial.println(btn2);
  if(btn1!=last_btn_state1 || btn2!=last_btn_state2){
    lastTime = millis();
  }

  if(millis()-lastTime>50){
    if(btn1!=btn_state1 || btn2!=btn_state2){
      btn_state1 = btn1;
      btn_state2 = btn2;
      if(btn1==HIGH && angle<180){
        angle += 20;
      }
      if(btn2==HIGH && angle>0){
        angle -= 20;
      }        
    }
  }
  myservo.write(angle);
  last_btn_state1 = btn1;
  last_btn_state2 = btn2;
}

    2) 회로 모델

    3) 동작

 

[3] 초음파센서(HC-SR04)

  - <나도 아두이노 할수있다 입문자용 - 메카솔루션> p63

  - 초음파는 귀에 들리지 않을 정도의 높은 주파수의 소리

  - 초음파는 340m/s 의 속도를 가지며, 이러한 초음파를 발신 및 수신하여 거리 측정 및 사물 감지가 가능

  - VCC와 GND핀을 통해 5V, 15mA의 전원을 입력받아 작동

  - Trig핀에 5V가 입력(센서 기준)될 때, 초음파 발신부에서 초음파 발신

  - 발신된 초음파가 장애물에 부딪혀 수신부로 돌아오면, Echo핀에 5V를 출력(센서 기준)

  1. Datasheet

출처 -&nbsp;https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf
출처 -&nbsp;https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf

  2. 초음파 센서 사용법

    1) Trig핀을 출력, Echo핀을 입력으로 pinMode 설정

    2) 초음파 발신부에서 초음파를 발신시키기 위한 Trig핀의 출력 조건은 High를 10㎲ 유지했다가 Low로 변환

    3) Trig핀의 출력이 Low가 되는 순간 모듈에서 초음파를 발신( 8 cycle Sonic Burst ) 및 Echo핀 High로 변환

    4) 발신된 초음파가 장애물에 부딪혔다가 돌아와서 초음파 수신부에 들어오면, Echo핀을 Low로 변환

    5) 즉, Echo핀이 High가 되는 순간부터 Low가 되는 순간까지 시간을 측정하여 거리를 계산한다.

    - 코드로 이해하기(내가 이해한 방식)

      1. digitalWrite(trig, HIGH); // Trig핀 High로
      2. delayMicroseconds(10); // Trig핀 High 상태 10us 유지(datasheet 상 조건)
      3. digitalWrite(trig, LOW); // Trig핀 Low로

        -> 이 시점에서 약간의 텀(약 2.1ms)을 두고 초음파 발신기에서 초음파 출발 및 Echo핀 High로 변환

        -> 3, 4사이에 딜레이를 2.2ms 정도를 주면 4에서 pulseIn 함수가 0을 반환한다.(시간은 실험 결과임)

            (즉, Echo핀이 이미 LOW->HIGH로 변해서, pulseIn 함수가 pulse를 인지하지 못한다.)
      4. double duration = pulseIn(echo, HIGH); // 마이크로초 단위
        -> pulseIn(echo, HIGH)은 최대 1초동안 Echo핀이 High로 변환되길 기다리고, High가 되었을 때부터 시간을

            측정하기 시작하여, 초음파가 돌아와서 Echo핀이 Low로 전환될 때까지 측정한 시간을 반환한다.

 

  3. 초음파 센서 예제1

    - 초음파 센서를 이용해 시리얼 모니터에 측정된 거리를 출력

    1) CODE

int trig = 10;  // 10번핀은 트리거
int echo = 9;   // 9번핀은 에코
void setup() {
  Serial.begin(9600);
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
}

void loop() {
  // 초음파 신호를 발신
  // => trig 핀의 입력이 low에서 high로 변하는 순간부터 시간을 측정하고 다시 low로 변경되는 시점까지의 시간을 us단위로 변환
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);

  // 초음파 신호를 수신
  // => 초음파를 발생시키고 수신될 때까지 시간을 측정
  // => echo핀으로 high신호가 들어오는 시점의 시간을 반환 - pulseIn()함수
  // low - high 로 변하는 시점부터 측정을 하려면 HIGH로 정의
  // high - low 로 변하는 시점부터 측정을 하려면 LOW로 정의
  double duration = pulseIn(echo, HIGH);// 마이크로초 단위
  // 거리계산
  // 시간, 속력
  double distance = 340 * duration / 10000 /2;

  // 측정한 거리를 출력
  Serial.print(distance);
  Serial.println("cm");
  delay(500);
}

    2) 회로 모델

    3) 시리얼 모니터

 

  3. 초음파 센서 + LED 예제2

    - 초음파 센서를 이용하여, 센서로부터 물체의 거리가 30cm 미만이면 LED가 켜지도록 구현

    1) CODE

// hc_sr04_exam1
// 초음파센서와 물체의 거리가 30cm미만이면 led불켜기
int led_pin = 11; // LED 핀
int trig = 10;  // 10번핀은 트리거
int echo = 9;   // 9번핀은 에코
void setup() {
  Serial.begin(9600);
  pinMode(led_pin, OUTPUT);
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
}

void loop() {
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);

  double duration = pulseIn(echo, HIGH);
  double distance = 340 * duration / 10000 /2;
  if(distance<30){
    digitalWrite(led_pin, HIGH);
  }else{
    digitalWrite(led_pin, LOW);
  }
  Serial.print(distance);
  Serial.println("cm");
  delay(500);
}

    2) 회로 모델

    3) 동작

- 끝 -

728x90