정보공간_1

[2기 광주 박정태]Arduino 의 모든것#3 본문

IT 놀이터/Elite Member Tech & Talk

[2기 광주 박정태]Arduino 의 모든것#3

알 수 없는 사용자 2012. 11. 19. 19:52

PWM

일반적인 MCU의 학습과정이라면 이부분쯤엔 Timer/counter의 기능이 있기 마련입니다. 하지만 아두이노에서는 이 Timer/counter 기능이 매우 간략하게되어있습니다. 전체 시스템을 만들고 그 주기를 관리하는 과정에서 이 기능은 매우 중요한 기능이지만 아두이노에서는 레퍼런스에서 이부분을 지원하지 않습니다. 예를들면 타이머 기능을 이용해 일정 시간마다 인터럽트를 걸어서 시스템의 주기를 정하고 일련의 행동을 하는게 꽤 중요한 일입니다. 하지만 아두이노에서는 이러한 일이 안되기 때문에 복잡한 시스템을 만드는데에는 적합하지 않습니다.

하지만 Delay같은 것으로 다른 방법을 통해 주기적인 일을 할 수 있기 때문에 전혀 불가능 한 일은 아닙니다. 또한 라이브러리를 추가할수 있고 MCU자체는 이 기능이 가능 하기때문에 추후 라이브러리를 직접 제작해서 Timer인터럽트라든지 counter기능을 추가해 볼 예정입니다.

하지만 Timer/counter기능의 중요한 기능중 하나인 PWM은 지원을 한다. PWM이란 Pulse Width Modulation의 약자로 디지털 신호를 구형파로 발생시켜 duty비를 변화 시키므로써 전압을 제어하는 것입이다.

Rising edge 와 다음 Rising edge의 간격을 주기라 하고 한 주기내의 High와 Low의 비율을 듀티비라 합니다. 1ms주기에서 50%의 듀티비를 같는PWM파형이라 하면 High가 0.5ms 바로 이어서 Low가 0.5ms 이런 파형을 나타내게 됩니다. 이 듀티비를 통해 전압의 평균값인 Vrms값을변화 시켜 아날로그 출력의 변화를 줄 수 있는 것입니다. Vrms 는 전압의 Root Mean Square value 로써 원래는 sine파의 평균전압을 구하는 방법입니다. 구형파는 1 or 0 이기 떄문에 1의 %를 구해서 전압에 곱해주면 평균값을 구할수 있습니다. 이 rms값을 통해 0~5까지 아날로그 출력을 낼 수 있는 것입니다.

analogWrite()

Description

Writes an analog value (PWM wave) to a pin. Can be used to light a LED at varying brightnesses or drive a motor at various speeds. After a call to analogWrite(), the pin will generate a steady square wave of the specified duty cycle until the next call to analogWrite() (or a call to digitalRead() or digitalWrite() on the same pin). The frequency of the PWM signal is approximately 490 Hz.

On most Arduino boards (those with the ATmega168 or ATmega328), this function works on pins 3, 5, 6, 9, 10, and 11. On the Arduino Mega, it works on pins 2 through 13. Older Arduino boards with an ATmega8 only support analogWrite() on pins 9, 10, and 11.

The Arduino Due supports analogWrite() on pins 2 through 13, plus pins DAC0 and DAC1. Unlike the PWM pins, DAC0 and DAC1 are Digital to Analog converters, and act as true analog outputs.

You do not need to call pinMode() to set the pin as an output before calling analogWrite().

The analogWrite function has nothing to do with the analog pins or the analogRead function.

Syntax

analogWrite(pin, value)

Parameters

pin: the pin to write to.

value: the duty cycle: between 0 (always off) and 255 (always on).

Returns

nothing

함수 이름에서 알수 있듯이 Analog출력을 위한 기능입니다. 주기를 바꾸는 것은 이 함수로는 불가능 합니다. 위에서 언급했듯이 주기는 490Hz로 발생하고 함수에 넘겨주는 Value값에 따라 듀티비가 변합니다. 0~255로 0의 듀티비를 가지면 Low의 파형이 255의 듀티비를 가지면 High의 파형이 128의 경우 듀티비 50%의 파형으로 전압이 약 2.5V로 출력을 내는 것과 같은 효과를 줍니다. 이를 응용하여 이 핀에 모터를 연결하여 듀티비를 가변시키면 평균 전압이 변하여 모터의 속도가 바뀌는 것을 알 수 있습니다. 비슷한 예로 LED의 밝기 조절도 가능합니다.

ADC

ADC(Analog to Digital converter)는 말그대로 아날로그의 신호를 디지털로 바꿔주는 역할을 합니다. PWM이 rms를 이용한 Analog출력이었다면 ADC는 아날로그를 디지털화해서 값을 읽어 오는 역할을 합니다. ADC는 주로 센서값을 읽는데 사용하는데 가장 간단한 예인 가변저항을 예로 들면 V=IR의 공식에 의해 가변저항을 돌려 전압값을 변화 시킬 수 있습니다. 이 변화되는 전압을 ADC하면 MCU상에서 전압값을 읽어 들일수 있는데 이것을 ADC라 합니다. 거의 모든 센서가 이 ADC를 통해 값을 읽어 온다고 할 수 있습니다.

analogRead()

Description

Reads the value from the specified analog pin. The Arduino board contains a 6 channel (8 channels on the Mini and Nano, 16 on the Mega), 10-bit analog to digital converter. This means that it will map input voltages between 0 and 5 volts into integer values between 0 and 1023. This yields a resolution between readings of: 5 volts / 1024 units or, .0049 volts (4.9 mV) per unit. The input range and resolution can be changed using analogReference().

It takes about 100 microseconds (0.0001 s) to read an analog input, so the maximum reading rate is about 10,000 times a second.

Syntax

analogRead(pin)

Parameters

pin: the number of the analog input pin to read from (0 to 5 on most boards, 0 to 7 on the Mini and Nano, 0 to 15 on the Mega)

Returns

int (0 to 1023)

MCU 기능인 ADC는 사용하기가 매우 까다롭습니다. Reference전압도 설정해주어야 하고 resolution도 설정해주어야 하고 매우 민감한 기능이기 때문에 사용하기가 다소 까다로운데 아두이노에서는 함수 하나만 쓰면 ADC값을 0~1023사이의 값으로 리턴해줍니다. 아두이노에서의 ADC는 5V 기준으로 0V를 0 5V를 1023으로 1024 의 분해능으로 ADC값을 표현합니다.

대부분의 센서들이 이와같은 ADC를 통해 값을 읽어옵니다.

Communication

MCU간의 통신은 매우 다양한 방법이 있습니다. 통신 규약에 따라 속도도 각양각색이고 방법도 다른 다양한 통신중 가장 간단하고 쉬운 Serial통신을 아두이노는 제공합니다. 1:n 통신을 지원하는 SPI I2C등 다양한 방법이 존재하고 ATmega또한 이 통신들을 지원하지만 아두이노에서는 이 Serial통신을 지원합니다. Uart통신이라고도 불리우는 이 통신은 무선통신디바이스로 가장 널리 쓰이는 블루투스의 통신 방법이기도 합니다.

하드웨어적 연결은 단순히 rx,tx 핀이 존재하고 GND로 전압의 레벨을 맞춰주고 rx는 tx와 tx는 rx와 연결만 시켜주면됩니다.

시리얼 통신의 규약과 패킷등에 대해서 많은 자료들이 있지만 아두이노를 설명하는 포스팅이기 때문에 통신규약에 대한 자세한 설명은 넘어가기로 하겠습니다.

Serial에 대해서는 레퍼런스에도 꾀 많은 함수들이 존재합니다.

현재 포스팅하면서 사용하고 있는 타겟 보드는 Serial을 4개 까지 지원 합니다.

비율을 따져보면 이는 꽤 많은 수라 생각합니다. 이렇게 시리얼통신을 다수를 지원하고 또 사용 함수도 많이 지원하는 이유는 아두이노의 목적을 좀더 잘 알수 있게 해줄수 있습니다. 아두이노 자체는 다른 MCU들에 비해 제한적인부분이 많이 있는게 사실이고 아두이노에 사용되는 MCU의 기능조차도 모두 사용하지 못합니다. 하지만 이런 MCU를 쉽게 사용하기 위함이 가장 크지만 아두이노 자체는 그 자체로 하나의 시스템을 만들기 보다는 PC를 이용한 하드웨어 제어 와 같은 중간의 용도로 사용하기 위함이 아닐까 생각합니다.

시리얼 통신을 시작하기 위한 기본적인 레지스터 셋팅은 함수 begin을 사용합니다.

begin()

Description

Sets the data rate in bits per second (baud) for serial data transmission. For communicating with the computer, use one of these rates: 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, or 115200. You can, however, specify other rates - for example, to communicate over pins 0 and 1 with a component that requires a particular baud rate.

Syntax

Serial.begin(speed)

Arduino Mega only:
Serial1.begin(speed)
Serial2.begin(speed)
Serial3.begin(speed)

Parameters

speed: in bits per second (baud) - long

Returns

nothing

시리얼 통신을위해서는 많은 셋팅을 해주어야 하지만 나머지 대부분의 셋팅은 가장 기본적인 셋팅으로 하고 보레이트(통신속도)만 인자로 넘겨줍니다. 보레이트에는 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200 의 속도를 지원합니다. 보레이트란 양 디바이스의 속도를 동기화 시켜주기 위한 값입니다. 예를들어 디바이스 A는 8Mhz의 클럭을 사용하고 디바이스 B는 16Mhz의 클럭을 사용한다고 하면 같은 신호도 다르게 받아들일수 있습니다.

이런 차이를 해결하기 위한게 바로 보레이트 입니다. 보레이트로 인해 서로다른 하드웨어적인 속도차이를 해결하는 것 입니다. 이외에도 시리얼 통신을 위해서는 패리티비트, 데이터수, 스탑비트, 플로우 컨트롤 등을 설정해주어야 합니다.

데이터 비트는 한번에 보내주는 데이터의 비트수를 설정하는것인데 패킷하나가 스타트비트,데이터비트,스탑비트 이렇게 이루어져 있습니다. 이때 데이터를 5~8로 설정할수 있는데 통상 8비트를 거의 사용하기 떄문에 기본8비트로 설정이 되어 있습니다.

패리티 비트는 오류를 검사하기 위한 하나의 알고리즘인데 없음으로 설정됩니다. 스탑비트는 1로 플로우 컨트롤은 사용하지 않음으로 설정이 됩니다. 시리얼통신의 기본은 8비트의 데이트를 주고 받는 것 입니다. 이 기능을 위한 함수가 바로 write()와 read() 입니다. write함수에 전달인자로 8Bit data 즉 1Byte의 데이터를 넘겨주면 이 데이터가 다른 디바이스로 넘어가게 되는 것 입니다. 그리고 다른 디바이스에서 이와같이 1Byte의 데이터를 보내면 read()함수를 통해 1Byte의 값을 리턴 받게 되는 것입니다. 이외의 함수들은 모두 이 두개의 함수를 응용해 문자열을 넘겨준다거나 버퍼에 Nbyte의 데이터를 받는다거나 하는 사용자의 편의를 위한 함수들 입니다.

이로써 간단하게나마 아두이노의 기본 함수들을 살펴보았습니다. 마지막으로 이 아두이노가 얼마나 사용하기가 편리한지 직접 AVR을 사용하는 Firmware C코드와 똑같은 기능을 하는 아두이노 코드를 비교해 보고 간단한 Serial통신으로 작동하는 열전사 프린터를 아두이노로 동작하는 영상을 보여드리겠습니다.

아주 간단한 시스템의 Firmware 코드와 똑같이 작동하는 아두이노 코드입니다. 시리얼통신을 하는데 외부인터럽트에 rising edge의 신호가 들어오면 0x4a의 신호를 보내주는 시스템입니다. Firmware코드는 동작은 물론간단하지만 셋팅하는 레지스터들이 꽤나 복잡한 것을 알수 있습니다. 하지만 아두이노는 그에비해 한두개의 함수로 모든 설정을 마칠수 있습니다. 물론 그만큼 더 세부적인 사항을 설정하는데 있어서 한계가 있지만 그정도의 기능을 하는 시스템을 만드는 사람을 타겟으로 만든 보드가 아니기 때문에 간단한 시스템을 만드는데 MCU를 처음 접해보는 사람이 사용하기 무척 편리하다는 것을 알 수 있습니다.

또 하나의 장점은 MCU의 레지스터를 설정함에 있어 레지스터들이 많고 복잡하기 때문에 많이 사용하는 사람들도 가끔은 실수를 할 수 있습니다. 이럴경우 디버깅이 꽤나 어렵습니다. 하지만 아두이노는 정해진 함수를 사용하기때문에 틀릴 염려가 없어 디버깅이 거의 필요가 없습니다.

아두이노로 테스트 해볼 디바이스는 바로 열전사 프린터 입니다. 아두이노관련 악세사리를 판매하는 홈페이지에서 구입할 수 있습니다. 시리얼통신으로만 영수증사이즈의 열전사지에 자신이 원하는 텍스트, 비트맵이미지등을 표현할 수 있습니다.

마지막에 배웠던 Serial관련 함수만사용하면 이 프린터로 자신이 원하는것을 표현할수 있는 매우 재미있는 디바이스 입니다. 예제소스를 참고하여 간단하게 프로그래밍을 해보았습니다. 판매사에서 데이터 시트를 제공하고 이 데이터 시트내에 명령어 Table이 있기 때문에 이를 이용하면 쉽게 이 프린터를 사용할 수 있습니다.

 

 

 

다음 그림과 같은 구조로 작동하게 됩니다. 아두이노는 PC에 프린터 기능을 Display해주고 사용자로부터 입력을 받아 입력받은대로 다시 프린터에 신호를 줘 프린터를 하게 됩니다. Serial기능만 이용해서 구현이 가능 합니다. 일반 아두이노는 Serial통신이 한개밖에 없어서 소프트웨어적으로 구현한 Serial통신을 이용하게 됩니다. 하지만 제가 사용하는 아두이노는 시리얼통신이 4개가 지원되기 때문에 Serial1과 Serial3을 이용했습니다.

 

 

 

 

 

 

 

 

 

 

 

 

아두이노와 PC를 연결하면 아두이노는 다음과 같은 메뉴를 보여줍니다. 사용자가 숫자를 입력하면 아두이노는 입력받은 숫자를 통해 정해진 동작을 하게 됩니다.