본문 바로가기
Nefus

NEFUS_Arduino

by JJWon 2023. 5. 8.

20230508

 

Arduino

아두이노는 하나의 브랜드이며, 오픈 소스를 기반으로 한 단일 보드 마이크로컨트롤러로 완성된 보드와 관련 개발 도구 및 환경을 말합니다. 다수의 스위치나 센서 등의 부품으로 외부와 상호작용이 가능한 물건들을 손쉽게 만들 수 있도록 만들어졌습니다. 

아두이노 통합 개발 환경(IDE)에서 컴파일과 업로드가 가능합니다. 아두이노 IDE는 C++ 언어 기반을 사용하며, 외부의 많은 공개 라이브러리가 존재합니다.

 

디지털(Digital)과 아날로그(Analog)

아날로그란 연속적으로 변환하는 어떠한 양 또는 데이터이고, 디지털은 2진수로 표현된 어떠한 양 또는 데이터를 말합니다. 아날로그는 파장, 진폭, 주기를 가지지만 디지털은 진폭과 주기를 가지지 않습니다. 

 

PMW

PMW는 디지털 신호를 아날로그 신호인 것처럼 보이게 하는 신호입니다. 예로 형광등을 들 수 있는데, 사람이 감지할 수 없는 정도로 빨리 깜빡거려서 실제로는 깜빡거리더라도 '계속 켜져있는 상태이다!' 라고 착각하는 경우를 생각하면 이해하기 쉽습니다.


20230515

포텐쇼미터(Potentiometer)

포텐쇼미터는 '가변저항기'라고도 불립니다. 가변저항은 전자회로에서 저항을 임의로 바꿀 수 있는 저항를 말합니다. 포텐쇼미터로 저항을 바꾸게 되면 전류의 크기도 바뀌게 됩니다. 전압을 가하면 설정에 따라 전압 일부를 전달하는 역할을 하기 때문에 스피커 볼륨 조절, 보일러 온도 조절 등의 기능을 위하여 부착됩니다. 

포텐쇼미터의 내부에는 탄소로 만들어진 둥근 회색 띠가 있는데, 이 띠를 통하여 전기가 흐르며 저항의 기능을 합니다. 세 단자 중 가운데를 제외한 양쪽 단자는 탄소 띠로 이어져 있고, 가운데 단자는 따로 떨어져 있습니다. 가운데 단자와 탄소 띠를 이어주는 것은 우리가 조절할 수 있는 조절 슬라이더와 연결되어 있는 와이퍼입니다. 그래서 우리가 조절 슬라이더를 돌리면, 오른쪽 단자를 통해 들어온 전기가 탄소 띠를 따라 흘러가다가, 중간에 와이퍼를 만나서 와이퍼 쪽으로 방향을 틀어 가운데 단자로 흘러가게 됩니다. 이 때 와이퍼가 어디에 있느냐에 따라서 탄소 띠를 얼마만큼 오래 따라가다가 와이퍼로 빠져나가는 지가 달라지기 때문에 저항값이 달라집니다. 참고로 탄소 띠를 따라가다가 빨리 와이퍼를 만나면 저항이 작아지고, 탄소 띠를 다 지날 쯤 되어서야 와이퍼를 만나면 저항이 커집니다. 이 원리를 이용하여 볼륨이나 온도를 조절하는 것입니다.

 

초음파센서(Ultrasonic Sensor)

초음파라는 인간의 청력 범위를 벗어난 오디오 주파수를 뜻합니다. 초음파 센서는 주파수를 사용하여 존재를 감지하거나 원격 물체에 대한 거리를 계산합니다.

초음파 센서의 송신기(TRIG)는 23kHz~40kHz 사이의 주파수를 포함하는 처프라는 고주파 음파의 짧은 버스트를 방출합니다. 이 소리의 펄스(매우 짧은 동안만 흐르는 전류)가 물체의 부딫혀서 반사된 일부 음파를 수신기(ECHO)가 수신합니다. 센서는 초음파 신호를 송신한 후 수신할 때까지의 시간을 측정하여 물체까지의 거리를 계산합니다.

 

조도센서(Photoresistor)

조도센서는 주변 밝기를 측정하여 입력 값으로 보내는 센서입니다. 조도는 단위 면적 당 단위 시간에 받는 빛의 양을 뜻합니다. 조도에 따라 저항의 값을 변화하는데, 빛의 양과 저항값은 반비례 관계이기에 주위가 밝으면 저항값이 감소하고, 주위가 어두우면 저항값이 증가합니다. 아무 방향으로 꽃아도 상관없다는 특징도 있습니다.

조도센서 윗부분에 있는 지그재그 모양의 주황색 부분이 광자의 양을 측정합니다. 광에너지를 받으면 내부에 움직이는 전자가 발생하여 전도율이 변하는 광전효과를 가지는 소자를 사용합니다. 광에너지를 받으면 센서 내부의 광도전체에서 반송자의 밀도가 높아지기 때문에 전류가 증가하고(==저항 감소), 광에너지를 받지 않으면 반송자의 밀도가 높아지지 않기 때문에 전자에 비해 전류가 잘 흐르지 않습니다(==저항 증가). 반송자에 관한 내용은 https://jjwon4.tistory.com/6 를 확인하시면 좋습니다. 

 

릴레이모듈(Relay Module)은 센서가 아닙니까?

릴레이모듈은 고전압, 대전류의 장치를 제어할 때 사용됩니다.

 

코드 정리하기

(1) Serial.Print()

void setup() {
	Serial.begin(9600); // 시리얼 통신 전 초당 9600비트를 전송하겠다는 통신속도 맞추기 
}
void loop() {
	Serial.print("hello!"); // serial monitor에 hello 출력
    delay(1000);
}

(2) Potentiometer

int val = 0; // 가변저항으로부터 아날로그 신호를 받을 변수 선언
void setup() {
	Serial.begin(9600);
    pinMode(11, OUTPUT); // 보드에서 아날로그 핀으로 쓸 수 있는 핀 중 하나 선택
}
void loop() {
	val = analogRead(A0); // 가변저항으로부터 아날로그 신호를 받아서 변수에 저장
    Serial.println(val); // 변수 출력
    val = map(val, 0, 1023, 0, 255); // 변수의 최댓값을 매핑(입력값의 범위를 출력값의 범위에 맞추기)
    analogWrite(11, val);
}

(3) Ultrasonic Sensor

#define TRIG 9 // 송신기 핀 설정
#define ECHO 8 // 수신기 핀 설정
void setup() {
  Serial.begin(9600);
  pinMode(TRIG, OUTPUT); // 송신기 핀 설정
  pinMode(ECHO, INPUT); // 수신기 핀 설정
}

void loop() {
  long duration, distance;
  digitalWrite(TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  duration = pulseIn (ECHO, HIGH); // 초음파 송신->수신 시간 저장
  
  // 3400*시간/1000000/2(편도) : 계산 공식

  distance = duration * 17 / 1000; // PC모니터로 초음파 거리값을 확인하는 코드
  
  Serial.println(duration); // 시간을 보여줌
  Serial.print("\nDIstance : ");
  Serial.print(distance); // 거리값 보여줌
  Serial.println(" Cm");
  delay(1000);
}

(4) Photoresistor

void setup() {
  Serial.begin(9600);
}

void loop() {
  int readValue = analogRead(A0); // 조도센서 값 측정
  Serial.println(readValue); // 조도센서 값 출력
}

(5) Relay Module

 int Relaypin = 3; // 릴레이 설정
int Switch = 9; // 스위치 설정

void setup() {
  pinMode(Relaypin, OUTPUT);
  pinMode(Switch, INPUT_PULLUP);
}

void loop() {
  if(digitalRead(Switch)==LOW){ // 스위치가 꺼져 있으면?
    digitalWrite(Relaypin, HIGH); // 릴레이 키기
    delay(100);
  }
  else{ // 스위치가 켜저 있으면?
    digitalWrite(Relaypin, LOW); //릴레이 끄기
    delay(100);
  }
}

 

작품 만들기

조도센서와 LED를 이용하여 조도센서값이 어느정도 되어야 LED에 불이 들어오는 지 확인하는 작품을 만들겠습니다. 세 개의 부품을 이용해야 하니, 제 원할 때만 작동되도록 스위치도 사용하겠습니다.

void setup() {
  Serial.begin(9600);
}

void loop() {
  int readValue = analogRead(A0);
  Serial.println(readValue);
  delay(1000);
}

20230517

LCD

문자를 화면에 출력하는 모듈입니다. LCD(Liquid Crystal Display)는 액정 디스플레이 또는 액정 표시 장치를 의미하고, 뒷면에 빛을 내는 백라이트를 배치하고 앞면에 액정을 두어 전기신호에 따라 빛을 차단하거나 통과시키는 방식으로 문자나 숫자 등을 표시합니다. GND, VSS, SDA, SCL 총 4개의 핀으로 이루어져 있으며, 각각 GND는 GND에, VSS는 5V에, SDA와 SCL은 아날로크 핀 A4, A5에 꽂습니다. lcd를 이용하기 위해서는 'LiquidCrystal_I2C.h' 라이브러리가 필요합니다. 아두이노에lcd는 가로로 16개의 문자를 출력할 수 있고, 세로로 2줄을 표현할 수 있기에 1602LCD라고도 합니다.

 

수위센서

수위 측정 센서는 물센서 라고도 불리며, 물의 여부를 확인하는 용도로 이용됩니다. 또한 센서가 물에 많이 잠길수록 흐르는 전류값이 조금씩 커지기도 합니다. 그러나 물이 닿아야만 전류가 통하는 것은 아니고, 아무 전도체나 대어도 전류가 통합니다. 오른쪽 핀은 GND에, 가운데 핀은 5V에, 왼쪽 핀은 아날로그 핀에 연결합니다.

 

과제

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  lcd.begin();
  pinMode(3, OUTPUT);
}

void loop() {
  digitalWrite(3,HIGH);
  delay(1000);
  lcd.setCursor(5,0);
  lcd.print("test");
  delay(1000);
  digitalWrite(3,LOW);
  lcd.clear();
  delay(1000);
}

20230531

단방향 전송 방식

데이터를 한쪽 방향으로만 전송하는 방식입니다. 안테나로 데이터를 수신할 수만 있는 TV를 예시로 들 수 있습니다.

 

반이중 전송 방식

양쪽 다 송신 가능하지만, 한 쪽이 데이터를 송신할 때, 반대쪽은 수신만 가능한 전송 방식입니다. 동시 음성 전송이 불가능한 무전기를 예시로 들 수 있습니다.

 

전이중(양방향) 전송 방식

데이터를 양쪽이 동시에 송수신할 수 있는 전송 방식입니다. 상대의 소리가 들릴 때도 목소리를 전달할 수 있는 전화를 예시로 들 수 있습니다.

 

동기식 전송 방식

연결된 두 장치가 별도의 회선을 통해 클럭신호(Clock Cycle)을 공유하여, 클럭 신호의 주기에 맞춰 데이터 송수신 시점을 일치시키는 전송 방식입니다. 데이터를 블록이라는 큰 단위로 묶어 전송하기 때문에 전송 효율이 높지만, 클럭 신호를 공유하기 위한 추가적인 회선이 필요합니다.

 

비동기식 전송 방식

송식측과 수신측 사이의 송수신 시점을 일치시키는 절차 없이 고정된 크기의 비트 묶음을 기본 단위로 하여 임의의 시점에 전송하는 방식입니다. 추가적인 회선이 필요없으나 시작 비트, 정지 비트가 삽입되어 전송 효율이 낮습니다. 시작 비트 0, 8비트 단위의 데이터 묶음, 정지 비트 1을 묶은 비트 묶음을 전송합니다. 정지 비트 이전에 전송 오류를 확인하기 위한 parity bit를 추가하기도 합니다.

 

직렬 전송 방식

데이터를 한 번에 하나씩 전송하는 방식입니다. 전송 오류가 적고, 회선이 하나라서 저렴하지만 전송 속도가 느립니다.

 

병렬 전송 방식

데이터를 한 번에 여러 개씩 전송하는 방식입니다. 전송 속도가 빠르지만 많이 회선이 필요하기 때문에 비싸고, 직렬 전송 방식에 비해 오류가 많습니다.

 

UART(Universal Asynchronous Reciver/Transmitter)

병렬 데이터의 형태를 직렬 방식으로 전환하여 데이터를 전송하는 통신입니다. '110001' 이란 데이터를 '1' '1' '0' '0' '0' '1' 같은 직렬 방식으로 전송합니다. UART는 비동기인데, 클럭 신호를 보냄으로 동기화가 되지 않기 때문에 시작하는 start bit와 끝나는 stop bit를 함께 보내서 동기화를 이룹니다. stop 비트 이전에 Parity bit도 있는데, 이 비트는 데이터 전송 과정에서 오류가 생겼는지 확인하기위해 추가되었습니다. 따라서 UART 통신은 8bit를 보내는데 start bit, stop bit, parity bit를 추가하여 총 12bit를 보냅니다.

 

I2C(Inter-Intergrated Circut)

아이투씨라고도 부르는데, 정식 명칭은 아이 스퀘어 씨 입니다. I2C는 IC 사이에 통신 링크를 제공하는 양방향 직렬 통신 프로토콜입니다. 이 통신을 하기 위해 2가닥의 선을 연결해야 합니다. 한 가닥의 선은 SDA로, 데이터를 주고받기 위한 선이고, 다른 한 가닥의 선은 SCL으로, 동기화를 위한 클럭 선입니다. 클럭 신호를 이용해서 데이터를 얼마나 보내는지 타이밍을 맞추기 때문에, 통식속도를 따로 정해주지 않아도 된다는 장점이 있습니다.  반이중 방식이기에 송신과 수신에 동시에 불가능합니다.


20230610

MiNiProject

#include <LiquidCrystal_I2C.h> // 추가
LiquidCrystal_I2C lcd(0x27, 16, 2); // lcd 객체 선언

/* 서보는 망가졌다!
#include <Servo.h> // 추가
Servo servo; // servo 객체 선언
*/

#define TRIG 9 // TRIG 핀 설정
#define ECHO 8 // ECHO 핀 설정
#define LEDY 12 // 노란 LED 핀 설정
#define LEDR 13 // 빨간 LED 핀 설정

int lcdCheck=0, lcdChange;

void setup() {
  lcd.begin(); // LCD 사용 시작
  Serial.begin(9600); // 테스트용 시리얼 통신 정의
  pinMode(TRIG, OUTPUT); // 보내는 핀이니까 출력
  pinMode(ECHO, INPUT); // 받는 핀이니까 입력
  pinMode(LEDY, OUTPUT);
  pinMode(LEDR, OUTPUT);
  /* 서보는 망가졌다!
  servo.attach(3);
  servo.write(90);
  */
  /* 부저는 빠졌다!
  pinMode(7, OUTPUT);
  */
}

void loop() {
  long duration, distance;
  digitalWrite(TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  duration = pulseIn(ECHO, HIGH);
  distance = duration * 17 / 1000; // 돌아오는 시간 cm로 환산
  /*초음파센서 테스트
  Serial.println(duration);
  Serial.print("\nDistance : ");
  Serial.print(distance);
  Serial.println(" Cm");
  */
  Serial.println(distance);

  lcdChange=0;

  if(distance>=10 && lcdCheck==1){ // 만약 거리가 멀다면
    digitalWrite(LEDR, HIGH); // 빨간 LED 켜기
    digitalWrite(LEDY, LOW);
    lcd.setCursor(5, 0);
    lcd.print("Far!!!"); // LCD에 Far!!! 출력하기
    /* 서보는 망가졌다!
    for(int i=170;i>=10;i--){ // 서보 돌리기
      servo.write(i);
      delay(10);
    }
    */
    /* 부저는 빠졌다!
    tone(7, 523); // '도' 음 출력하기
    */
    lcdCheck=0;
    lcdChange=1;
  }else if(distance<10 && lcdCheck==0){ // 만약 거리가 가깝다면
    digitalWrite(LEDR, LOW);
    digitalWrite(LEDY, HIGH); // 노란 LED 켜기
    lcd.setCursor(5, 0);
    lcd.print("Close!"); // LCD에 Close! 출력하기
    /*서보는 망가졌다!
    for(int i=10; i<170; i++){ // 서보 돌리기
      servo.write(i);
      delay(10);
    }
    */
    /* 부저는 빠졌다!
    tone(7, 783); // '솔' 음 출력하기
    */
    lcdCheck=1;
    lcdChange=1;
  }
  /* 부저는 빠졌다!
  if(lcdChange){
    servo.detach();
  }
  */
  
  delay(1000);
}

'Nefus' 카테고리의 다른 글

NEFUS_Network  (0) 2023.07.24
NEFUS_미연시프로젝트  (1) 2023.04.20
NEFUS_포인터  (2) 2023.04.12