[아두이노] 7 Segment Decoder(CD4511) 제어

IOT/아두이노|2019. 2. 16. 14:57

[아두이노] 7 Segment Decoder(CD4511) 제어



이번에도 새로운 칩을 소개 합니다. 7-segment Decoder(CD4511)은 7 Segment LED를 제어하는데 효율적인 칩입니다. 다른곳에서 원리만 이해하셨다면 사용 가능합니다. 이 칩은 4가지 값에 의해서 7개의 출력값을 만들어 낼 수 있습니다. 이 칩도 제 블로그에서 소개했던 내용인데 7 Segment LED를 포스팅 할때 한번에 소개하는게 나을 것 같아서 가상시뮬레이터에서도 제공되는 칩으로 이번에는 CD4511 칩을 이용해 실험하고자 합니다.

1. 7 segment Decoder(CD4511)



위 그림에서 보는것 처럼 입력 A,B,C,D 핀으로 아두이노에서 4개의 핀의 출력값을 CD4511 칩에 입력으로 받게 됩니다. CD4511 칩의 연결은 다음 과 같습니다.

  • Vcc핀 과 Gnd핀은 아두이노에 5V와 Gnd 핀에 연결
  • LT핀와 BI핀은 Vcc로 연결
  • LE핀은 Gnd로 연결
  • 입력 A,B,C,D핀은 아두이노 디지털핀 4개 연결(실험에서는 2,3,4,5핀 사용)
  • 출력 a,b,c,d,e,f,g핀은 7 Segment LED의 DP핀을 제외한 나머지 순차적으로 A,B,C,D,E,F,G핀에 연결

여기서 회로도 설계할때에 선 연결이 노가다 작업으로 좀 힘들지만 그래도 한번 이해하면 나중에 쉽게 사용이 가능해 집니다. CD4511 칩에 선들을 어떻게 연결하는지가 숙지하시면 됩니다.

2. 회로도 구성


  • 준비물 : CD4511 칩 1개, 7 Segment LED 1개(캐소드형임), 저항 330옴 1개, 저항 10k옴 4개, 아두이노우노, 뻥판
  • 내용 : CD4511 칩을 이용해서 7 Segment LED에 숫자를 출력하게 하자. 참고로 7 Segment LED(캐소드형)


CD4511 칩에 입력을 바로 아두이노의 출력값 5V를 보내지 않고 10K옴의 저항을 붙여줍니다. 스위치 버턴을 연상하시면 됩니다. 어짜피 상태값만 보내주면 되기 때문인거죠. 정확히 CD4511 칩의 허용 전압이 기억이 안나서 안전하게 저항을 붙였습니다. 데이터시트를 인터넷에서 찾아보셔서 허용 전압을 참고하시면 되겠습니다. 위에서 설명한 CD4511 칩의 핀들이 어디에 연결하는지 설명한대로 실제 선을 연결하시면 됩니다. 그리고 주의할 것은 7 Segment LED은 캐소드형 입니다.

처음에만 복잡해 보일뿐 익숙해지면 단순합니다. 핀에 마우스를 대면 핀 이름이 나오고 해당된 부품과 연결하시면 됩니다.

3. 코딩


  • 사용함수 : pinMode(출력핀, 모드), digitalWrite(출력핀, 상태값)
  • 내용 : 아두이노에서 4개의 출력 상태를 값을 CD4511 칩을 제어하여 7 Segment LED에 숫자를 0~9까지 순차적으로 출력해보자.(7 Segment LED은 캐소드형으로 이 기준으로 코딩함)

  • CD4511 제어 :
    • digitalWrite(출력핀, 상태값)으로 CD4511 칩의 출력값을 결정

참쉽죠. LED 제어할대 배운 PinMode()와 digitalWrite()함수만 사용하시면 됩니다.

설계

(1) 숫자 패턴만들기

CD4511 4개의 입력값을 받습니다. 그러면 4개의 상태를 8421 BCD 코드표를 참조하시면 좋습니다. 캐소드형 7 Segment LED를 하면 정확히 아두이노 핀의 역순으로 코딩하면 일치하게 됩니다. 그래서 이번 실험은 이해하기 쉽게 캐소드형 코딩을 선택했습니다.

0000 => 0
0001 => 1
0010 => 2
...

0은 0000 => 출력값은 1111110 됩니다.
0은 A[4] = {0,0,0,0}
그러면 0~9까지 10개의 패턴이니깐 2차배열변수로 만들면은 아래와 같이 만들어 지겠죠.

int data[10][4]={
   {0,0,0,0}, //0
   {0,0,0,1}, //1
   {0,0,1,0}, //2
   {0,0,1,1}, //3
   {0,1,0,0}, //4
   {0,1,0,1}, //5
   {0,1,1,0}, //6
   {0,1,1,1}, //7
   {1,0,0,0}, //8
   {1,0,0,1}  //9
};

(2) 숫자 출력

0은 A[4] = {0,0,0,0} 이고,
datapin은 datatpin[4] = { 5,4,3,2} 하면

 for(int j=0;j<4;j++){
    digitalWrite(datapin[j],A[j]);
 }

이렇게 됩니다. 하지만 10개의 패턴과 각 패턴의 상태값 4개를 2차 배열 위의 date[10][4]로 만들면 2차 for문을 사용하면

  for(int i=0;i<10;i++){
     for(int j=0;j<4;j++){
       digitalWrite(datapin[j],data[i][j]);
     }
     delay(1000);
  }     

여기서 delay(1000)을 두어 1초 단위로 0~9까지 7 Segment LED에 출력되게 됩니다.

코딩을 하면

int data[10][4]={
   {0,0,0,0}, //0
   {0,0,0,1}, //1
   {0,0,1,0}, //2
   {0,0,1,1}, //3
   {0,1,0,0}, //4
   {0,1,0,1}, //5
   {0,1,1,0}, //6
   {0,1,1,1}, //7
   {1,0,0,0}, //8
   {1,0,0,1}  //9
};
int datapin[4] ={5,4,3,2};

void setup(){
  for(int i=0;i<4;i++){
    pinMode(datapin[i],OUTPUT);
  }
}
void loop(){
   for(int i=0;i<10;i++){
     for(int j=0;j<4;j++){
       digitalWrite(datapin[j],data[i][j]);
     }
     delay(1000);
  } 
} 

4. 결과


결과 동영상을 보면 다이렉트로 전 과정을 동영상 촬영을 했는데 회로도를 만드는 과정에서 Vcc 선을 Gnd로 잘못 연결해서 가상시뮬레이터 처음 실행에서 CD4511 칩이 망가졌습니다. 가상시뮬레이터라서 실제로 CD4511 칩이 망가지는 것이 아니기 때문에 그렇게 큰 의미는 없지만 이걸 실제로 선을 잘못 연결한다면 칩에 문제가 생기겠지요. 다시 동영상으로 촬영할려다가 선 연결의 중요성과 이런 점에서 가상시뮬레이터를 사용의 장점이 될 것 같아서 그냥 올립니다.(실제로 다시 촬영하기 귀찮음!)

마무리


74HC595 칩은 3핀을 사용했지만 CD4511 칩은 4핀을 사용합니다. 그러면 이전 시간에 배운 74HC595 칩으로 하는게 좋을 것 같다는 생각을 하실 수 있습니다. CD4511 칩을 제어는 무지 간단 합니다. 아두이노 없이도 이 칩을 이용해서 7 Segment LED를 제어가 가능합니다.

그리고 74HC595+CD4511으로 7 Segment LED를 제어를 한번 해보세요. 이 두 칩을 배우고 나서 이걸 합쳐서 실험해보고 싶어져서 7 Segment LED를 제어 해보았어요. 이 내용은 다음 포스팅에 쓰도록 할께요. 한번 두 칩에 동작 원리를 생각하고 회로도를 구성하고 코딩해보세요.

한번 74HC595칩과 CD4511을 결합을 하면 어떻게 회로도가 표현 되는지 상상의 나래를 펼쳐보세요.


댓글()

[아두이노] 74HC595+ 7 Segment LED 실제 실험

IOT/아두이노|2019. 2. 15. 09:26

[아두이노] 74HC595+ 7 Segment LED 실제 실험



가상시뮬레이터에서 아두이노우노를 다루면서 실제 현실에서도 동일하게 작동을 하는지 궁금하신 분들이 있을꺼에요. 그래서 귀찮니즘을 안고 실제로 실험을 하였습니다. 예전에 74HC595 칩을 뻥판에 꼽을 개고생 했는데 뻥판이 싼거라 핀이 잘 안들어가서 핀 부분이 약간 오그라졌는데 이번에도 역시나 꼽을 때 오그라지고 뽑을 때 오그라져서 나오더군요. 몇번 실험하고 나면 74HC595 칩이 망가질것 같네요.

1. 회로도 구성



[아두이노] 쉬프트레지스터(74HC595) 제어 편에서 실제로 7 Segment LED도 뻥판에 배치를 해야하기 때문에 약간 배치하는 위치를 수정했네요.


좀 더 깔끔해진 회로도 모습이지요.

지난시간에 가상시뮬레이터로 설계한 모습에서 다시 가상시뮬레이터의 뻥판에 재배치한 모습입니다. 그런데 실제로 같은 위치에 배치하면 이런 모습이 아니라 지져분한 모습입니다. 가상시뮬레이터에서 회로도를 배치한대로 실제로 동일하게 배치했습니다. 참고로 저항은 220옴뿐이 없어서 이걸로 했습니다. 저항은 LED에 필요한 허용치 저항을 연결하면 되니깐 제 경우는 저항 220옴으로 실험했네요.


위 사진은 뻥판 연결된 모습인데 실험 중의 한 컷인데요. 선만 봐도 엄청 지져분하죠. 74HC595 칩을 뻥판에 꼽을 때 개고생 했네요. 핀 위치는 대충 가상시뮬레이터에서 연습 몇번해서 그런지 선 연결은 지져분할 뿐 간단했네요. 가상시뮬레이터에 연습없이 바로 실제로 실험한다면 선 연결할 때 실수하는 경우가 많겠죠.

2. 코딩


코딩은 지난시간에 숫자를 순차적으로 출력하는 로직을 그대로 집어 넣었습니다.

byte data[]={
0B10000001,  
0B11110010,
0B01001001,
0B01100000,
0B00110011,
0B00100100,
0B00000101,
0B11110000,
0B00000001,
0B00100000
};
int latchPin = 11; //ST_CP Pin
int clockPin = 12; //SH_CP Pin
int dataPin = 9; //DS Pin

void setup(){
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop(){
 for(int i=0;i<10;i++){
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, data[i]);
    digitalWrite(latchPin, HIGH);       
    delay(1000);
  }  
}

3. RaspberryPi3 에서 아두이노우노로 프로그램 이식


PC에서 RaspberryPi3를 원격 제어를 통해 아두이노 IDE를 띄워고 위 코딩을 복사한 뒤에 실제 아두이노우노에 프로그램 이식을 수행했습니다.
PC에 아두이노 IDE를 설치했다면 바로 PC에서 아두이노우노에 프로그램을 이식하면 됩니다.


4. 결과


아래 13초짜리 동영상은 실제 프로그램이 이식된 아두이노우노가 74HC595 칩에 숫자 패턴 데이터값을 전송하여 7 Segment LED에 숫자가 가상시뮬레이터에서 나왔던 결과와 동일하게 출력되는지 테스트한 결과입니다.


마무리


실제 아두이노우노로 실험을 해 보았습니다. 가상시뮬레터의 결과와 동일하게 나오는 것을 보실 수 있었을 겁니다. 이처럼 실제로 키트를 사서 실험을 하실 수 있지만 실제로 실험하면 가상으로 한것보다 시간도 많이 걸리고 손으로 일일히 노가다 작업을 많이 해야 합니다. 편하게 마우스로 선을 연결할 수 있는 것을 실제로 뻥판에 억지로 꼽고 하는게 쉽지가 않죠. 그리고 부품이 작어서 아무 지식도 없는 상태에서 보고 따라서 꼽을려고 하면 그것도 만만치 않습니다.

특히, 74HC595 칩의 경우는 작고 핀들의 네임들을 외우지 않는 이상 햇갈릴 수 있습니다. 하지만 가상에서는 마우스을 대면 핀 네임들을 쉽게 확인이 가능합니다. 가상시뮬레이터로 여러번 반복 실험을 하다보면은 실제 실험에서도 어렵지 않게 핀 연결을 할 수 있게 됩니다.

제가 아두이노우노를 실험할 때 실제 아두이노우노 키트가 있지만 가상시뮬레이터에서 하는 이유는 실제 아두이노키트를 사용해서 실험하는 것보다 가상시뮬레이터에서 더 쉽게 실험할 수 있기 때문입니다.

막연히 아두이노우노 키트를 사서 하는것보다 가상시뮬레이터로 충분히 즐긴 후 좀 더 다양한 실험을 하고 싶을때
아두이노 시리즈 중 원하는 싱글보드를 구매하셔서 실험하시면 됩니다.


댓글()

[아두이노] 직렬 연결한 쉬프트레지스터(74HC595) 제어

IOT/아두이노|2019. 2. 14. 09:32

[아두이노] 직렬 연결한 쉬프트레지스터(74HC595) 제어



이번에는 2개의 74HC595칩을 직렬로 연결하여 3개의 핀을 이용해서 2개 7 Segment LED를 제어하는 실험을 하였습니다. 이번에도 제 블로그에 포스팅 했던 내용인데 코딩은 최대한 원리를 설명하기 위한 로직이라서 기존 블러그에 있던 로직을 수정없이 그대로 소개하도록 하겠습니다. 여기다 살을 더 붙여서 60초 카운터 하는 로직을 설계할 수 있지만 그러면 군더더기 붙은 코딩으로 60초 변수를 만들고 if 조건문을 써서 십의자리와 일의자리를 쪼갤지 아니면 따로 카운터 변수로 정해서 조건문으로 표현할지 정하다 보면 본래 설명하고자하는 직렬 연결 설명이 복잡해 보일 수 있어 이번 포스팅은 간단히 어떻게 출력이 되는지만 실험하는 거라서 60초 카운터 출력은 독자의 몫으로 남겨 두겠습니다.

1. 직렬 쉬프트레지스터(75HC595) 연결



이전 시간에 75HC595 칩 하나를 아두이노에 연결하는 회도로를 이해했다는 전재하에서 기본 STCP, SHCP, DP 핀으로 해서 75HC595 칩을 제어를 하게 됩니다. 이 3핀을 제어하는데 직렬로 연결하면 위 그림처럼 연결을 하게 됩니다. STCP(결쇠)와 SHCP(클럭)핀은 공유합니다. DP핀은 오른쪽 75HC595 칩에 입력되고 그 입력된값이 Q7S 핀을 통해서 왼쪽 75HC595 칩의 DS 핀의 입력으로 들어 갑니다.

처음 아두이노에서 입력된 값이 16개의 값이 입력되면 앞에 8개 값이 왼쪽 75HC595 칩에 쌓이고 나머지 8개가 오른쪽 칩에 쌓여서 출력됩니다.

여기서 선색으로 대충 의미를 이해하시면 되겠습니다.

2. 회로도 구성


  • 준비물 : 75HC595칩 2개, 7 Segment LED 2개, 저항 330옴 2개, 아두이노우노, 뻥판
  • 내용 : 두개의 7 Segment LED에 숫자를 출력하게 하자.


74HC595 칩을 하나 사용할때도 복잡했는데 그림으로 2개를 사용하니깐 더 복잡해 보일꺼에요. 이전 시간에 한개로 했을때 선 연결과 동일하고 그걸 참고해서 두개를 동일하게 선 연결을 하시면 됩니다. 그리고 추가된것은 위의 직렬 쉬프트레지스터 연결을 보시면서 선이 왜 이렇게 연결되었는지 이해하시면 됩니다.

복잡해 보일뿐 단순합니다. 핀에 마우스를 대면 핀 이름이 나오고 해당된 부품과 연결하시면 됩니다.

3. 코딩


  • 사용함수 : pinMode(출력핀, 모드), digitalWrite(결쇠핀, 열림/잠금), shiftOut(데이터입력핀, 클럭핀, 순서, 데이터전송값)
  • 내용 : 아두이노에서 제공되는 shiftOut( )함수로 74HC595칩을 제어를 통해 2개 7 Segment LED에 숫자를 0과1, 1과2 ... 순차적으로 출력해보자.

  • 74HC595칩 제어 :
  • latchPin, clockPin, dataPin을 pinMode(출력핀, 모드)로 선언
  • digitalWrite(결쇠핀, 열림/잠금)으로 74HC595 칩에 입력할때 열림/잠금을 제어
  • shiftOut(데이터입력핀, 클럭핀, MSBFIRST, 전송값)으로 이걸 통해서 역순으로 데이터가 배치

설계

오른쪽 0부터 왼쪽 1부터 순차적으로 숫자를 출력

이전시간에

열림
쉬프트레지스트에 데이터 전송
닫침

코딩으로

digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, data[i]);
digitalWrite(latchPin, HIGH);       

숫자 1개는 8개 값이 필요합니다. 그러면 쉽게 생각해보세요. 숫자가 2개면 16개의 값이 필요합니다. 그러면 쉬프트레지스트로 shiftOut()을 통해 두번 데이터를 전송하면 되겠다는것이 떠올라야 겠죠.
0과 1, 1과2 이렇게 순차적으로 출력하도록 설계할꺼니깐 아래과 같이 표현하면 되겠죠.

    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, data[i]);
    shiftOut(dataPin, clockPin, MSBFIRST, data[i+1]);
    digitalWrite(latchPin, HIGH);       

코딩을 하면

byte data[]={
0B10000001,  
0B11110010,
0B01001001,
0B01100000,
0B00110011,
0B00100100,
0B00000101,
0B11110000,
0B00000001,
0B00100000
};
int latchPin = 11; //ST_CP Pin
int clockPin = 12; //SH_CP Pin
int dataPin = 9; //DS Pin

void setup(){
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop(){
  for(int i=0;i<9;i++){    
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, data[i]);
    shiftOut(dataPin, clockPin, MSBFIRST, data[i+1]);
    digitalWrite(latchPin, HIGH);       
    delay(1000);
  }  
}

4. 결과



마무리


3핀을 이용하여 2개의 74HC595 칩을 제어하여 2개의 7 Segment LED에 출력하였습니다.
회로도 보면 지져분하고 선연결이 복잡해 보일 수 있어요. 지난 시간에 배운 쉬프트레지스트 회로도를 디자인을 어느정도 이해하시면 2개든 3개든 보기에만 복잡해 보일뿐 참 쉬운 회로도입니다. 코딩도 지난시간에 했던 것에서 딱 한줄 늘어났을뿐 변화가 없습니다.

이 세줄만 이해하시면 몇개의 74HC595 칩을 사용해도 쉽게 해결됩니다.

열림
쉬프트레지스트에 데이터 전송
닫힘

오늘은 직렬 두개였으니깐

열림
쉬프트레지스트에 데이터 전송1
쉬프트레지스트에 데이터 전송2
닫힘

참쉽죠.

60초 카운터를 만들려 했는데 그러면 약간 직렬 제어 코딩에 혼동을 줄 수 있기 때문에 간단하게 두개를 어떻게 제어하는지만 배우는 것이 목적임으로 생략이 되었네요.

한번 여러분들이 60초 카운터 로직을 설계 해 보세요.
그리고 74HC595 칩의 원리로 어떤걸 표현하면 좋을지 상상의 나래를 펼쳐보세요.


댓글()

[아두이노] 쉬프트레지스터(74HC595) 제어

IOT/아두이노|2019. 2. 13. 14:32

[아두이노] 쉬프트레지스터(74HC595)



제 블로그에 포스팅 했던 내용인데 좀 어려운 내용이라서 이걸 소개해야하나 남감했지만 7 Segment LED의 연결되기 때문에 최대한 간단하게만 설명하겠습니다.

이전 시간에 7 Segment LED 제어를 배웠습니다. 이걸 사용하기 위해서 총 8핀을 아두이노에 연결해야 합니다. 문제는 2개 이상의 7 Segment LED를 제어할 경우 아두이노핀이 부족하게 됩니다. 그래서 아두이노 사용되는 핀을 줄일 수 있는 방법을 찾다보니깐 여러 칩중에 쉬프트레지스터라는 칩을 알게 되었으며 온라인 가상시뮬레이터에서도 모델명 75HC595칩(쉬프트레지스터)이 제공하기 때문에 이 칩을 이용해서 제어해보도록 하겠습니다.

1. 쉬프트레지스터(75HC595)


칩만보면은 햇갈립니다. 실제로 칩을 구매하실때 데이터시트를 꼭 인터넷에서 찾으셔서 살펴봐야 합니다. 물론 전 데이터시트를 보기가 참 힘들더군요. 간단히 칩구성과 핀 연결로 대충 이 칩의 작동원리만 이해하고 사용해 보았습니다. 참고로 칩을 사용하실때 칩에 사용되는 전압을 꼭 확인하시고 써야 합니다. 그렇지 않으면 칩이 망가질 수 있어서 조심해서 다루셔야 합니다.


  • 그림에서 보듯이 Vcc, Gnd은 그대로 해당 핀에 연결해주면 됩니다.
  • 데이터입력핀 DS핀 : 아두이노에서 데이터를 이칩에 보내게 됩니다.(총8개 출력값)
  • STCP 핀 : HIGH, LOW값으로 결쇠 역할을 하는 핀입니다. 칩에 입력할때 LOW 칩을 개방하고 입력을 끝내면 HIGH 칩닫음
  • SHCP 핀 : 클럭핀
  • MR 핀 : 5V 연결하더군요. 사용목적은 데이터시트 참고(저도 기억이 가물)
  • Q7S 핀 : 직렬 연결할때 사용합니다.이 칩 역시 8개값을 출력하기 때문에 더 많은 값을 출력하기 위해서 칩을 직렬 연결용으로 사용
  • Q0~Q7 : 각 핀으로 입력된 8개의 값을 출력합니다.

결론적으로 3개의 핀을 사용하여 결쇠핀, 클럭핀, 데이터핀으로 해서 이 칩을 제어할 수 있습니다. 가령 2개 이상의 75HC595를 사용해도 3핀만으로 직렬연결을 통해 제어가 가능합니다. 이건 다음에 소개하고 현재 이 칩을 아두이노에서 제어하는게 가장 중요합니다.

2. 회로도 구성


  • 준비물 : 75HC595 칩 1개, 7 Segment LED 1개, 저항 330옴 1개, 아두이노우노, 뻥판
  • 내용 : 숫자를 순차적으로 출력해보자.


칩이 정면으로 되어 있기 때문에 칩을 회전시켜야합니다. 그림을 잘 보시면 뒤집어져있는걸 보실꺼에요. 마우스로 해당칩에 끝점을 대면 핀이름이 나타납니다. 5V와 Gnd은 그림에서 보는것처럼 동일하게 배치하시면 됩니다.

참고로 Q0이 기름에서 보는것처럼 하단에 있어서 지난시간에 배운데로 A~G핀과 DP핀을 순차적으로 Q0~Q7까지 연결하면 선이 안이뻐서 Q0을 그냥 DP핀(점 LED)으로 했네요. 나머지 Q1~Q7을 A~G핀으로 연결했습니다. 그래서 배열변수값들이 지난시간에 제대로 이해 못하셨다면 약간 혼동되실꺼에요.

  • 7 Segment LED 제어 :
    74HC595칩의 Q0~Q7핀을 통해서 A~G핀과 DP핀 연결

3. 코딩


  • 사용함수 : pinMode(출력핀, 모드), digitalWrite(결쇠핀, 열림/잠금), shiftOut(데이터입력핀, 클럭핀, 순서, 데이터전송값)
  • 내용 : 아두이노에서 제공되는 shiftOut( )함수로 74HC595칩을 제어를 통해 7 Segment LED에 숫자를 순차적으로 출력해보자.

  • 74HC595칩 제어 :
    • latchPin, clockPin, dataPin을 pinMode( )로 선언
    • digitalWrite(결쇠핀, 열림/잠금)으로 74HC595칩에 입력할때 열림/잠금을 제어
    • shiftOut(데이터입력핀, 클럭핀, MSBFIRST, 전송값)으로 이걸 통해서 역순으로 데이터가 배치

설계

(1) 숫자패턴 배열변수 만든다.



7 Segment LED 연결된 것이 DP핀, A~G핀이 Q0~Q7순으로 순차적으로 연결됩니다. 홀짝에서 홀수일때 DP핀에 불이 들어오게 싶다면 숫자 0이면 G핀과 DP핀만 꺼지면 되니 10000001 이 됩니다. 그런데 1일때 0100111이겠지라고 생각하시면 안됩니다. MSBFIRST은 현재 연결핀 순서라면 역순이 됩니다. 11110010이 되어야 합니다.

이걸배열변수로 하면

byte data[]={
0B10000001,  
0B11110010,
0B01001001,
0B01100000,
0B00110011,
0B00100100,
0B00000101,
0B11110000,
0B00000001,
0B00100000
};

아마 지난시간을 생각하면 2차 배열변수로 생각하셨던 분도 있을꺼에요. 이건 하나의 값으로 표현이 가능합니다.
이걸 16진수로 하면 0x81 이 됩니다. 데이터숫자값으로 표현이 가능합니다. 이 같은 2진수 비트로 해서 다시 표현하면 위 배열처럼 나타나게 됩니다. 위 표현은 기계가 이해하기 쉬운 숫자형태입니다.

진법을 알아야하는 간단히 설명하자면
10000001 은 패턴이고 2진수입니다.
1000 0001로 4개씩 쪼개서 16진수로 나타냅니다.
8과 1로 표현됩니다.

0001=>1
0010=>2
0011=>3
.....
원래 8421 표를 숙지해야 하는데 현재 이것이 중요한것이 아니기 때문에 대충 네개로 묶으면 16진수 3개씩 묶으면 8진수라는 정도로 의미만 이해하세요.
16진수로 배열변수 값을 한다면 0x81로 표현해서 저장해도 동일한 결과가 나옵니다. 그냥 이해하기 쉽게 위 배열변수의 형식으로 이해하셔서 코딩하세요.
10진수가 아닌 기계가 이해하기 쉬운 숫자형태로 표현한다고 생각하세요.

(2) 74HC595칩에 원하는 숫자패턴을 전송한다.

  • 출력핀모드 선언 :
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);

(3) 74HC595칩에 숫자패턴을 입력한다.

digitalWrite(latchPin, LOW); //열림
shiftOut(dataPin, clockPin, MSBFIRST, data[i]); //패턴입력
digitalWrite(latchPin, HIGH); //닫힘   

(4) 7 Segment LED에 출력한다.

74HC595칩(Q0~Q7) => 7 Segment LED(DP,A~G) 출력

코딩을 하면

byte data[]={
0B10000001,  
0B11110010,
0B01001001,
0B01100000,
0B00110011,
0B00100100,
0B00000101,
0B11110000,
0B00000001,
0B00100000
};
int latchPin = 11; //ST_CP Pin
int clockPin = 12; //SH_CP Pin
int dataPin = 9; //DS Pin

void setup(){
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop(){
 for(int i=0;i<10;i++){
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, data[i]);
    digitalWrite(latchPin, HIGH);       
    delay(1000);
  }  
}

4. 결과



마무리


3핀을 이용하여 74HC595 칩을 제어하여 7 Segment LED에 출력하였습니다. 쉬프트 로직은 사실 좀 복잡합니다. 코딩 독해능력이 있어야 하는 부분임으로 그냥 함수명만 이해해 주세요. 위의 참고출처 가시면 튜토리얼로 쉬프트 함수의 로직을 살펴볼 수 있습니다. 독해능력이 되시면 어떤식으로 74HC595 칩에 데이터를 보내는지 확인하실 수 있을 꺼에요.

코딩에 자신있는분들은 본인이 직접 로직을 짜는분들도 있지만 초보분들은 그냥 있는 함수만 잘 사용하여 원하는 동작을 수행하는게 중요합니다.

digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, data[i]);
digitalWrite(latchPin, HIGH);       

이것이 코딩의 전부입니다. 이걸 통해서 74HC595 칩을 제어할 수 있어서 쉽게 원하는 글자나 숫자를 7 Segment LED에 출력을 할 수 있는 것이죠.

이 세줄만 이해하시면 됩니다.

열림
쉬프트레지스트에 데이터 전송
닫힘

이 문장만 숙지하시고 한번 이 세줄을 가지고 뭘 만들지 상상의 나래를 펼쳐보세요.


댓글()

[아두이노] 7 Segment LED 제어

IOT/아두이노|2019. 2. 12. 13:23

[아두이노] 7 Segment LED 제어



오늘은 LED 제어의 연장선상으로 7 Segment LED를 제어해 보도록 하겠습니다. 사용될 함수는 LED 제어때 사용한 pinMode( ), digitalWrite( )만 이해하시면 쉽게 제어를 할 수 있습니다.

1. 7 Segment LED


A,B,C,D,E,F,G,DP 핀으로 총 8개의 핀으로 구성되어 있습니다. 각 핀은 위 그림에서 보는것 같지 해당 위치의 LED에 불을 제어하는 핀으로 생각하시면 됩니다. 실제로 구매하시면 애노드형과 캐소드형이 있는데 위아래핀이 애노드 7 Segment LED이고 좌우고 캐소드였나 암튼 가상시뮬레이터에서 사용하는게 애노드형 초기 기본으로 되어 있는데 속성창에서 캐소드형으로 바꿔서 실험할 수 있습니다.

애소드와 캐소드 차이

7 Segment LED핀들이 가상시뮬레이터에서는 핀에서 COM1, COM2 핀이 있는데 아무핀이나 하나에 5V(+)핀이면 애노드형이고 Gnd(-)핀이면 캐소드형이 됩니다.

  1. 애노드 : A~G,DP핀이 0V이고 COM1 or COM2가 5V이면 해당 핀 LED에 불이 들어옵니다.
  2. 캐소드 : A~G,DP핀이 5V이고 COM1 or COM2가 Gnd이면 해당 핀 LED에 불이 들어옵니다.

쉽게 말해서 서로 반대라고 생각하시면 됩니다. 애노드형은 출력핀이 0일때 LED에 불이 들어오고 캐소드형은 출력핀이 1일때 LED에 불이 들어온다는 것만 이해하시면 됩니다. 참고로 7 Segment LED를 구매하실때 제품이 애노드형인지 캐소드형인지 확실히 확인하시고 구매하세요. 그래야 햇갈리는 핀연결과 코딩을 하지 않습니다.

2. 회로도 구성


  • 준비물 : 7 Segment LED 1개, 저항 330옴 1개, 아두이노우노
  • 내용 : 알파벳과 숫자를 출력해보자.

애노드형모델캐소드형모델



대충 붉은선이 5V에 연결되어 있고 검은선이 Gnd에 연결된 모습을 보면 대충 알겠죠.

##3. 코딩

  • 사용함수 : pinMode( ), digitalWrite( )
  • 내용 : 애노드형모델 기반으로 알파벳과 숫자를 순차적으로 출력하는 코딩을 해보자.

  • 7 Segment LED의 각 led 제어 :
    pinMode(핀, 모드)으로 전류를 출력할 핀들을 출력모드(OUTPUT) 사용하겠다고 선언
    digitalWrite(핀, 상태)은 HIGH(5V) or LOW(0V)로 전류를 출력할지 말지를 결정(여기서, 1은 5V, 0은 0V)

7 Segment LED도 내부에 LED들을 제어하기 때문에 LED 제어할때랑 동일합니다. 애노드형이기 때문에 0일때 불이 들어고 1일때 불이 꺼진다는 것만 생각하시고 코딩에 들어가세요. LED 제어의 복습차원이라고 생각하시면 됩니다. 참고로 알파벳과 숫자를 만드는 수작업인 노가다가 필요합니다.

설계

(1) 알파벳(A,B,C,D,E,F)과 숫자(0,1,2,3,4,5,6,7,8,9) 만들기



A글자 만들려면 LED D핀이 꺼지고 나머지 핀들이 켜져야 겠죠.(켜기=0, 꺼지기=1)

00010000

배열로 A[8]={0,0,0,1,0,0,0,0} 이 된다. 이건 하나의 A글자의 패턴입니다. 그러면 각 글자와 숫자의 패턴을 배열변수로 만들어야겠죠. 참고로, 앞에 7개는 글자나 숫자를 만드는 핀이고 마지막 8번째는 DP핀으로 점 LED 입니다. 0을 설정한 이유는 그냥 점 LED를 켜지는 것을 테스트 목적인것이지 의미는 없다는 점 참고하세요. 점 LED 빼고 싶다면 00010001 이러면 되겠죠.
아래 2차배열로 표현할때 점 LED은 글자가 출력할때 그냥 같이 켜지게 했고 숫자가 출력할때에 그냥 꺼지게 했어요. 원래 여러개 연결한다면 소숫점으로 사용하면 좋겠는데 한개 7 Segment LED라서 그냥 테스트로 켜지는지 보기위한 실험으로 의미는 없습니다.

int segValue[16][8] = {
   {0,0,0,1,0,0,0,0}, //A
   {1,1,0,0,0,0,0,0}, //B
   {1,1,1,0,0,1,0,0}, //C
   {1,0,0,0,0,1,0,0}, //D
   {0,1,1,0,0,0,0,0}, //E
   {0,1,1,1,0,0,0,0}, //F
   {0,0,0,0,0,0,1,1}, //0
   {1,0,0,1,1,1,1,1}, //1
   {0,0,1,0,0,1,0,1}, //2
   {0,0,0,0,1,1,0,1}, //3
   {1,0,0,1,1,0,0,1}, //4
   {0,1,0,0,1,0,0,1}, //5
   {0,1,0,0,0,0,0,1}, //6
   {0,0,0,1,1,1,1,1}, //7
   {0,0,0,0,0,0,0,1}, //8
   {0,0,0,0,1,0,0,1}  //9  
};

(2) 알파벳과 숫자를 만들었다면 실제 출력해야겠죠.

  • 핀배열 변수 선언 :
int segPin[8]={2,3,4,5,6,7,8,9}; 
  • 출력핀모드 선언 :
for(int i=0;i<9;i++){
    pinMode(segPin[i], OUTPUT);
  }
  • 출력 : 이부분이 실제 코딩 로직의 전부입니다. 각 패턴를 for문으로 루프 도는게 전부임
for(int i=0;i<16;i++){ //16패턴
  for(int j=0;j<8;j++){ //패턴값
   digitalWrite(segPin[j], segValue[i][j]);        
}
  delay(1000);
}  

애노드형모델 코딩을 실제 하면은

int segValue[16][8] = {
   {0,0,0,1,0,0,0,0}, //A
   {1,1,0,0,0,0,0,0}, //B
   {1,1,1,0,0,1,0,0}, //C
   {1,0,0,0,0,1,0,0}, //D
   {0,1,1,0,0,0,0,0}, //E
   {0,1,1,1,0,0,0,0}, //F
   {0,0,0,0,0,0,1,1}, //0
   {1,0,0,1,1,1,1,1}, //1
   {0,0,1,0,0,1,0,1}, //2
   {0,0,0,0,1,1,0,1}, //3
   {1,0,0,1,1,0,0,1}, //4
   {0,1,0,0,1,0,0,1}, //5
   {0,1,0,0,0,0,0,1}, //6
   {0,0,0,1,1,1,1,1}, //7
   {0,0,0,0,0,0,0,1}, //8
   {0,0,0,0,1,0,0,1}  //9  
};
int segPin[8]={2,3,4,5,6,7,8,9}; //사용핀{a,b,c,d,e,f,g,dp} 순서대로임

void setup() {

  for(int i=0;i<9;i++){
    pinMode(segPin[i], OUTPUT);
  }
}
void loop() {
  for(int i=0;i<16;i++){
    for(int j=0;j<8;j++){
     digitalWrite(segPin[j], segValue[i][j]);        
  }
    delay(1000);
  }  
}

for문에 대해서 저번에 설명을 했으며 for문을 이해해야만 왜 이렇게 코딩이 되었는지 이해가 되실꺼에요.
혹시 이해가 안되시는 분들은 LED 제어(아두이노)를 다시 한번 보시고 간단히 소개된 for문을 보시고 대충 어떤 느낌인지 살펴보세요.

여기서 캐소드형 경우는

패턴배열변수값들을 반대로 하시면 됩니다.

int segValue[16][8] = {
   {1,1,1,0,1,1,1,1}, //A
   {0,0,1,1,1,1,1,1}, //B
   {0,0,0,1,1,0,1,1}, //C
   {0,1,1,1,1,0,1,1}, //D
   {1,0,0,1,1,1,1,1}, //E
   {1,0,0,0,1,1,1,1}, //F
   {1,1,1,1,1,1,0,0}, //0
   {0,1,1,0,0,0,0,0}, //1
   {1,1,0,1,1,0,1,0}, //2
   {1,1,1,1,0,0,1,0}, //3
   {0,1,1,0,0,1,1,0}, //4
   {1,0,1,1,0,1,1,0}, //5
   {1,0,1,1,1,1,1,0}, //6
   {1,1,1,0,0,0,0,0}, //7
   {1,1,1,1,1,1,1,0}, //8
   {1,1,1,1,0,1,1,0}  //9  
};

코딩에서는 for문을 사용해서 led 출력핀들의 모드와 출력상태를 표현하는 것과 2차배열로 7 Segment LED패턴을 표현하는 것 두개뿐이 없습니다. 패턴을 2차배열로 표현하는 노가다 작업만 있을 뿐이죠.

4. 결과



애노드형 모델을 실험 동영상입니다.



마무리


LED 제어의 연장선상의 7 Segment LED제어를 해 보았습니다. 한개짜리지만 실제 4개짜리로 묶여진 부품도 있어서 좀 더 다양한 표현을 할 수 있습니다. 글자나 숫자를 출력할 수 있으면 이걸로 많은걸 표현이 가능합니다.

실생활에서 보면 시계를 떠오르시는분들이 많겠죠. 또는 거리에 나가면 가장 가깝게 신호등에 숫자가 출력되는걸 보실 수 있을꺼에요. 그러면 아두이노로 신호등을 만들고 7 Segment LED로 신호등의 타이머로 현실과 비슷하게 표현을 가능하겠죠. 이걸 대충요 종이로 신호등을 만들어서 제어하면 아이들에게 재밌는 교통 교육용이 될 수 있겠죠.

오늘 배운 패턴 배열변수는 무척 중요합니다. 꽤 많이 사용하는 2차배열변수인데요. 다음에 LED CUBE나 8x8 도트매트릭스를 소개할지 모르겠지만 계속해서 사용합니다. 배열변수를 혹시 모르시겠다면 관련글들을 검색해서 꼭 공부해주세요.


댓글()

[아두이노] 조도센서 제어

IOT/아두이노|2019. 2. 11. 13:34

[아두이노] 조도센서 제어



오늘은 간단히 조도센서를 제어하는 실험을 해보겠습니다. 조도 센서는 빛의 밝기에 따라서 전류값이 달라지는데 이 전류값을 아날로그핀에서 입력으로 받아서 빛에 의해서 어떤 행동을 하기 위한 곳에서 사용할 수 있는 재밌는 센서입니다. 쉽게 생각하시면 가로등을 예로 들 수 있겠죠. 밤이되면 조도센서를 이용해서 가로등을 자동으로 켜지게 할 수 있겠죠.

1. 회로도 구성


  • 준비물 : green led 1개, 조도센서 1개, 저항(220옴) 1개, 저항(10k옴) 1개, 아두이노우노, 뻥판
  • 내용 : 특정 조도센서값을 기준으로 green led에 불이 들어오게 한다.

A모델(-)방향 입력값B모델(+) 방향 입력값



어둠(0) ~ 밝음(255)
어둠(255) ~ 밝음(0)

2. 코딩


  • 사용함수 : Serial.begin( ), Serial.print( ), Serial.println( ), map( ), analogRead( ), pinMode( ), digitalWrite( )
  • 내용 : A모델을 기반으로 조도값이 100이하면 불이 들어오게 코딩을 해보자

  • 시리얼모니터 출력 :
    Serial.begin(9600)으로 시리얼통신을 사용하겠다고 선언
    Serial.print(출력값)은 출력값을 아두이노 IDE 시리얼모니터에 값을 출력하고 새로운 라인으로 안넘어감
    Serial.println(출력값)은 출력값을 출력하고 새로운 라인으로 넘어감

자세히 알고싶다면 => 출처 : https://www.arduino.cc/en/Serial/Println

  • green led 제어 :
    pinMode(핀, 모드)으로 전류를 출력할 핀 13번을 출력모드(OUTPUT) 사용하겠다고 선언
    digitalWrite(핀, 상태)은 13번핀을 HIGH(5V) or LOW(0V)로 전류를 출력할지 말지를 결정

  • 조도센서 입력 :
    map(입력값,입력최소값,입력최대값,변환최소값,변환최대값)으로 입력(0~1023)값을 자동으로 매핑시켜 (0~255)으로 변환시킨다. 즉, 알아서 크기에 맞게 값을 잡아준다고 생각하시면 됨.
    analogRead(아날로그입력핀) 전류의 값을 읽어옴

설계

  1. 조도센서를 읽어옴
    int m_cds = map(analogRead(cdspin),0,1023,0,255);
  2. 조도센서의 값이 100이하면 led가 켜지게 한다.
    if(m_cds){
    digitalWrite(greenpin, HIGH);
    }
    else {
    digitalWrite(greenpin, LOW);
    }

A모델 코딩을 실제 하면은

int greenpin = 13;
int cdspin = A0;

void setup()
{
  Serial.begin(9600);
  pinMode(greenpin, OUTPUT);
}

void loop()
{
  int m_cds = map(analogRead(cdspin),0,1023,0,255);
  
  Serial.print("CDS =  ");
  Serial.println(m_cds);
  
  if(m_cds<100) { 
     digitalWrite(greenpin, HIGH);  
  }
  else {
      digitalWrite(greenpin, LOW);  
  }
  
}

0~1023으로 잡고 시작하고 싶다면 map()함수는 필요 없겠죠. 입력값을 자신이 원하는 값(0~255)의 범위로 추가로 만들어 보았어요.

그냥 아날로핀값을 읽어서 그 값을 if문으로 해서 led에 불이 들어오게 할지 말지만 정하면 되니깐 위 코딩에서 절반이상 코딩량을 줄어 듭니다. 정확히 실험을 하기 위해서 그 값을 시리얼모니터에 줄력하기 위해 코딩이 늘어나고 또 입력된 값을 특정값의 범위로 맞추고 싶을때 map()함수가 추가되었을뿐 제어는 간단합니다.

if(analogRead(cdspin) < 300) digitalWrite(greenpin, HIGH);  

else  digitalWrite(greenpin, LOW);  

딱 두문장으로 끝낼 수 있죠. 원리는 이 두문장이고 약간 조미료를 추가한것이 A모델 코딩입니다. 원리만 이해하셔도 돼요.

결과



마무리


오늘은 간단한 실험을 해 보았습니다. 조도센서는 빛에 따라서 값의 변화가 일어납니다. 실제로 전류의 변화가 일어납니다. 이 전류값은 아날로핀으로 0~1023사이의 값으로 읽어오게 됩니다. 이 값을 기반으로 아두이노에서 제어를 하게 됩니다. 쉽게 떠오르는 것은 가로등이 있겠죠.

여러분들은 조도센서로 뭘 하고 싶으신가요. 예술가를 예를 들어볼께요. 어떤 작품을 만들었는데 그 작품에 빛에 반응한다고 생각해보세요. 그리고 RGB led를 작품에 부착한다면 조도센서값들에 따라서 작품은 다체로운 색상들을 만들어 낼 수 있다면 관람객과 소통하는 작품을 구현할 수 있겠죠.

또는 조도센서를 언제쯤 어두워지고 언제쯤 밝아지는지 데이터를 매일 수집하면 빅데이터로 활용도 가능해지겠죠.

한번 조도센서를 사용한다면 어디에다 사용할지 상상의 나래를 펼처보세요.


댓글()

[아두이노] 거리측정센서로 3D 랜더링을 할 수 있을까?

IOT/아두이노|2019. 2. 10. 15:11

[아두이노] 거리측정센서로 3D 랜더링을 할 수 있을까?


영화 출처 : 프로메테우스

영화 프로메테우스의 한장면의 일부입니다. 동굴 탐사를 하기 위해서 드론같은 비행물체를 2개 띄우는 장면으로 붉은빛을 주기적으로 동굴벽에 비추는데 영화상에서 센서의 하나겠지요. 비행물체는 비행하면서 붉은 빛을 비추면서 동굴의 정보를 추출하게 됩니다. 그리고 우주선 본체에서 추출된 정보를 통해서 동굴 통로를 3D 랜더링을 하게 됩니다.

빛이 비추는 지점에 대한 거리 정보를 추출하지 않을까 생각되네요. 비행물체를 계속 이동하면서 일정각도와 일정거리로 이미지와 거리측정을 통해 각 벽면의 좌표점을 추출하지 않을까 생각됩니다.

그렇다면은 아두이노로 표현을 한다면 과연 어떻게 할까요 한번 생각해 봅시다.

1. 아두이노로 구현한다면 어떻게 할까요?


이미지 정보를 빼고 거리정보만으로 정보를 추출한다면 우선 가설은 이렇습니다. 비행물체는 아두이노드론으로 설정하고 드론본체의 중심에 초음파센서들을 부착하고 360도 거리 정보를 추출한다고 가정해 봅시다.


동굴 A에서 B까지 1도씩 360도의 거리 정보를 초음파센서로 각 좌표 정보를 추출하게 만든다면 원을 그린 것처럼 360개의 벽과의 거리 정보를 추출하게 됩니다. 그러면 드론의 현재 기준위치 정보에서 하나의 단층 좌표점들을 추출할 수 있겠죠. 그러면 이런 좌표이미지를 단층으로 해서 계속 누적시키면 어떻게 될까요. 드론이 일정간격 마다 벽과의 거리 꼭지점 단층 이미지들이 만들어 지겠죠. 가령 수백장의 단층이미지를 얻었다고 치면 여기서 각 꼭지점을 연결하면 3D 랜더링을 하게 되면 3차원 모델링 된 이미지를 얻을 수 있겠죠.

2. 대충 꼭지점을 연결한다면 이런 느낌!



각 꼭지점 사이의 거리는 드론이 일정이동거리이고 세로축은 초음파센서로 거리를 측정하는 지점이 되겠죠. 꼭지점은 가로의 한면만 나타낸 것이죠. 여기서 세로로 360개의 꼭지점을 얻을려면 x,y은 드론의 위치 좌표이고 z은 벽과의 거리로 (x,y,z)의 꼭지점을 360개 만들어 낼 수 있고 이정보는 세로 단층 이미지를 만들어 낼 수 있게 됩니다. 이 정보는 3D 랜더링을 하기위한 기본 정보가 되겠죠.

여기서 세로축으로 바라보면은 아래와 같은 모습이겠죠. 드론은 x,y 좌표가 되고 그 기준으로 z은 벽과의 거리가 되겠죠.


이 좌표들을 드론이 일정이동 간격으로 측정하하면서 이동하고 그정보를 중앙컴퓨터가 계산하여 좌표를 3D 랜더링을 하게 하면 동굴의 3D 이미지를 만들 수 있겠죠.

3. 영화는 왜 한축을 기준으로 회전해서 빛을 안쐈을까?


단순히 기준점으로 세로축으로 360도 회전해서 측정한다고 생각해 보세요. 그러면 어떤 문제가 생길까요. 바로 동굴은 매끈한 원형이 아니고 불규칙한 모습 때문입니다.


보는것과 같이 사각지대가 발생합니다. 가려진 부분은 그냥 이으면 빈공간이여도 매꾸어져 버립니다. 그래서 중심축으로 360도 회전이 아니라 영화에서 처럼 전망과 후방과 그리고 45도 각도로 해서 센서가 거리를 측정하게 됩니다.

비행물체가 일정간격으로 이동할때 마다 일정한 패턴으로 측정이 이뤄지는데 이동전과 이동후의 측정된 거리정보에서 후방측정과 후방 45도 측정시 그 각도지점은 이동전 (x,y) 좌표에 측정된 단층정보에 새롭게 측정된 사각지대 정보를 추가로 덮어 씌운다면 보다 정확한 단층이미지가 생성되겠죠. 그래서 영화에서는 전방, 후방, 45도 각도별 거리 정보를 추출하는 장면을 보여주기 위해서 붉은 빛으로 패턴을 보여준것 같다는 생각이 듭니다.

쉽게 말해서 영화에서는 일정간격으로 앞좌표, 현재좌표, 다음좌표의 정보를 거리 정보를 추출하여 그 정보를 종합해서 3차원 이미지를 만들어 낸 것이죠.

4. 비행물체의 비행은 어떻게 할까?


무인 자동비행을 해야하기 때문에 드론의 비행 좌표는 동굴의 중심으로 해서 날아가야 합니다. 하지만 동굴은 동글한 모양이 아니기 때문에 계산해야겠지요. 어떻게 해서 날아가야할까요. 위치정보 센서와 같은 기타 센서등을 이용도 해야겠지만 거리측정만으로 한다고 가정해 봅시다.


비행물체 전방에 거리측정센서를 부착해서 전방의 측정된 좌표 거리값 중 임의의 A,B의 중 가장 가까운 값을 기준으로 그 값을 2로 나누는 지점이 중심거리가 되고 그 지점을 (x,y,z)의 비행 좌표로 하면서 이동하면 되겠죠.

마무리


이건 초음파센서만을 이용해서 설정한 가설입니다. 거리측정 센서는 다양합니다. 중요한것은 거리를 측정할 수 있으면 할 수 있는 것들을 설명하기 위해서 영화의 한 대목을 한번 아두이노로 표현한다면 어떻게 할 수 있을까의 상상의 나래입니다.

그리고 3D 랜더링하는 기술은 소개하지 않았습니다. 공간 꼭지점(x,y,z)를 구할 수 있으면 그 점들을 이으면 폴리건(면)을 만들 수 있습니다. 이건 컴퓨터그래픽스 프로그램언어 영역이라서 주제에서 벗어남으로 그 부분에 대한 설명을 생략합니다. 저 또한 3D 랜더링 기술을 한때 공부한적은 있습니다. 지금은 알고리즘도 기억 안나네요.

원래 주제를 초음파레이더를 소개할까 했지만 아직 서보모터 포스팅이 들어가지 않아서 아쉽게도 초음파레이터는 다음에 시간이 되면 소개할까 합니다.

물론 구글 검색하면 동영상강좌나 블로그에 초음파레이더가 쉽게 검색되고 꽤 유명해서 자료가 많습니다. 중고생들 실험 소재로 많이 사용합니다. 스크래치를 이용한 초음파레이더나 프로세싱을 이용한 초음파레이더 예제는 차고 넘쳐서 궁금하신분들은 구글 검색을 통해서 찾아보세요.

우선 거리를 측정할 수 있다면 뭘 할 수 있을까 중요합니다.

암튼 거리측정이란 단어를 한번 머리속에서 상상의 나래를 펼쳐 보세요. 그리고, 아두이노를 공부하실때 그냥 대충 남들이 만드니깐 따라 만들지 마시고 SF 영화같은데 보면서 저장면을 아두이노로 표현한다면 과연 어떻게 표현이 될까하고 상상을 하면 많은것들이 떠오르게 됩니다. 거리측정센서를 처음 공부할때 거리측정기를 기준점(x,y)가 되면 거리를 깊이(z)로 해서 공간 좌표를 추출할 수 있을 것이고 이를 통해서 3D 랜더링도 가능하지 않을까 하고 상상의 나래를 펼친적이 있네요. 그리고 프로메테우스란 영화가 떠오르더군요. 별거 아닐것 같은것들이 꽤 재밌는 발상을 하게 되면 재밌는 작품들이 만들어 집니다.

거리측정으로 할 수 있는것을 저처럼 한번 상상의 나래를 펼처보세요.

댓글()

[아두이노] 초음파줄자 응용

IOT/아두이노|2019. 2. 9. 12:46

[아두이노] 초음파줄자 응용




초음파센서로 줄자를 만들려면 대충 이런식으로 A, B의 벽까지의 거리를 측정하면 쉽게 줄자가 만들어 질 수 있겠죠.
이걸 표현하기 위해서 실험을 하고자 합니다.

1. 회로도 구성


  • 준비물 : 초음파센서3핀 2개, 스위치버턴 1개, 아두이노우노, 뻥판
  • 내용 : 벽과 벽사이의 거리를 측정하는 줄자를 구현해보자.

스위치를 누르면 아두이노우노 본체를 기준으로 양쪽 두지점의 벽과 벽사이 거리를 측정하도록 하기 위해서 회로도를 우선 아두이노우노 기준으로 양쪽 방향으로 초음파센서를 배치하여 회로도를 구성하였습니다.


2. 코딩


  • 거리계산 : ((float)(340 * 초음파거리시간값) / 10000) / 2;
  • 두지점거리계산식 : 아두이노우노를 10cm로 가정할경우
    total=v1+v2+10; => v1(A초음파), v2(B초음파), 10(아두이노우노본체크기)
  • 내용 : 스위치를 누르면 A,B 초음파 거리를 측정하고 그 결과를 시리얼모니터에 출력한다.

우선 스위치버턴은 복습차원으로 내부풀업저항을 이용합니다. 그래서 pinMode은 INPUT_PULLUP으로 선언합니다. 그리고 스위치 버턴값을 읽기 위해서 digitalRead(핀번호) 함수를 사용합니다. 지난 스위치버턴 포스팅에서 이미 소개했으며 복습차원으로 스위치 버턴을 사용하였습니다.

void setup() {
  Serial.begin(9600);
  pinMode(5,INPUT_PULLUP);
}
void loop() {  
  if(digitalRead(5)==0){
    float v1=UltrasonicDistance(6);
    float v2=UltrasonicDistance(7);
    float total=v1+v2+10;
    Serial.println(total);
    delay(500);
  }  
}

float UltrasonicDistance(int m_pin){
  pinMode(m_pin,OUTPUT); 
  digitalWrite(m_pin, LOW); 
  delayMicroseconds(2); 
  digitalWrite(m_pin,HIGH); 
  delayMicroseconds(10); 
  digitalWrite(m_pin,LOW); 
  
  pinMode(m_pin,INPUT);    
  float duration = pulseIn(m_pin, HIGH);  
  return duration / 57.5;  
}

여기서 2개의 초음파 거리측정을 해야하는데 그러면 두번의 중복 코딩이 발생합니다. 지난시간에 배웠던 C언어문법 외부함수로 재정의하여 뺐습니다.

복습하자면

float 초음파거리(int A){
 return 거리식;
}

초음파거리함수에 인자는 핀번호입니다. 함수 앞에 float는 변수 선언에서 설명한 자료형입니다. 즉, 함수 앞에서 자료형이 표현되었다는 것은 return의 명령어로 자료형(float)으로 반환한다는 의미입니다. 여기서는 좀 더 정확한 거리계산을 위해서 실수형으로 거리 계산된 값을 반환하겠다는 의미인거죠. 만약 정수형(int, long)으로 반환하겠다면 앞에 정수자료형을 선언하시면 됩니다.

loop()함수에서 사용할때는

<
v1=초음파거리(6)

이렇게 하면 6번핀의 초음파센서가 거리계산을 한뒤에 그 값을 반환하여 v1에 저장하게 됩니다.
v1 6번핀에 연결된 초음파센서 거리값이 저장됩니다.

초음파거리 계산식을 외부함수로 재정의함으로써 중복코딩을 줄이게 됩니다.
loop()안에는 아두이노 전원이 공급되고 반복되는 작업 명령들이 수행됩니다. 가독성을 위해서는 될 수 있으면 loop()함수에 선언되는 코딩들은 최소화 해야합니다. 그래야 가독성이 좋고 나중에 수정하기도 편합니다.

코딩 순서는

  1. 스위치버턴을 누르면 거리를 계산한다.
    pinMode(5,INPUT_PULLUP); //선언
    if(digitalRead(5){ //동작
    거리계산;
    }
  2. A, B초음파 거리 계산측정한다.
    float v1=UltrasonicDistance(6); //A 초음파거리계산
    float v2=UltrasonicDistance(7); //B 초음파거리계산
  3. 최종거리 계산한다.
    float total=v1+v2+10;
  4. 시리얼모니터에 그 결과를 출력한다.
    Serial.begin(9600); //선언
    Serial.println(total); //출력

3. 결과



마무리


코딩은 우선 어떤 명령을 내릴지 한글로 메모장에다가 순서를 정하여 글로 써보세요. 그리고 그 명령에 대해 사용할 함수들은 각 부품을 다룰때 쓰던 함수들을 그대로 사용하시면 됩니다. 어렵게 생각하실 필요없이 각 부품을 소개할때 거기에 사용한 함수들 2~3개를 기억했다가 그 함수의 의미를 이해하고 그것을 응용해서 표현하시면 됩니다.

정교한 초음파센서를 이용해서 건축현장에서 건물안에 길이를 측정할 때 유용하겠죠.

또 초음파로 어떤것을 표현할 수 있을까요. 상상의 나래를 펼쳐 보세요.


댓글()

[아두이노] 거리경보장치 응용

IOT/아두이노|2019. 2. 7. 18:50

[아두이노] 거리경보장치 응용



예전에 실험한 내용인데 초음파 응용편으로 소개할까 합니다. 거리경보장치는 실생활에 가장 유사한것이 자동차 후진 주차할때 경보장치를 연상하시면 될꺼에요. 뒤에 장애물과의 거리가 위험할때 나는 경보음을 생각하시면 아마 이해가 빠를꺼에요.

1. 회로도 구성


  • 준비물 : 초음파센서3핀 1개, led 2개, 저항 220옴 2개, 피에조부저 1개, 아두이노우노, 뻥판
  • 내용 : 장애물과의 거리가 50cm미만일때 경보음과 Red Led에 불이 들어오고 위험을 알리고, 50cm이상일때 Green Led에 불이 들어오고 안전상태를 표현합니다.


2. 코딩


  • Led : 선언-pinMode(핀번호, OUTPUT) 제어-digitalWrite(핀번호,상태값); 로 상태값 1(5V) or 0(0V)

  • 피에조부조 : 제어-tone(출력핀,음계,음길이), noTone(출력핀)으로 음과 음사이를 끊어줌

  • 초음파센서 : 선언pinMode(핀번호, 입/출력모드), delayMicroseconds(시간값)으로 마이크로초로 잡게 딜레이 시킴, pulseIn(7, HIGH)로 초음파가 장애물에 부딪치고 되돌아온 거리시간값을 입력받음

  • 거리계산 : ((float)(340 * 초음파거리시간값) / 10000) / 2;


코딩 설계는

  1. 초음파센서 거리 측정한다.
  2. Led 2개로 안전/위험 상태를 나타낸다.
  3. 피에조부조에서 위험거리일때 경보음이 울리게 한다.

1번 코딩 :
지난시간의 초음파 거리측정 코딩을 그대로 적용한다. 하지만 안전/위험 상태를 기준을 50cm로 설정한다면 어떻게 코딩해야할까요. 지난시간에 배웠던 문법 if문 조건이 참/거짓으로 나뉘면 쉽겠죠.

  • 거리측정은 7번핀에서 pulseIn(7, HIGH)로 거리시간값을 ((float)(340 * 초음파거리시간값) / 10000) / 2 로 거리가 구함
  • if(거리<50) {처리문1; } else {처리문2;}

2번 코딩 :
led 2개로 led은 위험, green은 안전으로 1번 코딩에서 50cm미만일때 red led 켜고, 50cm이상일때 green led 켜면 되겠죠.

if(거리<50){
    digitalWrite(11, HIGH);  
    digitalWrite(10, LOW);  
}
else
{
   digitalWrite(11, LOW);  
   digitalWrite(10, HIGH);  
}

참쉽죠

3번 코딩 :
경보음은 피에조부저에서 tone(), noTone()함수를 어떤 음계로 음의길이를 어느정도 할지는 자유입니다. 그런데 어디에 코딩할까. 50cm이하 일때 경보음을 울려야 겠죠.

if(거리<50){
    tone(12,523,1000/8);     // 도음으로 8분음표(음길이)
    delay(1000/4*1.30);             
    noTone(12);            
}
else
{
}

이렇게 해서 코딩은 간단히 해결되었습니다. 쪼개서 보면 별거 없습니다. 처음 기준이 되는 부품이 어떤 상태가 되면 다른 부품이 그 상태를 기준으로 어떻게 변화되는지만 글로 한번 설계해보시고 그걸 코딩으로 표현하시면 됩니다.

초음파센서로 거리가 50cm미만이면 위험상태(red led 켜고, 피에조부저 경보음)와 안전상태(green led 켜기)를 표현한 것 뿐이죠. 그런데 이걸 다 합쳐진 코딩을 보면 복잡해 보일 수 있습니다. 하지만 부품 한개 한개의 제어한 것들을 합치니깐 복잡해 보일뿐 부품을 개별적으로 생각하시면 아주 간단한 코딩입니다.

종합해서 코딩하면은

void setup() {  
  pinMode(11, OUTPUT);
  pinMode(10, OUTPUT);
}
void loop() {   
  pinMode(7,OUTPUT); //7번핀 출력모드로
  digitalWrite(7, LOW); 
  delayMicroseconds(2); 
  digitalWrite(7,HIGH); 
  delayMicroseconds(10); 
  digitalWrite(7,LOW); 
  
  pinMode(7,INPUT);    //7번핀 입력모드로
  float duration = pulseIn(7, HIGH);
  float distance = duration / 57.5;  
  

  if(distance < 50){    //50cm 미만 경보발동

    digitalWrite(11, HIGH);  
    digitalWrite(10, LOW);  

    tone(12,523,1000/8);     // 도음으로 8분음표(음길이)
    delay(1000/4*1.30);             
    noTone(12);            

  } else{                   //50cm 이상 안정거리
    digitalWrite(11, LOW);  
    digitalWrite(10, HIGH); 
  } 
}  

3. 결과



마무리


led, 피에조부저, 초음파센서를 각각 이전 시간에 배웠고 그걸 합쳐서 하나의 경보장치를 만들어 보았습니다.
또, 어떤것들이 있을까요 한번 상상의 나래를 펼쳐보세요.

초음파센서가 은근 재밌는 소재라 또다른 응용편을 다음에 소개 할께요.


댓글()

[아두이노] 초음파센서 제어

IOT/아두이노|2019. 2. 6. 11:01

[아두이노] 초음파센서 제어



오늘은 재밌는 소재로 거리를 측정할 수 있는 초음파센서를 사용하여 실험하는 내용을 다뤄 보겠습니다. 실제 초음파센서를 구매하시면 4핀으로 구성되어 있는데 가상시뮬레이터에서는 초음파센서가 3핀으로 되어서 어떻게 코딩해야하나 혼동 되실 수 있지만 원리는 동일하니깐 어렵게 생각하실 필요는 없습니다.

1. 초음파센서



초음파센서를 부품을 실제 구입하면 1200원정도 하는 초급 초음파센서를 구매하실수 있을꺼에요. 핀은 총 4핀으로 전원(+,-) 2핀, 입력핀, 출력핀으로 구성되어 있습니다. 하지만 가상시뮬레이터에서는 3핀으로 구성되어 있으면 입력/출력을 한핀에서 다 제어해야 합니다.

가상 시뮬레이터 코딩은 이 한핀을 어떻게 제어할지만 생각하시고 표현하시면 됩니다.

2. 초음파센서 계산 공식


  • 공식 : 기본 340 (위 1200원짜리 4핀 초음파센서 초음파속도입니다.)
    거리 = ((초음파속도 * 센서시간값) / 10000) / 2

            ((float)(340 * duration) / 10000) / 2;  
    

초음파속도 : 실제 사용하는 초음파센서 부품의 초음파속도입니다. 즉 초음파센서마다 초음파속도는 다르고 부품을 구매하실때 제공되는 정보를 잘 확인하시면 정교한 계산을 하실 수 있을꺼에요.

센서시간값 : 초음파센서에서 초음파가 나가고 앞에 장애물에 부딪치고 되돌아오는데 까지 걸리는 시간값입니다. 왕복시간값이라고 생각하시면 됩니다. 그래서 마지막에 나누기 2를 함으로써 초음파센서의 위치에서 장애물까지의 거리가 나오게 되는 것이죠.

3. 초음파센서 코딩

  digitalWrite(7, LOW); 
  delayMicroseconds(2); 
  digitalWrite(7,HIGH); 
  delayMicroseconds(10); 
  digitalWrite(7,LOW); 
   
  float duration = pulseIn(6, HIGH);
    
  float distance = ((float)(340 * duration) / 10000) / 2;  
    

7번핀이 출력모드이고 6번핀은 입력모드입니다. 7번핀으로 초음파를 쏘고 되돌아오는 초음파를 6번핀에서 읽게 됩니다. 그 값은 시간값이고 초음파공식에 대입하여 계산하게 됩니다.

  1. 초음파를 쏘기 전 초음파출력핀을 LOW(0)으로 한다. => 초기단계
  2. 딜레이 delayMicroseconds()함수는 시간을 마이크로초로 딜레이 시킬 때 사용. => 대기시간단계
  3. 초음파출력핀을 HIGH(5V)으로 한다. => 초음파를 출력 시작
  4. 딜레이 delayMicroseconds()함수로 대기한다. => 초음파를 쏘는 시간이다.
  5. 초음파출력핀을 LOW(5V)으로 한다. => 초음파 출력 중지

쉽게 말해서 초기상태는 초음파 출력핀 0V 상태로 2마이크로초로 초기상태로 뒀다가 7번핀을 통해 10마이크로초동안 초음파를 쏘고 난뒤에 초음파 출력핀 0V으로 10마이크로초동안만 초음파를 쏜 신호값을 거리계산에 사용한다는 점만 이해하시면 된다.

pulseIn(입력핀, HIGH)함수 : 펄스 신호의 길이를 잴 때 사용합니다. 초음파 되돌아 왔을때 HIGH->LOW가 되는 시점까지의 시간값을 반환하는 함수입니다. 좀 어려울 수 있습니다.
그냥 저 함수로 초음파 거리 시간값을 읽어오는 구나 정도만 처음에 이해하시면 됩니다.

정 모르겠다면 통으로 저 코딩을 외우시면 됩니다. 초음파센서를 사용할때 저 코딩으로 제어하는 구나 정도만 이해하시면 됩니다.

4. 회로도 구성


  • 준비물 : 초음파센서3핀 1개, 아두이노우노

5. 코딩


void setup() {
  Serial.begin(9600);
}
void loop() {   
  pinMode(7,OUTPUT); //출력모드  초음파 출력
  digitalWrite(7, LOW); 
  delayMicroseconds(2); 
  digitalWrite(7,HIGH); 
  delayMicroseconds(10); 
  digitalWrite(7,LOW); 
  
  pinMode(7,INPUT);    //입력모드로 초음파 입력
  float duration = pulseIn(7, HIGH); //초음파 거리 시간값 읽기
  float distance = duration / 57.5;  // ((float)(340 * duration) / 10000) / 2;   

  Serial.println(distance);   
} 

핀의 입력/출력모드 setup()함수에 선언된다고 했는데 여기서는 loop()함수에서 선언하였습니다. 왜 그렇게 했을까요. 그것은 바로 7번핀을 입력모드와 출력모드를 둘 다 사용해야 하기 때문에 계속 핀모드를 변경해야 합니다. 그래서 loop()함수에 선언된거죠.

초음파를 출력하기전에 7번핀을 출력모드로 선언했다가 다시 7번핀을 pulseIn()함수로 입력을 받을때에는 그 앞에 7번핀을 입력모드로 선언해야겠죠. 이런식으로 해서 7번핀으로 입력/출력모드 제어가 가능해 지는 것이죠.

 float distance = duration / 57.5;  // ((float)(340 * duration) / 10000) / 2;   

이식은 공식에서 최대한 줄이고 가상시뮬레이터에서 좀 더 거리가 비슷하게 나타내기 위해서 근사값 57.5로 표현했습니다. 실제로 하실때는 정식 공식을 사용하세요. 가상시뮬레이터에서는 정식 공식으로 대입하면 오차 거리가 좀 크게 나서 일부러 공식을 줄이고 줄인 공식에서 숫자를 앞뒤로 근사값들을 임의로 정해서 여러차례 실험한 뒤에 가장 오차가 적게 나오는 값이 57.5여서 이렇게 식을 만들었습니다.

실제로 하실때에는 정식 공식을 사용하시고 정식 공식을 써도 오차 거리가 발생할때에 그 부품에 맞게 근사값들을 잡아서 오차 거리를 줄이시면 아마 될꺼에요.

시리얼모니터 출력

지난시간에 사용했지만 복습차원으로 다시 설명하자면

아두이노 IDE 시리얼모니터를 사용하기 위해서

void setup()
{
 Serial.begin(9600);
}
void loop(){
Serial.println(distance);   
}

setup()함수에서 시리얼 통신을 시작한다고 선언(Serial.begin) 하고 loop()함수에서 시리얼모니터로 출력(Serial.println) 합니다.

Serial.println(출력값);   

이정도만 우선 알아두세요.

6. 결과

마무리


실제로 한다면 4핀 코딩을 해야하는데 아래와 같이 실험하시면 됩니다.

void setup() {
  Serial.begin(9600);
  pinMode(7,OUTPUT); //출력모드
  pinMode(6,INPUT);    //입력모드
}
void loop() {    
  digitalWrite(7, LOW); 
  delayMicroseconds(2); 
  digitalWrite(7,HIGH); 
  delayMicroseconds(10); 
  digitalWrite(7,LOW); 
   
  float duration = pulseIn(6, HIGH);
  float distance = duration / 57.5;  // ((float)(340 * duration) / 10000) / 2;  

  Serial.println(distance);   
}  

이 초음파센서 하나로 어떤곳에 사용하면 좋을까요 한번 상상의 나래를 펼쳐보세요. 초음파센서가 거리를 측정할 수 있는 재밌는 부품이여서 거리를 측정할 수 있으면 할 수 있는 것들이 참 많습니다. 한번 생각해 보세요.


댓글()

[아두이노] 곰세마리멜로디(피에조부저)

IOT/아두이노|2019. 2. 5. 14:32

[아두이노] 곰세마리멜로디(피에조부저)



1. 악보


2. 멜로디 배열변수 만들기

음계+음길이

위의 악보에서 음계랑 음길이를 메모장에서 간단히 표시해 보자.

도도도도도
4 8 8 4 4
미솔솔미도
4 8 8 4 4
솔솔미솔솔미
8 8 4 8 8 4
도도도
4 4 2

솔솔미도
4 4 4 4 
솔솔솔
4 4 2
솔솔미도
4 4 4 4 
솔솔솔
4 4 2

솔솔미도
4 4 4 4
솔솔솔라솔
8 8 8 8 2
도솔도솔
4 4 4 4
미레도
4 4 2

5옥타브음계

5옥타브 음계 도레미파솔라시도 이것만 이용 합니다.

5옥타브 음계에서 벗어난 음계를 사용할 경우 위 사이트 가셔서 다른 옥타브 음계를 참조하셔서 사용하시면 됩니다. 귀찮은 분들은 전음계를 다 복사해와서 만드셔도 됩니다.

#define NOTE_C5  523   //도
#define NOTE_D5  587   //레
#define NOTE_E5  659   //미
#define NOTE_F5  698   //파
#define NOTE_G5  784   //솔
#define NOTE_A5  880   //라
#define NOTE_B5  988   //시
#define NOTE_C6  1047  //도

멜로디배열변수

계이름을 매크로변수(#define) 이름으로 배열변수에 저장하시면 됩니다. 그냥 도를 523으로 저장해도 되지만 이름으로 표현하시면 음계를 쉽게 구별할 수 있기 때문에 숫자보다는 변수 이름으로 만들어서 코딩하는걸 추천 드려요.

int melody[] = {
NOTE_C5,NOTE_C5,NOTE_C5,NOTE_C5,NOTE_C5,               //도도도도도
NOTE_E5,NOTE_G5,NOTE_G5,NOTE_E5,NOTE_C5,               //미솔솔미도
NOTE_G5,NOTE_G5,NOTE_E5,NOTE_G5,NOTE_G5,NOTE_E5,       //솔솔미솔솔미
NOTE_C5,NOTE_C5,NOTE_C5,                               //도도도
NOTE_G5,NOTE_G5,NOTE_E5,NOTE_C5,                       //솔솔미도
NOTE_G5,NOTE_G5,NOTE_G5,                               //솔솔솔
NOTE_G5,NOTE_G5,NOTE_E5,NOTE_C5,                       //솔솔미도
NOTE_G5,NOTE_G5,NOTE_G5,                               //솔솔솔
NOTE_G5,NOTE_G5,NOTE_E5,NOTE_C5,                       //솔솔미도
NOTE_G5,NOTE_G5,NOTE_G5,NOTE_A5,NOTE_G5,               //솔솔솔라솔
NOTE_C6,NOTE_G5,NOTE_C6,NOTE_G5,                       //도솔도솔
NOTE_E5,NOTE_D5,NOTE_C5                                //미레도
};

멜로디음길이배열변수

각 음계의 음길이가 각기 다르기 때문에 4분음표, 8분음표, 2분음표 등의 박자길이를 숫자로 해서 멜로디음길이배열변수를 만들어서 순차적으로 음계랑 음길이를 나중에 코딩에서 합쳐서 음을 만들어 내기 위해서 배열변수로 해서 음계과 음길이를 따로 만듭니다.

int noteDurations[]={
4,8,8,4,4,
4,8,8,4,4,
8,8,4,8,8,4,
4,4,2,
4,4,4,4,
4,4,2,
4,4,4,4,
4,4,2,
4,4,4,4,
8,8,8,8,2,
4,4,4,4,
4,4,2
};

3. 회로도 구성


준비물 : 피에조부저 1개, 아두이노우노


지난 시간의 회로도와 동일합니다.


4. 코딩


지난 시간의 코딩에서 2번의 멜로디를 만든 배열변수를 추가를 하여 약간 코딩을 변경하시면 됩니다.

#define NOTE_C5  523    //도
#define NOTE_D5  587    //레
#define NOTE_E5  659    //미
#define NOTE_F5  698    //파
#define NOTE_G5  784   //솔
#define NOTE_A5  880   //라
#define NOTE_B5  988   //시
#define NOTE_C6  1047 //도


int tonepin = 12;


int melody[] = {
NOTE_C5,NOTE_C5,NOTE_C5,NOTE_C5,NOTE_C5,
NOTE_E5,NOTE_G5,NOTE_G5,NOTE_E5,NOTE_C5,
NOTE_G5,NOTE_G5,NOTE_E5,NOTE_G5,NOTE_G5,NOTE_E5,
NOTE_C5,NOTE_C5,NOTE_C5,

NOTE_G5,NOTE_G5,NOTE_E5,NOTE_C5,
NOTE_G5,NOTE_G5,NOTE_G5,
NOTE_G5,NOTE_G5,NOTE_E5,NOTE_C5,
NOTE_G5,NOTE_G5,NOTE_G5,

NOTE_G5,NOTE_G5,NOTE_E5,NOTE_C5,
NOTE_G5,NOTE_G5,NOTE_G5,NOTE_A5,NOTE_G5,
NOTE_C6,NOTE_G5,NOTE_C6,NOTE_G5,
NOTE_E5,NOTE_D5,NOTE_C5
};

int noteDurations[]={
4,8,8,4,4,
4,8,8,4,4,
8,8,4,8,8,4,
4,4,2,
4,4,4,4,
4,4,2,
4,4,4,4,
4,4,2,
4,4,4,4,
8,8,8,8,2,
4,4,4,4,
4,4,2
};


void setup() { 
} 
void loop() {
  for (int i = 0; i < 49; i++) {
    
    int Durations = 1000/noteDurations[i];    // 음계의 음길이 계산
    tone(tonepin, melody[i], Durations);    
    int pauseBetweenNotes = Durations *1.3 ;
    delay(pauseBetweenNotes);
    noTone(tonepin);
  }

}

이번에는 loop()에 반복수행하도록 한번 표현해봤습니다.

int Durations = 1000/noteDurations[i];    // 음계의 음길이 계산

음의 출력이 melody[i], noteDurations[i]로 매칭되어 음이 나오게 됩니다.

음길이 계산식이 원래 고정 1000/4여서 외부에 변수로 표현했지만 실제 곰세마리악보에서 보듯이 음길이가 다르기 때문에 melody[i], noteDurations[i]를 맞추기 위해서 for문 안에다 표현을 하였습니다.

그리고 보기 좋게 하기 위해서 따로 Durations로 변수를 만들어서 i번째 음길이를 가져와서 음길이를 계산한 표현을 하였습니다. 물론 tone(tonepin, melody[i], 1000/noteDurations[i])으로 표현해도 되겠지만 코딩은 각각 구분짓고 경계를 나누어 코딩하는게 시각적 가독성이 좋습니다. 그래서 일부로 이건 음길이 계산이다라고 별도로 한줄로 표현한 것이죠.

나머지 코딩부분은 이전 시간의 코딩과 동일합니다. 다른점은 멜로디 음계와 음길이를 별도로 배열변수에 저장했다는 것이죠.

5. 결과

실제로 회로도 구성이 쉬워서

라즈베리파에 설치한 아두이노 IDE 을 통해 바로 아두이노에 프로그램을 이식했습니다.


문제는 동영상 촬영했는데 소리는 원래 크게 들렸는데 녹화시 너무 작게 소리가 들어가서 실제 실험동영상은 올리는 것을 포기 했고 사진만 올립니다.

마무리


사실 tone(), noTone(), delay() 세함수를 제어하는 것일 뿐 별다른게 없습니다. 물론 음길이 공식이 1000/noteDurations와 Durations*1.3 으로 딜레이 시간을 준 공식을 추가된 것은 있지만 함수는 3개뿐이 사용 안했고 응용도 저 세개 함수만 사용한 실험이였습니다.

단지 멜로디를 만들기 위해서 배열변수로 코딩량만 늘어났을 뿐이죠. 코딩량은 늘어났지만 사실 멜로리 코딩은 위 악보에서 음계와 음길이를 추출하는 것은 쉽기 때문에 거기서 실제 배열변수로 만드는것은 어렵지 않게 2번 내용을 보시면 하실 수 있을거라고 생각됩니다.

예전에 자전거 멜로디를 만들어서 실험했지만 최근 음악 관련 포스팅을 할때 곰세마리악보를 이용해서 이번 아두이노에서도 곰세마리악보를 이용해 멜로디를 만들어 봤네요.

한번 다른 악보를 보고 멜로디를 만들어보세요.


댓글()

[아두이노] 피에조부저 제어

IOT/아두이노|2019. 2. 4. 14:54

[아두이노] 피에조부저 제어



1. 회로도 구성


  • 준비물 : 피에조부조 1개, 아두이노우노
  • 내용 : 12번 핀을 주파수 출력핀으로 사용하여 멜로디를 만들어 보자.

회로 구성은 보는것과 같이 간단하다.



2. 코딩


  • 출처 : https://www.arduino.cc/en/Tutorial/toneMelody
  • 함수 : tone(핀번호, 주파수, 출력시간), noTone(핀번호), delay(시간값)
  • 내용 : 주파수 값은 해당 사이트에서 제공되는 값으로 도레미파솔라시도 출력해보자.

#define NOTE_C5  523   //도 (5옥타브 음계 데이터)
#define NOTE_D5  587   //레
#define NOTE_E5  659   //미
#define NOTE_F5  698   //파
#define NOTE_G5  784   //솔
#define NOTE_A5  880   //라
#define NOTE_B5  988   //시
#define NOTE_C6  1047 //도

int tonepin = 12;
int melody[] = { NOTE_C5, NOTE_D5, NOTE_E5, NOTE_F5, NOTE_G5, NOTE_A5, NOTE_B5, NOTE_C6 }; //도레미파솔라시도
int noteDurations = 1000 / 4; //톤길이(4분음표)

void setup() {
  for (int i = 0; i < 8; i++) {
    tone(tonepin, melody[i], noteDurations);
    int pauseBetweenNotes = noteDurations * 1.30;
    delay(pauseBetweenNotes);
    noTone(tonepin);
  }
}
void loop() {
}

첫번째 :
#define은 매크로 변수로 NOTE_C5란 변수명은 523이란 숫자를 지칭한다. 매크로상수라고만 이해하시면 된다. 523의 별명으로 NOTE_C5라고 불리운다라고 생각하면 될듯요. 각 주파수 값을 숫자로 이게 도인지 솔일지 모르잖아요. 그걸 별명으로 이름을 지어주는 거라고 생각하시면 됩니다.

두번째 :
setup()함수에 로직을 짠 이유는 loop()함수에다가 코딩해도 됩니다. 그런데 멜로디를 무한 반복해서 듣는건 좀 그래서 처음 한번만 수행하는 setup()함수에 1번만 멜로디를 듣도로 실험하기 위해서 setup()에 코딩했습니다. setup()에 코딩해야하는건 아니고 그냥 1회만 멜로디 출력시키기 위해서 이쪽에다 코딩했을뿐 의미가 있는건 아닙니다.

세번째 :
tone()과 notone()은 확실히 음과 음사이를 끊어주기 위한 것으로 하나의 음계의 소리가 귀로 들을때 들리는 음의 구별하기 위해서 처음과 끝을 나타내는 위치로 생각하시면 됩니다.
그리고 그 사이 delay() 함수의 길이가 1.3배함으로 음과 음의소리가 음과 음의길이사이의 딜레이가 발생시키게 합니다. 이걸 구별해서 이해하실려면 1.3대신에 더 큰 숫자를 넣고 돌려보세요. 음을 실제로 들어보면 왜 delay()함수를 넣은지 이해가 되실꺼에요.

melody[] 변수는 배열변수로 하나의 이름으로 여러개의 저장소를 갖는데 int melody[8]로 선언되면 8개의 그릇을 갖게 됩니다. 각 그릇은 다른 값을 저장이 가능합니다. 배열변수는 안에 숫자로 위치를 나타냅니다.
가령 melody[0]=523 , melody[1]=587, .... 이렇게 각 그릇해 주파수 값을 저장되어 있는 것이죠.

for문으로 0~7까지 루프를 돌잖아요.

tone(tonepin, melody[0], noteDurations);

이것은

tone(12, 523, 1000/4);

되는 것이죠.

하나의 음계의 동작은 도라는 음계를 4분음표이고 그걸 피에조부조로 들리게 한다면 아래와 같이 수행되게 됩니다.

tone(핀번호, 523, 1000/4); //도 4분음표
int pauseBetweenNotes = (1000/4) * 1.30; //4분음표 딜레이시간
delay(pauseBetweenNotes);
noTone(핀번호); 

여기서 도레미파솔라시도 총 8번 반복 수행해서 각 melody[i]값이 음계가 출력되는 것이죠.

3. 결과


마무리


오늘은 tone(), noTone()의 함수에 대해 배웠습니다. 이걸 통해서 피에조부저를 통해 멜로디를 만들었습니다.
그러면 한번 곰세마리를 악보를 보고 멜로디를 만들어 보세요.

참고할것은 여기서, 도레미파솔라시도는 4분음표로 고정해서 멜로디를 만들었습니다.
하지만 모든 음악이 4분음표만 있는게 아니죠.

힌트는,
1000/4은 4분음표면 1000/8은 8분음표겠죠. 1000/2은 2분음표이고요.
도레미파솔라시도의 4분음표일때
int noteDurations[]={4,4,4,4,4,4,4,4}; 이렇게 하면 음표 배열을 만들어지겠죠.
Durations=1000/noteDurations[i]으로 하면 해당 음계에 음표를 만들 수 있겠죠.

한번 곰세마리를 만들어 보세요.
내일 곰세마리 멜로디를 올리도 할께요.


댓글()

[아두이노] 스위치 버턴 제어

IOT/아두이노|2019. 2. 3. 10:51


[아두이노] 스위치 버턴 제어




스위치를 누르면 스위치 내부의 선이 연결되어 전류가 공급되고 LED가 켜지게 된다. 이걸 아두이노에서 제어해보도록 하자.

기본 동작



1. 회로도 구성 (풀업, 풀다운)


  • 준비물 : led 1개, 저항 220옴 1개, 10k옴 1개, 스위치 1개, 뻥판, 아두이노우노
  • 내용 : 스위치를 누르면 led의 불이 들어오게 한다.

풀업풀다운
회로도



풀업과 풀다운의 상태 값을 알아야 한다. 내부적인 전류 흐름을 이해해야 하지만 스위치 배치가 풀업과 풀다운으로 상태로만 처음 구별만 하자.
풀업은 전류가 공급되는데 스위치 버턴을 누르지 않은 상태면 7번으로 입력값이 1이 된다. 하지만 스위치를 누르면 전류가 gnd로 낮은 곳으로 흐르기 때문에 7번핀은 입력값이 0이 된다. 풀다운 반대로 스위치를 누르지 않은 상태에서는 전류가 흐르지 않기 때문에 7번핀의 입력값은 0이 되고 스위치를 누르면 전류가 흐르기 때문에 1의 값을 갖게 된다.

그럼 코딩은 살펴보도록 하자.

2. 코딩


void setup()
{
  pinMode(13, OUTPUT);
  pinMode(7, INPUT);
}

void loop()
{
  digitalWrite(13, digitalRead(7));  
}

첫번째 :
led를 켜기 위해서 pinMode()함수로 13번핀을 출력모드로 우선 선언하였다. 그리고 스위치 버턴을 눌렀을때 그 값을 입력을 받기 위해서 7번핀을 입력모드로 선언하였다. OUTPUT 전류를 밖으로 출력하는 것이고 INPUT은 전류를 안으로 입력받는 것이다. OUTPUT/INPUT만 구분하여 이해하면 된다.

두번째 :
led 켜기 위해서 digitalWrite(출력핀, HIGH/LOW)로 불이 들어오게 한다. 이건 지난 시간에 반복해서 실험한 함수이다.
그러면 입력받는것은 digitalRead(7)함수이다. 출력은 Wirte이고 입력은 Read란 단어만 숙지하면 된다.
digitalRead(7)은 7번핀을 전기신호를 입력받겠다는 의미로 이해하시면된다. 그리고 7핀에 들어온 값이 반환값으로 나오게 된다.

쉽게 말해서 임의의 stat변수 그릇이 있다면

state = digitalRead(7);

이러면 7번핀의 입력값이 1 or 0 값중 하나를 반환한다. 가령 전류가 흘러 입력값이 1이 된다면 이 함수를 통해 1이 반환되어서 state=1 이 된다.

풀업 회로도라면
초기 상태는 스위치가 누르기 전 상태는 digitalRead(7)은 1이 되고 digitalWrite(13,1)로 출력되어 led가 켜져있는 상태가 된다.누르면 0이 되어 led가 꺼진다.

풀다운 회로도라면
초기 상태는 스위치가 누르기 전 상태는 digitalRead(7)은 0이 되고 digitalWrite(13,0)로 출력되어 led가 꺼져있는 상태가 된다.누르면 1이 되어 led가 켜진다.

둘의 원리만 이해하면 된다.

3. 저항없이 풀업스위치 회로도 구성



저항이 없을때 INPUT_PULLUP모드로 내부 풀업 저항을 사용하기 위한 배치도 이다.

4. 저항없이 풀업스위치의 코딩

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(7, INPUT_PULLUP);
}

void loop()
{
  digitalWrite(13, digitalRead(7));  
}

PinMode에서 OUTPUT/INPUT 모드 외에 INPUT_PULLUP모드가 있다. 이건 내부 풀업 저항을 사용하겠다는 건데 그냥 저항없이 입력모드로 사용하겠다고 간단히 이해만 하자.

모드만 INPUT_PULLUP만 이해 하면 된다.

5. 고민해야할 것

스위치를 누르면 불이 들어와야 풀업모드를 사용하면 위 코딩에서는 불이 먼저 들어오는게 불편함을 느껴야 합니다.
풀다운으로 해야하는게 아닌가라고요. 사실 풀업을 사용하는 이유는 아두이노 칩 자체가 전류가 공급되면 각 핀에서 소량의 전류가 흐르게 됩니다. 쉽게 말해서 노이즈로 생각하면 될꺼에요. 풀업모드가 이 문제점에 좋다고 하네요. 그래서 스위치 관련 아두이노 소스들을 찾아보시면 거의 다 풀업모드를 사용하더군요.

그런데 중요한것은 스위치를 누르면 불이 들어와야지 하겠죠. 위 코딩은 원리를 이해하기 위한 목적으로 코드를 최소한 한것이고요. 코드를 변경해야겠죠. 즉, 7번의 값으로 led 불이 들어오는 상태를 결정하는 건 동일하지만 누를때 우리가 생각하는 개념으로 불이 들어오게 하기 위해서 하나의 C문법을 배우도록 하죠.

C문법

if(조건문){
  처리문1;
}
else{
  처리문2;
}

예)

if(k>10){
     printf("k가 10보다 크다!\n");
}
else {
     printf("k가 10보다 크다!\n");
}

k가 10보다 크면 처리문1이 수행되고 k가 10보다 작으면 처리문2가 수행됩니다. 참일때 if문의 처리문1이 거짓일때 else의 처리문2가 수행됩니다. 한줄의 코딩일때는 괄호 생략이 가능함.

f(k>10) printf("k가 10보다 크다!\n");
else printf("k가 10보다 크다!\n");

그냥 else 문을 생략가능함

if(k>10) printf("k가 10보다 크다!\n");

k가 10보다 크면 printf문을 수행하고 크지 않으면 if문을 빠져 나온다.

다중 if문은

if(조건1) 처리문1;
elseif(조건2) 처리문2;
else 처리문3;

첫번째 조건1이 참이면 처리문1을 수행하고 끝나지만 조건1이 거짓이면 조건2로 넘어가서 참이면 처리문2를 수행하고 끝나고 거짓이면 else 처리문3문을 수행하고 끝난다. 한줄일때는 괄호를 생략했지만 처리문이 여러 명령문일때는 괄호로 묶어야 한다. 이점만 주의하면 if문을 사용하는데 어려움이 없다.

코딩

int state = digitalRead(7);
if(state ==1) digitalWrite(13, LOW);  
else digitalWrite(13, LOW);  

7번 핀의 초기값이 스위치 누르기 전 값은 1이기 때문에 state 그릇에 1의 값이 저장된다. 조건문에서 스위치를 누르기 전이니깐 led은 LOW가 되어야겠죠. 스위치를 누르면 7번핀은 0이 되고 state = 0으로 조건문은 거짓으로 led은 HIGH가 되면 되겠죠.

원리를 이해하시면 코딩이 바로 안되면 글로써 문장을 만들어보세요.

  1. 스위치를 누르지 않은 상태가 1이니깐 우선 그 값을 변수로 정해서 담아둬야지
  2. state변수가 초기 1의 값이니깐 조건문을 써서 led 불을 꺼진 상태로 둬야지 state==1일때 led 꺼져있어야겠지.
  3. state==0이면 스위치가 눌러지니깐 led 켜야겠지

이걸 문장을 코드로 바꾸시면 되겠죠. 2, 3번은 꼭 if(state==1)을 안해도 됩니다. if(state==0)을 해도 되겠죠. 그러면 명령어 처리문은 반대가 되겠죠.

코딩은 표현하고 싶은데로 자연스럽게 표현 하시면 됩니다.

6. 결과



마무리


간단히 INPUT_PULLUP 모드를 이용한 스위치 버턴 제어를 해 보았습니다.
사실 Led 관련 응용 예제를 오늘 거론하고 싶었지만 약간 프로그램코딩에 치우치는 경향도 있고 둘이상의 부품의 조합을 하는 것들이라서 나중에 거론할까 합니다.
우선은 하나하나의 부품 제어를 통해 부품을 이해하는게 더 중요하다고 생각되어 당분간 부품 제어에 초점을 맞추겠스니다.


'IOT > 아두이노' 카테고리의 다른 글

[아두이노] 곰세마리멜로디(피에조부저)  (0) 2019.02.05
[아두이노] 피에조부저 제어  (0) 2019.02.04
[아두이노] 3색 LED 제어  (0) 2019.02.02
[아두이노] 코딩 구조  (0) 2019.01.31
[아두이노] LED 제어  (0) 2019.01.30

댓글()

Fritzing 회로도 디자인

유용한팁|2019. 2. 3. 10:47

Fritzing 회로도 디자인



오늘은 회로도를 그리는 사이트를 하나 소개하도록 하겠습니다. 아두이노를 어느정도 공부하셨던 분이라면 이 사이트를 아마도 알고 계시거나 사용하고 있으시겠죠. 아두이노를 배운지 얼마 안되신 분들을 위해서 소개합니다. 사실 다음 실험에 사용될 부품이 가상시뮬레이터에서는 제공되지 않는 부품이라서 어쩔 수 없이 Fritzing으로 디자인 하게 되었네요. 그래서 바로 사용하는 것보다 이런 소프트웨어가 있다는 것을 미리 설명하는게 좋을 것 같아서 포스팅을 하게 되었습니다. 그러면 Fritzing에 대해 살펴보도록 하죠.

1. Fritzing 소프트웨어 다운로드


상단에 공식홈페이지를 링크를 걸어 놓았습니다. 거기로 들어가시면 아래와 같은 홈페이지가 열립니다.

여기서 다운로드를 누르시면 다운로드 페이지로 넘어 갑니다.

여기서, 'No Donation' 클릭하시고 다운로드를 클릭하시면 됩니다. 이 창은 무료로 소프트웨어를 제공하는데 비영리사이트라서 후원이 필요한 부분인데 후원을 하실분들은 금액을 누르고 다운로드 하시면 되고 그렇지 않는 분들은 'No Donation'를 눌러서 받으셔도 됩니다.

참고로 설치 소프트웨어가 아니라 무설치 실행 소프트웨어입니다. 소프트웨어는 압축형태로 제공되며 압축을 플고 바로 실행하시면 됩니다.

2. Fritzing 실행


실행 첫 페이지는 Welcom항목 페이지가 열려 있는데 브레드보드로 눌러주시면 위와 같은 창으로 보이게 됩니다. 가상시뮬레이터랑 사용법은 동일합니다. 사용할 부품을 드래그를 통해 이뤄집니다. 가상시뮬레이터에서 제공되지 않는 다양한 부품들을 제공하기 때문에 디자인할 때 꽤 유용한 프로그램입니다.

아두이노 쇼핑몰 같은 곳에서 부품들을 판매할 때 다자인 그림을 많이 활용 사용합니다. 그만큼 유용한 프로그램이라는 소리인 거죠.

사용법은 가상시뮬레이터에서 부품을 드래그 하고 배치하는 것은 동일하지만 차이점은 선을 연결할 때 좀 다릅니다. 가상시뮬레이터는 꺽이는 지점에서 한번 쉬고 다시 그 지점에서 다시 이동하는데 Fritzing 은 시작점과 끝나는 점을 먼저 연결한 뒤에 꺽을 지점을 마우스로 클릭해서 드래그하면 선이 꺽이게 됩니다.

아래 그림처럼 꺽을 지점에서 클릭한 상태로 아래로 마우스를 드래그 하면 클릭한 위치의 선이 꺽이게 됩니다

처음에는 가상시뮬레이터의 선 연결과 Fritzing의 선연결하고 살짝 혼동이 올 수 있는데 그렇게 어렵지 않습니다. 몇번 연습하시다보면 자연스럽게 사용할 수 있을 꺼에요.

3. Fritzing을 외부 부품 가져오기


Fritzing은 설치하면 모든 부품을 제공하지는 않습니다. 많은 부품을 제공하기는 하지만 그렇다고 해서 모든 부품을 다운받은 프로그램 안에는 없습니다. 기본 부품들만 제공 되니깐요.

여기서, 없는 부품은 디자인을 포기해야 할까요. 그렇지 않습니다. 많은 오프라인 Fritzing 족들이 github에 공개하고 있습니다. 우리는 검색을 통해서 해당 부품이 있는 github 주소로 찾아가서 다운로드를 받고 그걸 여러분들이 사용하는 Fritzing에 import 시키면 됩니다.

1) 부품 검색법

대충 어떤 느낌으로 검색하면 되겠죠.



2) 부품 가져오기

아래 그림에서 CORE Parts에 세모 모양의 클릭이 있을 꺼에요 그걸 클릭하시면 "Import ..." 있는데 다운로드 받은 것을 Import 폴더로 옮겨서 여기서 여시면 부품은 부품 목록이 있는 곳으로 옮겨지게 됩니다. 아니면 부품 목록에서 마우스 커서를 위치하고 마우스 오른쪽 버턴을 누르면 창이 나타납니다 클릭을 하시든 마우스 오른쪽 버턴을 누르든 편하신 방식을 선택하시면 됩니다.

3) 부품 확인

정상적으로 부품을 가져왔네요. 외부 부품을 가져온게 MINE항목의 My Parts에 해당조이스틱 부품이 등록되어 있습니다.

이 부품을 배치하고 선을 연결하면 회로도를 완성 할 수 있겠죠.

마무리


Fritzing 소프트웨어에 대해서 간단히 살펴 보았습니다. 다음 포스트 내용이 조이스틱이라서 가상 시뮬레이터에서 제공되지 않는 부품이라 그림으로 표현하기 참 애매해서 Fritzing을 사용하였습니다. 바로 쓰기에 앞서 간단히 Fritzing을 소개하는게 좋을 것 같아서 오늘의 포스팅 주제로 결정 했네요.

한번 다운로드 받으셔서 간단히 사용을 해보셨으면 합니다.

은근 회로도 표현 디자인이 재미가 있습니다. 그리고 PCB모드도 있고 코드창도 있어 나중에 아두이노로 어떤 것을 만들었는데 한번에 디자인과 코드를 해놓고 파일 형태로 보관해 놓으시면 아주 유용하겠죠. 필요할 때 꺼내 쓸 수 있으니깐요. 디자인도 없는 부품은 외부에서 오픈 디자인 파일을 가져다가 디자인도 할 수 있으니깐요. 가상시뮬레이터면 없는 부품은 해당 부품의 사진을 가져다가 포토샵같은 곳에서 그려야 하는데 Fritzing은 그럴 필요가 없다는 것이 정말 좋은 것 같아요.

아두이노로 뭘 표현하고 정리용으로 Fritzing에서 마무리 표현을 하시면 보관용으로 사용하기 좋은 소프트웨어겠죠.

댓글()

[아두이노] 3색 LED 제어

IOT/아두이노|2019. 2. 2. 12:34

[아두이노] 3색 LED 제어




이번 시간에는 3색 Led를 제어하는 시간입니다. 한개의 3색 led를 어떻게 RGB 색으로 나타내는지 실험하도록 하죠.

1. 회로도 구성


  • 구성 : 3색LED 1개, 저항 220옴 3개, 뻥판, 아두이노우노

3색 LED의 각 꼭지점에 마우스를 대면 red, green, blue란 단어가 보여진다. 각각 보기 편하게 전선을 각 색상선으로 바꿔 준다. 저항은 클릭한 뒤에 Ctrl+C로 복사 한 뒤에 원하는 위치에 마우스 대고 Ctrl+V하면 복제가 된다.

그리고 두번째 검정색선(Gnd)로 연결하면 회로도 구성은 끝난다. 그런데 실제 부품은 제품 정보를 보시고 색선을 구별하셔야 합니다.

2. 코딩


  • 함수 : pinMode(핀번호,모드), analogWrite(핀번호, 색값), delay(시간값)
  • 코딩 내용 : R->G->B로 3색을 순차적으로 간단히 출력하는 로직을 짜본다.

int rpin=11;
int gpin=9;
int bpin=10;

void setup()
{
  pinMode(rpin, OUTPUT);
  pinMode(gpin, OUTPUT);
  pinMode(bpin, OUTPUT);
}

void loop()
{
  analogWrite(rpin, 255);
  analogWrite(gpin, 0);
  analogWrite(bpin, 0);
  delay(1000);
  
  analogWrite(rpin, 0);
  analogWrite(gpin, 255);
  analogWrite(bpin, 0);
  delay(1000);
  
  analogWrite(rpin, 0);
  analogWrite(gpin, 0);
  analogWrite(bpin, 255);
  delay(1000);  
}

첫번째 :
변수 선언에서 int은 자료형으로 변수의 그릇의 크기를 나타낸다. rpin, gpin, bpin으로 3개의 변수를 선언하고 그 변수 그릇에 각각 해당핀 값을 저장시켜 놓는다.

두번째 :
setup()함수는 초기화 작업 코딩하는 부분으로 11, 10, 9핀을 OUTPUT(출력모드)로 아두이노에서 외부로 전류를 보내는 출력모드로 사용하겠다는 것이다.
여기서, 주의할 것은 사용된 핀이 다른 디지털핀과 다르다는 것이다. 0~13번 디지털 핀 중에 6개의 핀은 앞에 (~)에 붙은 핀들이 있는데 아두이노우노 보드를 보면 표시 되어 있다. 이것은 아날로그값을 출력으로 내보낼 수 있는 핀이다. 즉 0~255의 전류로 신호를 출력할 수 있는 특수한 핀이다. 실제 아날로그 값이 나가는게 아니라 아날로그 값이 나가는 것처럼 느낌의 전류 신호를 제어해서 내보낼 수 있는 핀으로 생각하면 된다.
3개의 RGB 핀은 각각 0~255의 값의 범위로 해서 다양한 색상을 만들어 낼 수 있다.

3번째 :
loop()함수에서 기존의 digitalWirte(rpin,100)하면 안된다. 디지털출력은 0과 1의 값만 OV와 5V만 존재한다. 즉, 0이 아닌 값은 무조건 5V의 전류가 흐르게 된다. 그렇게 되면 다양한 색을 만들어 낼 수 없다. (~핀)을 사용하기 위해서는 analogWrite(rpin,100)을 해야 합니다. 0~255사이의 전기신호를 보내기 위한 함수 이고 이 함수를 통해서 아날로그 100의 값의 전기신호를 내보내게 된다. 그래서 RGB Led은 rpin을 통해서 100이란 전기신호값의 색밝기로 보여지게 된다.
여기서는 1초 단위로 max 값 255로 R->G->B로 색이 나오도록 출력한 코딩입니다.

rpin을 255의 전기신호를 보내고 gpin, bpin은 0의 전기신호를 보내면 자동으로 Red 색이 출력되겠죠. 함수의 의미만 잘 이해하시면 다양한 색으로 출력이 가능합니다.

3. 고민해야 할 것


여기서 고민을 해야 합니다. 색을 만들기 위해서 analogWrite()함수가 세번 loop()함수에 표현을 해야하는게 불편함을 느껴야 합니다.
여러가지 색을 표현하고자 한다면 매번 3개의 함수를 loop()함수 안에서 코딩으로 표현하는 것은 엄청 비효율적이지요. 그래서 C언어 문법 하나를 배우도록 하죠.

C언어 문법


  • 문법 : 외부사용자함수()

외부사용자함수란 프로그래머가 직접 함수를 만드는 것이죠. 특정 중복되는 동작을 함수로 묶어서 그 함수를 호출하여 해당 동작을 수행할 수 있게 만들 수 있습니다. 즉, pinMode(인자1, 인자2); 이렇게 함수에 2개의 인자값을 넣어서 pinMode()함수 동작을 수행되는데 이런식으로 직접 프로그래머가 함수를 만들어서 RGB 인자값을 넣어서 색을 출력하는 함수를 만들면 간단한 코딩이 되겠죠.
3개의 analogWrite()함수로 RGB led의 색이 결정되는 원리를 배웠습니다. 그러면 이 원리를 이용해서 하나의 새로운 함수를 만들어 보죠.

void Color(int red, int green, int blue)
{
  analogWrite(rpin, red);
  analogWrite(gpin, green);
  analogWrite(bpin, blue); 
}

이렇게 Color라는 함수를 만들면 이 함수를 표현하여 RGB 색을 출력할 수 있게 됩니다. loop()함수 안에다 아래와 같은 방식으로 코딩하면 좀 더 깔끔한 코딩이 되겠죠. 여기서 인자값 (255,0,0)은 (red,green,blue)라는 변수에 저장되게 됩니다. 그 값이 3개의 analogWrite()함수에 각각 인자값이 대입하여 전기 신호를 출력하게 되는 것이죠. 간단한 원리죠.

Color(255,0,0);
delay(1000);
Color(0,255,0);
delay(1000);
Color(0,0,255);
delay(1000);

또, 고민을 해보세요. 지난 시간의 for()문을 이해 했다면 for()문을을 이용해서 RGB의 각 값을 순차적으로 변화시켜서 여러가지의 색을 만들어 볼 수 도 있겠죠.

웹언어를 공부하신분이라면 색을 나타날때 아래 예처럼 16진수로 각각 두자리가 RGB로 3개의 색을 나타내는 것을 알고 있을 겁니다.

예) #ff0000(red), #00ff00(green), #0000ff(blue)

참고 자료를 보시면 색을 좀 더 자세히 나눌 수 있겠죠.
각각 00~ff의 16진수 범위를 10진수 0~255로 색의 범위를 잡아서 색을 정하면 되겠죠.

4. 결과






마무리


RGB led를 한개를 제어해 봤습니다. 이전 led 제어 코딩에서 analogWrite()라는 함수를 새롭게 한개 배웠습니다.
이 함수로 하나의 RGB Led에 원하는 색으로 표현할 수 있게 된 거죠.
그러면 이것을 현실에서 이용하는 것들이 무엇일까요?
가장 가까운것은 현재 당신이 보는 스마트폰이나 pc 모니터를 생각하시면 됩니다. 쉽게 bmp 이미지 파일을 생각하는게 더 이해가 쉬울지 모르겠군요. bmp 이미지 파일은 픽셀단위로 해서 각 픽셀당 RGB색값이 할당 되고 이게 합쳐져서 이미지로 보여줍니다. RGB led 한개를 하나의 픽셀로 생각해 보세요. 수많은 RGB led를 각각 픽셀로 색의 값으로 밝혀진다면 이걸 다 연결하면 하나의 이미지 처럼 픽셀 이미지가 완성 되겠죠.
대충 어떤 느낌이신지 아시겠지요. 실험에 사용한 RGB led은 집중된 밝기가 아니고 분산된 밝기여서 사실상 이미지화 한다는 것이 무척 어렵지만 특수 led의 경우는 가능하겠죠.
네오 픽셀이라는 RGB 색을 만들어 내는 부품이 있습니다. 이걸로 실제 모니터로 구현한 외국인분들도 있습니다.
유사 표현으로는 주변 전광판을 생각하시면 되겠죠.

그리고 상상을 해보세요. RGB led은 3색을 섞어서 다양한 색을 만들어 낼 수 있습니다. 그러면 이걸로 뭘 할 수 있을까 끊임없이 상상해보세요. 0~255까지의 값의 색을 지정할 수 있다. 그러면 센서를 이용해서 그 센서의 값에 따라 밝기를 나타낸다면 뭔가 시각적인 데이터 표현이 가능하겠죠. 그러면 이걸 어떤부품과 연결해서 표현하면 좋을지 상상을 더해 보세요.

원한 하나의 부품을 사용하고 그 원리를 이해하면 단순히 거기서 끝나면 안됩니다.
그 부품이 다른 부품만 결합하면 또 다른 시너지 효과를 발휘 할 수 있으며 또 그 부품의 원리를 잘 이해하면 그 자체의 기능만으로 재밌는 표현이 가능하게 됩니다.

단순히 한개의 RGB를 제어했지만 이걸 어떻게 제어 하느냐에 따라서 표현하고자 하는 목적에 따라 당신이 생각하는 그 이상의 표현을 할 수 있으며 그런 표현들을 현실에서 아두이노를 다루는 분들이 작품으로 만들고 있습니다.
현재의 여러분들이 이걸 통해서 어떤 상상을 하느냐에 따라서 그 가치가 달라지는 점을 유념하세요.

끊임없이 의문을 갖고 생각을 통해 많은것들을 표현하길 바래요.
다음은 이전 시간에 led와 이번시간의 설명한 내용을 기반으로 상상할 수 있는 것들을 이야기 해보도록 하죠.


'IOT > 아두이노' 카테고리의 다른 글

[아두이노] 피에조부저 제어  (0) 2019.02.04
[아두이노] 스위치 버턴 제어  (0) 2019.02.03
[아두이노] 코딩 구조  (0) 2019.01.31
[아두이노] LED 제어  (0) 2019.01.30
아두이노의 기초  (0) 2019.01.27

댓글()

[아두이노] 코딩 구조

IOT/아두이노|2019. 1. 31. 13:46

[아두이노] 코딩 구조




void setup() {
//초기화 작업
}

void loop() {
//수행한 명령어 로직
}


setup()함수와 loop()함수로 구성되어 있는데 아두이노에 전원이 공급되면 처음 한번만 setup()함수가 수행되고 난 뒤 loop()함수가 전원이 공급되는 동안 무한 반복 호출 된다.


그래서 setup()함수에는 한번만 수행할 명령 코드를 이곳에다 표현하고 계속 반복되는 동작의 명령 코드를 loop()함수에 표현하게 된다.

1. 코딩 연습


  • 주제 : 아두이노에서 LED를 깜박이게 하고자 한다.
  • 명령어 : pinMode(), digitalWrite(), delay()함수

원래는 회로를 먼저 설계한 뒤에 설계한 회로가 원하는 동작을 수행하도록 코딩을 그 다음에 한다. 하지만 여기서는 코딩을 연습하는게 목적임으로 코딩하는 법을 먼저 배워보자.

세개의 함수에 대해서 간단히 이해하자.
pinMode(핀번호, 모드)로 아두이노 해당 핀번호를 입력/출력 모드를 지정하는 함수이다. 즉, 해당 핀을 전류를 받는 입력모드로 쓸지 전류를 내보내는 출력모드로 쓸지를 정하는 것이다. 여기서 LED를 깜박이게 하는건 LED로 전류를 보내야 한다. 그렇기 때문에 LED와 연결된 핀을 출력모드로 지정해야 합니다.

만약 13번핀을 이용해서 LED에 전류를 공급하고 싶다면

pinMode(13,OUTPUT); 라고 표현이 됩니다. 13번 핀을 통해서 LED로 전류를 공급하겠다는 의미인거죠.

13번 핀을 출력모드로 준비상태가 되었습니다. 그러면 이제 깜박이게 한다는 것은 전류가 흐를때 LED 불은 켜지고 전류가 흐르지 않을때 LED 꺼지겠지요.
이제 전류를 보내는 명령을 써야겠지요. 13번 핀을 출력모드로 전류를 외부로 보내는 준비 상태였다면 이제 전류를 실제 공급하는 명령어를 표현해야 됩니다.

digitalWirte(13, HIGH); 라고 표현을 하게 되면, 디지털13번 핀을 HIGH로 한다는 명령어 입니다. HIGH은 매크로 상수로 고정 숫자값인데 그 값을 우리가 이해하기 쉬운 네임으로 지정한 것이죠. (HIGH=TRUE=1) 와 (LOW=FALSE=0)의 표현으로 1과 0을 매크로(#define선언 된) 네임으로 생각하시면 됩니다. 여기서 중요한게 아니라 HIGH은 1로 5V의 전류란 의미로 이해하시고 LOW은 0으로 0V의 전류라고 생각하시면 됩니다.
결론은 13번 핀에 5V의 전류를 보내라는 뜻인거죠.

1초 단위로 LED를 깜박이게 하고 싶다고 상상을 해보세요. 13번핀에 5V의 전류가 흘렀다가 1초후 0V로 전류가 안흘렀다가 다시 1초후 5V가 흐르게 하면서 이렇게 반복적인 수행을 하면 1초 단위로 LED를 깜박이게 되겠죠.

delay(1000); 함수는 1000은 1초를 나타납니다. delay=대기 1초간 대기하라는 뜻이죠. LED를 1초 단위로 깜박이고 싶다면 1초동안 켜지고 1초동안 꺼져야 겠죠. 즉, 1초동안 전원이 공급된 상태로 대기해야 한다는 뜻이죠. 그래서 이 함수를 사용하게 됩니다.

이 세개의 함수를 이제 배치를 해야합니다. setup()함수와 loop()함수에 배치해야 하는데 어떻게 해야할까요.
처음 한번만 수행하는 함수는 setup()함수에 코딩한다고 했죠. 13번이라는 핀을 전류를 밖으로 내보내는 출력모드로 사용한다고 했습니다. 그런데 매번 13번을 출력모드를 쓸거야 하고 반복할 필요가 없죠.
그래서

void setup() {
pinMode(13, OUTPUT);
}

이렇게 한번만 수행해도 되니깐 setup()함수에 넣으면 좋겠죠. 다음으로는 LED를 1초 단위로 깜박이는 하는데 한번만 깜박이는게 아니고 계속 반복해서 깜박이잖아요. 그래서 setup()함수에 넣어서 한번만 깜박일 이유가 없죠. loop()함수에서 반복해야지 1초 단위로 깜박이게 되는 것이죠. 그래서 loop()함수에 코딩하는 것이죠.

배치가 가장 중요합니다. 함수의 기능에 대해서 잘 이해하시고 나면 배치가 무난할 거에요.

void loop() {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000); 
}

코드를 자세히 보면 13번핀을 HIGH(5V)의 전류을 내보내라고 명령합니다. delay()함수로 1초동안 대기하게 됩니다. 그러면 1초동안 아두이노에서 5V의 전류가 외부로 1초동안 공급하게 됩니다. 다시 13번핀을 LOW(0V)의 전압을 내보내라고 명령합니다. 이말은 0V니 전류가 흐르지 않는 것이죠. delay()함수로 1초동안 대기하게 됩니다. 1초동안 LED에 전류가 공급 안되니 꺼져있겠죠. 반복함수이니 다시 loop() 첫문장 13번에 HIGH(5V)의 전류를 내보내는 명령을 반복 수행합니다.
결론은 1초 단위로 LED는 깜박이게 되는 것이죠.

setup()함수와 loop()함수의 사용 목적을 잘 이해하고 거기에 맞게 명령어를 잘 배치하여 로직을 설계하시면 됩니다.

13번 핀을 출력모드로 지정한 후 13번 핀에 1초동안 5V의 전류를 공급과 0V의 전류 공급을 반복하는 코딩을 해 보았습니다. 핀 모드를 지정하는 법과 디지털핀에 전류를 공급하게 하는 명령어와 대기함수만 잘 사용하면 아두이노를 이미 절반은 배웠다고 생각하시면 됩니다.

2. 회로 설계


  • 재료 : LED 1개 , 저항 220옴 1개, 아두이노보드, 뻥판


3. 결과




실제 시뮬레이터를 돌리면 빨간 LED가 1초 단위로 무한 깜박이게 됩니다.
보는 것 같이 깜박이면 정상적으로 동작된 것이죠. 여기서 유심히 보면 보드 자체에 작은 LED 전구가 깜박이는걸 보실꺼에요.
이건 13번 핀에 보드 자체가 연결되어 있는 LED라서 특이 사항은 아니고 원래 13번 핀 자체가 특정한 목적 기능을 가진 핀이라서 그걸 보드상에서 확인하기 위한 LED라서 나중에 13번을 구지 선택해서 쓸 필요 없고요. 다른 핀으로 실험하시는걸 추천 드려요.

마무리


코딩을 잘 하기 위해서는 C언어의 변수와 상수란 개념과 문법은 IF, FOR, WHILE문의 개념만 잡으시면 왠만한 표현을 자유자재로 표현이 가능합니다. 몇가지 실험을 하다보면은 자연스럽게 해당 문법을 다루다보면 이해가 가게 됩니다. 구지 프로그램언어를 모른다고 해서 코딩을 못하는게 아니고 단순히 블록처럼 함수 단위로 코드를 상상하시면 됩니다.
우리가 일기장에 일기를 쓰듯이 어떤 동작을 글로 써서 그 글에 맞게 명령어함수를 순차적으로 배치만 하시면 됩니다.
코딩은 어렵지 않고 너무 깊은 사고를 요구하지도 않으면 쉽게 상상을 코딩화 하면 됩니다.

'IOT > 아두이노' 카테고리의 다른 글

[아두이노] 스위치 버턴 제어  (0) 2019.02.03
[아두이노] 3색 LED 제어  (0) 2019.02.02
[아두이노] LED 제어  (0) 2019.01.30
아두이노의 기초  (0) 2019.01.27
아두이노 가상시뮬레이터  (0) 2019.01.24

댓글()

[아두이노] LED 제어

IOT/아두이노|2019. 1. 30. 19:45

LED 제어(아두이노)




1. 발광다이오드(LED)



다리가 긴쪽이 +(애노드), 짧은 쪽 -(캐소드) 이다. 애노드와 캐소드 용어로 구지 생각하지 말고 다리길이에 따라 +, -만 구분하시면 된다.

참고로 발광다이오드는 색깔에 따라 필요한 전압이 다릅니다. 일일히 표로 만들기 귀찮아서 괜찮은 표가 있어서 해당 블로그 표를 인용합니다.


출처 : Arduino - LED 저항값 달기
기본적으로 필요 전압이 golsufan09 블로그의 발광다이오드 표를 인용했습니다.

계산법 - 옴의 법칙


V(전압)=I(전류) * R(저항)

R= V/I = (5V-1.8V)/20mA

기본적으로 LED은 표에서 보는 것 처럼 약 2~3V의 전압에 작동을 하는데 아두이노가 5V의 전압을 제공함으로 최소 100옴을 저항이 필요합니다.

그냥 5V의 전압이 공급되면


감당할 수 없는 전압 LED은 그냥 터지고 만다. 그래서 저항을 붙이는데 저항은 흐르는 전류의 양을 조절해주는 수도꼭지 같은 역활을 한다. 즉, 수도꼭지를 돌리면 물의 양을 조절하는 것처럼 저항의 값에 따라서 전류의 양을 조절 가능하다. 그래서 아두이노에서 부품과 모듈을 사용할때에 아두이노의 나오는 전압과 부품과 모듈에서 필요로 하는 전압이 다를때 저항을 사용한다. 특수한 경우를 제외하고는 거의 모듈 형식의 부품을 사용하기 때문에 초보분들은 그렇게 깊게 생각 안하셔도 된다. 그냥 머리속에서 수도꼭지만 생각하시면 된다.

5V의 전압에 저항(220옴)을 붙이면



위 사진과 전류의 변화를 잘 비교하면 된다.

참고로 직접 회로도를 제작하지 않는 이상은 그냥 모듈로 만들어진 부품을 아두이노와 연결해서 자신이 원하는 표현만 잘 해내면 된다.

2. 뻥판



구멍이 촘촘히 뚤려 있다. 여기서 각 점에서 파란선을 주목하길 바란다. 뻥판 내부에 파란선이 그어진 만큼 각 점들은 내부선으로 연결되어 있다. 그래서 LED와 저항을 배치할때에 겹치지 않고 분리 해서 구분하여 배치해야한다.
점들 내부에는 선으로 저런식으로 연결되었구나를 머리속에 담아 놓으시면 됩니다.

실제로


이렇게 연결된 느낌으로 이해하시면 된다. 하지만 이렇게 할려면 각 부품을 납땜해야 한다. 부품마다 분리 되어 있는데 납땜하면 한번 실험하고 말것도 아니고 계속 다양한 실험을 하기 위해서 뻥판을 사용한다. 뻥판에 부품을 꼽기만 하면 납땜을 하지 않아도 부품간 연결을 쉽게 할 수 있어 주로 뻥판을 사용한다.

3. LED 실험



이전 시간에 13번 핀을 출력모드로 깜박이는 실험을 하였다. 아래와 같이 회로도를 배치하고 코딩도 1초 단위로 깜박이는 예제이다.



void setup() {
pinMode(13, OUTPUT);
}

void loop() {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000); 
}


여기서 여러개의 LED를 제어해보자

회로도


  • 준비물 : led 5개, 저항 220옴 5개, 뻥판, 아두이노우노

components 클릭하시면 부품 이미지들이 하단에 나오고 해당 부품을 드래그 하시면 자동으로 불러오게 된다.
그리고 뻥판에 배치하시고 저항값을 지정하고 선은 마우슨 왼쪽으로 클릭해서 선을 연결하시면 됩니다. 자동으로 마우스 왼쪽 버턴을 누르면 해당 위치에 선이 생성되고 다음 마우스 왼쪽 누른 위치에 끝점이 되어 선이 생성된다.

코딩 - 블록 체크되어있는 걸 누르면 해제된다. 순수 코딩창으로 넘어간다.


  • 내용 : 순차적으로 LED 깜박이기



void setup()
{
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(9, OUTPUT);
}

13,12,11,10,9번 핀을 출력모드로 선언한다. pinMode()함수는 이전 시간에 공부했기에 출력모드로 5핀을 지정만 해주면 된다.

void loop()
{
  digitalWrite(13, HIGH);
  delay(1000); 
  digitalWrite(13, LOW);
  digitalWrite(12, HIGH);
  delay(1000); 
  digitalWrite(12, LOW);
  digitalWrite(11, HIGH);
  delay(1000); 
  digitalWrite(11, LOW);
  digitalWrite(10, HIGH);
  delay(1000); 
  digitalWrite(10, LOW);
  digitalWrite(9, HIGH);
  delay(1000); 
  digitalWrite(9, LOW);  
}

로직은 13번 핀이 5V가 전류가 공급되고 1초 대기했다가 13번핀을 0V를 보내고 동시에 12번핀에 5V의 전류를 보낸다. 이런식으로 1초 단위로 13번에서 부터 9번핀까지 순차적으로 전류를 공급했다가 끊어주기만 하면 간단한 원리이다.

자세히 보면 뭔가 함수명이 중복해서 코드를 선언하고 실행 명령을 내리는 느낌을 받았을 것이다.10개이상의 LED를 깜박인다고 생각해보자. 10개이상의 핀을 선언하고 10개 이상의 핀을 HIGH, LOW를 시키는 코딩을 일일히 표현해야 한다면 얼마나 비 효율적인 코딩이겠는가 여기서 C언어 문법 하나를 배워서 간단히 코딩을 바꿔 보자.

C언어 문법


  • 구조
    for(초기값1, 조건식2, 증감연산4){
    처리문3;
    }

예) 1부터 10까지 더하기
int i,sum;
sum=0;
for(i=1;i<=10;i++){
sum=sum+i;
}

int i, sum; 에서 자료형 int은 담을 수 있는 그릇의 크기이고, i와 sum은 변수명으로 어떤 값을 저장하는 그릇으로 생각하면 된다.
자료형이랑 작은 접시냐 큰 접시냐로 값을 저장할 수 있는 크기를 결정하는 표현으로 생각하면 된다. i와 sum의 변수의 그릇을 int형 크기의 그릇으로 선언했다는 정도만 지금은 이해하면 된다.

for문은 동작 순서는 1->2->3->4->2->3->4->2->3->4.... 이렇게 순차적으로 반복 수행한다. 2번의 조건식이 참이면 처리문을 반복 수행하고 거짓이면 for문을 빠져나오게 된다.

그래서 for문 i은 1로 초기값을 지정되고 조건식 i<=10로 i가 10보다 작거나같은가 묻는다. 조건식이 참인가 거짓인가 비교하게 된다. 초기값이 1이기 때문에 조건식은 참이 되어 처리문3을 수행한뒤 i++(증감) i=i+1과 같다. 1씩 증가하는 증감연산자이다.
초기값이 1이고 조건식이 참이여서 sum = sum +1이 된다. sum은 초기값이 0이기 때문에 sum=0+1로 sum=1이 된다.
i++로 i은 2가 되고 다시 2은 10보다 작거나같냐고 물으면 참이기 때문에 sum=sum+2로 이전 sum값이 1이기 때문에
sum=1+2로 sum=3이 저장된다.
이런식으로 i는 다시 1이 증가하여 1, 2, 3, 4, 5, 6, 7, 8, 9, 10이 될때까지 반복하게 된다. i가 11이 되면 거짓으로 for문은 더이상 수행하지 않고 빠져나오게 된다.
그래서, 1부터 10까지의 합 55가 최종적으로 sum에 저장된다.

sum = 1+2+3+4+5+6+7+8+9+10; 이렇게 일일히 다 표현한다면 10개니깐 이렇게 했지만 1000까지 합으로 구한다고 생각해보자 1000개의 숫자를 다 코딩한다고 상상해 보자 엄청 힘들고 비효율적이게 된다.
간단히 sum=sum+i로 i를 1000번 반복해서 sum에 누적 합계를 구하면 쉽고 간단하게 코딩으로 해결이 가능하다.

이처럼 아두이노에서 led가 5개면 대충 위 코딩처럼 일일히 표현이 가능하겠지만 10개이상이면 저걸 다 일일히 코딩하는 건 엄청 비효율적이다. 이럴때 for문을 사용한다면 단 몇줄로 쉽게 해결할 수 있게 된다.

int i;
void setup()
{
  for(i=13;i>8;i--){
    pinMode(i, OUTPUT);
  }
}

i 변수가 13으로 초기화 하고 i는 8보다 크다가 조건식이다 참임으로 처리문 pinMode()함수에서 13번 핀을 출력모드로 선언한다. 여기서는 감소연산자 i--은 i=i-1이다. 1씩 감소한다. 즉 다음핀 12번이 8보다 큰가 조건식이 된다. 참임으로 12번핀이 출력모드로 선언된다. 이런식으로 13번핀부터 9번핀까지 출력모드로 선언하게 된다.
pinMode()함수를 중복해서 코딩할 필요 없이 for문으로 5번 반복하게 된다.

이와 같이 5개핀을 이제 깜박이게 하는 원리도 동일하다.

void loop()
{
  for(i=13;i>8;i--){
    digitalWrite(i, HIGH);
    delay(1000); 
    digitalWrite(i, LOW);    
  }
}

동일한 for문으로 13번 핀을 5V전원을 공급하고 1초 대기했다가 13번핀을 0V가 된다. 이때 다시 i가 12로 감소하고 12번핀에 5V의 전원이 공급되고 1초 대기했다가 다시 0V가 된다. 이런식으로 9번핀까지 깜박이고 i가 8이 되면 for문을 빠져나오고 loop()문이 끝나고 다시 재 반복되게 된다. 계속 13번핀에서 9번핀까지 1초 단위로 깜박이게 된다.

4. 결과




마무리


처음 Led 한개를 깜박였다면 순차적으로 5개의 led를 깜박이게 했다. 그러면 한번 상상을 해보자 홀짝으로 깜박이게 한다면 어떻게 해야할지를 핀 값을 홀짝만 나눠서 전원을 공급하면 되겠죠.
5개 핀이니깐 홀수 3개핀 짝수 2개핀으로 정해서 3개핀에 전원을 동시게 5V공급했다가 1초후 전원을 OV로 한뒤에 짝수 2개핀을 5V로 공급하면 되겠죠.
이걸 홀짝으로 나눠서 반복하면 홀짝으로 깜박이게 됩니다.
그럼 다시 정순으로 순차적으로 깜박이게 했는데 정순으로 깜박인 후 다시 역순으로 깜박이게 한다면 로직을 상상해 보세요.
또 다른 방식으로 Led를 깜박이게 상상해보세요.
그리고 led을 깜박이는 원리를 적용가능한 것들을 현실세계에서 찾아보세요.
대표적인 예로 신호등 제어를 들 수 있겠죠.
만약 led를 이용해 신호등을 만든다고 상상해보세요. 신호등의 원리를 이해하면 그 원리에 맞게 led를 깜박이게 하면 되겠죠.
이외도 한번 led를 깜박이게 한다 그러면 현실에서는 어떤 것들이 이와 유사한 것들이 있는지 상상해 보세요.
다음에는 led가 과연 어떠한 표현이 있는지를 살펴보도록 하죠.


'IOT > 아두이노' 카테고리의 다른 글

[아두이노] 스위치 버턴 제어  (0) 2019.02.03
[아두이노] 3색 LED 제어  (0) 2019.02.02
[아두이노] 코딩 구조  (0) 2019.01.31
아두이노의 기초  (0) 2019.01.27
아두이노 가상시뮬레이터  (0) 2019.01.24

댓글()

아두이노의 기초

IOT/아두이노|2019. 1. 27. 15:01

아두이노의 기초



1. 아두이노 구조




      • 상단
        Digital pin : 핀번호 0~13핀으로 구성되었으며 0(0V) 과 1(5V)의 신호를 보내고 받을 수 있다. 여기서 PWM핀은 6개의 핀을 제공하면 아날로그 출력(0~255)를 내보낼 수 있다.
        시리얼통신핀 : TX(출력1번), RX(입력0번)
        GND(핀) : 전류 마이너스(-) 핀

      • 하단
        Power 부분: 하단 왼쪽 POWER(3.3V, 5V, Gnd, Vin)으로 구성되어 있다.
        Analog pin : 아날로그 입력을 받을 수 있는 핀으로 0~1024(2의 10승)값을 받을 수 있다. 총 6개의 핀으로 구성되어 있다. 여기서 디지털핀으로 핀모드를 지정해주면 사용도 가능하다. 핀모드를 지정안해주면 본래 목적으로 아날로그 값을 입력받는데 사용된다.



지금 각 핀에 대해서 이핀은 무슨 핀이고 저 핀은 무슨핀이다라고 설명해 봤자 의미가 없다. 아두이노를 실제로 실험을 하다보면 아 이 핀이 이런 핀이구나라는 걸 이해할 것이다. 단지 여기서는 핀 구성이 대충 이런식으로 되었다는 정도만 머리속에 담아 놓으시면 된다.

2. 아두이노 Atmega328P 구조




전압 = 5V
디지털핀 14핀(6의 PWM핀제공)
아날로그입력핀 6핀
플래쉬메모리 : 32kb
SRAM : 2kb
클럭 속도 : 16MHz


이 Atmega328P는 사용하기 위해 전원 공급과 통신 등 몇가지 기능을 추가하여 덕지 덕지 붙여 놓은게 아두이노우노입니다. 기본적으로 이 칩은 내부 클럭이 최대 8Mhz정도의 클럭속도는 냅니다. 그래서 크리스탈을 붙여 16Mhz의 속도를 낼 수 있게 합니다. 이 칩에 프로그램을 이식할 수 있는게 32kb 만큼의 용량의 프로그램 밖에 이식할 수 없으며 변수공간도 2kb인가로 아주 제한적이여서 사용 용도로도 아두이노는 복잡한 계산 보다는 단순 작업에 사용됩니다.

쉽게 말해서 Atmega328P 칩에 전류를 공급하고 이 칩에 기록된 프로그램 명령어를 전류가 공급되는 동안 칩 핀을 통해서 입력받거나 출력하는 동작을 계속 반복한다고 생각하시면 된다.

칩 각 핀에는 고유의 역할이 있고 그 핀을 통해서 디지털 신호나 아날로그 신호를 받거나 내보내는 작업을 잘 수행하기 위해서 아두이노를 배우는 것이죠. 아두이노는 종류도 다양하고 칩도 다른데 중요한것은 머리속에서 칩에다 전류를 공급되면 칩에 기록된 명령어를 핀을 통해서 수행한다는 개념만 머리속에 담아 놓으시면 기본 베이스는 끝납니다.

그리고 아두이노를 배우는 것은 이 칩에 기록할 명령어 로직을 짜는법을 배우는 것이라는 점만 머리속에 담아 두세요. 여기서 코딩은 어렵지는 않습니다. 과거에는 하나에서 열까지 전부 다 개발자가 머리속에서 짜내어야 했지만 현재는 기본적인 라이브러리가 다 제공되고 엑셀처럼 각 함수의 의미만 잘 이해하면 쉽게 함수(블록)단위로 코딩이 가능합니다. 그래서 예술쪽 있는 분들이 아두이노와의 결합 작품을 많이 시도하고 만들어내는 이유이기도 하죠.


마무리




아두이노를 공부하는 분들은 어느정도 깊게 들어가면 아두이노로 이것저것을 붙여가면서 좀 복잡한 연산 작업을 수행할려고 한다. 뭔가 아두이노로 두뇌 역활을 하는 작업을 수행하려고 배보다 배꼽이 더 큰 모듈들을 붙여가면서 억지로 그 기능을 구현 시키기도 한다.

뭔가 좀 복잡한 연산이나 다양한 기능을 추가하면서 제어를 하고 싶다면 차라리 라즈베리파이와의 연동을 추천 드립니다. 재밌는 것은 라즈베리파이를 배우는 분들은 반대로 단순작업을 수행하는데 라즈베리파이를 이용하는 경우가 많다. 그냥 아두이노로 표현하는게 더 나을 작업을 구지 라즈베리파이로 구현 시킬려는 분들도 많다. 그래서 아두이노를 배우고 나서 라즈베리를 배우는게 가장 이상적이라고 저는 생각되네요.

'IOT > 아두이노' 카테고리의 다른 글

[아두이노] 스위치 버턴 제어  (0) 2019.02.03
[아두이노] 3색 LED 제어  (0) 2019.02.02
[아두이노] 코딩 구조  (0) 2019.01.31
[아두이노] LED 제어  (0) 2019.01.30
아두이노 가상시뮬레이터  (0) 2019.01.24

댓글()