2013년 4월 16일 화요일

1.1 <외도> 득템 그리고 지름신

잠시 딴짓거리 하느라 연재가 지연되고 있습니다.
일이 바빠서..... 는 핑계고..
사실 다 만들어서 시운전도 끝낸 상태인데. 글로 적는게 늦어지고 있습니다.

범인이 두개 있는데.. 하나는 바로 아두이노의 mpu와 같은 AVR 계열의 ATMEGA128 보드. 누가 버린걸 주운 걸 다시 얻었다. 같은 AVR칩이니 아두이노와 호환되지 않을까 하는 생각에 구글링 시작.. 오랜 삽질 끝에 칩이 타버린걸 알았고.. 그래도 그 과정에서 avr stduio, wiring 같은 개발 도구들을 알게 되었다. 그리고 좋은 스승을 만나 덤으로 내공도 전수 받고 각종 잡템 (커넥터, 점퍼, 어래이핀 등)들도 얻게 되는 행운을 가져다 주었다.

AVR ATMEGA128 사무실 직원이 어디서 주워와서 건네주었다


그리고 또 하나.. 문제의 라즈베리파이 (RaspberryPi). 미국에서 25, 35불에 불티나게 팔렸다는 바로 그 미니 PC. 한국 쇼핑몰에선 5만 2천원. 일단 지르고 여러가지 간을 보고 있다. I/O 핀도 있고, OS도 올릴 수 있고, 속도도 아두이노와는 급이 좀 다른 놈이다. 여러가지 용도를 생각하고 있는데 일단 xbmc 깔아서 멀티미디어 서버로 좀 써볼라고 한다.

왼쪽이 Arduino UNO 오른쪽이 RaspberryPi

나중에 이 두놈 사용기도 올려 보도록 한다. 물론 시간이 될 때 ^_^

2013년 4월 6일 토요일

1. 휴대폰으로 자동차를 운전하자 (1)

벚꽃을 기대한 주말이지만 비바람이 친다.
즐기기도 전에 다 지게 생겼다.

일단 약속대로 블루투스 자동차를 만들어 본다. 장애물은 세가지 정도

  • 아두이노에서 블루투스를 사용하기
  • 모터 제어
  • 스마트폰에서 리모컨 프로그래밍

일단 전체 작전도



위에 말한 세 가지 영역 모두 초보다. 그래도 시작해 본다. 우선 준비물 챙기기


왼쪽부터 아두이노 UNO, 블루투스 슬레이브 UART, 모터드라이버 쉴드, 그리고 최신형 페라리, 각종 점퍼 및 핀어레이 (왼쪽상단 우정 출연한 저분은 만국 공용의 길이 측정자, 그리고 아쉽게도 카메라빨 못받으신 납땜기, 니퍼, 스트리퍼,...) 그리고 무엇보다 중요한 고무밴드.. 어떠한 충돌에도 안전을 보장할 것이다..

블루투스는 슬레이브로 사야한다. 그냥 서버역할을 하니 마스터겠지 하고 생각했는데.. 슬레이브가 맞다. 그리고 또 이상한 단어 UART.. 깊게가면 재미 없다. 그냥 이건 비동기식 시리얼 통신이고 무엇보다 동기식보다 싸고 보편적이라는 것 정도만 알고 넘어간다. 자세한건 구글링..

일단 말로만 때워도 되는것 부터 시작...


모터제어 (PWM: Pulse Width Modulation 제어)

이것은 자동차를 정회전, 역회전, 회전 속도 바꾸기 등등 때문에 필요한 것이다. 항상 그렇지만 새로운 단어는 거창하게 들리는 동시에 귀에 거슬린다. 알고 보면 간단한 내용인데..
회전 방향 바꾸는 거는 생각만으로도 쉽다. 그냥 0 또는 1 걸어서 구분만 시켜주면 받는놈이 어찌 할테니.. 문제는 속도 제어다. 디지털은 0,1 만 있어서 0.34 같은 중간값이 필요한데 어찌할까? 여기서 나온게 PWM 제어이다. 일단 위키 http://en.wikipedia.org/wiki/Pulse-width_modulation 를 링크는 거는데.. 너무 전문적인 설명이고..

예를들면 10초 단위로 신호를 보내는데

1초 5V - 9초 0V -1초 5V - 9초 0V - ....  와
5초 5V - 5초 0V -5초 5V - 9초 0V - ....

는 어떤 차이가 있을건 당연하다.. 그런 차이를 응용하는게 PWM 방식이다.
아두이노는 그런방식으로 아날로그 (analog) 신호를 만들어 낸다. analogRead, analogWrite 함수가 그것이다.  (사실 매뉴얼 보면 아날로그 포트, 디지털 포트를 구별해 놓았는데.. 모든 포트에서 pwm을 지원하기는 하는것 같다. 다만 지정된 핀은 별도 회로에서 pwm을 지원해서 mpu에 부담을 덜 주는 것인지... 그것은 차차 확인해 봐야 겠다)

여기서 질문
"그냥 아두이노 신호를 모터에 직접 넣으면 되지 왜 드라이버쉴드가 필요해요 ?"
여러가지 이유가 있겠지만 큰 두가지 이유

  • 아두이노 출력은 5V가 한계다. 만약 12V로 구동되는 자동차 모터라면 직접 쓸 수 없다는 얘기다. 
  • 또 한가지 중요한 건, 설령 모터가 5V로 구동 된다 하더라도 문제는 전류다. 여러번 나온 얘기지만 모터는 "파워" 도구이다. 반면 아두이노 출력은 모두 시그널이다. 이걸로 직접 모터를 구동하다가는 과전류가 흘러 아두이노 보드 타버릴 수도 있고, 설사 방지 회로가 있더라도 모터는 전류 부족으로 제대로 구동되지 않는다.  그냥 아두이노 출력은 LED 켜기정도? 자세한건 아두이노 매뉴얼에 허용 출력이 나와 있을것이다..
아두이노 호환 드라이버들이 많이 나온다. 엄밀하게 말하면 호환이라고 하기엔 좀 어색하다. 그냥 아두이노 핀배치에 일치하는 모터드라이버로 별도의 점퍼선이 필요치 않은 보드 정도가 좀더 맞는 말일 것이다. 그런 것들을 "쉴드"라고 부른다. 모터드리이버 말고도 이더넷, Wi-Fi 등 종류가 많다.. 딱 필요한 기능만 있는 부품 보다는 당연히 비싸다.

모터 드라이버 쉴드를 등에 업은 아두이노

어쨋건 큰맘먹고 드라이버는 아두이노쉴드 중 하나를 구매.. 그것도 나중을 생각해서 2A 짜리로.. 당연히 바퀴 두개를 별도로 제어하려면 출력은 2개가 있어야 한다. PLL 제어 기능까지 있다는데.. 일단 머리아프니 패스.. 어짜피 사용할 계획도 없고..

별도의 회로 연결은 필요없다. 4개핀은 아두이노와의 통신에 사용하고, 나머지 핀은 그대로 아두이노에 연결시켜 주는 통로 역할을 한다. 4개 핀은 반드시 기억해 두었다가 모터제어 프로그래밍에 쓰고.. 그 나머지 안쓰는 핀 중에 적당한놈 골라서 나중에 블루투스에 쓰면 된다.

아두이노-드라이버-모터의 연결을 마쳤으면 이제 아두이노IDE 로 가서..

//4,5,6,7번은 모터쉴드에 예약되었습니다
int E1 = 6; // motor1 속도
int M1 = 7; // motor1 전.후진 
int E2 = 5; // motor 2 속도
int M2 = 4; // motor 2 전.후진

void setup(){
  pinMode(M1,OUTPUT);
  pinMode(M2,OUTPUT);
  pinMode(E1,OUTPUT);
  pinMode(E2,OUTPUT);
}

void loop(){
     digitalWrite(M1,LOW); //방향 
     digitalWrite(M2,LOW); //방향
     analogWrite(E1,255); // 0-255
     analogWrite(E2,255); // 0-255
}


더 이상 무슨 설명이 필요한가.. 코드에 이미 설명이 다 되어있고.. 이게 소스 전부다.. 양쪽바퀴 모두 가장 빠르게 전진하라는 내용이다. 물론 나중에 리모컨 신호를 받아서 적절한  처리를 해 주는 작업을 할 것이다... 참고로 아두이노 PWM (analog) 출력은 0-255 사이의 값으로 조정한다.. 255면 계속 모터에 최대 전원을 준다는 얘기다.  참고로 analogRead 도 있는데 그것은 0-1024 값을 쓰니 혼돈하지 말것..

쓰다보니 길어졌다. 다음 블루투스 연결로 이어진다..

2013년 4월 4일 목요일

0.1 <간지> 몸풀기 피아노. 풀업 풀다운

약속은 블루투스 자동차 조종편이었으나. 사이에 간지를 넣어야 겠다. 어짜피 이리된거 이쪽에서 느끼는거 다 올려 보려 한다.

학부때 "전자공학개론" 이라는 과목을 들었다. 기계공학을 전공했던 터라 머가 먼지 통.. 학점도 바닥이었던걸로 기억한다. 지금 생각해 보면 제일 중요한 개념을 터득하지 못하고 강의에 임했던 탓이다.

"파워" vs "시그널"

고등학교때 까지는 전기 하면 주로 "파워"만 다루었던걸로 기억된다. 불을 킨다거나 열을 낸다거나.. 전원과 저항이 전부인 회로...  그런데 갑자기 트랜지스터가 나온다. 아니 저걸 증폭해서 뭘 하자는거지??  고백하면 그 땐 그랬다.. 지금와 생각하면 정말 한심 스럽지만.. 다행히 나이를 먹어서인지 좋은 인연때문인지 그 무엇이건 간에 파워와 시그널을 지금은 구별하게 되었다.

다시 아누이노로 돌아오자.. 우선 몸풀기로 버튼을 달아 피아노를 친다. 급하신 분들을위해 우선 최종 완성품 그림부터..

윈도우에서는 가로인데 업로드 하니 세로그림

버튼 8개와 스피커 1개.. 저걸로 도레미파솔라시도를 칠려고하다. 소스는 머 볼것도 없이 간단하다.

tone (2, 440) ;

이리하면 2번핀으로 연결된 출력단자에 440Hz 소리를 내준다. 참고로 각음에 대한 주파수는

도 * C: 262Hz
레 * D: 294Hz
미 * E: 330Hz
파 * F: 349Hz
솔 * G: 392Hz
라 * A: 440Hz
시 * B: 495Hz
도 * C: 524Hz 

이리된다. 그래서 대충 버튼 눌러지면 소리내는 로직은..

if (digitalRead(버튼 핀번호1)) tone(2,주파수1) ; 
elseif (digitalRead(버튼 핀번호2)) tone(2,주파수2) ;
.....
else  noTone(2) ;
....
....
이렇게 8개를 매칭하고 돌리면 될줄 알았는데.......
웬걸.. 이상하게 작동 한다. 도를 눌렀는데 미가 나오고.. 머 이런식이다..
스케치 (아두이노 프로그램을 이리 부른다. 사실은 C 코드다) 는 생략. 위에 충분히 설명이 되었다고 본다. 너무 간단하기 때문에..

풀업, 풀다운 저항

저항이면 저항이지 풀업은 머고 풀다운은 먼가? 
(저 자신도 이걸 만들면서 터득한 내용입니다. 사실 대부분의 내용이 그렇습니다.)
누르면 불이 들어오고 끄면 불도 꺼져야 하는게 스위치가 아니더냐?
맞는 말이다. 그러나 여기서 간과한게 있다. 지금 파워를 다루는게 아니고 "시그널"을 다루는 것이다. 
스위치를 누르면 불이 들어오는게 분명히 맞다.
근데 디지털 회로에서는 스위치를 껐을때 불이 꺼지는것이 아니라
"끌지 말지 나도 몰라" 라고 보는게 정답이다.

즉 0인지 1인지 구별할 수 없는 상태가 되는 것이다. 그런 상황을 피하기 위해 저항을 사용한다. 풀업저항 소자가 따로 있는게 아니고 그런 용도에 사용되는 방법의 이름을 풀업, 풀다운이라고 부른다. 이해를 돕기 위해 그림을 보자..


왼쪽 그림에서 스위치가 닫히면 당연히 A에 5V 가 걸리지만 열렸을 때는 둥둥 떠다니는 상태가 된다. 한마디로 판독 불가.. 반면 오른쪽 회로에서는 닫히면 A에 5 열리면 0V 가 확실히 걸리게 된다. (위 그림은 그라운드쪽에 저항이 연결되었으므로 풀다운 저항이라 부름..)

이렇게 회로를 고치고 나서 피아노를 두드려 본다. 
원하는 결과가 나온다.

ps: 이 외 몸풀기가 더 있었는데 기억이 안난다. 기록을 뒤져보고 쓸만한게 있으면 올리겟습니다.



0. 하드웨어 생초보 아두이노를 접하다 !!

공돌이긴 하지만 소프트웨어에 친숙해 왔던 환경 때문에 하드웨어에 대한 일종의 두려움이 있었다. PC에 주변 장치 만들어 시리얼로 데이터 받는것을 많이 보기는 했지만 진작 나 자신은 어떻게 하는지 먼 영역의 일이었다..

실제로 접근하기 힘들었던게..

   private void button1_Click(object sender, EventArgs e)
        .......

만 보고 다루다가 

  0xFF ..
  PORTD1 ..

와 같은 텍스트롤 보기엔 우선 짜증 부터 난다. 위에 것은 언어에 비교적 가깝다. 버튼이 클릭되는것이 어찌 된다는 얘기다.. 그러나 밑에것은. 암호 그 자체다. 

그렇지만 주변환경이 나를 찝적거린다. 직업상 어찌 하다보니 c# USB 시리얼 통신부분 소스를 보게 되었다. 아주 일부분만 소게하자면... 

        public GADC24()
        {
            ready = false;
            usbDevices = new USBDeviceList(CyConst.DEVICES_CYUSB);
            myDevice = usbDevices[0x04B4, 0x2000] as CyUSBDevice;
            if (myDevice == null)
            {
                //Text = "No device found";
                return;
            }
       
            controlEP = myDevice.EndPointOf(0x00) as CyControlEndPoint;
            commandEP = myDevice.EndPointOf(0x06) as CyBulkEndPoint;
            dataEP = myDevice.EndPointOf(0x82) as CyBulkEndPoint;
            if (controlEP == null || commandEP == null || dataEP == null)
            {
                 return;
            }
            foreach (USBDevice dev in usbDevices)
             CheckFPGADone();
            ResetDAQ();
   
        } 


첫 줄 보고 질린다.. 대충 이야기는 여기서 부터 시작된다. 같은 사무실에 라즈베리파이 (사실 그땐 그것이 무엇인지 전혀 몰랐다)로 3D프린터를 집에서 취미생활로 만드는 고수가 있다. 그 사람과 커피 한잔 하면서 이런저런 얘기하다가 그사람의 추천으로 아두이노를 접하게 된다. 일단 그림 부터


대충 이리 생긴 물건이다.. 칩이 있고 구멍이 있는걸 보니 저기다 멀 꽂으면 칩이 어찌저치 주기도/받기도 하게 생겼다.. 실제 또 그렇다.. 그런데 그런 건 많지 않는가.. 정작 내가 놀란건 저놈과 대화하는 언어였다.. 시리얼을 하기위해서 딱 필요한건.. http://arduino.cc/ 에서 개발환경을 다운받고 적절한 곳에 압축을 풀고.. 다음 화면과 같이




void setup() {
  Serial.begin(9600);
}

void loop() {
    Serial.println("Hello !!"); 
}

놀랍겠지만 이게 다다. 컴파일하고 업로드 하면 작동이 된다. 이게 문명히 C 같은데 main() 이 안보인다. 난 이게 아두이노의 성공 요인이라고 본다 main()은 사실 있다. 감추어 놓았을뿐 대충 구조는

main() {
   setup();
   for (;;) loop();
}

와 같이 구성되어 있다. 두 가지 면에서 놀랐다.

  • 사람이 보고 직감할 수 있다. 아 시리얼을 하는구나 대충 9600의 속도로.. 아 "Hello" 라고 인사를 하는구나
  • 기나긴 디바이스 셋업 과정을 한줄로 끝내는구나.. (사실 이게 최고의 매력임 !!)

모든게 그렇듯 그 안에서 일어나는 일은 어찌저찌 해볼 수 있는데, 모든게 진입장벽을 지나고 나서의 일이다. 
아두이노!!  하드웨어로의 진입장벽을 뚫을 수 있는 너무나 좋은 물건이다


이에 힘입어 첫번째 프로젝트..
장난감자동차+아두이노+블루투스 를 연결 휴대폰으로 조종!!