앞에서 공부한 내용을 바탕으로 코드를 작성했다.
1. 4개의 LED로 구현한 2진 카운터
delay() 함수 대신 millis() 함수를 이용하여 counter_time_previous, counter_time_current를 비교해서
1초의 시간 간격마다 카운터를 1씩 증가하도록 만들었다.
따로 counterLED()함수를 만들어 카운터에 해당하는 숫자를 boolean형으로 만들어 LED로 2진 표현을 할 수 있도록 하였다.
또한 4자리 이진수는 15가 최대이므로, counter가 16이 되면 0으로 초기화시키도록 했다.
2. 가변저항을 이용하여 아날로그값 읽기
아날로그 입력을 할 수 있는 핀 A0을 가변저항을 위한 핀으로 정의해뒀다.
analogRead()함수를 이용하여 가변저항의 값을 얻어 그 값을 Serial.print()를 통해 시리얼 모니터로 확인할 수 있다.
3. 아날로그 값을 이용해 LED 밝기 조절
LED의 밝기를 가변저항을 통해 얻은 아날로그 값으로 조절한다.
analogRead()는 0~1023값을 반환하므로 analogWrite()에 사용하기 위해서,
map()함수를 이용하여 0~255사이의 값으로 변환한다.
4. 아날로그 값을 이용해 모터의 속도를 조절
모터의 이동 시간간격을 아날로그 값으로 조정한다.
map()함수를 이용하여 5~300 사이의 값으로 변환하였다.
값이 클수록 시간 간격이 커지므로 모터의 속도는 느려진다.
#include <Servo.h>
static const int LED_pins[] = {2,3,4,5}; //카운터를 위한 LED
static const int controlled_LED = 6; //밝기 조절 LED
static const int vResistor = A0; //A0핀에 가변저항
static const int servoPin = 11; //PWM 출력이 가능한 핀
unsigned long counter_time_previous, counter_time_current;
unsigned long counter_interval = 1000; //1초 간격으로 카운트
int counter = 0;
Servo myServo;
unsigned long servo_time_previous, servo_time_current;
int servo_interval = 10; //현재 이동시간 간격
int servo_angle = 0; //현재 모터 각도
int angle_step = 1; //모터 각도의 증감
void setup() {
//시리얼 통신
Serial.begin(9600);
//카운터
for(int i =0;i<4;i++){
pinMode(LED_pins[i],OUTPUT);
digitalWrite(LED_pins[i], LOW);
}
//LED
pinMode(controlled_LED,OUTPUT);
digitalWrite(controlled_LED, LOW);
//가변저항
pinMode(vResistor, INPUT);
//서보모터
myServo.attach(servoPin);
myServo.write(servo_angle);
delay(100);
counter_time_previous = millis();
servo_time_previous = millis();
}
void counterLED(int c){
boolean on_off; //LED의 state
for(int i =0;i<4;i++){
on_off = c & (0x1 <<i); //c를 2진수로 LED로 표기
if(on_off){
digitalWrite(LED_pins[i],HIGH);
}
else{
digitalWrite(LED_pins[i],LOW);
}
}
}
void loop() {
counter_time_current = millis();
servo_time_current = millis();
//카운터
if(counter_time_current - counter_time_previous >= counter_interval){ //1초 경과
counter_time_previous = counter_time_current;
if(++counter==16) counter = 0; //4자리 이진수는 최대 15까지 출력, 16이 되면 0으로 초기화
}
counterLED(counter);
//가변저항을 통해 아날로그 값 읽기
int Analog_value = analogRead(vResistor);
Serial.print("가변저항 값: ");
Serial.println(Analog_value);
//LED
int value = map(Analog_value,0,1023,0,255); //0~1023을 0~255로 변환
analogWrite(controlled_LED,value);
//서보모터
int new_interval = map(Analog_value,0,1023,5,300);
if(new_interval != servo_interval){
servo_interval = new_interval; //이동 시간 간격 조정
}
if(servo_time_current - servo_time_previous >= servo_interval){
servo_time_previous = servo_time_current;
servo_angle += angle_step; //현재 각도를 조정
if(servo_angle > 180){
servo_angle = 180;
angle_step *= -1;
}
else if(servo_angle < 0){
servo_angle = 0;
angle_step *= -1;
}
//0~180도 사이로 회전이 가능하기 때문에
//범위를 넘어가면 방향 전환
myServo.write(servo_angle);
}
}
하드웨어 구성
위의 코드에서 설정한 핀 번호에 근거해 회로를 구현했다.
사용한 하드웨어:
LED 5개(붉은색 4, 노란색 1), 220Ω 저항 5개, 로터리형 15mm 가변저항 10KΩ, DGservo 9g
결과 영상
728x90