레이블이 특징인 게시물을 표시합니다. 모든 게시물 표시
레이블이 특징인 게시물을 표시합니다. 모든 게시물 표시

2015년 11월 4일 수요일

아두이노의 tone() 함수로 멜로디 연주하기

 아두이노에는 tone()함수가 제공되는데 부저나 스피커로 음을 발생시킬 수 있는 함수이다. 기본 문법은 다음과 같다.

tone(pin, freq [, duration]);

  • pin : 부저나 스피커가 연결된 디지털 핀번호
  • freq : 주파수 (범위 : 31 ~ 65535)
  • duration : (옵션) 음의 발생 시간

여기서 duration은 주파수 지속시간으로서 이 시간이 지난 후에 noTone()함수가 자동으로 호출되는 것과 같은 효과를 낸다.  duration이  생략되면 noTone()함수가 호출될 때까지 음이 계속 발생된다. 예를 들어서 11번 핀에 부저가 연결되었다면 다음과 같이 한다.

tone(11, 262); // ‘도’음 발생
delay(500);
noTone(11);

이 코드는 ‘도’음을 0.5초간 발생시키는데 다음과 같이 할 수 있다.

tone(11, 262, 500);

이렇게 하면 음 발생 직후 다른 작업을 수행할 수 있으며 500ms후에는 내부 인터럽트가 발생하여 음발생이 자동으로 정지된다. 하지만 단음만 생성할 경우에는 상관없지만 연속음을 생성할 경우에는 주의해야 한다.

tone(11, 262, 500); // ‘도’음
tone(11, 294, 500); // ‘레’음
tone(11, 330, 500); // ‘미’음

이렇게 하면 맨 마지막의 ‘미’음만 발생하게 된다. (왜?) 따라서 올바른 동작을 위해서는 다음과 같이 해야 한다.

tone(11, 262); // ‘도’음 발생
delay(500);
tone(11, 294); // ‘레’음 발생
delay(500);
tone(11, 330); // ‘미’음 발생
delay(500);
noTone(11);
tone(11, 262); // ‘도’
delay(500);
tone(11, 294); // ‘레’
delay(500);
tone(11, 330, 500); // ‘미’

tone()함수는 내부적으로 타이머를 사용하므로 다음과 같은 점들을 주의해야 한다.
  • 이 함수를 사용할 경우 3번 11번 핀의 PWM이 정상적으로 동작되지 않는다.
  • 한 번에 하나의 주파수만 발생시킬 수 있으며 여러 핀에 동시에 다른 음을 발생시킬 수 없다.

 특정 음에 해당되는 주파수를 일일이 숫자로 기입하는 것은 가독성 면에서 좋지 않으며 이를 개선하기 위해서 아두이노에서는 음의 주파수만을 모아놓은 “pitches.h”라는 헤더파일을 제공한다. 내용은 다음과 같다.

/*************************************************
* Public Constants
*************************************************/
#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978

이 헤더파일은 전역 상수 정의로만 이루어져 있으므로 실행 파일의 용량을 증가시키진 않는다. 따라서 이 파일을 폴도에 복사한 후 인클루드시켜서 필요한 주파수를 사용하면 된다.

#include “pitches.h”
…
tone(11, NOTE_C3, 1000); // 3도 ‘도’음을 1초간 발생
...

이렇게 주파수(숫자) 대신 상수 이름을 사용하면 가독성이 높아지게 된다.


2015년 7월 5일 일요일

자바(JAVA) 개요

 자바(JAVA)는 컴퓨터 프로그래밍 언어 중의 하나로 썬마이크로시스템스(Sun Microsystems, 이하 썬) 라는 회사에서 개발하여 1996년 1월에 초기 버전이 발표된 객체 지향 (object-oriented) 언어이다. 썬의  제임스 고슬링, 아서 밴 호프와 같은 엔지니들이 처음 설계하였다고 알려져 있다.

    
[그림 1] 자바의 창시자인 제임스 고슬링과 마스코트(duke) 이미지

 원래는 썬의 엔지니어들에 의해서 가전 제품에 탑재될 소프트웨어를 만들려는 목표로 1990년에 개발이 시작되었다. 프로젝트의 초기에는 C++을 확장하여 사용하려 했지만 적합하지 않다고 판단하여 C++의 장점은 취하고 단점은 보안한 새로운 언어인 Oak 가 만들어졌다. 이후에 인터넷에 적합하도록 개발 방향이 바뀌면서 자바로 이름을 바꾸고 정식 버전을 1996년 1월에 발표하였다. 인터넷이 보급되면서 운영 체제와 상관 없이 어디에서든 실행할 수 있는 자바의 특성과 자바 애플릿(applet)의 인기에 힘입어 널리 사용되기 시작하였다.

 자바는 “Write once, run anywhere”라는 모토에 충실하여 한번 작성되어 컴파일된 실행 파일은 운영 체제와 상관없이 실행 가능하다. 이것이 가능한 이유는 자바 컴파일러는 소스 프로그램을 특정 기계어로 번역하지 않고 가상 언어로 번역한다. 그리고 그 가상 언어를 특정 기계어로 번역하여 실행하는 시스템을 자바 가상 머신(Java virtual machine, JVM)이라고 한다. (이름에 머신이라는 말이 붙어 있지만 이것도 프로그램이다.) 이 자바 가상 머신(Java Virtual Machine)은 여러 OS용으로 만들어져 있으므로 이것이 설치된 곳이라면 윈도PC, 맥, 리눅스, 서버 컴퓨터, 심지어 가전 제품 등 가리지 않고 어디에서든 자바 프로그램을 실행할 수 있다. 이러한 장점으로 인해서 자바는 다양한 기종의 컴퓨터와 운영 체제가 공존하는 인터넷 환경에 적합한 언어로서 인터넷의 발전과 함께 많은 사용자를 확보해 나갔다. 또한 기존의 C++언어의 장점은 채택하되 잘 사용하지 않는 부분은 배제하고 비교적 배우기 쉬운 간결한 문법도 사용자층을 넓히는데 한몫했다. 그리고 풍부한 클래스 라이브러리(Java API)가 공개되어 있기 때문에 프로그래머는 이것을 잘 활용하면 손쉽게 강력한 기능의 프로그램을 작성할 수 있다.

 자바를 처음 개발해서 보급했던 썬마이크로시스템스는 2010년에 데이터베이스로 유명한 오라클 (Oracle) 이라는 회사에 합병되었으며 따라서 현재 자바는 오라클사에 의해서 유지/배포되고 있다. 한 예로 구글의 안드로이드는 자바의 API를 이용하여 작성한 달빅(Dalvik)이라는 가상 머신 위에서 자바로 작성된 앱을 구동하며 자바 개발자들을 안드로이드로 끌어들여 큰 성공을 거두었다. 하지만 이로 인해서 오라클과 구글 간 자바  API의 사용료(저작권료)에 대한 소송이 진행되고 있기도 하다.

 자바 언어의 특징은 다음과 같이 요약할 수 있다.

  1. 운영체제에 독립적이다. 한번 만들어진 실행 파일은 자바 가상 머신이 설치된 곳이라면 어느 곳에서든지 바로 실행할 수 있다.
  2. 겍체 지향 언어이면서 배우기 쉽고 간결한 문법을 가지고 있다.
  3. 포인터(pointer)를 다룰 필요 없이 메모리 관리를 가상 머신이 자동으로 수행한다.
  4. 네트워크, 분산 처리, 멀티 쓰레딩을 지원한다.
  5. 최근에는 성능도 많이 개선되어 c/c++로 작성된 프로그램에 비해서도 그 실행 속도가 뒤지지 않는다.

 앞으로는 이러한 특징을 가지는 자바 언어의 기본적인 개발 방법에 대해서 알아보도록 하겠다.


2015년 6월 20일 토요일

맥시마(maxima)를 공부하면서 느낀 점들

 이번 학기에 <공학수학1> 교과목에 적용해 보려고 Maxima를 날마다 조금씩 공부하면서 강의용 부교재도 작성하고 있다. 당연한 이야기지만 프로그램 하나를 익히는 데에도 인내심을 가지고 시간을 꾸준히 투자해야 한다는 것을 새삼 느끼고 있다.

: Prof. William F. Schelter (1947-2001. 수학자, Maxima를 유지, 발전시킴)

이런 무료 프로그램이 한두 개가 아니긴 하지만 긴 세월 동안 이 프로그램을 개발해오고 지금도 시간을 들여서 업그레이드를 해 주고 있는 익명의 프로그래머들이 참 대단하게 느껴진다. 뭔가 다른 수익 모델도 없어 보이는데 말이다.


 사용에 큰 불만은 없는데 하나 꼽아보라면 전반적으로 명령어 기반의 프로그램이라서 (윈도우만 사용해 온 나로서는) 익히는데 시간이 많이 걸린다는 점이다. 위의 그림은 미분방정식을 푸는 것인데 명령이 직관적이지 않고 여러 줄의 명령이 입력되어야 한다. (그렇지만 미분방정식을 기호적으로 풀어주는 것만으로도 대단한 것이다.) 그리고 자연 로그 함수의 이름이 log() 여서 수학책의 log함수(밑수가 10인)와 혼동된다는 점 정도이다. 자연 로그는 ln(), 그냥 로그 함수는 log()였으면 좋았을 텐데.

 이 내용을 학생들이 잘 따라와 줄까 하는 점도 조금 걱정이 되긴 하는데 딱딱한 수식만 나열하면서 수업을 하는 것 보다는 흥미를 끌 수는 있을 것 같다. 시간이 되면 기본 사용법 동영상도 몇 개 만들어 보고 싶다.


2015년 6월 3일 수요일

ATmega8(A)의 세부적인 특징

 ATmega8(A)의 PDIP(parallel dual in-line, 핀 배치가 평행한 두 줄 모양) 패키지의 외형은 다음 그림과 같이 14 핀씩 두 줄이며, 각 핀의 번호 및 명칭은 다음과 같다.
[그림 1] ATmega8(A) PDIP 패지키의 핀 배열

[표 1] 핀의 이름과 기능
핀이름
기능
비고
Vcc/GND
uC를 구동시킬 전원 연결
동작 필수 기능
/RESET
리셋핀
XTAL1/XTAL2
클럭신호 입력 핀
PB0,PB1,…,PB7
8bit 범용 입출력 포트
포트
PD0,PD1,…PD7
8bit 범용 입출력 포트
PC0,PC1,…PC6
7bit 범용 입출력 포트
RXD, TXD, XCK
시리얼 통신을 위한 핀
통신
SCK,MISO,MOSI, /SS
SPI통신을 위한 핀 (ISP에 사용)
SCL, SDA
Two-Wire Interface (TWI)
INT0, INT1
외부 인터럽트 핀
T0, T1
TOSC0, TOSC1
타이머 클럭 입력 핀
타이머/카운터
OC1A, OC1B, OC2
타이머/카운터 출력핀
ICP1
타이머/카운터 1의 입력캡춰 핀
AVCC
ADC의 전원 인가 핀
ADC
AREF
ADC의 기준전압 인가 핀
ADC0,…,ADC5
ADC를 수행할 노드 연결 핀
AIN0, AIN1
아날로그 비교를 위한 핀

 ATmega8(A)는 AVR계열 중에서 28개의 핀을 가진 uC이다. (AVR중 tiny계열에는 8핀만을 가지는 uC도 있다). 핀의 명칭을 보면 P로 시작하는 핀들이 가장 많이 눈에 띄는데 이들은 포트(port)를 뜻한다. ATmega8(A)는 8bit로 입출력을 제어할 수 있는 2개의 양방향 포트(port)를 가지며 포트B(PB0~PB7), 포트D(PD0~PD6)라고 칭한다. 포트라는 것은 μC가 입력 신호를 받거나 출력 신호를 내보내는 통로라고 이해하면 된다. 하나의 핀은 2가지 전압(0V와 5/3.3V)만을 가질 수 있으므로 하나의 bit를 표현할 수 있다. 8개의 핀을 조합해서 8bits 즉 1byte를 구성한다. 즉 사용자 프로그램에 의해서 포트 핀은 0V 전위를 가질 수도 5V전위를 가질 수도 있으며 (출력일 경우) 외부의 0V 혹은 5V의 전압값을 읽어 들일 수도 있다(입력일 경우). 양방향이라는 것은 동일한 포트가 입력과 출력으로 모두 사용할 수 있다는 의미이다.

 총 28개의 핀들 중에 전원을 인가하는 8/20/21번(VCC, AVCC, AREF)과 8/22번(GND)을 제외한 나머지 23개의 핀이 모두 포트의 기능을 가지고 있다. 또한 핀 수가 28개로 제한이 되어있기 때문에 하나의 핀이 두 개의 기능을 가지는 경우도 있다. 이 경우 내부 I/O레지스터를 조작하여 어떤 기능으로 사용할 것인가를 지정할 수 있다.

[그림 2] ATmega8(A)의 내부 구조도

 [그림 2]에 ATmega8A의 전체 기능별 블럭도가 도시되어 있다. 이 그림을 보면 8bit 데이터버스가 모든 구성요소에 연결되어 있다. 하지만 레지스터와 ALU간에는 전용선로가 깔려있어서 ALU가 레지스터에서 데이터를 읽고 쓰는 것이 가장 빠르다. ALU는 연산에 필요한 데이터를 레지스터에서 읽어오며 또한 연산 결과를 레지스터에 바로 반영한다.

 PC(program counter)는 현재 실행되는 프로그램의 번지를 저장하는 메모리이다. 오류가 없는 프로그램이 어셈블되어서 ISP기능 등을 이용하여 프로그램이 플래쉬롬에, 그리고 데이터가 EEPROM에 저장이 되어 있을 것이다. uC는 전원과 적합한 클럭이 인가되고 리셋핀에 high(5/3.3V) 신호가 인가되면 PC(program counter)는 $000으로 초기화되고 프로그램 메모리의 $000번지부터 명령어를 하나씩 명령레지스터(instruction register)로 읽어 들인다. 이때 현재 실행해야 할 프로그램의 번지가 저장되어 있는 곳이 바로 PC이고 16bit 로 구성되어 있다. 따라서 초기에는 PC에 $0000값이 입력되고 명령어를 하나(대부분 1word 이지만 어떤 명령어는 2word) 읽어 들이고 1(혹은 2)가 증가한다. 읽어 들인 명령어는 명령레지스터에 저장된 후 명령 해독기(instruction decoder)에서 어떤 일을 수행하라는 명령어인지를 해독한다. 해독이 끝나면 해당되는 작업을 수행하기 위해 적절한 제어신호가 제어선(cotnrol lines)에 의해서 전달된다. 현재의 명령어를 해독하고 수행하는 동시에 다음 명령어(즉 PC가 가리키는 번지에 저장된 명령어)를 명령레지스터로 읽어 들인다. 그렇기 때문에 거의 모든 명령어가 1클럭 싸이클에 수행되는 것이고, 만약 시스템이 4MHz 클럭으로 동작한다면 최대 4MIPS의 수행속도를 낼 수 있는 것이다.

 AVR은 하버드 구조(Harvard structure)를 채택하여 프로그램과 데이터를 위한 메모리와 버스가 서로 분리되어 있다. 즉 프로그램메모리와 데이터메모리가 따로 존재하고, 각각의 메모리를 접근하기 위한 주소 및 데이터 버스선도 따로 존재한다. 프로그램 메모리는 2단계 파이프라인(2-stage pipeline) 방식으로 동작하여 프로그램이 수행되는 동안에 다음 명령어를 읽어 들인다. 데이터 버스를 통해서 SRAM이나 EEPROM에서 데이터를 레지스터로 읽어오거나 반대로 쓸 수도 있다. 그리고 모든 주변장치들이 데이터버스를 통해서 레지스터와 연결되어 있다.