led는 긴쪽이 (+), 짧은 쪽이 (-)입니다.
전압이 높은 곳이 (+), 낮은 쪽이 (-). 전류는 (+)방향에서 (-)로 흐릅니다.
저항은 1kΩ을 사용합니다.
사용된 핀은 GND와 디지털핀 13번입니다.
LED의 밝기는 LED에 흐르는 전류에 비례합니다.
아두이노의 디지털 핀 HIGH는 5V를 인가합니다.
아두이노의 디지털핀에서 GND까지의 회로의 총 전압은 5V입니다.
이 때 저항이 커진다면 LED의 밝기는 ?
저항이 작아진다면?
저항이 0에 가까워지면???
저항을 바꿔가면서 led 밝기를 실험해 봅시다.
옴의 법칙 V=IR
기본적으로 LED자체에 저항이 있기때문에 전류가 ∞까지 가지는 않지만 허용전류를 넘어서거나
너무 큰 전류가 계속 흐르게 되면 소자가 타버립니다.
저항이 낮은 소자일 경우 항상 저항을 연결해서 사용합시다.
PWM
디지털 신호는 0과1, 이렇게 2가지의 상태만 줄 수 있는데 아날로그는 다양한 상태를 가질 수 있다.
디지털 신호로 아날로그 신호처럼 다양한 크기의 상태를 나타내기 위한 기법이 바로...
PWM : 펄스 폭 변조 (Pulse With Modulation )이다.
위 그림과 같이 1(5v)가 인가된 시간을 조절해서 구현한다. 5v의 전압이 인가되면 전류가 흐르게 되고 led에 불이 켜진다. 이 때 항상 1의 상태를 유지하는것이 아니라 짧은 주기로 0과 1의 상태를 번갈아간다. 실제로 led불빛은 꺼졋다가 켜지는걸 반복하지만 이 주기가 매우 짧으면 우리는 그걸 인식하지 못하고 계속 켜져있는 걸로 인식한다.
단, 꺼진 시간만큼 불빛의 세기가 약해진 것 처럼 보인다.
꺼져있는 시간이 25%이면 Duty Cycle은 75%이다.
아두이노에서는 14개의 디지털 핀중 6개(3,5,6,9,10,11)를 PWM 신호로 사용할 수 있다.
digitalWrite(pin번호,HIGH)는 대신 analogWrite(pin번호, 0~255)로 Duty Cycle을 조절할 수 있다.(255이 100%)
실습 1 : led가 점점 밝아지도록 해보세요,
int led=6;
void setup() {
// put your setup code here, to run once:
pinMode(led,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
for(int i=0;i<256;i++){
analogWrite(led,i);
delay(30);
}
}
실습2. 3개의 led가 1초마다 돌아가면서 켜지도록 해보세요.
int red=12;
int green=10;
int blue=8;
void setup() {
pinMode(red,OUTPUT);
pinMode(green,OUTPUT);
pinMode(blue,OUTPUT);
}
void loop() {
digitalWrite(red, HIGH);
digitalWrite(green, LOW);
digitalWrite(blue, LOW);
delay(1000);
digitalWrite(red, LOW);
digitalWrite(green, HIGH);
digitalWrite(blue, LOW);
delay(1000);
digitalWrite(red, LOW);
digitalWrite(green, LOW);
digitalWrite(blue, HIGH);
delay(1000);
}
문제1. Serial에 문자 'r'을 입력하면 빨간색이, 'g'를 입력하면 초록색이, 'b'를 입력하면 파란색이 켜지도록 해보세요.
int red=12;
int green=10;
int blue=8;
void setup() {
pinMode(red,OUTPUT);
pinMode(green,OUTPUT);
pinMode(blue,OUTPUT);
Serial.begin(9600);
}
void loop() {
if(Serial.available()){
char inputRGB=Serial.read();
Serial.println(inputRGB);
if(inputRGB=='r'){
digitalWrite(red, HIGH);
digitalWrite(green, LOW);
digitalWrite(blue, LOW);
}else if(inputRGB=='g'){
digitalWrite(red, LOW);
digitalWrite(green, HIGH);
digitalWrite(blue, LOW);
}else if(inputRGB=='b'){
digitalWrite(red, LOW);
digitalWrite(green, LOW);
digitalWrite(blue, HIGH);
}
}
}
※기본적으로 Serial에 문자열을 입력해도 Serial은 byte단위로 읽기 때문에 한 문자씩 읽는다.
Serial.read는 Serial의 입력을 읽을 때 loop함수가 빠르게 돌면서 한글자씩 읽는다.
if(Serial.available()){
char inputRGB=Serial.read();
Serial.println(inputRGB);
}
위의 코드는 사용자가 'rgb'라는 3글자를 입력한 후 enter를 눌러도 loop 처음 돌 때 r, 2번째 돌 때 g, 3번째 돌 때 b를 받는다.
문자열을 받기 위해 문자를 한개씩 읽지않고 한번에 읽는 방법은 여러가지가 있다.
※이제부터 소스코드의 핀번호와 회로도가 다를 수 있습니다. 알아서 맞춰주세요.
문제2. Serial.readString() 및 String.indexOf()함수를 이용해서 "rg"를 입력하면 빨간색,초록색 ,"gb"를 입력하면 초록색,파란색 처럼 문자열에 r,g,b가 포함돼어있으면 해당 led가 켜지도록 해보세요.
C에는 기본적으로 String이 없지만 아두이노에서는 String 타입을 제공해준다.
(우리가 아는 String이랑 비슷하지만 똑같지는 않다.
https://www.arduino.cc/reference/ko/language/functions/communication/serial/readstring/)
Serial.readString()은 사용자가 문자열 'rgb'를 입력하면 Serial 버퍼에 글자를 모두 읽기 위해 내부적으로 setTimeOut()을 호출한 후 그 시간 동안(기본 1000ms) 버퍼의 글자를 모두 읽어 문자열 String으로 만든 후 반환한다.
#define RED 13
#define GREEN 12
#define BLUE 11
void setup() {
pinMode(RED,OUTPUT);
pinMode(GREEN,OUTPUT);
pinMode(BLUE,OUTPUT);
Serial.begin(9600);
}
void loop() {
if(Serial.available()){
String s=Serial.readString();
int r=s.indexOf('r');
int g=s.indexOf('g');
int b=s.indexOf('b');
digitalWrite(RED,LOW); digitalWrite(GREEN,LOW); digitalWrite(BLUE,LOW);
if(r!=-1)digitalWrite(RED,HIGH); if(g!=-1) digitalWrite(GREEN,HIGH);
if(b!=-1) digitalWrite(BLUE,HIGH);
}
}
문제2-2. Serial.readString은 이는 문자열이나 바이트숫자를 읽어오는 경우에 함수 내부에 지정된 setTimeOut(default 1000) 이 실행된다. 즉, 읽어오고 1초동안 프로그램이 멈춘다. loop함수 내에서 while문과 Serial.read()를 이용해서 문자열을 받은 다음에
문제 2번처럼 동작하도록 해보세요.
#define RED 13
#define GREEN 12
#define BLUE 11
void setup() {
pinMode(RED,OUTPUT);
pinMode(GREEN,OUTPUT);
pinMode(BLUE,OUTPUT);
Serial.begin(9600);
}
void loop() {
String s="";
char ch;
while (Serial.available() > 0)
{
ch = Serial.read();
s.concat(ch); // 문자열을 잇는 함수
delay(10);
int r=s.indexOf('r');
int g=s.indexOf('g');
int b=s.indexOf('b');
digitalWrite(RED,LOW); digitalWrite(GREEN,LOW); digitalWrite(BLUE,LOW);
if(r!=-1)digitalWrite(RED,HIGH); if(g!=-1) digitalWrite(GREEN,HIGH);
if(b!=-1) digitalWrite(BLUE,HIGH);
}
if(!s.equals("")){
Serial.println(s);
}
}
문제 3 . 30초마다 신호가 바뀌는 신호등을 만들어봅시다. 어떤 신호등은 특정 시간이 되면 노랑색 불만 반짝입니다.
특정 시간대신에 Serial에 'yellow'를 입력하면 노랑색 불이 반짝이고, 'basic'을 입력하면 기본 신호등이 되도록 해봅시다.
#define RED 13
#define GREEN 11
#define YELLOW 12
void setup() {
pinMode(RED,OUTPUT);
pinMode(GREEN,OUTPUT);
pinMode(YELLOW,OUTPUT);
Serial.begin(9600);
}
boolean isYellow=false;
void loop() {
String s="";
char ch;
while (Serial.available() > 0)
{
ch = Serial.read();
s.concat(ch); // 문자열을 잇는 함수
delay(10);
if(s.equals("yellow")){
isYellow=true;
}else if(s.equals("basic")){
isYellow=false;
}
}
if(isYellow){
digitalWrite(GREEN,LOW);
onYellow();
}else{
digitalWrite(YELLOW,LOW);
onBasic();
}
if(!s.equals("")){
Serial.println(s);
}
}
void onYellow(){
digitalWrite(YELLOW,HIGH);
delay(1000);
digitalWrite(YELLOW,LOW);
delay(1000);
}
void onBasic(){
digitalWrite(RED,HIGH);
digitalWrite(YELLOW,LOW);
digitalWrite(GREEN,LOW);
delay(5000);
digitalWrite(RED,LOW);
digitalWrite(YELLOW,HIGH);
digitalWrite(GREEN,LOW);
delay(1000);
digitalWrite(RED,LOW);
digitalWrite(YELLOW,LOW);
digitalWrite(GREEN,HIGH);
delay(5000);
}