티스토리 뷰

Arduino

[Arduino] PWM을 활용한 LED의 밝기 조절

생각많은 소심남 2012. 1. 30. 14:26
요즘 LED를 통한 공부를 책을 읽어보면서 하고 있습니다.

여러분도 알다시피 디지털 세상에서의 정보는 0과 1로 표현됩니다. 물론 한번에 주는 정보량을 변화시켜서 다양한 숫자를 표현할수도 있지만 실질상으로는 0과 1로만 구성되어있다고 하는게 맞는 표현이겠지요?

이전까지 다뤘던 제어들 역시 이런 정보를 이용해서 테스트했습니다. 그런데 한번쯤 이런 고민을 해볼 수 있지 않을까요? 지금 밝기가 너무 밝은데.. 스위치를 통해서 밝기 조절을 하고 싶다. 어떻게 해야할까?

그런데 디지털 세상에서 표현되는 값만으로는 LED는 껐다와 켰다만 구별할 수 있습니다. 그래서 이전 예제에선 잠깐 나왔던 것처럼 digitalWrite(LED,HIGH)를 하면 켜지고 digitalWrite(LED,LOW)를 해주면 꺼집니다.

이때는 사람의 눈이 갖는 특징을 이용해야 합니다.

제일 첫번째 다뤘던 예제로 다시 돌아가면

 
라고 되어있는데 여기서 이 깜빡임을 빠르게 해보겠습니다.
 


또 이렇게도 바꿔봅니다.


한번 결과를 비교해보세요.
분명 이렇게 준다면 LED가 깜빡깝빡 거려야 함에도 우리 눈이 보기에는 계속 켜지있는 것처럼 보입니다.
그리고 실제로 보기에도 그냥 켜진것에 비해서 밝기가 조금 어두워진것을 확인할 수 있습니다.
만약 LOW일때의 시간을 놔두고 HIGH일때의 시간을 1ms으로 한다면 LED가 딱 보기에도 어두워보이는 것을 확인할 수 있을겁니다.


먼저 이야기했던 효과를 바로 잔상효과라고 합니다. 사람의 눈은 일정이상으로 깜빡이는 것에 대해서는 그 깜빡임이라는 동작자체를 인식못하는 특징이 있습니다. 그래서 우리가 보는 만화같은 것도 보신 분은 알겠지만 여러개의 컷을 그려놓고 연속적으로 사람에게 보여주면 사람들은 그걸 하나의 연속되 동작이라고 착각하게 됩니다. 지금 이것도 마찬가지지요. 엄청빠르게(사실 사람의 눈으로 1ms단위의 차이를 인지하기 힘듭니다.) 깜빡이기 때문에 우리 눈은 연속적이라고 착각하는 겁니다.

이제 그 밝기를 delay차이를 둬서 변화시켰는데 이런 것을 Pulse Width Modulation이라고 합니다. 줄여서는 PWM..
같은 주기를 가지고 있는 것에 대해서 HIGH와 LOW의 비를 적절하게 조절함으로써도 이렇게 밝기변화를 줄 수 있습니다.

그런데 고려해볼 것이 있습니다. 항상 이렇게 써야할까요? 난 밝기 변화를 50%를 주고 싶은데 이렇게 하면 코드의 길이가 불필요하게 길어지고 또 여러개 쓰면 귀찮아집니다. 그래서 아두이노 내에서는 9,10,11 핀에 이런 것을 그냥 표현해두었습니다. 다만 이기능을 활용하려면 기존에 배웠던 digitalWrite() 와 대비되는 개념으로 analogWrite()라는 것을 써야 합니다. 사용되는 개념은 똑같습니다. analogWrite()도 역시 변수를 두개 받고 맨 처음에는 Write를 할 주체를 씁니다.
그대신 다음으로 들어갈 변수가 0~255 사이라는 것이 이전에 배웠던 개념과 다른 것이겠지요.

digitalWrite(주체,값) - 값: HIGH or LOW
analogWrite(주체,값) - 값: 0~255사이의 값 

 
쉽게 생각하시면 0과 1사이의 간격을 256등분해서 자른것으로 보시면 됩니다. 따라서 이대로 표현하자면 LED는 256단계로 밝기 조절이 가능합니다. 여기에는 전자쪽 말로 Adc라는 개념이 들어가는데 이 부분은 그냥 넘어가겠습니다. 그냥 256등분쪼개서 표현할 수 있는게 analogWrite()라고만 아시면 될거 같습니다.

아무튼 이걸 쓰려면 LED의 +쪽은 9~11 사이와 연결이 되어있어야 하겠지요?

 
자세히 보시면 아시겠지만 9,10,11번 핀 밑에는 조그맣게 PWM이라고 적혀있습니다. 이핀들중 하나에 연결하면 되겠습니다. 물론 지난 포스팅에서도 이야기했었지만 저항이 타는 것을 막기위해서 200~2k옴 사이의 저항도 달아주는 것이 좋습니다.

자 이제 본격적인 예제입니다.
 


여러분들은 다들 노트북도 갖고 계실겁니다. 혹시 절전모드로 들어갔을때 전원LED가 어떻게 변화하는지 확인해보셨나요?

일부는 모르겠지만 거의 대부분은 LED가 은은하게 깜빡깜빡거릴겁니다. 전에 배웠던 digitalWrite()라는 걸로는 표현하려면 적절하게 delay()를 써야하겠지만 힘들겠지요. 그럼 위와 같이 하면 어떻게 될까요?
우선 i값이 있어서 처음 for루프안으로 들어가면 i값이 변하면서 그 값이 LED에 들어갈겁니다. 이제 i가 255가 되면 for루프를 돌면서 i값이 감소할 것이고 LED에 그 값이 들어가겠지요.
이 과정을 거치면서 LED의 밝기는 변하게 될 것 입니다. 

 
여기서 코드에 의문을 가질 필요가 있습니다. 왜 delay(10)을 써서 일부러 시간을 둔걸까요?
원서인 '손에 잡히는 아두이노' 책에서는 다룬 개념이 있지만 제가 안한 부분이 있습니다. 바로 bouncing이라는 겁니다.
(구글에도 arduino Bouncing이라고 쳐보시면 많은 결과 찾으실 수 있을겁니다.)

우리가 접하고 있는 이 전자회로는 논리적입니다. 또 철저합니다. 그리고 예측할 수 없습니다.
어떻게 보면 모순적인 개념일 수도 있겠지만 기기자체는 자신이 받은 값에 대해서는 철저하게 결과 값을 내보냅니다. 그런데 그렇다고 그 결과 값이 항상 똑같지 않습니다. 물론 오실로스코프로 측정해보면 거의 비슷해보이겠지만 스케일을 확 줄여보면 그 일정하다고 생각하는 값안에는 수많은 잔물결들이 있습니다. 이런 걸 발생하는 요인은 많습니다. 오차가될 수도 있고 회로를 설계하다가 이물질이 묻어서 일수도 있고, 어쩌면 밝혀지지않은 또다른 이론이 이 값에 영향을 줄 수도 있습니다. 

물론 이 같은 값은 과학자와 기술자들에 의해서 모델링이 되어왔고 오차를 최소화할 수 있는 방안에 근접하고 있습니다.
갑자기 이 이야기를 왜 꺼냈냐면, 우리가 analogWrite(LED,128)이라고 해서 LED에 128에 해당하는 값이 꼭 들어가는 게 아니라는 겁니다. 128이라는 값 아래 위로는 129와 127이라는 값이 있고 앞에서 언급한 사유로 인해서 128이 아닌 이 값들이 들어갈 가능성이 있는겁니다. 물론 값은 128에 가깝겠지만요..

그런데 그렇게 127이나 129에 있는 상태에서 값이 확 변해버리면 아두이노는 이전에 받은 값을 무엇이라고 생각할까요?
뭐 거의 대다수는 128이라고 받아들이겠지만, 아주 일부분은 이상한 값(바운싱)으로 받아드릴겁니다. 물론 이건 우리가 원치않는 결과이기도 하겠고요. 그래서 아두이노가 이같은 값을 정확히 인식하는 것을 도와주기 위해서 약간의 텀을 두는 겁니다. delay(10)을 주는 이유도 이런 바운싱을 제거하는 방법중에 하나였습니다. 물론 코드가 복잡해지면 바운싱을 제거하는 방법으로는 다른 걸 고민해봐야겠지요.

말이 조금 길어졌네요. 아무튼 위와 같은 방법으로 LED의 밝기를 은은하게 바꿀 수 있습니다. 물론 이 방법을 사용하기 위해서는 analogWrite()를 정확히 쓰는 법에 대해서 알아둬야 하겠지요?


 

댓글