[1] 채터링(Chattering)
- <아두이노 마스터1 우노보드 기초 - 신동욱> p104
1. 채터링이란??
- 전자 회로 내의 스위치 접점이 닫히거나 열리는 순간에 기계적인 진동에 의해 매우 짧은 시간안에
스위치가 붙었다가 떨어지는 것을 반복하는 현상
- 이 문제를 해결하는 방법을 Debouncing(디바운싱)이라고 하며, 하드웨어적인 방법과 스프트웨어적인 방법 존재
https://blog.naver.com/PostView.nhn?isHttpsRedirect=true&blogId=roboholic84&logNo=220880882127
푸쉬버튼의 단점[채터링/디바운스/플로팅/바운딩]
안녕하세요! 메카솔루션입니다. 오늘은 스위치의 단점 대해 자세히 알아보고자 합니다. 그전에 푸쉬 버튼의...
blog.naver.com
2. Debouncing - 소프트웨어적인 방법
- 어제 작업한 예제인, 5. 풀다운 방식 + LED제어 예제2 에서 채터링 문제 보완
- 입력된 값(read_data)이 이전의 버튼 상태(lastBtnState)와 다르면 그 때의 시간을 기록 - lastTime
- 현재 시간과 lastTime의 차이가 50ms 보다 작을 경우 led 반전 안함
- 다시 lastBtnState에 read_data를 저장
- 다시 loop 새로 시작하고 read_data와 lastBtnState 가 같으면 시간 기록을 안함
- 이전 loop에서 기록한 lastTime과 이번 loop에서의 현재 시간의 차이가 50ms보다 작을 경우 led 반전 안함
- 이 과정 반복하다가, milli() - lastTime 이 50ms이 넘으면 led 반전 실행 및 btn_state에 read_data 저장
// push_btn_led_exam5_chattering
// chattering문제 해결
// push버튼을 누르면 led가 켜지고, 다시 누르면 led가 꺼지도록
// 풀다운 방식으로 처리하기
// 입력핀 11
// 출력핀 8
int push_btn = 11;
int led_pin = 8;
// 여러가지 상태값을 저장할 변수
int btn_state = 0; // push버튼의 현재 상태값을 저장하는 변수
boolean led_state = 0; // boolean으로 led의 상태를 정의
boolean lastBtnState = 0; // push버튼의 마지막 상태값을 저장할 변수
long lastTime = 0; // 스위치가 눌려진 시점의 시간을 측정 - chattering구간을 체크하기 위해
void setup() {
Serial.begin(9600);
pinMode(push_btn, INPUT);
pinMode(led_pin, OUTPUT);
}
void loop() {
// 입력핀으로 설정한 13번 핀의 입력된 현재 값을 읽어서 저장
// 1. 디지털 핀에 입력된 값을 읽기
int read_data = digitalRead(push_btn);
// 2. 스위치 이전 상태가 지금과 다르면 작업한 시점의 ms를 기록
// - 버튼이 눌려지면 현재상태를 파악해서 이전과 다른 값인 경우 버튼이 눌려진 시간을 기록한다.
if(read_data != lastBtnState){
lastTime = millis(); // 1/1000초 단위로 기록
}
if(millis()-lastTime > 50){ // 최초로 측정된 시간보다 경과한 시간이 50정도면 chattering기간으로 인지
Serial.println("=========================================");
if(read_data!=btn_state){
btn_state = read_data; // 스위치의 상태가 누른 값과 다르면 버튼의 상태값을 변수에 저장
if(read_data == HIGH){ // 풀업 방식으로 버튼을 연결하거나, HIGH 대신 LOW를 쓰면 버튼을 뗄 때 LED ON
led_state = !led_state; // led의 상태값을 반전(true=>false, false=>true)시켜서 저장
}
}
}
digitalWrite(led_pin,led_state);
lastBtnState = read_data;
}
- 이 코드의 각 변수의 변화와 버튼 동작, LED 동작의 관계를 엑셀로 정리하였다.
- 컴퓨터가 코드 각 줄을 읽어서 수행하는 시간을 5ms로 가정(실제론 더 빠르므로, 더 많은 loop를 돌게 됨)
- 초기화 이후 1 loop 모두 돌고 2 loop 돌기 직전 찰나의 순간에 버튼을 눌렀다고 가정
- 버튼 해제 상태 -> 버튼 누름 -> 버튼 해제 싸이클 완료 후
=> btn_state, read_data, lastBtnState 가 모두 0으로 초기화 됐고, LED는 켜진 상태가 되었다.
- 같은 방식으로 LED가 켜진 상태에서, 버튼을 눌렀다가 떼는 과정 완료 후
=> btn_state, read_data, lastBtnState 가 모드 0으로 초기화 되고, LED는 꺼진 상태가 될 것.
- 만약 chattering이 발생한다면 중간에 read_data가 바뀌기 때문에 더 많은 loop를 돌아야 할 것이다.
- Arduino IDE에 내장된 예제에도 Debounce 코드가 구현되어 있음
[2] 아날로그 입출력
- <아두이노 마스터1 우노보드 기초 - 신동욱> p163~p169
1. 입출력 핀
1) 아날로그 입력 핀(ADC: Analog to Digital Converter)
- 보드 왼쪽에 ANALOG IN 구역에 A0, A1, A2, A3, A4, A5
- 입력되는 아날로그 신호를 디지털 신호로 변환(Analog to Digital)
- ADC를 통해 변환된 디지털 신호의 값은 10bit로 0~1023 의 값을 가진다.
2) 아날로그 출력 핀(PWM: Pulse Width Modulation)
- 보드 오른쪽에 DIGITAL(PWM~) 중에 '~' 표시가 있는 번호 : 3, 5, 6, 9, 10, 11
- 출력되는 디지털 신호(0,1)를 아날로그 신호처럼 출력(이를 PWM 신호라고 한다)
- 과거에는 DAC(Digital to Analog Converter)를 사용하였지만, 최근에는 PWM 신호 사용
- PWM 신호는 8bit로 0~255 의 값을 가진다.
2. PWM(Pulse Width Modulation, 펄스 폭 변조)
https://docs.arduino.cc/learn/microcontrollers/analog-output
Basics of PWM (Pulse Width Modulation) | Arduino Documentation | Arduino Documentation
Basics of PWM (Pulse Width Modulation) Learn how PWM works and how to use it in a sketch.. The Fading example demonstrates the use of analog output (PWM) to fade an LED. It is available in the File->Sketchbook->Examples->Analog menu of the Arduino software
docs.arduino.cc
- 디지털 신호로 아날로그 신호를 표현해주는 방식
- 디지털 신호에는 0(0V, LOW), 1(5V, HIGH) 밖에 없음
- 실생활의 상태량(property)은 아날로그인 경우가 많음(속도, 조도, 온도, 습도 등)
- 이러한 아날로그 값을 0, 1 만으로는 표현하기 힘들기 때문에, 0(0%)과 1(100%) 사이의 값을 출력하기 위한 방식
- 5V와 0V를 한 번씩 출력하는 것이 한 주기(cycle)
- 한 주기에서 5V 신호가 차지하는 비율을 Duty Cycle
- analogwrite(핀 번호, 값) : 지정된 PWM 출력 핀에 0~255값을 출력
① 핀 번호
- 3, 11(Timer2), 9, 10(Timer1) : 490Hz
- 5, 6(Timer0) : 980Hz
② 값
- 0~255
- Duty Cycle = 값 / 255 * 100%
3. 디지털 출력으로 PWM 신호 표현
- LED를 풀다운 방식으로 연결하고, 입력핀은 8번(digital)을 사용
- 디지털 출력으로 HIGH/LOW를 반복하되, 켜져있는 시간과 꺼져있는 시간을 조절하면, LED의 밝기를 조절 가능
- 10ms가 한 주기이므로, 아날로그라고 치면 주파수가 100Hz (1초에 주기가 100번 나옴)
- 한 주기인 10ms 중에 HIGH가 1ms, LOW가 9ms 이므로, 10% Duty Cycle
- 업로드 하면, 마치 계속 켜져있는 것처럼 보이지만, LED의 밝기가 그냥 HIGH를 받을 때보다 어둡다.
- HIGH/LOW 시간 비율을 조절하여 LED의 밝기를 조절할 수 있다.(즉, Duty cycle 조정)
// analog_test1
int led = 8;
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
digitalWrite(led, HIGH); // HIGH == 1 -> LED on
delay(1);
digitalWrite(led, LOW); // LOW == 0 -> LED off
delay(9);
}
4. 아날로그 출력 예제1
- LED를 풀다운 방식으로 연결하고, 출력 핀은 11번(PWM)을 사용
- analogWrite(핀 번호, 값) 함수에서 값을 0~255, 255~0 으로 변화시켜서 아날로그 신호를 출력
- 업로드 하면, LED의 밝기가 어두워졌다 밝아졌다를 반복한다.
1) CODE
// analog_test2
// PWM 테스트 - pulse width modulation
// 아날로그를 디지털 신호로 바꾸기 위한 방법
// PWM은 8bit를 사용 - 2의 8승 = 256가지 즉, 0~255 를 표현 가능
// ADC(Analog Digital Converter) - 10bit(2의10승 = 1024가지)
int led = 11;
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
// 0부터 255까지 셋팅되고 255가 넘으면 다시 0부터 작업이 철
// 밝아졌다가 어두워지는 모든 값들을 적용
for(int i=0; i<256; i++){
analogWrite(led, i);
delay(10);
}
for(int i=255; i>=0; i--){
analogWrite(led, i);
delay(10);
}
}
2) 동작
4. 가변저항(Potentiometer)
https://m.blog.naver.com/compass1111/221166512331
가변저항 (포텐셔미터) 원리 (about Potentiometer)
서보모터에서 포텐션미터에 대해서 잠시 언급이 되었는데요. 말이 나온 김에 포텐션미터에 대해서 함께 알...
blog.naver.com
- 내부 구조가 위 그림과 같이 생겼다.
- 기본적으로 1, 3번 핀은 5V, GND 어느 쪽이든 사용할 수 있고, 2번 핀에는 보드의 입력핀과 연결
- 1과 3 중 어느 쪽에 5V를 연결했느냐에 따라서 서로 반대의 저항이 걸린다.
- 결론만 얘기하면, 5V가 연결된 쪽으로 와이퍼가 이동할 수록 입력핀의 값이 커진다.(구체적 계산은 위 블로그에)
5. 아날로그 입력(가변저항) 예제
- 가변저항을 이용해 아날로그 입력핀으로 들어오는 값을 시리얼 모니터에 출력
- 가변저항의 저항을 변경해줌에 따라서 시리얼 모니터에 0~1023 의 값이 출력된다.
1) CODE
// analog_read_test
void setup() {
Serial.begin(9600);
}
void loop() {
int readValue = analogRead(A0);
Serial.println(readValue);
delay(1000);
}
2) 회로 모델
6. 아날로그 입력(가변저항) + 디지털 출력(LED) 예제
1) CODE
// analog_exam1
// 가변저항과 LED를 이용해서 가변저항의 값이 500이상이면 불을 켜고 500미만이면 불을 끄기
int led_pin = 4; // LED 연결 핀
int p_pin = 0; // 가변저항 연결 핀
void setup() {
Serial.begin(9600);
pinMode(led_pin, OUTPUT);
}
void loop() {
int readValue = analogRead(p_pin);
Serial.println(readValue);
if(readValue >= 500){
digitalWrite(led_pin, HIGH);
}else{
digitalWrite(led_pin, LOW);
}
delay(100);
}
2) 회로 모델
3) 동작
7. 아날로그 입력(가변저항) + 아날로그 출력(LED) 예제
- 가변저항을 통해 들어온 입력값을 받아 LED를 아날로그 값으로 제어하여 밝기를 조절
- 아날로그 입력값은 0~1023 이지만, 출력값은 0~255 이므로, 입력값을 0~255로 변환하는 과정이 필요하다.
-> pwmValue = (float) readValue / 1023 * 255;
- 그러나 매번 이런 변환 과정을 식으로 만들어서 쓰기에는 번거롭기 때문에 제공되는 함수가 있다.
- map( 변수, 변수의 최소값, 변수의 최대값, 적용할 값의 최소값, 적용할 값의 최대값)
-> pwmValue = map(readValue, 0, 1023, 0, 255);
1) CODE
// analog_exam2
// analog_test2와 같은 결과를 가변저항과 led를 이용해서 표현
// - 가변저항의 값이 커지면 LED의 밝기가 밝아지고
// - 가변저항의 값이 작아지면 led의 밝기가 어두워지도록
int led_pin = 3; // LED 연결 핀
int p_pin = 0; // 가변저항 연결 핀
void setup() {
Serial.begin(9600);
pinMode(led_pin, OUTPUT);
}
void loop() {
int readValue = analogRead(p_pin);
// int pwmValue = (float)readValue/1023 * 255;
// map( ) 함수를 이용해서 값을 변환
// 평가할 기준이 되는 변수, 변수의 최소값, 변수의 최대값, 적용할 값의 최소값, 적용할 값의 최대값
// ------------------------ ---------------------------------
// 실제 변수가 갖는 값의 범위 변환할 값의 범위
int pwmValue = map(readValue, 0, 1023, 0, 255);
Serial.print(readValue);
Serial.print('\t');
Serial.println(pwmValue);
analogWrite(led_pin, pwmValue);
delay(100);
}
2) 회로 모델
3) 동작
8. 아날로그 입력(가변저항) + 아날로그 출력(LED) + 디지털 입력(버튼)
1) CODE
// analog_exam3
// LED 3개, push 버튼 풀업으로 1개, 가변저항 1개를 준비해서 작업
// - LED 3개 -> PWM
// - 가변저항 -> 아날로그 입력
// - push 알아서 연결
// [동작]
// - 가변저항의 값이 0~300 이면, LED1 ON 상태
// - 가변저항의 값이 301~700 이면, LED2 ON 상태
// - 가변저항의 값이 701~1023 이면, LED3 on 상태
// - push 버튼을 누르면 모든 led가 off
int led_pin1 = 11; // led1 핀번호
int led_pin2 = 10; // led2 핀번호
int led_pin3 = 9; // led3 핀번호
int btn_pin = 8; // push 버튼 핀 번호
int p_pin = 0; // 가변저항 핀 번호
int preReadValue = 0; // 이전 loop 아날로그 값을 저장
void setup() {
Serial.begin(9600);
pinMode(led_pin1, OUTPUT);
pinMode(led_pin2, OUTPUT);
pinMode(led_pin3, OUTPUT);
pinMode(btn_pin, INPUT);
}
void loop() {
int readValue = analogRead(p_pin);
int btn_value = digitalRead(btn_pin);
Serial.print(readValue);
Serial.print(' ');
Serial.println(btn_value);
if(abs(readValue-preReadValue)>1){ // 가변 저항을 변화 시켜서 readValue가 변하면 LED 작동하도록
led_on(readValue);
}
if(btn_value==0){
led_allOff();
}
preReadValue = readValue;
}
void led_on(int readValue){
if(readValue<=300){
analogWrite(led_pin1, 255);
}else if(readValue<=700){
analogWrite(led_pin2, 255);
}else{
analogWrite(led_pin3, 255);
}
}
void led_allOff(){
analogWrite(led_pin1, 0);
analogWrite(led_pin2, 0);
analogWrite(led_pin3, 0);
}
2) 회로 모델
3) 동작
[3] RGB LED와 RGB LED 모듈
- <아두이노 마스터1 우노보드 기초 - 신동욱> p173
1. RGB LED
- 일반 LED가 특정한 색깔만 출력할 수 있었다면, RGB LED는 RGB 각 색을 0~255인 PWM 신호를 받아 조절하여
다양한 색깔을 출력할 수 있는 LED이다.
- 즉, (0,0,0)을 출력하면, 출력이 0이므로 빛을 내지 않을 것이고, (255,255,255)를 출력하면 밝은 하얀 빛을 낸다.
- 컴퓨터 모니터에서 RGB(0,0,0)이 검정이지만, 검정은 빛이 없는 것이므로 LED에서는 출력이 없는 것으로 이해.
- RGB LED는 Common이 (+)냐 (-)냐에 따라 RGB LED Anode, RGB LED Cathode 로 나뉜다.
2. RGB LED 모듈
- RGB LED는 저항을 따로 연결해서 써야 했다면, RGB LED 모듈은 저항이 내장되어 있어서 바로 연결해서 사용 가능
- 기능과 사용법은 RGB LED와 동일하다.
- 사진은 Common Cathode이고, common Anode 모듈도 있다.
- 끝 -
'프로젝트형 IoT 서비스 개발 4회차 > 2. 엣지 디바이스 제어' 카테고리의 다른 글
[Day42] 2022-03-29(화) 아두이노7 - 부저, 조도센서, PIR센서, 온습도센서, LCD1 - 김서연 강사님 (0) | 2022.03.29 |
---|---|
[Day41] 2022-03-28(월) 아두이노6 - RGB LED, 서보모터, 초음파센서 - 김서연 강사님 (0) | 2022.03.28 |
[Day39] 2022-03-24(목) 아두이노4 - LED제어3(Push button, 풀업/풀다운) - 김서연 강사님 (0) | 2022.03.24 |
[Day38] 2022-03-23(수) 아두이노3 - C언어 기초2, LED제어2 - 김서연 강사님 (0) | 2022.03.23 |
[Day37] 2022-03-22(화) 아두이노2 - C언어 기초1, LED제어1 - 김서연 강사님 (0) | 2022.03.22 |