'adc'에 해당되는 글 4건

  1. 2017.03.19 아날로그 입력 및 온도계 예제
  2. 2017.03.11 Arduino Uno R3의 개요
  3. 2015.12.10 BLDC와 PMSM의 토크
  4. 2014.04.23 C 언어로 개발시 유의사항
Embedded Lecture/Arduino2017. 3. 19. 10:07


아날로그 입력 핀에 온도 센서를 연결하여 실시간으로 Arduino IDE 환경의 PC 모니터링 창에 실시간으로 현재의 온도를 일정 시간 간격으로 보여주는 예제입니다. 사용할 온도 센서는 LM35-DZ인데, 이는 3단자 소자로 전원공급 단자, GND 그리고 출력단자로 구성되며 제조사가 제공하는 간단한 응용회로는 다음과 같습니다.


 


이 소자는 0~100˚C를 측정할 수 있는 센서로 5V의 전원전압을 공급하면 섭씨 1˚C 변화에 10mV의 전압을 출력합니다. 따라서 현재 온도가 섭씨 100˚C라면 출력전압은 100˚C*10mV=1V가 됩니다. 결국 온도 센서는 LM35-DZ는 0~100˚C 사이의 섭씨 온도 변화에 대해서 비례적으로 0~1V의 출력전압을 내보내게 됩니다.


void setup() {

    Serial.begin(9600);

}


void loop() {

    Serial.println(getTemp());

    delay(1000); // 1s에 시간지연을 줍니다.

}


float getTemp() {

    short sVal = analogRead(A0); // Default 모드로 최대 5V를 1024 레벨의 값으로 읽습니다.

    float voltage = sVal*5.0/1024; // 실제로 읽어드린 아날로그 값으로 변환합니다.

    return voltage*100; // 섭씨 온도로 환산하여 반환합니다.

}


위 코드는 결국 온도 센서를 이용하여 매 1s마다 측정된 섭씨 온도를 Arduino IDE 환경의 PC 모니터 창에 지속적으로 보여주게 됩니다.


<1초마다 온도를 감지하여 표시하는 결과 화면>


만일 ADC의 기준 전압으로 내부 전압인 1.1V를 사용한다면 분해능(resolution)은 약 5배 정도 개선되는 효과를 얻을 수 있으므로 위의 코드를 기준 전압을 내부 전압으로 사용하는 코드로 수정하였습니다. 단, 온도 센서는 100˚C까지만 유효하고 따라서 센서의 최대 전압은 1V까지만 유효하게 됩니다.


#define SUPPLY_VOLTAGE 1.1


void setup() {

    Serial.begin(9600);

    analogReference(INTERNAL); // ADC의 기준 전압을 내부 전압 1.1V로 사용함을 지정합니다.

}


void loop() {

    Serial.println(getTemp());

    delay(1000);

}


float getTemp() {

    short sVal = analogRead(A0);

    float voltage = sVal*SUPPLY_VOLTAGE/1024;

    return voltage*100;

}



'Embedded Lecture > Arduino' 카테고리의 다른 글

아두이노 라이브러리의 설치  (0) 2017.04.11
아날로그 출력(PWM)  (0) 2017.03.20
아날로그 입력  (0) 2017.03.18
인터럽트와 volatile 지시자  (1) 2017.03.18
아두이노의 TWI(I2C) 통신  (0) 2017.03.18
Posted by Nature & Life


Arduino Uno R3는 가장 널리 사용되는 입문용 기본 보드로 R3는 세번째 버젼을 의미합니다. 이 보드는 8-bit 마이크로 콘트롤러인 ATmega328P을 탑재하며 PC와 USB로 연결할 수 있어 프로그램 다운로드 및 시리얼 통신에 가능합니다. 그 밖에도 ATmega16U2의 또 다른 마이크로 콘트롤러를 내장하는데, 이는 기존 보드들에서 사용하던 FTDI FT232R USB-to-Serial 드라이버 칩을 대체하기 위한 것으로 USB-to-Serial 변환 프로그램이 들어 있습니다. ATmega328P는 1KB의 부트로터(Bootloader)용을 포함한 32KB의 Flash 메모리와 2KB의 SRAM, 1KB의 EEPROM을 갖고 있으며, 클럭 속도(Clock speed)는 16MHz입니다.


5V로 동작하는 이 Uno 보드의 전원공급은 두 가지 방법이 있는데, 첫번째는 USB로부터 제공되는 5V를 그대로 사용할 수 있으며, 두번째로는 7~12V의 AC 어댑터를 잭에 꼽아 외부에서 공급하는 방법인데 이는 Uno 보드가 내부적으로 5V를 정류하는 레귤레이터(Regulator)를 내장하고 있기 때문이며 위의 두 가지 전원이 모두 연결되어 있다면 외부 전원이 우선이 됩니다.



디지털 입출력 핀 14개 (0번~13번)

디지털 입출력 핀들을 이용해서 외부의 이진 신호를 읽어들어나 또는 이진 신호를 내보낼 수 있다. 디지털 입출력으로 사용되면서 또한 다른 기능을 가지는 핀들이 있는데, 이 기능들은 한 핀으로 두가지를 다 사용할 수는 없으며 다른 기능은 다음과 같습니다.

    • 0번~1번: 시리얼 통신에 사용되어 USB로 PC와 통신을 할 수 있습니다.

    • 2번~3번: 인터럽트(interrupt) 기능을 갖습니다.

    • 3, 5, 6, 9, 10, 11번 핀은 PWM 기능을 가지며 아날로그 출력을 흉내낼 수 있다.


아날로그 입력 핀 6개 (A0~A5)

외부의 아날로그 입력값을 읽어들여 ATmega328P칩 내부의 ADC(Analog to Digital Converter)를 이용하여 0~1023 사이의 숫자로 변환합니다. 이때 필요한 기준 전압은 5V 이지만 1.1V의 내부 전압이 사용될 수 있으며 AREF핀으로 기준 전압을 직접 인가할 수도 있습니다. 그리고 아날로그 핀은 디지털 입출력 핀으로도 사용할 수 있습니다.


아날로그 출력핀 6개 (3,5,6,9,10,11번 핀)

아날로그 출력핀은 0~5V사이의 전압 값(256레벨)을 가질 수 있으며 이는 PWM(Pulse Width Modulation) 방식으로 동작하므로 흉내를 내는 것입니다.


인터럽트 (2, 3번 핀)

2번과 3번 핀에 가해진 외부 이벤트를 감지하여 사용자가 원하는 방향으로 이를 처리하기 위한 기능으로 이를 인터럽트 처리(interrupt handling)라 부르는데, 즉 이 핀들에 변화가 있는면 하드웨어는 즉각적으로 알리고 이때 사용자가 원하는 정해진 동작을 코딩하여 사용합니다.



ICSP for ATmega328 : 기존의 ATmega328P에 ICSP(In Circuit Serial Programming)를 위한 SPI 통신용 6핀 포트입니다. ICSP는 전통적으로 마이크로 컨트롤러에 직접 펌웨어를 프로그래밍하기 위해 마련된 것입니다.


ICSP for USB interface : 기존의 ATmega16U2에 ICSP(In Circuit Serial Programming)를 위한 SPI 통신용 6핀 포트입니다. 


TWI(I2C) 통신 : A0, A1 핀




Posted by Nature & Life


BLDC 모터의 경우에는 전기각의 매 60도 간격으로 구형파 파형의 전류를 한번에 2개 위상에 가하여 구동하며, 나머지 한 개의 위상은 전력을 가하지 않은 floating 상태로 역기전력(Back EMF; BEMF)를 관측하고 이를 이용하여 6-step commutation을 실시합니다.


따라서 BLDC 모터의 구동은 근본적으로 토크 리플(Torque ripple)이 발생할 수 밖에 없으며 그러므로 시스템에서 토크 리플이나 음향 노이즈가 큰 문제가 되지 않고 감당할 수 있는 수준일 때 사용된다는 것입니다. 하지만 PMSM은 사인파(정현파)형 전류를 3개 위상에 모두 동시적으로 가하여 구동하여, 토크가 매끄럽고 음향 노이즈가 낮다는 것입니다.


이러한 Brushless 모터의 구동을 위해서는 고정자에서 회전 자기장을 만들어 낼 수 있도록 외부에서 제어를 해주어야 하며, 고정자 코일에 토크가 최대가 되도록 전류를 공급하기 위해서는 회전자의 현재 위치에 대한 정보가 반드시 필요하게 됩니다. 이를 위해서 센서나 광학 엔코더(optical encoder)를 사용하는데 이는 가격 상승의 원인이며 이러한 센서들이 다양한 드론(Drone)의 비행 환경에서 감도가 떨어지고 주변 시스템의 잡음 등의 영향으로 센서가 없는 센서리스(Sensorless) 모터를 채택한다는 것입니다.


그러므로 BLDC 모터의 경우에는 회전자의 위치를 파악하기 위해서 floating 상에서 유기된 역기전력(BEMF)이 '0'을 교차하는 순간(Zero-Crossing Point)을 감지하여 회전자와 주어진 고정자 권선 간의 상대적 위치에 대한 정보을 알아내어 위상 정류를 동기화시키는 간단한 방법을 사용합니다. 여기서 역기전력이 '0'인 순간은 자속의 절대값이 최대인 순간을 포착하는 것과 같습니다.



반면에 PMSM의 경우에는 2상의 전류를 감지하여 모터의 복잡한 다변수 비선형 상태 방정식을 이산화(digitized)하여 수치해석적으로 실시간 계산을 통해 회전자 위치를 지속적으로 얻어 반영하는 구조로, 회전자의 토크가 최대가 되도록 고정자 3상의 전류를 공급하게 됩니다. 따라서 PMSM의 센서리스 제어를 위해서는 BLDC와는 달리 고성능의 ADC와 32-bit 이상의 빠른 속도, 때로는 부동 소수점 연산장치(Floating Point Unit; FPU)를 갖는 마이크로컨트롤러(MCU)가 필요하게 된다는 것입니다.



위 그림에서 좌측은 사다리꼴 파형의 역기전력을 갖는 BLDC 모터와 우측은 정현파형의 역기전력을 갖는 PMSM의 각 시간에 따른 토크의 변화를 나타냅니다. 각 상의 토크 T는 역기전력 e와 전류의 i에 곱에 비례하므로 전체 토크 Te = Ta + Tb + Tc 는 이론적으로 일정하게 보입니다. 하지만 실제로는 BLDC 모터의 경우 사다리꼴의 윗변의 폭이 좁아져 토크는 리플이 생기게 됩니다.




'Flight Controller 이해 > 모터제어이론' 카테고리의 다른 글

모터의 토크 발생원리  (2) 2015.12.12
BLDC와 PMSM의 구조  (0) 2015.12.12
BLDC vs. PMSM  (0) 2015.12.09
BLDC의 장단점  (0) 2014.04.03
BLDC모터란?  (0) 2014.04.01
Posted by Nature & Life
Embedded Programming/C2014. 4. 23. 09:33


AVR은 C 언어로 개발하는 경우에도 assembler 못지 않게 최적화된 코드를 생성하기에 다양한 장점이 있습니다. 그 중에서도 avr-gcc라는 컴파일러를 사용하는 것으로 avr-gcc는 전 세계 다양한 사용자(소위 Hacker)들에 의해 개발되어 공유하는 것으로 시행착오를 통하여 결점이 최소화되었다는 것입니다.


AVR을 C 언어로 개발시에는 일반적인 O/S 환경에서가 아닌 AVR 하드웨어에 기반을 두기 때문에 몇 가지 유의사항들이 있습니다.

 

 

 

 

1) 일반적인 C 언어와는 달리 이진수(binary)를 사용할 수 있으며, Boolean 타입의 변수는 사용할 수 없습니다. 

이진수는 예를 들어 0b0100 식으로 표현하며 Boolean 타입 변수 대신에 int형의 0과 1로 대체하여 사용하면 됩니다.


2) 인터럽트 서비스 루틴은 가능한 한 간결하게 작성합니다.

일반적인 C 언어와는 달리 AVR 하드웨어는 외부 인터럽트나 Timer, USART, ADC 등의 주변장치들로부터의 인터럽트를 처리하기 위한 ISR() 함수로 반환값이 없으며 특별히 호출하지도 않습니다. 이러한 인터럽트 서비스 루틴(Interrupt Service Routine, ISR)은 다음과 같은 이유로 최대한 간결하게 작성해야 합니다.


첫째는 인터럽트 함수 내에서는 지역변수가 Register가 아닌 Stack에 저장되므로 처리가 느리기 때문이며, 

둘째는 하나의 인터럽트 처리가 길어지면 이어서 발생하는 다른 인터럽트 처리를 실행하지 못하기 때문입니다.


대부분의 인터럽트는 Timer의 overflow를 처리하기 위한 것으로 만일 인터럽트를 제때에 처리하지 못한다면 AVR 칩이 외부 시스템과 실시간으로 작동하는 경우에는 치명적인 오류가 생길 수 있게 됩니다. 그러므로 인터럽트 발생시 많은 작업을 요구하는 경우에는 인터럽트 루틴에서 Flag를 간단히 설정하여 개시하고 메인 루틴에서 이를 처리하게 해야 합니다.


3) 인터럽트 서비스 루틴 내에서 전역변수들은 volatile로 선언합니다.

컴파일시 최적화를 위해 컴파일러는 나름데로 그 상황에 맞는 상수값으로 처리하도록 하는 경우가 있는데, 이것이 인터럽트 서비스 루틴에서는 의도하지 않은 오류를 초래하기 때문입니다. 그러므로 인터럽트 서비스 루틴에서는 전역변수들은 volatile로 선언하여 컴파일러가 임의로 해석하지 못하게 방지합니다.

ex) volatile char k; 


4) 외부 메모리가 있는 경우가 아니라면 재귀호출(Recursive call)을 사용하지 않는 것이 좋습니다. 

연속되는 재귀호출은 한정된 메모리에 Stack을 쌓이게 하며 결국에는 Stack overflow를 발생시킬 수 있기 때문입니다.


5) 대용량을 갖는 상수 배열(array)은 const 키워드를 사용하여 프로그램 메모리(Flash Memory)에 저장합니다.

AVR에서 변수는 SRAM에 저장하는데 고기능 AVR을 사용하지 않고 기능을 구현하려면 SRAM의 용량을 아껴야 합니다. 따라서 변하지 않는 대용량 상수들은 코드를 적재하는 Flash Memory에 저장하여 SRAM을 확보하는 것이 바람직합니다.

ex) const uint8_t value[64] = 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,

                                  29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,

                                  54,55,56,57,58,59,60,61,62,63,64};

  

 

 

Posted by Nature & Life