아두이노 PORT MANIPULATION 기법에 의한 barGraph 예제 재구성
라즈베리도 시작하시고 싶으신가요?
이 책에서 해답을 찾으세요.
교보문고에서 판매중입니다.
_____________________up to here, Commercial!___________________________________________________
barGraph 아두이노 예제는 디지털 핀 2,3,∙∙∙,11 번까지 LED 와 전류 제한 저항을 배선해 둔 상태에서, 아날로그 채널 A0에서 0∼1023까지의 아날로그 값을 읽어 100으로 나눠주어 0∼10까지의 값이 얻어지면 해당 하는 숫자만큼의 LED를 ON 해주는 코드이다.
이 barGraph 코드를 PORT MANIPULATION 기법으로 바꾸어 보도록 한다.
LED 와 전류 제한 저항이 배선된 디지털 핀 2,3,∙∙∙,11 번 중에 디지털 핀 번호로 2∼7번까지는 PORTD 3∼8번까지에 해당하며 디지털 핀 번호로 8∼11번까지는 PORTB 1∼4번까지에 해당한다.
우선 PORTD 와 PORTB에 속하는 핀들의 방향 설정 레지스터 즉 DDRD 와 DDRB를 다음과 같이 출력으로 설정하도록 하자.
DDRD = B11111100;
DDRB = B00001111;
DDRD에서 00으로 설정된 비트는 RX와 TX 해당하는 통신 핀이므로 LED 설치에서 제외된 곳이다.
아울러 가변저항으로부터 아날로그 전압을 읽어들이는 A0는 PORTC에서 입력 즉 0의 값으로 설정해야 하는데 굳이 하지 않아도 작동의 문제가 없음에 유의하고, 그 대신 다른 레지스터들을 다음과 같이 설정한다.
ADMUX = B01100000;
ADCSRA = B10000011;
여기까지의 내용들은 setup() 문에서 통신속도 설정과 함께 이루어져야 한다.
loop() 문에서는 아날로그 디지털 변환이 시작됨과 동시에 8비트 해상도의 데이터가 저장되어 있는 ADCL 레지스터의 값을 아두이노 정수형 변수에 옮겨 담는 작업이 필요하다.
물론 8비트냐 10비트냐의 문제는 Atmega328 칩의 ADLSR 레지스터 사용과 연관하여 8비트 데이터 1개를 중심으로 나머지 8비트 속에 포함된 2비트 데이터를 왼쪽에 배치하는냐 아니면 오른쪽에 배치하는냐의 문제이다. 만약 오른쪽에 2비트를 배치하게 되면 8비트 이진 데이터가 2자리씩 왼쪽으로 이동하는 셈이 되는데 정확하게 4배로 커지게 된다. 즉 256까지의 데이터를 왼쪽으로 2자리 이동 시킨다는 의미는 1024까지의 데이터를 나타내게 된다. 오른 쪽 하위 자리에 2비트가 추가된다면 해상도가 조금 개선될 수 있을 것이다.
0∼255까지의 8비트 데이터를 읽어서 25로 나누면 10개의 LED를 ON OFF 할 수 있는 0∼10까지의 값이 얻어진다. PORTD 에 6개 PORDB에 4개의 LED 가 설치되어 있으므로 입력 값이 7 미만이면 2개 포트 중 DDRD는 입력 값 개수만큼 ON 하고 PORTB는 전체 OFF 해야 한다. 반대로 7 이상이면 포트 중 DDRD는 전체 ON 하고 DDRB는 입력 값에서 6을 뺀 만큼 ON하면 된다.
마지막으로 delay(500) 또는 그 이상을 인위적으로 주고 가변 저항을 아주 서서히 돌려야 하나씩 순차적으로 LED 가 ON 되는 것을 볼 수 있다.
이러한 PORT MANIPULATION 기법은 아두이노의 16MHz 라는 느린 클럭 속도로 인해 빠른 연산을 요하는 드론 비행제어 보드 코딩에 필수적이므로 아두이노 드론 입문자는 반드시 숙지해야 할 코딩 기법임에 유의하자.
DDRB_barGraph_01
#include <avr/io.h>
byte Dsegments[]={B00000000,B00000100,B00001100,B00011100,B00111100,B01111100,B11111100};
byte Bsegments[]={B00000000,B00000001,B00000011,B00000111,B00001111};
//ledPins: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
void setup() {
Serial.begin(9600);
ADMUX = B01100000; //set analog A0 input channel
ADCSRA = B10000011;
DDRD = B11111100; //set pins 2,3,4,5,6,7 as OUTPUT mode @PORTD
DDRB = B00001111; //set pins 8,9,10,11 as OUTPUT mode @PORTB
PORTD = B00000000;//initialize pins 2,3,4,5,6,7 as LOW
PORTB = B00000000;//initialize pins 8,9,10,11 as LOW
}
void loop() {
ADCSRA |= (1 << ADSC);//Start Conversion
int sensorReading = ADCH;// read 8 bit data
int ledLevel = sensorReading/25;//int sensorReading = analogRead(analogPin)
Serial.println((int)ledLevel);
if (ledLevel<7) {
PORTB = Bsegments[0];
PORTD = Dsegments[ledLevel];
}
if (ledLevel >= 7) {
PORTD = Dsegments[6];
PORTB = Bsegments[ledLevel-6];
}
delay(500);
}