[D3.js] 막대형 차트에 애니메이션 효과 부여

D3.js/D3.js|2019. 10. 22. 09:00

[D3.js] 막대형 차트에 애니메이션 효과 부여


지난 시간에 막대형 차트와 간단한 애니메이션 효과를 실험해 보았습니다. 지난 시간에 다룬 내용을 기반으로 두가지 내용을 합쳐서 간단한 실험을 해보도록 하겠습니다. 내용은 막대형 차트를 기본베이스로 하고 이 막대 이미지를 애니메이션 효과를 부여하는 실험입니다.

1. 막대형 차트 예제



<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>codingman</title>    
    <style>
    .chart div {
      font: 10px sans-serif;
      background-color: steelblue;
      text-align: right;
      padding: 3px;
      margin: 1px;
      color: white;
    }
    </style>
  </head>
  <body>
    <div class="chart"></div>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script>
      var data = [10, 20, 30, 40, 50];

      d3.select(".chart").selectAll("div").data(data)
        .enter().append("div")
        .style("width", function(d) { return d*10 + "px"; })
        .text(function(d) { return d; });
    </script>    
  </body>
</html>

위 기본소스는 지난시간에 다룬 내용입니다. 위 내용을 모를 경우 [D3.js] 막대형 차트로 보는 D3.js post를 읽고 오시면 됩니다.

[결과]


2. 위 막대형 차트를 애니메이션 효과 부여


       .transition() 
         .duration(2000)  
                 이동좌표;

위 코딩만 사용 합니다. 막대이니간 막대를 2초동안 특정이동좌표로 이동하라는 명령코딩을 내릴 수 있습니다.

막대형 차트와 합쳐서 코딩을 하면 다음과 같습니다.

  <script>
       var data = [10, 20, 30, 40, 50];

      var div = d3.select(".chart").selectAll("div").data(data)
           .enter().append("div")
             .style("width", "0px")
             .transition()   
             .duration(2000)               
             .style("width", function(d) { return d*10 + "px"; })
           .text(function(d) { return d; });
</script>  

위 코딩은 style()함수로 초기 시작위치는 width값을 0px로 하였습니다. 그리도 애니메이션 효과로 데이터 값의 길이만큼 그려지게 표현 했네요.

[결과]


3. 역방향 애니메이션 효과


위에서 왼쪽에서 오른쪽으로 막대가 이동했다면 반대로 이동하는 것을 궁금해 해야 합니다. 그러면 반대의 경우는 어떻게 이동 할까요.

방금 했던 코딩에서 한줄만 제거 하시면 됩니다.

  <script>
       var data = [10, 20, 30, 40, 50];

      var div = d3.select(".chart").selectAll("div").data(data)
           .enter().append("div")
//           .style("width", "0px")
             .transition()   
             .duration(2000)               
               .style("width", function(d) { return d*10 + "px"; })
             .text(function(d) { return d; });
</script>  

시작 위치를 0px로 안하면 됩니다.

[결과]


마무리


오늘은 d3.js에서 막대형 차트와 애니메이션 효과를 합쳐서 표현해 보았습니다.단순히 막대형 차트로만 표현하면 밋밋한 모습이였지만 딱 두줄이 추가함으로 뭔가 있어 보이는 표현이 되었네요.

오늘 내용은 지난시간의 다룬 내용을 합친 실험입니다.

'D3.js > D3.js' 카테고리의 다른 글

[D3.js] HTML의 SVG 태그  (0) 2019.10.24
[D3.js] 애니메이션 효과 순환 동작  (0) 2019.10.23
[D3.js] 애니메이션 효과  (0) 2019.10.21
[D3.js] 막대형 차트로 보는 D3.js  (0) 2019.10.18
[D3.js] Data 실시간 처리  (0) 2019.10.17

댓글()

[D3.js] 애니메이션 효과

D3.js/D3.js|2019. 10. 21. 09:00

[D3.js] 애니메이션 효과


데이터를 웹페이지에 시각화 할 때 단순한 형태의 차트 이미지로 보여주면 뭔가 부족해 보일 수 있습니다. 데이터 시각화를 하고 시각화한 이미지가 실시간으로 움직이며 데이터가 살아 움직이는 효과를 보여 주면 좀 더 멋진 시각화 데이터가 되겠죠. 오늘은 간단한 애니메이션 효과로 이미지를 실시간으로 계속 움직이게 하는 표현을 실험하고자 합니다. 저도 기초부터 하나씩 잡아가는 단계라 깊게는 설명을 못드립니다.

1. SVG태그로 시각화 영역 설정


가로x세로 크기의 배경색은 blue로 지정하면 다음과 같습니다.

 //<svg width="300" height="300" style="background: blue"> 추가
  var canvas = d3.select("body").append("svg")
    .attr("width",300)
    .attr("height",300)
    .style("background-color","blue");

처음에 attr()함수에 "background-color"를 지정했는데 왜! 배경색이 안나오지 하고 삽질하고 찾아보니깐 style()함수로 지정해야 되더군요.

[결과]


위 결과 이미지를 보면 캔버스로 시각화 데이터가 그려질 영역이라고 보시면 됩니다.

2. 시각화 이미지 원 만들기


원이 그려 질 cx가 30, cy 150의 위치에 r=15인 원을 그리고 원의 색은 red로 지정하면 다음과 같습니다.

//<circle cx="30" cy="150"  r="15" fill="red> 추가
    var circle = canvas.append("circle") 
              .attr("cx",30)
              .attr("cy",150)
              .attr("r",15)
              .attr("fill","red");

위에 캔버스에서 특정 좌표(30,150) 위치에 원을 그립니다.

[결과]


3. 캔버스의 원을 움직이게 하기


 //<circle cx="30" cy="150"  r="15" fill="red> 추가
    var circle = canvas.append("circle")
              .attr("cx",30)
              .attr("cy",150)
              .attr("r",15)
              .attr("fill","red");
        circle.transition()   //시작전 1초 대기(delay)했다가 2초동안  현재위치에서 x축 300위치로 이동한뒤 원 제거
                .duration(2000)  
                .delay(1000)
              .attr("cx",300).remove();

circle을 이동하는데 duration(2초) 동안 이동합니다. 대기시간은 1초이고 cx가 300이 될때까지 이동을 2초동안 하게 됩니다. 즉, 초기 circle이 그려진 위치에서 2초동안 cx가 300인 위치까지 움직인다고 보면 되겠죠.
참가로 remove()함수는 제거 함수인데 2초동안 움직인 후 해당 원은 제거 합니다. 원을 한곳에 계속 쌓아 둘 필요는 없으니깐요.

4. d3.interval()함수를 실시간 처리


이전 시간에는 기존의 자바스크립트 언어에서 setTimeout()함수로 처리를 했지만 이번에는 d3.interval()함수를 통해서 한번 처리를 해볼까 합니다.

render(); //처음한번수행
d3.interval(render, 3000); //3초간격으로 render()함수 호출함

이렇게 표현하면 3초 간격으로 render()함수가 호출이 됩니다 어떤 의미 인지 아시겠지요. 오늘 배운 애니메이션 효과를 3초 간격으로 동작하도록 해볼까요.

5. 종합 코딩


<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>codingman</title>
</head>
<body>

<script src="https://d3js.org/d3.v5.min.js"></script>
  
  <script>
 //<svg width="300" height="300" style="background: blue"> 추가
  var canvas = d3.select("body").append("svg") 
    .attr("width",300)
    .attr("height",300)
    .style("background-color","blue");    
    
  function render(){
     //<circle cx="30" cy="150"  r="15" fill="red> 추가
    var circle = canvas.append("circle") 
              .attr("cx",30)
              .attr("cy",150)
              .attr("r",15)
              .attr("fill","red");
        circle.transition()   //시작전 1초 대기(delay)했다가 2초동안  현재위치에서 x축 300위치로 이동한뒤 원 제거
                .duration(2000)  
                .delay(1000)
              .attr("cx",300).remove();
    }
    render(); //처음한번수행
    d3.interval(render, 3000); //3초간격으로 render()함수 호출함 
</script>
</body>
</html>

[결과]


단순하게 원 하나를 수평으로 이동시키는 실험이였습니다. 하지만 이 한동작의 원리만 제대로 이해하셔도 많은곳에 사용할 수 있습니다. 가령 막대형 차트에 적용 한다고 상상해 보세요. 각 막대기가 데이터 길이만큼 애니메이션 효과로 움직이면서 막대가 그려지겠죠. 한번 머리속에서 그려 보세요.

마무리


오늘은 d3.js에서 제공하는 실시간 동작 명령 interval함수에 대해서 살펴 보았습니다. 그리고 실시간 처리를 할 때 CSS의 부분인 애니메이션 효과를 D3.js함수를 이용하여 간단히 움직이는 동작을 코딩했습니다. 이런 동작 원리를 이해하시면 차트가 처음 열릴 때 움직이는 차트를 한번쯤은 보셨을 꺼에요. 그와 같이 애니메이션 효과를 부여하면 좀 더 멋진 데이터 시각화를 할 수 있습니다.

맛보기로 간단히 원을 수평으로 움직이게 실험했는데 여러분들 수직으로 한번 움직이게 해보세요. 원이 그려지는 초기 위치를 수정하고 cy값으로 변경하시면 되겠죠. 그리고 duration()함수의 시간값을 수정하여 빠르게 또는 느리게 움직이게 해보세요. 또는 interval()함수내 시간값을 수정하여 빠르게 또는 느리게 움직임을 만들어 보세요. 다양한 움직임을 만들어 낼 수 있을 거에요.

댓글()

[D3.js] 막대형 차트로 보는 D3.js

D3.js/D3.js|2019. 10. 18. 09:00

[D3.js] 막대형 차트로 보는 D3.js



오늘은 막대형 차트를 간단히 하나를 막들어 보았는데 D3.js에서 튜토리얼로 아주 좋은 예제가 있어서 D3.js 튜토리얼로 나온 예제로 이야기를 풀어 나갈까 합니다. D3.js를 배우면 좋은 점으로 설명하기 가장 좋은 예제일 것 같습니다.


위 링크로 가시면 튜토리얼에 Let’s Make a Bar Chart 예제가 있습니다. D3.js를 처음 시작하면 이 막대형 차트 시각화부터 시작합니다. 저도 비슷하게 다른 막대형 차트 표현을 했는데 위 출처의 예제가 너무 완벽해서 이걸로 소개하는게 좋을 것 같아서 제 코딩은 잠시 접어 둡니다.


1. HTML 막대형 차트


출처 : November 5, 2013Mike Bostock - Let’s Make a Bar Chart



위 막대형 차트가 출처 "Let’s Make a Bar Chart" 코딩 소스를 기반으로 살펴보면 막대형 챠트 이미지가 HTML로 만든다면 이렇게 코딩이 됩니다.

[ "Let’s Make a Bar Chart" 코딩 소스]

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>codingman</title>    
    <style>
    .chart div {
      font: 10px sans-serif;
      background-color: steelblue;
      text-align: right;
      padding: 3px;
      margin: 1px;
      color: white;
    }
    </style>
  </head>
  <body>
    <div class="chart">
    <div style="width: 100px;">10</div>
      <div style="width: 200px;">20</div>
      <div style="width: 300px;">30</div>
      <div style="width: 400px;">40</div>
      <div style="width: 500px;">50</div>    
    </div>
  </body>
</html>

기존의 HTML에서는 div 태그를 일일히 코딩해야 합니다. 이 표현을 자바스크립트로는 for문으로 해서 div태그를 5번 반복하여 출력하면 됩니다. 그렇게 코딩을 하면 좀 지졉분하게 코딩되고 복잡해 보일 수 있는데 이런 코딩을 아주 쉽고 간단하게 표현할 수 있는게 D3.js API입니다.

2. D3.js 막대형 차트



위 표현을 D3.js를 이용하여 표현 하면 다음과 같습니다. 위 CSS 부분은 그대로 두고 다음 body 태그 안에 div태그 부분만 수정하면 됩니다.

  <body>
    <div class="chart">
      데이터 출력되는 부분;
    </div>
  </body>

위 코딩에서 데이터 출력되는 부분으로 막대형 차트에서 데이터 막대가 그려지는 부분입니다. 이 부분을 D3.js를 이용하여 표현하면 다음과 같습니다.

  <body>
    <div class="chart"></div>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script>
      var data = [10, 20, 30, 40, 50];

      d3.select(".chart").selectAll("div").data(data)
        .enter().append("div")
        .style("width", function(d) { return d*10 + "px"; })
        .text(function(d) { return d; });
    </script>    
  </body>

하나씩 살펴보면,

d3.select(".chart").selectAll("div").data(data)

select()함수로 클래스명이 "chart"를 가리키고 그 가리킨 위치에 selectAll()함수로 모든 div를 선택하게 됩니다. div태그가 있던 없던 우선 선택된 영역의 div들을 선택한다고 보시면 됩니다. data()함수는 시각화 data인자로 넣습니다. 갱신이 아닌 추가이기 때문에 갱신영역의 코딩은 현재 필요 없습니다. 추가 이기 때문에 추가영역에 데이터를 막대이미지로 출력하면 됩니다

div 태그 추가

.enter().append("div")

수평 막대이미지를 만들기 때문에 스타일에서 width의 값을 데이터 값에 맞게 지정하면 됩니다. 아래 d값은 순차적으로 배열 data 변수의 값을 반환하여 스타일을 지정합니다.

.style("width", function(d) { return d*10 + "px"; })

위 표현이 data가 10이면 막대 길이를 d*10으로 하면 100이 되고 스타일은 아래와 같이 추가 되었다고 생각하시면 됩니다.

<style>
  .chart div {
    width: 100px;
  }
</style>

5개의 데이터 이기 때문에 이 과정을 5번 수행되고 5개의 막대이미지가 그려집니다.

막대 이미지 안에 data를 텍스트 형태로 출력하기 때문에 텍스트 출력은 CSS에서 오른쪽 정렬 글자색 White로 표현되도록 설정되어 있고 D3.js에서는 텍스트만 뿌려주면 됩니다. 그 표현은 아래와 같이 코딩하면 됩니다.

.text(function(d) { return d; });

d는 배열 data 변수의 값을 순차적으로 출력됩니다.

결론은

.style("width", function(d) { return d*10 + "px"; })
.text(function(d) { return d; });

막대이미지를 데이터 d만큼 그리고 그 안에 데이터 d값을 출력한다는 의미입니다.

3. D3.js 막대형 챠트를 갱신 및 추가 한다면


<script>
  var data = [10, 20, 30, 40, 50];

  d3.select(".chart").selectAll("div").data(data)
     .enter().append("div")
     .style("width", function(d) { return d*10 + "px"; })
     .text(function(d) { return d; });
</script>    

위 코딩에서 어떻게 해야 할까요.

  var data = [10, 20, 30, 40, 50];

  var div = d3.select(".chart").selectAll("div").data(data)
     .style("width", function(d) { return d*10 + "px"; })
     .text(function(d) { return d; })
  div.enter().append("div")
     .style("width", function(d) { return d*10 + "px"; })
     .text(function(d) { return d; })
  div.exit().remove();

한번 테스트 해 볼까요.

<script>
  var data = [10, 20, 30, 40, 50];
  function render(data){
    var div = d3.select(".chart").selectAll("div").data(data)
          .style("width", function(d) { return d*10 + "px"; })
          .text(function(d) { return d; })
        div.enter().append("div")
          .style("width", function(d) { return d*10 + "px"; })
          .text(function(d) { return d; })
        div.exit().remove();
  }
  render(data);

  setTimeout(function(){render([20,10,33]);},1000);      
  setTimeout(function(){render([50,40,30,20,10]);},2000);      
</script>   

[결과]


마무리


D3.js로 코딩을 할 때는 위와 같이 순수 시각화 하는 데이터 영역만 간단하게 표현하기도 하고 CSS의 부분을 D3.js 함수로 이용하여 새로 갱신하거나 추가할 수 있습니다. 아예 처음부터 D3.js 함수로 표현해도 되지만 이렇게 하면 코딩이 길어지고 보기 불편합니다. 고정되는 CSS코딩 부분은 CSS 영역에서 처리하고 D3.js에서는 막대차트에서 막대이미지에 직접적으로 변경이 이루어지는 스타일부분만 코딩해주면 왠만한 차트 표현을 한페이지 코딩으로 고퀄리티 코딩을 할 수 있습니다.

어떻게 코딩할지는 여러분들의 몫이지만 여러분들이 한번 잘 생각해보시고 코딩 스타일을 잡아가시기 바랍니다. 오늘 살펴 본 막대형 차트는 CSS부분을 어느정도 기본 개념이 탑재 된 상태에서 봐야 하는 부분입니다. 혹시 CSS부분이 이해가 안되신다면 CSS 부분은 이곳 https://www.w3schools.com/css/ 사이트에 가셔서 한번 읽어 오셔서 보셨으면 합니다.

오늘 핵심 코딩은 딱 두줄입니다.

.style("width", function(d) { return d*10 + "px"; })
.text(function(d) { return d; })

수평 막대이미지를 길이를 지정하고 안에 텍스트 값을 출력하는 명령이 핵심입니다. 나머지 코딩은 D3.js 기본틀을 기준입니다. 기본틀의 의미만 이해하시면 딱 위 두줄로 CSS 스타일과 잘 접목하여 막대형 차트를 그릴 수 있게 됩니다.

'D3.js > D3.js' 카테고리의 다른 글

[D3.js] 막대형 차트에 애니메이션 효과 부여  (0) 2019.10.22
[D3.js] 애니메이션 효과  (0) 2019.10.21
[D3.js] Data 실시간 처리  (0) 2019.10.17
D3.js 기본 틀  (0) 2019.10.16
D3.js 버전5로 공부 시작  (0) 2019.10.15

댓글()

[D3.js] Data 실시간 처리

D3.js/D3.js|2019. 10. 17. 09:00

[D3.js] Data 실시간 처리


시각화 데이터를 웹페이지에 열때 기본적으로 처음 한번만 해당 데이터를 읽어와 화면에 챠트와 같은 이미지로 출력을 하게 됩니다. 한번만 html문서로 출력을 한다면 뭔가 부족해 보일 수 있습니다. 대개 html 문서 상의 데이터들은 실시간 데이터를 다루는 경우가 많습니다. D3.js에서 이러한 데이터를 실시간 처리를 하는 코딩이 필요합니다. 그래서 오늘의 내용은 D3.js 상의 데이터를 일정시간 시간단위로 데이터를 갱신하는 실험을 해보겠습니다.

1. 기본 소스


지난 시간의 p태그에 data 값을 출력하는 예제를 통해 실시간 처리를 해보도록 하죠.

<body>
  <p>1</p>
  <p>1/p>
  <p>1</p>
<script src="https://d3js.org/d3.v5.min.js"></script>
  
<script>
    var data = [1,2,3,4,5];
    
    //갱신
    var p = d3.select("body").selectAll("p").data(data)
           .text(function(d){return d;})
    //추가
        p.enter().append("p")
           .text(function(d){return d;})
    //종료
        p.exit().remove();
</script> 
  
</body>

[결과]

1
2
3
4
5

위와같이 html 문서가 열릴 때 처음 한번만 data 값들을 순차적으로 p태그에 출력하게 됩니다. 여기서 html 상의 데이터들이 출력한 상태에서 일정 시간 단위로 새로운 데이터로 갱신 시키는 코딩을 간단히 표현해 보겠습니다.

2. setTimeout() 함수를 통한 갱신


setTimeout(function(){호출함수(data);},1000);

다른 방법도 있지만 간단히 의미 전달로 setTimeout 함수를 사용해 보고자 합니다. setTimeout함수는 호출함수를 1초(1000) 후 호출하게 됩니다. 즉, 호출함수에 인자값을 새로운 data로 하여 호출함수를 수행하게 하면 일정 시간단위로 데이터 갱신 할 수 있게 됩니다.

위 기본소스를 간단히 수정해 볼까요.

기본 text()출력을 수행하는데 전체 코딩 부분을 render()함수로 묶어서 처리하도록 하겠습니다.

var data = [1,2,3,4,5];
function render(data){
  출력문;
  setTimeout(function(){render([k,12,13]);},1000);   
}

render함수가 1초(1000) 단위로 호출되게 됩니다. 동작은 render함수가 호출되면 내부동작을 수행하고 마지막 SetTimeout 함수를 통해 다시 render함수가 새로운 data값으로 재호출 됩니다. 재호출 되는 시간을 1초로 하였는데 이 표현을 통해 반복 수행을 하게 되면 1초 단위로 호출되어 데이터 값이 갱신을 하게 되더군요. 정확한 표현은 아니고 생각나는데로 표현한 것입니다.

[소스]

<body>

<script src="https://d3js.org/d3.v5.min.js"></script>
  
<script>
    var data=[1,2,3,4,5];
    var k = 1;
    function render(data){
      var p = d3.select("body").selectAll("p").data(data)
           .text(function(d){return d;})
         p.enter().append("p")
           .text(function(d){return d;});
         p.exit().remove();
      k++;
      setTimeout(function(){render([k,12,13]);},100);      
  } 
  render(data);   
   
</script>
</body>

위 소스는 0.1초 단위로 갱신이 되는데 결과 영상을 짧게 보기 위해서 갱신 시간으로 아주 짧게 만들었네요. 결과는 아래 움짤로 재편집 했습니다.

[결과]


처음 데이터 1,2,3,4,5값이 p태그에 text()함수를 통해 출력이 됩니다. 그다음 새로운 데이터 값 3개가 들어오고 기존에 5개의 p태그에서 3개의 p태그 값이 갱신되어 집니다. 여기서 나머지 2개의 값은 remove()함수를 통해 제거가 됩니다.

참고로, k변수를 새로 만들어서 k++로 표현하였는데 k값은 실시간으로 갱신되는 데이터 값을 보기 위한 표현으로 의미를 둘 필요는 없는 변수입니다. 결과를 실시간 갱신이 이루어지는지 보기 위해서 표현한 부분입니다.

마무리


위 setTimeout()함수외에도 다른 표현 방법으로 타이머함수도 있으며 몇가지 다르게 표현하는 방법들이 있었는데 간단히 실시간 데이터 갱신을 하게 된다면 이런 느낌으로 코딩을 하고 그 결과를 간단히 보기 위한 표현으로 보시면 되겠습니다.

'D3.js > D3.js' 카테고리의 다른 글

[D3.js] 애니메이션 효과  (0) 2019.10.21
[D3.js] 막대형 차트로 보는 D3.js  (0) 2019.10.18
D3.js 기본 틀  (0) 2019.10.16
D3.js 버전5로 공부 시작  (0) 2019.10.15
시각화 문서 D3.js를 도전해보자  (0) 2019.10.14

댓글()

D3.js 기본 틀

D3.js/D3.js|2019. 10. 16. 09:00

D3.js 기본 틀



오래전 D3.js v4로 잠깐 기초를 독학했는데 이번에 v5로 기본틀을 다시 정리를 해보려고 하네요. 예전 post에서 "사각화 문서 D3.js를 도전해보자"에서 잠시 다루었는데 이번 post는 기본 틀 부터 해서 순차적으로 내용을 정리하여 간단히 post를 해볼까 합니다.

기본 틀


예제를 통해 간단히 살펴보겠습니다.

    var data = [1,2,3,4,5];
    
    //갱신
    var p = d3.select("body").selectAll("p").data(data)
           .text(function(d){return d;})
    //추가
        p.enter().append("p")
           .text(function(d){return d;})
    //종료
        p.exit().remove();

위 소스에서 보듯이 딱 3개의 구조로 이루어졌습니다.

  • 갱신 : body라는 태그를 선택하고 그 위치에 있는 모든 p태그를 선택하라 그리고 data값을 text()함수를 통해 순서대로 출력한다.
  • 추가 : 만약 선택된 태그가 3개이고 data가 5개인 경우 나머지 2개의 data는 갱신을 못시키기 때문에 추가부분에서 p태그를 append()함수로 추가하여 text()함수로 해당 새로운 p태그에 값을 text형태로 출력한다.
  • 종료 : exit()종료하는데 remove()함수로 인해 만약 p태그가 7개이고 data 5개 일 때 나머지 2개는 제거 됩니다.

여기서, 태그는 body, p 태그로 실험했지만 다른 태그로 접근해서 실험을 하셔도 됩니다. 또, 디테일 접근으로 html문서의 태그 id, class로도 접근을 할 수 있습니다.

예제) p태그가 3개일 때

<body>
  <p>a</p>
  <p>b/p>
  <p>c</p>
<script src="https://d3js.org/d3.v5.min.js"></script>
  
<script>
    var data = [1,2,3,4,5];
    
    //갱신
    var p = d3.select("body").selectAll("p").data(data)
           .text(function(d){return d;})
    //추가
        p.enter().append("p")
           .text(function(d){return d;})
    //종료
        p.exit().remove();
</script> 
  
</body>

[결과] 기존 p태그에 1,2,3으로 갱신이 되고 새롭게 p태그 2개가 추가되어 총 5개의 값을 출력했네요.

1
2
3
4
5

**예제) p태그가 7개일 때 **

<body>
  <p>a</p>
  <p>b/p>
  <p>c</p>
  <p>d</p>
  <p>e</p>
  <p>f</p>
  <p>g</p>

<script src="https://d3js.org/d3.v5.min.js"></script>
  
<script>
    var data = [1,2,3,4,5];
    
    //갱신
    var p = d3.select("body").selectAll("p").data(data)
           .text(function(d){return d;})
    //추가
        p.enter().append("p")
           .text(function(d){return d;})
    //종료
        p.exit().remove();
</script>
  
  
</body>

[결과] : 데이터는 5개이고 그러면 선택된 p태그 7개에서 5개는 갱신이 되고 나머지 2개는 exit()종료하는데 나머지 remove()함수로 제거 되게 됩니다.

1
2
3
4
5

그리고, exit() 종료함수만 있고 remove()함수를 제거하면 아래와 같이 출력됩니다.

1
2
3
4
5
f
g

remove()함수에 대한 의미를 잘 이해하시면 됩니다.

정리


초반에 태그 위치 선택은 select(), 태그 범위 선택은 selectAll(), 선택 태그 범위의 출력 할 데이터은 data()함수로 사용합니다.
enter(), append() 아직 데이터가 남아 있을 때 나머지를 해당 태그를 추구할 때 사용하는 함수입니다.
오늘 post에서는 text()함수가 있는데 갱신과 추가 부분에 text() 함수가 표현 되었는데 갱신부분의 기존의 p태그와 추가부분의 새로운 p태그에 data값을 출력하는데 text()함수로 텍스트 형태로 출력시키는 문장입니다. 이 부분을 다른 형태로 하면 해당 행터로 값을 출력합니다. 기본 테스트 이기 때문에 text()함수를 사용한 것이고 원하는 형태로 출력하고자 할 때 이 부분을 잘 활용하여 응용하시면 됩니다.
마지막 종료부분은 exit()함수는 종료이고 remove()은 나머지 부분을 제거하는 함수입니다. remove()함수만 주의하면 기초적인 부분에서는 어려움이 없는 것 같아요.

코딩을 할 때 저 세부분의 영역으로 나눠서 코딩을 하면 됩니다. 기존의 태그에서 갱신이나 추가하고 싶을 때 해당 영역 위치에 원하는 동작 명령 코딩을 삽입만 하면 됩니다.
그리고 , 아래 변수 p로 선언하고 d3코딩을 저장했는데, p변수로 해당 명령 코딩을 접근하기 쉽게 하기 위해서 입니다. 여기서 d3로 동작시키고자 하는 해당 태그명을 변수명으로 하시면 나중에 변수명만 보면 어떤 태그에서 특정 동작이 이루어지는지 쉽게 구별할 수 있습니다. 변수명으로 의미를 잘 전달 할 수 있는 이름으로 지어주는게 좋습니다.

var p = d3.select("body").selectAll("p").data(data)
           .text(function(d){return d;})

위 코딩을 보면 p라는 변수명만 보면 p태그에서 뭔가의 동작을 수행했겠구나 하고 쉽게 식별이 됩니다. 나중에 여러 태그을 복합적으로 사용할 때 아주 좋습니다. 태그간 d3표현을 할 때 한쪽 태그에서 다른쪽 태그의 d3 동작을 가져올 때 해당 변수명으로 가져와서 접근하면 코딩 구별하는데 쉽고 코딩도 깔끔해집니다. 이부분은 자주 사용되는 표현이라 나중에 post에 담아보겠습니다.

'D3.js > D3.js' 카테고리의 다른 글

[D3.js] 애니메이션 효과  (0) 2019.10.21
[D3.js] 막대형 차트로 보는 D3.js  (0) 2019.10.18
[D3.js] Data 실시간 처리  (0) 2019.10.17
D3.js 버전5로 공부 시작  (0) 2019.10.15
시각화 문서 D3.js를 도전해보자  (0) 2019.10.14

댓글()

D3.js 버전5로 공부 시작

D3.js/D3.js|2019. 10. 15. 09:00

D3.js 버전5로 공부 시작



새벽형 인간이 되기로 한 시점에서 아침의 시간이 많이 남아서 따로 공부할 것을 찾다가 D3.js를 한번 제대로 공부해보고자 예전 기초 지식과 현재 새롭게 공부하는 내용을 토대로 정리하는 자료로 post를 작성해 볼까 합니다. 사실 아두이노 실험을 현재 사정 상 못해서 D3.js로 넘어왔네요. ^^

1. D3.js 시작 전 사전 학습


D3.js를 바로 시작하는 것도 좋지만 사전 학습으로 미리 공부해 놓으면 배우기가 무지 쉽습니다. D3.js은 기본적으로 자바스크립트 문법을 취하고 있으며 D3.js의 데이터 시각화 문서의 쓰이는 기본 베이스 형식이 HTML의 SVG, CSS의 표현 기능을 간단히 D3.js화 하여 표현합니다. 그래서 자바스크립트, SVG, CSS를 미리 학습해 놓으면 D3.js의 API 함수를 쉽게 이해하고 사용 할 수 있습니다.



위 참고 post를 한번 읽고 오시면 되겠습니다.


-사전 학습 : HTML, CSS. JavaScript 참고 사이트 https://www.w3schools.com/


사전 학습은 w3chools 사이트에 가셔서 기본 문법을 배워 오시면 좋습니다.

2. D3.js의 장점


데이터 시각화 문서를 D3.js API 함수를 이용하여 간단히 표현 할 수 있습니다. 데이터를 챠트와 같은 그림으로 표현 할 때 자주 사용되는 기본 표현들을 함수 단위로 제공해 주고 있습니다. 말로만 좋다고 하는 것 보다 기본 예시를 들어 설명하는게 좋겠죠.

이 예제는 https://d3js.org/ 의 첫 페이지 예제입니다. 보면 극단적으로 비교한 예제인데 꼭 이런 코딩을 이렇게 간단히 표현 할 수 있다는 느낌을 전달한 예제이니깐 절대적 표현 비교로 보시면 안됩니다.

<body>
  <p> hellow World!</p>

<script>
var paragraphs = document.getElementsByTagName("p");
for (var i = 0; i < paragraphs.length; i++) {
  var paragraph = paragraphs.item(i);
  paragraph.style.setProperty("color", "white", null);
}
</script>
</body>

위 예제는 복잡한 표현인데 p태그의 컬러를 white로 지정하는 문장입니다. p태그의 문장이 white로 출력하면 배경색을 white계열에 가까워서 색이 뚜렷하게 안나오네요. 그래서 배경은 black으로 지정 한 후에 출력 결과가 아래와 같습니다.


위 코딩은 D3.js와 극단적으로 차이를 보이기 위한 예시로 보이네요. 꼭 위 처럼 코딩하지는 않습니다. 그냥 극단적 예시로 보면 될 듯 하네요.

d3js.org 홈페이지의 위 코딩 예시는 D3.js로 표현하면 아래와 같이 간단히 표현 할 수 있다고 장점을 소개 합니다.

d3.selectAll("p").style("color", "white");  

한줄로 위 4줄의 긴 코딩을 간단히 selectAll(), style()함수로 표현을 하게 됩니다. 배경도 이 방법으로 같이 표현이 가능합니다.

그러면, 아래와 같이 "Hellow World!"라는 문장을 black에서 white 글자색으로 출력을 아래와 같이 코딩을 하게 됩니다.

<body>
<p> hellow World!</p>
<script src="https://d3js.org/d3.v5.min.js"></script>

<script>
d3.selectAll("p").style("color", "white");  
d3.select("body").style("background-color", "black"); 
</script>
</body>    

이런식으로 극단적 비교하는 예시를 올라와 있네요. 극단적 표현이지만 딱 한줄로 복잡한 여러줄의 코딩을 D3.js로 줄여서 표현이 가능합니다. D3.js은 쉽게 말해서 데이터 시각화 표현들에서 자주 사용되는 표현들을 함수로 미리 만들어 놓고 제공해주는 API라고 생각하시면 될 듯 싶네요.

방금 간단히 D3.js 공식 홈페이지에 나온 예제 일부분을 가져 와서 보여 드렸습니다. 위 예제어서 추가로 D3.js 표현들이 있는데 생략을 했습니다. 가셔서 나머지 부분들을 읽어 보시기 바랍니다.

3. D3.js 공부하기 어려운 점


D3.js를 통한 코딩은 꽤! 단순한 형태로 코딩을 하게 됩니다. 이미 만들어 놓은 API를 이용하기 때문에 API에서 제공되는 함수만 이용해도 고퀄리티 표현을 쉽게 할 수 있습니다. 하지만 D3.js를 공부하는 것에도 어려운 점이 있네요. 그것은 버전 별 충돌입니다. 해당 함수는 해당 버전에서만 허용되는 경우들이 있습니다. 그래서, 여러분들이 사용하는 버전의 함수들이 다른 버전으로 바꿀 때 정상적으로 작동하지 않는 경우가 발생합니다. 그러면 공동 작업하는 모든 사람들이 공유된 하나의 버전으로만 코딩을 해야한 다는 점이 불편합니다. 새로운 사람이 새로운 버전으로 참여 할 경우 이전 버전 사용자들과의 소통이 약간 불편할 수 있겠죠.

그리고 또 한가지는 새로운 버전보다 구버전의 예제들이 많습니다. 당연한 이야기 이지만 D3.js에서 처음 공부하는 사람들은 자연스럽게 최신 버전 API를 사용하게 됩니다. 그런데 공부하는 사람들은 참고하는 예시들은 구버전에서 사용한 예시들이 많기 때문에 그대로 따라할 때 가끔 버전 문제로 정상적으로 작동하지 않아 해당 표현을 최선 버전 표현으로 바꾸기 위해 이중 공부를 해야 합니다. 구버전 표현을 이해해야하고 그 표현을 신버전으로 표현 할 수 있는 능력이 필요합니다. 처음 배우는 사람에게는 이 또한 큰 장벽이 될 수 있습니다.

4. D3.js 배워야 하는 이유


요즘 웹사이트를 돌아 보시면 데이터 시각화 문서들은 거의 대부분 실시간 시각화 문서들이 주류를 이루고 있습니다. 과거 단순하게 챠트로 처음 페이지가 열릴 때 한번만 출력하는 고정된 문서의 형태를 취했다면 요즘은 고정된 데이터 시각화 표현에 그치지 않고 실시간 갱신으로 통한 보다 생동감 있는 시각화 문서를 만들어 보여주고 있는 이 시기에 시대의 흐름에 맞게 지식을 습득해야 겠죠. D3.js은 이런 데이터 시각화 문서에 특화된 API 함수들을 제공하고 있습니다. 이걸 사용하면 초보분들도 충분히 독학으로 데이터 시각화 문서를 만들 수 있기 때문에 배워 두시면 좋습니다. 현재 써먹는 일이 없더라도 알아두시면 나중에 도움이 되실 꺼에요.

마무리


이번에 한번 새벽 3시에 기상이고 아침 시간적 여유가 있을 때 D3.js를 제대로 공부해 볼까 합니다. 아직 과거 기초지식만 있는 상태라도 챠트 표현이 초보 수준이지만 잘 정리해서 제대로 된 결과물을 만들어 볼려고 도전해 보네요. 중간에 일정이 바뀔 수 있지만 현재는 시간 여유가 생겨서 post 형식으로 정리를 해놓으려고 합니다.

'D3.js > D3.js' 카테고리의 다른 글

[D3.js] 애니메이션 효과  (0) 2019.10.21
[D3.js] 막대형 차트로 보는 D3.js  (0) 2019.10.18
[D3.js] Data 실시간 처리  (0) 2019.10.17
D3.js 기본 틀  (0) 2019.10.16
시각화 문서 D3.js를 도전해보자  (0) 2019.10.14

댓글()

시각화 문서 D3.js를 도전해보자

D3.js/D3.js|2019. 10. 14. 09:00

시각화 문서 D3.js를 도전해보자


오늘은 D3.js에 대해 간단히 소개할까 합니다. D3(Data-Driven Documents)는 한마디로 표현하자면 데이터를 시각화하는 문서로 실시간성을 갖고 수치를 그림 챠트와 같은 형태로 쉽게 표현할 수 있다는 점이 큰 장점을 지니고 있습니다. 제가 오래전에 잠깐 기초를 독학으로 공부한 적이 있는데 이제 기억도 가물 거리네요. 이제는 쓰는 방법도 기억이 안나네요. 어렴 픗한 기억으로 한자락을 가지고 포스팅을 해볼까 합니다. 혹시 Steem API를 이용해 데이터를 시각화로 보여주는 사이트를 보신적 있을꺼에요. 그 사이트와 같은 형태로 steem 데이터를 시각적으로 표현해주는데 특화된 API라고 생각하시면 됩니다. 혹시 데이터 시각화에 관심 있으신 분들이 있다면 D3.js를 공부를 해보라고 추천 드리고 싶네요.

하지만 전 공부하다가 포기했습니다. 실전에 써먹을 곳이 저에게 없었고 미리 공부해 놓더라도 사실 버전이 달라지면 약간 혼동과 충돌이 일어나기 때문에 일관성이 약간 부족하다는 점이 단점이여서 시간을 투자하기가 애매해서 포기 했네요. 열심히 현재 버전을 공부했는데 나중 새로운 버전이 나오고 새로운 버전으로 공부한 사람이 과거 버전으로 공부한 사람과 같이 협동해서 작업 할 때 버전 별 충돌 부분이 생기면 참 애매해지는 경우가 생기지 않을까 썩먹을 날이 오면은 제대로 공부를 해보고 싶은 라이브러리라고 생각만 하고 포기했네요.

1. D3.js 설치





해당 첫페이지에서 d3.zip라고 라이브러리를 다운 받을 수 있습니다. 그리고 script 링크 주소 선언을 통해 설치없이 사용이 가능합니다.

2. D3.js 문법


주로 사용되는 기본 함수

  • d3.select - 현재 문서에서 특정 태그 하나를 선택
  • d3.selectAll - 현재 문서에서 특정 태그 전체를 선택
  • selection.attr - 선택된 태그의 속성값 지정
  • selection.data - 참조 연결할 데이터 가져옴(선택된 태그에 데이터 매칭)
  • selection.enter - 데이터 갯수만큼 태그가 부족할시에 플레이스홀더를 반환
  • selection.append - 새로운 태그를 추가
  • selection.exit - 종료(더 이상 필요없는 태그는 반환)
  • selection.remove - 현재 문서에서 선택된 태그를 제거



위 문법 문장의 표현은 홈페이지 가시면 나온 예제인데요 대충 저렇게 세부분의 영역으로 나눠서 생각해 볼 수 있습니다.

d3.select(사용될영역태그).selectAll(선택태그) => d3이 사용될 영역위치를 선택하고 선택된 영역안에 특정 선택태그들을 모두 선택한다는 명령입니다.

data()함수는 선택태그에 사용될 데이터인데 태그와 1:1 매칭된다고 생각하시면 더 쉬울꺼에요.

text()함수내에서 콜백함수를 사용했는데 콜백함수는 d값인데 이것은 data에서 순차적으로 가져온 값(forEach)이고 리턴하니깐 이렇게 되겠죠. text("4")로 표현이 됩니다. 그럼 선택된 태그로 4값을 출력하라는 명령이 됩니다. print 출력함수라고 생각하시면 됩니다. 여기서 'body"안에 선택된 'p'태그들이 이미 데이터 값을 가지고 있으면 어떻게 될까요. 바로 지워지고 새로운 값으로 갱신됩니다. 업데이트가 되는 것이죠. 그렇지만 중요한 것은 'p'태그가 선택된것이 3개라면 선택된 3개 태그의 값만 갱신됩니다. 즉, 이말은 "4, 8, 15"까지의 data 값만 'p'태그에서 갱신이 되고 끝난다는 것이죠. 업데이트만 된다고 생각하시면 됩니다. 나머지 "16, 23, 42"은 쓸 수 없습니다.

그래서 나온것이 다음 문장 //Enter라고 나와 있는데 이 문장 대신에 추가라고 생각하시면 됩니다.

enter().append("p") 하면 실행하는데 더이상 선택 태그가 없으면 "p"태그를 새로 생성하라는 명령으로 이해하시면 됩니다.
그리고 나서 .text()함수를 통해서 나머지 "16, 23, 42"가 'p'태그에 출력 됩니다.

글보다 애래 그림을 보시는게 이해가 더 빠르겠지요.


갱신부분은 'p'태그가 3개뿐이고 해당 "p"태그의 값만 "1,2,3"이 data값에서 순서대로 3개 "4,8,15"로 갱신이 되고 거기서 끝나게 됩니다. 하지만 부족한 부분은 다음 append() 명령으로 나머지 데이터 갯수만큼 추가하게 됩니다. 위에서 data()는 선택된 'p'태그랑 1:1 매칭이라고 했죠. 그래서 나머지 데이터도 1:1 매칭하기 위해서 나머지 갯수만큼 'p'태그가 늘어나는 것이죠.

마지막 exit()함수는 끝내는 문장인데 remove()함수로 나마지 태그를 제거하라는 명령입니다. 이런 경우도 있겠죠. 'p'태그가 10개가 있는데 데이터가 6개라면 어떻게 될까요. 6개의 태그에 데이터를 출력했는데 나미저 4개의 'p'태그에도 데이터가 있으면 충돌나서 혼동이 발생하겠죠. 그래서 해당 데이터 만큼 수행 한 뒤에 나머지 태그가 남아있으면 그 태그는 지우라는 명령으로 이해하시면 됩니다. 즉, 10개의 'p'태그가 기존에 있지만 데이터 6개를 갱신 한뒤에 나머지 4개 태그는 문서상에서 지워버려라는 의미로 해석하시면 됩니다.

다르게 표현할 수도 있습니다. 해당 위치에 값만 갱신이 필요한 경우는 remove()함만 없애 주면 됩니다. 남은 태그는 그냥 두라는 의미로 종료가 되겠죠.

3. D3.js 예제로 느끼자.


<!doctype html>
<html>
<head>
  <title>D3</title>
  <script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
  <div id="aaa"><p>aaa</p></div>
  <div id="bbb"><p>bbb</p></div>
  <div id="ccc"><p>ccc</p></div>
  
  <script>
  var data =[1,2,3,4,5];
  function render(data){
    var p = d3.select("#bbb").selectAll("p").data(data)
           .text(function(d){return d;})
        p.enter().append("p")
           .text(function(d){return d;})
        p.exit().remove();
  }  
  
  render(data);    
  </script>
  
</body>
</html>

select()함수는 태그를 선택한다고 했는데 여기서 "#bbb"로 id를 선택할 수 있습니다. 'body' 태그 안에 'div' 태그 중 세개의 id가 있습니다. 여기서 두번째 'bbb' id 영역을 선택한다고 생각하시면 됩니다. 그리고 그 영역에서 사용되는 태그가 "p"태그입니다. 그런데 "p" 태그는 1개뿐입니다. data 값을 text()로 출력하게 되면 우선 첫번째 "bbb"가 출력된 값이 '1' 업데이트 됩니다. 그리고 더 이상 태그가 없으니깐 다음 문장에서 append("p")로 태그를 추가하게 됩니다. 그리고 나서 나머지 새로 생성된 "p"태그에 "2,3,4,5" 값이 출력되는 것이죠. 그러면 그 결과가 어떻게 나타날까요.

결과

위 그림처럼 "bbb" 위치에 값은 '1'로 갱신이 되고 추가로 나머지 4개의 데이터 값이 출력이 됩니다. 대충 어떤 느낌의 구조인지 아시겠지요.

이런식으로 D3.js은 웹페이지들은 실시간으로 수정과 삭제 그리고 시각화를 할 수 있습니다. 자바스크립트로 표현 하려고 하면 불필요하게 많은 코딩량을 추가해야 합니다. 하지만 이런 기본 문법에서 몇가지만 추가하면 다양한 표현이 가능 해집니다. 자주 사용되는 함수들을 깔끔하게 정리해서 만들어 놓은 라이브러리죠.

재밌는 것은 모든 표현을 D3.js로 할 수도 있지만 다른 css, javascript 표현을 같이 사용할 수 있습니다. 어떤 분들은 css와 javascript로 많이 하신분들은 일부분만 D3.js를 이용하시는 분들도 있고 어떤 분들은 아예 D3.js로 하신분들은 css, javascript에서 사용되는 표현을 잘 모르니깐 모든 표현을 D3.js 문법에 맞게 표현하시기도 합니다. 어떻게 표현하는 것이 좋다고 할 수 없고 그냥 자신이 편한 코딩으로 하시는게 가장 좋겠죠.

4. D3.js 오픈 예제 소스



보시는 것처럼 예제들이 있는데 다양한 D3.js 시각화 예제들이 오픈소스로 공개되어 있습니다. 믈론 라이센스를 잘 확인하시고 쓰셔야 합니다. 하지만 학습용으로는 이만한 예제는 없습니다. 소스까지 다 공개되어 있으니깐요.

5. D3.js API Reference



D3.js 메인창에서 문서 항목를 클릭하시면 이 창이 뜨는데 한국어를 지원합니다.


여기서 API Reference를 선택하시면 됩니다.


이렇게 함수에 대한 의미가 잘 소개 되어 있는데 샘풀 예제가 없어서 처음 하시는 분들은 익숙치 않을꺼에요. 그럴때에는 구글 검색을 하시면 됩니다.
참고로 D3.js를 바로 하시기 전에 아래 링크 걸린 사이트에서 HTML과 그 안에 SVG를 집중적으로 공부하시고 CSS도 어느정도 습득하시고 하면 더 빠르게 배울 수 있습니다.

대부분 시각화하면 그림 형태로 출력하는 경우가 많습니다. 시각화 문서를 하는 이유가 그림 형태로 표현하기 위해서이죠. 바로 D3.js로 표현하는 걸로 들어가기 전에 HTML로 SVG에 대한 속성이나 표현을 잠깐 읽으시고 들어가시면 D3.js가 좀 더 쉽게 다가올꺼에요.

- HTML, CSS. JavaScript 참고 사이트 : https://www.w3schools.com/

- 유튜브 : Introduction to D3 - 강사: Curran Kelleher

제가 처음에 D3.js를 공부하면서 배울때 유튜브 검색에서 찾아낸 강의 내용입니다. 이분 링크사이트 가시면 소스가 파트별 공개되어 있습니다.
참고로 v3 버전용 강의입니다. 전 v4로 연습했는데 이게 서로 매칭해서 함수 찾는데 시간 무자게 잡아 먹었어요. 따라 하실때 v3로 그냥 하시는 걸 추천 드려요. v5으로 최근걸로 하시면 답답 하실꺼에요. "왜! 안돼!" 에러난 위치를 보고 함수명이 잘못되었고 그 함수명이 어떻게 바뀌었는지 일일히 찾아서 표현을 바꿔야 하기 때문에 시간이 엄청 소요 됩니다. 강의 들으면서 수시로 레퍼런스를 찾아가서 해당 함수를 찾으셔야 합니다.
그냥 속편하게 v3로 따라서 연습을 끝내고 나서 익숙해지면 그제서 v5로 연습하시고 변경된 부분만 바꾸시면 될꺼에요.
암튼 이분 강의 내용은 기본적인 웹 내용을 먼저 설명해주고 D3.js을 들어가니깐 전부 다 가르쳐 준다고 생각하시면 됩니다.
한방에 다 해결되는 것이죠. 따로 공부할 필요 없이 이분 것 한시간 30분가량 되는 내용인데 꼭 보시라고 추천 드려요. 제가 쉽게 d3.js를 이해하는데 가장 큰 도움을 준 유튜브 강좌였던 것 같습니다.

마무리


D3.js는 시각화 라이브러리로 아주 강력합니다. 단순히 위에서 소개한 내용은 기초입니다. 시각화에 사용되는 함수들이 꽤 잘 정리되어 있고 함수로 많이 만들어 놓았기 때문에 어려움 자바스크립트 표현들을 쉽게 접근할 수 있습니다. 혹시 프로그램을 처음 입문하시는 분들이라면 D3.js를 공부해보시는 추천드립니다.

어제 D3.js에서 json 읽는 법을 거론하면서 포스팅으로 D3.js를 소개하면 좋을 것 같아서 이렇게 소개하게 되었네요. 물론 웹 프로그램을 좀 하시는 분들은 다들 D3.js를 어느정도 알거나 접해보셨을 꺼에요.

이제 입문하시는 분들이라면 한번 공부해보시는 것도 나쁘지 않을 것 같아서 이렇게 소개합니다. 그리고 Steem API로 읽은 데이터를 D3.js로 이용하시면 재밌는 것들을 아마 많이 만드실 수 있을거에요. Steem API와 연동한다면 활용범위는 엄청 넓어진다고 생각 되네요.

시각화 전용 API이깐요. 화려한 그래픽으로 표현하고 싶은데 표현력이 부족하시다면 여기서 제공하는 함수로 한번 도전해 보세요.


'D3.js > D3.js' 카테고리의 다른 글

[D3.js] 애니메이션 효과  (0) 2019.10.21
[D3.js] 막대형 차트로 보는 D3.js  (0) 2019.10.18
[D3.js] Data 실시간 처리  (0) 2019.10.17
D3.js 기본 틀  (0) 2019.10.16
D3.js 버전5로 공부 시작  (0) 2019.10.15

댓글()

당신은 어떤 성격의 소유자인가요?(성격유형검사)

유용한팁|2019. 10. 9. 09:00

당신은 어떤 성격의 소유자인가요?(성격유형검사)



예전에 성격테스트를 할 일이 었어서 우연히 알게 된 사이트인데 개인적인 생각이지만 꽤! 잘맞는 것 같아요. 여러분들도 한번 자신는 어떤 성격의 소유자인지 테스트를 한번 해보세요.

무료 성격유형검사



16Personalities라는 사이트인데 상단의 빨간 상자 모양으로 표시한 위치에 언어를 선택 할 수 있는데 클릭해서 한국어로 선택하시면 됩니다. 다양한 언어로 테스트를 받을 수 있네요. 위에 무료 성격 유형 검사 사이트를 링크 한곳에 "/ko"라고 붙이면 알아서 한국어로 번역 된 페이지가 나타 납니다.

위에 항목에서 성격유형을 선택하면 성격 유형들을 잘 분류해 놓았는데 성격 분류를 크게 분석형, 외교형, 관리자형, 탐험가형으로 나뉘고 각 유형에서 다시 세부적으로 4가지 유형으로 나뉘는데 직접 가셔서 확인 해보세요

검사 시작



위 그림에서 질문에 대해 동의와 비동의가 있는데 총 7개 원에서 어느정도 동의하느냐 비동의하느냐를 클릭하시면 되고 동의도 비동의도 아니다면 가운데 회색원을 클릭하시면 됩니다. 어렵지 않고 부담없이 순간 생각하는 느낌으로 빠르게 선택하세요. 잘 맞춰야 겠다는 생각이나 뭔가 좋의 성격이 나오도록 의도된 답안을 작성하시면 안됩니다. 그래야 정확한 진단을 할 수 있으니깐요.

테스트 결과


저의 테스트 결과는 다음과 같습니다.


"선의의 옹호자"로 나오더군요 마음, 에너지, 본성, 전술, 자아 등을 각각 몇퍼센트의 성격을 가지는지 표시 되는데 자신의 성향을 수치화 한 것 뿐이고 전체적 성격을 보시면 됩니다. 재밌는 것은 "선의의 옹호자"의 내용을 읽어보면 평소 제가 가지고 있는 생각과 비슷하게 나와서 놀랐습니다. 내 삶의 방향과 제가 추구하는 그런 세계관이 잘 맞아 떨어지더군요. 처음 이 검사를 재미로 했는데 평소 가지고 있던 생각들이 "선의의 오호자"자의 성격과 많이 비슷해서 결과가 나와서 개인적인 생각이지만 어느정도 적중도가 높아 보이더군요. 표본이 저 혼자여서 적중도를 말하기 애매하지만 여러분들은 얼마나 비슷한 결과가 나오는지 한번 테스트 해보세요.

여러분들도 한번 테스트 해보시고 가능하시면 댓글로 일치하는지 알려주세요. 얼마나 적중도가 높은지 통계를 내고 싶네요.

여러분들은 어떤 성격의 소유자인가요?

마무리


추가로, 온라인으로 MBTI 검사라는 것도 있는데 한번 그것도 검색을 통해 찾아보시고 테스트를 해보세요. MBTI은 온라인 상에서 정식 테스트가 아니라 누가 문제지를 만들어 올린 것 같아서 해당 페이지 경로는 링크를 걸어 놓지 않겠습니다. 온라인 상에서 이런 진단 사이트들이 많기 때문에 관련 키워드로 온라인 검사가 있는지 한번 찾아보시고 검사를 해보세요.


'유용한팁' 카테고리의 다른 글

대화형 ChatGPT 소개  (2) 2023.03.12
[온라인 도장] 문서에 도장 삽입하기  (0) 2019.07.01
Fritzing 회로도 디자인  (0) 2019.02.03
논문 검색  (0) 2019.02.02
구글 스케치업으로 온라인 3D 도면 디자인 하기  (0) 2019.02.01

댓글()

[아두이노] 엔트리로 초음파레이더 졸작

IOT/아두이노|2019. 10. 8. 09:00

[아두이노] 엔트리로 초음파레이더 졸작



스크래치로 뭔가 표현한 작품을 하나 만들면 좋을 것 같아요. 엔트리에 초음파센서와 서보모터를 제어하는 블록이 있기에 이 두 블록을 가지고 표현할 수 있는 작품으로 떠오르는 것은 초음파레이더가 있더군요. 멋지고 좀 더 깔끔하게 블록을 만들면 좋은데 대충 post 주제를 정하고 막코딩을 해서 느낌만 비슷하게 초음파 레이더 원리 동작만 수행하는 간단한 졸작을 하나 만들어 봤네요.

1. 스크래치로 초음파레이더 설계


설계 :

  • 초음파센서 값 읽기
  • 초음파센서로 반경 180도 범위의 100미만 거리에 장애물을 감지하기 위해서 서보모터 회전
  • 엔트리 화면에 레이더 각도 바 표시
  • 초음파센서로 물체 감지했을 때 감지한 위치에 물체 표시

대충 4가지 형태로 나누어 표현 하겠습니다.

초음파센서 값 읽기


지난시간에 초음파센서값을 읽기를 했었습니다. 아래와 같은 표현을 하시면 됩니다.


변수블록에서 거리라는 변수를 만드시고 거리 블록에다가 초음파센서 센서값 블록을 배치하면 계속 반복하기로 실시간으로 현재 거리변수에 초음파센서 값이 저장되게 됩니다.

초음파센서로 반경 180도 범위의 100미만 거리에 장애물을 감지하기 위해서 서보모터 회전


서보모터를 제어하는 블록을 가지고 180도 회전을 좌/우로 왔다 갔다 해보도록 합시다.


위 블록을 보시면 우선 각도라는 변수 블록을 만들어 주세요. 그리고 초기값으로 0으로 처음 정하게 됩니다. 그리고 서보모터오 0도로 초기각도를 잡아 주는데 다음 동작을 수행하지 않도로 3초의 대기시간을 부여 합니다.

계속 반복하기로 각도는 1씩 증가하고 그 각도를 1도씩 증가한 각도로 회전을 하게 됩니다. 그리고 180도까지 회전했다가 반대로 180도에서 0도로 1도씩 감소시켜 0도가 될때까지 반복하게 됩니다 이렇게 해서 0~180도 회전을 왔다 갔다 하게 됩니다.

엔트리 화면에 레이더 각도 바 표시




회전을 시키면 그 회전된 각도를 엔트리에 표시하기 위해 하나의 바 이미지를 붓으로 그리는 표현을 했습니다.

초기 위치는 좌표(0,-100)로 레이더 바의 시작 위치가 됩니다 방향은 0도로 했기에 오른쪽에서 왼쪽으로 회전하게 됩니다. 초기 상태니 붓(펜)이 그려져 있으면 모두 지우라는 명령이고
붓의 색과 굵기를 초기로 지정합니다.

그다음 계속 반복하기 블록이 반시계방향으로 180도 회전했다가 시계방향으로 180도 회전하는 반복문이 안에 표현되어 있어 왔다 갔다 반복하면서 레이더 바의 움직임을 표시합니다. 이 바는 현재의 각도 위치만 표시 되어 야 하기 때문헤 한번 그리고 난뒤 다음 바를 그릴 때 먼저 모든 붓 지우기로 바을 지우고 나서 다시 그립니다.

반시계 방향으로 180도 회전


모든 붓 지우기는 이전 그려진 레이더 바를 지우는 명령이고 그리기 시작과 그리기 멈추기 사이에 붓으로 그리는 작업이 수행됩니다. 시작위치는 좌표(0,-100) 지점에서 이동방향이 200이면 좌표(0,-100)꼭지점에서 이동방향쪽으로 200지점까지 붓으로 그리게 됩니다. 즉, 하나의 선이 그려집니다. 그 선을 -1도 각도회 회전시키는 명령입니다. 이걸 180번 하기 때문에 1도씩 오른쪽에서 왼쪽으로 하나의 선이 그려집니다. 이전 선을 지우고 새로운 선이 그려지는 과정을 반복하게 됩니다. +1도 씩 180번 회전하면 반대로 왼쪽에서 오른쪽으로 레이더 바가 회전하겠죠.

초음파센서로 물체 감지했을 때 감지한 위치에 물체 표시


초음파센서로 장애물을 감지하면 장애물이 감지한 위치에 장애물임을 표시하는 오브젝트를 표시를 하겠습니다.


빨간 상자가 물체 표시 마크입니다. 그리고 총 세 블록으로 나누어서 블록코딩을 하였습니다.

첫번재 블록은 시작하면 장애물 표시가 엔트리 화면에 표시되면 안되겠죠. 그래서 모양을 숨겨야 합니다. 이 숨긴 본체 오브젝트 이미지는 사용하지 않고 복제본을 사용 할 꺼에요. 복제본을 사용하는 이유는 일정시간이 되면 소멸 시키기 위혀서 입니다. 무한으로 장애물 표시를 화면에 표시하면 안되겠죠. 일정 시간이 되면 자동으로 사라져야 하기 때문에 이 본체 이미지는 숨기고 복제본 이미지로 만들었다 삭제했다 이런식으로 해서 필요할 때만 생성하도록 하여 물체 그리기의 낭비를 줄입니다.

두번째 블록은 계속 반복하기가 있는데 만일 거리값이 100이하면은 100미만의 장애물만 감지하겠다는 의미가 100미만의 장애물리 감지되면 자신을 즉 모양숨기기를 했던 본체 원을 복제본을 만들겠다는 명령입니다. 복제본을 무한으로 연속 만들면 컴퓨터에 무리가 가기 때문에 0.5간격으로 체크해서 복제본을 만들게 됩니다.

세번째 블록은 복제본이 생성이 되면 수행되는 블록입니다. 장애물 감지된 위치에 복제본을 이동시켜야 하기 때문에 초기 지점인 좌표(0,-100)에거 장애물 감지한 거리값을 토대로 이동 방향으로 "거리x2"만큼 움직이기라는 블록으로 감지된 위치로 원을 표시합니다. 왜! 2를 곱했냐면 엔트리 창 화면의 100까지의 거리는 너무 짧아서 좀 더 크게 보기 위해서 2배 거리를 키워 화면상에 좀 크게 보이게 표시 했다고 생각하시면 됩니다. 여기서, 복제본을 이동시켰지만 원본 모양이 숨겨져 있기 때문에 숨겨진 복제본으로 이동하여 화면에 표시가 되지 않습니다. 그래서 모양보이기로 화면에 보여지게 하고 2초동안 장애물 표시를 하다가 해당 복제본이 삭제하기로 소멸시키게 표현 했네요.

이러헥 해서 초음파센서로 장애물이 감지되면 그 위치에 장애물 표시를 하고 표시된 마크는 2초후 소멸된다고 생각하시면 됩니다.

[결과]


2. 엔트리 초음파 레이더 회로도




3. 엔트리 블록 코딩



위 오브젝트 창에 전부 블록 코딩합니다.

[1단계] 초음파센서로 장애물 감지 블록 코딩


[2단계] 서보모터 회전과 붓으로 레이더 바 표시 블록 코딩


[3단계] 장애물 감지 시 장애물 표시 마크를 복제본을 생성하여 해당 위치에 장애물을 표시 했다가 2초 후 소멸 시키는 블록 코딩


4. 결과


한손에 폰을 들고 한돈에 초음파센서를 들고 찍다보니 영상이 많이 흔들리고 정확히 촬영이 되지 못했네요. 간단히 레이더 바로 현재의 각도를 표시하고 100 미만의 장애물 감지시 장애물 표시가 되게 나오도록 했네요. 참고로 서보모터의 회전은 위 블록코딩은 불안전 합니다. 그 이유는 지속적으로 회전을 시키라는 메시지를 아두이노에 보내고 아두이노는 그 메시지가 누족되기 때문입니다. 만약 딜레이 대기시간이 없다면 엔트리의 회전 레이더바가 180도 회전이 끝더라고 서보모터가 90도도 회전을 못하는고 회전이 누적되어 있게 됩니다. 180도를 왔다 갔다 한바퀴 돌고 난뒤에도 서보모터는 일정 각도뿐이 회전을 못하게 됩니다. 만약 중지 명령을 내리면 누적된 서보모터는 중지 명령이 떨어져도 누적된 회전만큼 계속 회전 동작을 수행합니다. 서보모터 따로 엔트리 따로 동작하는 결과가 발생하게 됩니다. 위 블록도 그냥 0.5초 대기를 줘서 서보모터의 회전각을 유사하게 맞춘 것이지 정확히 일치하지 않습니다. 단지 원리를 이해하기 위한 실험이여서 대충 블록 코딩을 했을 뿐이지 감안하시고 보시기 바랍니다.


노이즈 값도 장애물로 인식해서 장애물 표시가 뜨네요.

마무리


엔트리를 사용하면서 엔트리 따로 아두이노 따로 동작하는 현상이 발생하였습니다. 엔트리 블록 코딩은 엔트리 기준으로 동작하기 때문에 아두이노가 엔트리에 맞게 동작을 하는지 확인을 할 수 없습니다. 물론 엔트리가 중간의 특정핀에 전류가 공급되게 하고 그 전류를 다시 특정핀에서 확인하여 전류가 흐르는 상태인지 체크를 통해 중간에 체크 블록을 만들면 해결 되기는 합니다. 너무 복잡해지기 때문에 그 부분은 생략합니다.

아무튼 위 블록 코딩은 불안전환 코딩이고 엔트리가 무조건적인 명령문을 수행 할 뿐 아두이노의 서보모터 동작이 정상적으로 작동하는지 체크하지 못했기 때문에 졸작이라는 문구를 붙이게 되었네요. 그리고 초음파센서 거리 측정을 서보모터가 회전 했을 때 그 안에서 측정을 했어야 했는데 블록 코딩을 설명을 하기 위해서 분류했는데 그상태로 두고 말았네요. 완성하고 나니 이 부분이 참 아쉬운 부분이네요.


댓글()

[아두이노] 엔트리로 아두이노 제어

IOT/아두이노|2019. 10. 7. 09:00

[아두이노] 엔트리로 아두이노 제어



지난 시간까지 해서 S4A 스크래치와 ScratchX로 아두이노와 연결하여 제어를 해보았습니다. 오늘은 마지막으로 국산 엔트로로 아두이노를 연결하여 제어해 보는 시간을 갖도록 하겠습니다. 엔트리도 ScratchX 마찬가지로 온라인상에서 웹브라우저로 아두이노를 연결하여 제어를 하게 됩니다 ScratchX 플러그인을 설치하여 연결했다면 엔트리는 따로 PC에 연결 프로그램을 설치해야 연결 할 수 있습니다. 엔트리를 이용한 아두이노 제어는 의외로 간단하여 사용하기 편합니다.

이제부터 엔트리로 아두이노를 제어를 해봅시다.

1. 엔트리



엔트리 공식 사이트에 들어가사 작품만들기를 누르면 아래와 같이 기본 창이 뜹니다.


스크래치를 먼저 공부한 분들은 창이 처음에 좀 불편할 수 있고 블록들이 좀 더 많은데 스크래치는 간단히 최소 블록만 제공하는데 약간 엔트리는 약간 상황들을 더 추가한 블록들로 블록의 갯수가 좀 더 많습니다. 스크래치는 어떤 프로그램을 쓰더라고 기본베이스는 전부 동일합니다. 선택은 여러분들이 편한 걸 사용하시면 됩니다.

2. 엔트리에서 하드웨어 연결 프로그램 설치 및 연결


1) 하드웨어 연결 프로그램 설치


엔트리에 아두이노우노와 연결을 하기 위해서는 하드웨어 연결 프로그램을 설치해야 합니다.

하드웨어 블록은 누르면 아래와 같은 5개의 선택 항목이 나타납니다.


  • 연결 프로그램 다운로드 : 이 프로그램을 PC에 다운로드 받으시면 됩니다.
  • 연결 안내 다운로드 : 일반 PC 설치와 블루투스 설치에 관한 자세한 안내서입니다.
  • 엔트리 아두이노 소스 : 펌웨어 소스인데 안받으셔도 됩니다.
  • 하드웨어 연결하기 : 연결프로그램을 열고 연결하면 되기 때문에 구지 사용하지 않습니다.
  • 연결 프로그램 열기 : PC에 연결프로그램이 설치되어 있으면 이걸 클릭하면 연결프로그램이 실행 됩니다.

첫번째 연결 프로그램을 다운로드 받아서 설치하면 끝납니다.

2) 하드웨어 연결


연결 프로그램 열기를 클릭 하시면 PC에 설치된 연결 프로그램이 실행 되고 아래와 같은 창이 뜹니다.


위 그림을 보면 다양한 보드를 제공합니다. 아두이노 Uno 정품보드로 처음에 사용해 보세요. 그리고 초음파센서나 Servo모터를 사용할 경우 아두이노 Uno 확장모드를 사용하시면 됩니다.

아두이노 Uno 정품보드를 클릭을 해보세요. 아래와 같은 창으로 넘어갑니다.


현재 아두이노를 연결 안해서 연결중으로 표시되는 데 연결되면 연결성공이라고 뜹니다. 여기서, 처음 한번만 펌웨어 설치를 누르시면 됩니다. 연결이 제대로 안되면 드라이버 설치를 처음 한번 눌러서 설치하시면 됩니다. 참고로 이 창은 닫으시면 안되고 계속 열어놓으셔야 엔트리와 아두이노 간의 연결이 유지 됩니다.

3) 엔트리에서 아두이노가 인식 상태




위 그림처럼 "하드웨어가 연결되었습니다"라는 멘트가 뜨고 아두이노 Uno 정품보드 블록들이 생성 됩니다. 5개의 블록 뿐이 없습니다. 스크래치 블록과 5개의 블록을 가지고 블록코딩을 하시면 됩니다.

4) 엔트리에서 아두이노 Uno 정식보드 블록


5개의 블록들을 간단히 살펴보도록 하죠.ㅁ


analogRead(pin);

아날로그 입력으로 0~1023 사이의 값을 가져옵니다.



digitalRead(pin);

디지털 입력으로 해당핀에 0 or 1의값을 가져옵니다.



digitalWrite(pin, value)

디지털 출력으로 HIGH(켜기) or LOW(끄기)의 출력을 표현 하니다.



analogWrite(pin, value)

0~255사이의 아날로그 출력을 할 수 있습니다.



map(analogRead(pin), 0, 1023, 0, 100);

입력 숫자만 원하는 형태로 바꾸면 됩니다.

2. 엔트리와 아두이노 실험


실험은 아두이노 Uno 확장모드에서 이루어집니다. 아두이노 Uno 확장모드를 선택하고 펌웨어 설치를 다시 한번 해주세요.

그러면, 아래 그림처럼 블록이 몇개 더 생성 됩니다. 확장모드에서는 초음파센서와 서보모터와 피에저부조를 제어할 수 있는 블록이 추가되었네요.


1) 회로도





2) 블록 코딩



위 블록 코딩은 간단한 테스트 입니다.

첫번째 블록 코딩은 디지털 13번 핀을 1초 단위로 깜박이는 "Blink예제" 입니다.
두번째 블록 코딩은 거리라는 변수에 만들고 그 변수에 초음파센서값을 저장합니다. 그리고 엔트리봇이 1초동안 초음파센서로 측정한 거리 만큼 x좌표로 이동시키라는 블록 코딩입니다.

지난 시간에 다른 스크래치 프로그램에서 변수 선언에 배웠고 엔트리에서도 동일하니깐 설명은 생략합니다. 초음파센서는 아두이노에 연결하는 Trig, Echo핀만 주의해서 연결하고 해당 핀 값을 블록코딩에 정확히 기입하셔야 정확한 결과가 나옵니다.

3) 결과


영상을 보시면 왼쪽에 원이 있습니다. 이 원은 1초 단위로 색이 바뀝니다. 아두이노 Red LED와 같은 시간으로 동작합니다. 즉, 엔트리의 원와 아두이노 LED를 동일한 시간대에 동작을 수행합니다. 엔트리와 아두이노의 표현을 일치시키는 느낌이지요. 나중에 이런 느낌의 표현은 엔트리를 가지고 아두이노를 제어 할 때 많이 사용합니다.

그리고 거리는 제가 가지고 있는 초음파센서가 최대 145정도 거리 값이 나오더군요. 0~145사이를 앞에 장애물이 감지 될때 거리를 측정 할 수 있네요. 0~145사이의 x좌표로 엔트리봇이미지가 이동하게 됩니다. 별 의미 없고 초음파 센서로 엔트리봇을 움직이게 하는 간단한 테스트 입니다.


마무리


이렇게 해서 S4A 스크래치, ScratchX, 엔트리에서 아두이노를 연결하는 방법을 간단히 알아 보고 간단한 예제로 제어까지 하였습니다. 얼핏 보면은 스크래치로 아두이노 제어하는게 편해 보일꺼에요. 그냥 해당 블록을 배치하고 아두이노를 코딩하지 않고 쉽게 제어가 되기 때문에 구지 아두이노를 C언어를 공부하고 코딩 할 필요가 있을가 하고 생각하시는 분들도 있을 거에요. 그런데 실상은 전혀 그렇지 않습니다. 더 복잡하고 더 어렵습니다.

그 이유는 간단한 제어는 이미 블록이 제공 되기 때문에 그 블록을 사용하여 쉽게 아두이노 동작을 수행 했을 뿐 조금만 변화를 주면 블록 코딩은 너무 복잡해 집니다. 오늘 배운 아두이노 Uno 정품보드의 블록을 보시면 5개 블록만 제공합니다. 이 블록을 가지고 초음파센서와 Servo모터를 제어한다고 생각해 보세요. 답이 안보이죠. 다행히 아두이노 Uno 확장모드에서 해당 블록을 제공하기 때문에 쉽게 제어 할 수 있는 것 뿐이죠.

즉, 스크래치로 아두이노를 제어하기 위해서는 제어 할 블록이 없다면 그 블록은 여러분들이 만드셔야 합니다. 그리고 만들기 힘들 경우는 해당 펌웨어 소스에 가서 일부 소스 내용을 수정을 해야 합니다. 아니면 누군가 만들어 놓은 펌웨어 소스를 가져다가 사용해야 합니다. 스크래치로 수많은 부품을 제어를 할 때 쉽게 딱 만든 블록으로 코딩하기 힘듭니다. 오픈 블록이나 펌웨어 소스를 쉽게 찾을 수 없고 찾는 다 해도 단적인 제어만 가능하고요 여러 부품들을 연계해서 제어 한다면 무지 힘들꺼에요. 어느 순간이 되면 그냥 프로그램언어를 배우고 함수 단위 코딩을 하는게 더 쉽다는 것을 느끼게 될 꺼에요.

C언어 기본 문법을 배우고 오픈 라이브러리 함수들을 사용하여 함수 단위로 C언어 코딩을 하는게 나을 거라 생각 됩니다. 처음에는 C문법을 배우는게 좀 버거울 수 있지만 기본 개념만 잡아 놓으면 오히려 스크래치를 제어하는 것보다 쉽게 다양한 전자부품을 제어 할 수 있을 거에요. 스크래치는 그냥 어린아이들에게 전자 공부를 쉽게 하기 위한 도구로만 생각하시면 됩니다.

그리고, 스크래치와 아두이노 연계는 프로세싱과 아두이노 연계과 유사힙니다. 프로그램 언어에 관심이 있으면 처음부터 프로세싱과 아두이노로 나아가는 걸 추천 드려요. 처음에는 프로세싱와 아두이노 연계 표현이 어렵지만 나중에 어느정도 궤도에 오르시면 오히려 자유로운 표현을 쉽게 할 수 있어 편하게 느끼실 꺼에요. 참고로, 프로세싱과 순수 아두이노 소스는 오히려 오픈 소스가 더 많고 쉽게 찾을 수 있기 때문에 프로그램 언어 독해력만 있으면 충분히 독학으로 공부 할 수 있으니깐 한번 도전해 보세요.


댓글()

[아두이노] ScratchX로 아두이노 제어

IOT/아두이노|2019. 10. 4. 09:00

[아두이노] ScratchX로 아두이노 제어



지난 시간에 S4A 스크래치로 아두이노를 제어하는 방법을 알아 보았습니다. S4A 스크래치 말고도 다른 스크래치로도 아두이노를 제어 한다고 했었죠. S4A 스크래치는 해당 스크래치 프로그램을 PC에 설치 한 뒤에 아두이노를 연결했지만 이번에 배울 스크래치는 온라인 상에서 웹브라우저로 아두이노를 연결하여 제어 할 수 있는 ScratchX에 대해 이야기를 하고자 하겠습니다. 유사하게 국산 엔트리도 있지만 우선 ScratchX로 아두이노를 실험해 봅시다.

1. ScratchX



스크래치 형태로 여러가지 실험을 할 수 있는 베타 버전입니다. 오래 전 부터 베타 버전이였는데 아직도 베타 버전이네요. 온라인 상에서 스크래치x는 외부 하드웨어와 연동하여 다양한 실험을 할 수 있는 서비스를 제공하고 있습니다.


위 그림을 보시는 것처럼 다양한 확장 프로그램들 제공합니다. 원하는 실험을 선택하시면 해당 실험에 맞는 스크래칙 블록들이 세팅되어 있어서 특정한 전용 실험이 가능합니다. 첫번째 이미지는 아두이노인데 아두이노와 연결하여 실험할 수 있는 확장프로그램으로 생각하시면 됩니다.

2. 스크래치 플러그인 설치


온라인 상에서 스크래치 프로그램을 사용하기 위해서 Adobe 플래시 플레이어가 설치되어 있어야 합니다. 이 부분은 ScrtchX 사이트에 가셔서 해당 확장프로그램을 실행시켜보시면 Adobe 플래시 플레이어가 안깔려 있으면 설치하라는 멘트가 나오고 설치되어 있으면 활성화 할지를 선택하라는 멘트가 나올꺼에요. 여러분들이 직접 설치가 안되었으면 설치하고 활성화 안되었으면 활성화 시키면 됩니다. 이부분은 설명이 필요 없겠죠.

플러그인 설치하셔야 외부 아두이노와 연결을 할 수 있습니다.




플러그인 다운로드 주소로 가시면 Mac과 윈도우 버전으로 나뉘고 크롬과 다른웹 브라우저로 나뉩니다. 참고로 플러그인을 설치한다고 무조건 다 실행되지는 않습니다.

윈도우 64bit 운영체제에서는 크롬버전을 설치를 해도 연결이 안됩니다.


다른 웹브라우저용 플러그인을 설치를 해도 대부분 위처럼 연결이 안되거나 아예 플러그인이 인식이 대부분 안되네요.


위 그림처럼 파이어폭스에서 빨간불로 플러그인 인식이 안되더군요. 알아보니깐 윈도우 64bit에서는 안되고 32bit 특정 버전을 설치하면 인식이 된다고 하네요.

오기가 생겨서, 크롬, 파이어폭스, 오페라, 익스플로우, 엣지, 웨일, 오페라 네온, 스윙 브라우저들을 다 실행 시켜보았습니다. 연결인 안되는 노란불이 들어오거나 플러그인 인식이 안되는 빨간불이 들어오더군요. 딱 하나 스윙 브라우저가 정상적으로 인식이 되었습니다.

스윙 브라우저를 찬양하라!


스윙 브라우저에서 정상적으로 아두이노가 연결이 되었네요. 정상 연결인 초록불이 들어 왔습니다. 안되면 파이어폭스 특정 버전으로 다시 설치 할까 했는데 그럴 필요가 없어졌네요. 스윙 브라우저로 정상적으로 플러그인이 작동해도 다행이였어요.

3. 아두이노 펌웨어


아두이노에 펌웨어 소스를 이식해야 하는데 따로 다운로드를 받을 필요가 없습니다. 아두이노 IDE에서 제공되는 펌웨어 소스를 그대로 사용 가능합니다.


위 그림에 표시된 StandardFimata 소스를 아두이노에 이식한 후 ScratchX에 연결 하시면 됩니다.

4. ScratchX 실행


확장프로그램 중 아래 그림처럼 이미지를 클릭해서 들어 가시면 됩니다. 처음 블록 코딩을 잘 모르시는 분은 아래 sample project를 누르시면 됩니다. "blink 예제"가 세팅되어 있거든요.


전 그냥 이미지를 클릭하고 아무것도 되어 있지 않는 빈상태로 들어 갔네요.

추가블록에 아두이노 연결이 성공하면 아두이노 블록들이 표시 됩니다. 아두이노 블록과 스크래치 블록들을 조합하여 1번, 2번 블록을 아래 그림처럼 배치해 보세요.


1번 블록 : 13번 핀을 led A에 연결은 디지털pin으로 출력모드로 led_A~led_D로 4개의 출력모드로 되어 있습니다. 해당 핀을 연결한다는 것은 해당 13번 핀을 디지털 출력모드로 선언으로 이해하시는 것이 좋을 것 같아요.

const byte led_A = 13;
void setup()
{
  pinMode(led_A, OUTPUT);
}

2번 블록 : led_A핀을 켜기(HIGH)->1초대기-> led_A핀을 끄기(LOW) -> 1초대기 를 무한 반복합니다. 즉, 1초 단위로 깜박이는 동작을 수행하게 됩니다.

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

아두이노 코딩을 해보셨다면 대충 어떤 느낌의 블록 코딩인지 아시겠지요.

주의할 점은 스크래치를 실행을 누른다고 무조건 실행이 되지 않습니다. 위 1번 블록을 먼저 클릭해서 세팅을 한 뒤에 실행을 눌러야 정상적으로 동작합니다. 왜! 실행을 눌렀는데 13번 LED가 깜박이지 않는 거야 하고 실수를 범할 수 있으니 꼭 1번 블록 코딩을 먼저 클릭을 한번 한 뒤에 실행버턴을 눌러 실행하시기 바랍니다.

4. 실행


1) 회로도





2) ScratchX에서 블록 코딩



주의 : "when device is connected" 블록은 먼저 수동으로 클릭해서 세팅 한 후 클릭했을 때 실행을 수행하시기 바랍니다 그냥 클릭했을 때 누르면 작동 안해요.

3) 결과


정상적으로 Red LED가 깜박이네요.


마무리


ScratchX로 실험 할 때는 플러그인 문제가 가장 골치거리 입니다. 그리고 플러그인이 가끔 인식이 잘 안될 때가 있습니다. 다시 해당 확장 프로그램을 접속하시거나 아두이노의 USB를 PC에서 분리 했다가 다시 연결해 보세요. 몇번 시도하면 정상적으로 인식 됩니다.

S4A 스크래치 보다는 온라인 상에서 실시간으로 연결 할 수 있다는 장점이 있는데 문제는 플러그인 문제가 브라우저마다 인식 문제가 있기 때문에 불편 합니다. 그래도 따로 프로그램을 설치 할 필요없이 플러그인만 설치하면 되니깐 빠르게 인터넷이 연결 된 아무 PC에서 실험을 할 수 있어 괜찮은 것 같아요.

S4A 스크래치로 아두이노 연결하는 것만 post하기가 약간 그런 것 같아서 다른 스크래치도 다 연결해 보는 실험을 하면 괜찮을 것 같아서 ScratchX와 아두이노 연결 편을 post로 작성해 보았네요. 내일은 엔트리로 연결을 해보겠습니다. 한번에 스크래치와 아두이노 연결 부분을 post로 다 정리해 놓아야 겠어요.


댓글()

[아두이노] S4A 스크래치에서 아두이노로 이미지 조정하기

IOT/아두이노|2019. 10. 1. 09:00

[아두이노] S4A 스크래치에서 아두이노로 이미지 조정하기



오늘은 어제 이야기 하려다 못한 내용으로 아두이노로 스크래치 이미지를 컨트롤하는 실험을 해볼까 합니다. 스크래치와 아두이노는 서로 쌍방 통신이 가능합니다. 스크래치에서 아두이노에 연결된 Sensor를 읽을 수 있고 아두이노에서 스크래치에 그려지 이미지(케릭터)를 조정을 할 수 도 있습니다. 서로 쌍방 통신으로 읽기/출력이 가능하기 때문에 스크래치를 이용하면 재밌는 것들을 만들 수 있습니다. 어제는 스크래치에서 아두이노 출력하는 LED 깜박이기 였다면 오늘실험은 스크래치에서 아두이노 값을 읽어 오는 방법을 간단히 실험해 보겠습니다. 내용은 아두이노에 연결 된 가변저항기를 조절하여 스크래치 상 고양이 케릭터를 조정해보는 실험이 되겠습니다.

1. S4A 스크래치 이미지 세팅


무대 세팅 : 


무대 창을 누르면 스크립트/배경/소리가 있는데 여기서 배경에서 새로운 배경을 가져오기 눌러 스크래치에 제공되는 배경 이미지를 찾아 적당한 걸 가져오시면 됩니다. 참고로, 소리를 눌러보세요. 여러가지 사운드를 제공하는데 게임같은 것을 만들 때 배경음악으로 사용하면 좀 더 그럴싸한 표현을 할 수 있습니다.

스프라이트 고양이 추가 :


위 화살표를 보시고 스프라이트 파일 선택을 눌러서 고양이 이미지를 가져 옵니다, 참고로 왼쪽에 스프라이트 창에서 모양을 눌러 가져오기를 다시 눌러서 다른 고양이 장면을 가져 오세요. 그러면 하나의 스프라이트창에 두개의 이미지를 넣을 수 있습니다. 이렇게 하면 두 이미지를 교대로 교체하면 고양이 걷는 모션을 만들어 낼 수 있습니다. 참고로, 무대 세팅에서 배경 이미지도 무대에 여러개 배경 이미지를 배치 할 수 있습니다. 그렇게 되면, 무대는 상황에 따라 각기 다른 배경 이미지를 사용할 수 있게 됩니다.

이렇게 해서 이미지 세팅은 끝났습니다.

하지만 아래 창을 보시면 무대 창이 아두이노 이미지에 묻혀 있어서 뭔가를 만들려고 해도 아두이노 때문에 표현하기가 힘들어 보이죠.


위 아두이노 스프라이트 이미지는 삭제할 수 없습니다. 삭제하면 아두이노 연결이 안되니깐요. 그렇기 때문에 아두이노 스프라이트는 안보이게 숨겨야 합니다.

아두이노 핀 값을 출력하는 창은 마우스 오른쪽 버턴을 해당 창에서 클릭하면 아래와 같이 숨기기 기능 선택 창이 뜨고 숨기기로 안보이게 할 수 있습니다.


그 다음 아두이노 그림은 아래 창에서 편집을 눌러 주세요.


그러면 아래 창이 나타나고 지우기를 눌러주세요.


그리고 무대 배경 색의 점을 만드시든 적당한 티 안하는 점을 하나를 아무 위치에 찍어 주시고 확인을 눌러주세요. 그러면 해당 점이 아두이노우노가 됩니다.


이렇게 해서 아두이노 관련 이미지들이 사라졌습니다. 참고로 자세히 보시면 하얀 점이 있지요. 그냥 post 예시를 들기 위해서 하얀색 점으로 한 것이고요. 이 점을 마우스로 클릭해서 드래그 하시면 이동이 됩니다. 해당 점을 안보이는 곳으로 드래그 하시면 완벽하게 숨길 수 있습니다.

이렇게 해서 이미지 세팅이 끝났네요. 이제는 아두이노 세팅과 스크래치 블록코딩을 합시다.

2. 아두이노우노 조정기 만들기



위 그림처럼 간단합니다. 가변저항을 A0핀에 연결하여 가변저항을 돌리면 발생하는 가변저항값을 토대로 스트래치 이미지를 움직이게 할 꺼에요.

이제 아두이노우노에 S4A 스크래치를 사용할 수 있게 펌웨어 소스를 이식시켜야 합니다.



위 post에서 아두이노우노에 펌웨어 소스를 인식하는 방법을 지난시간에 이야기 했기 때문에 설명은 생략하고 위 post를 보시기 바랍니다.

이렇게 해서 아두이노우노에서 기본 세팅은 끝났습니다.


3. S4A 스크래치 블록 코딩


S4A 스크래치에서 가변저항 값 읽기


아두이노 가변저항기에서 가변저항값을 읽기 위해서는 우선 그 가변저항값을 저장하는 변수를 선언해야 합니다. 케릭터 이동에 가변저항값이 사용하기 때문에 변수 이름을 move라는 변수를 하나 만들겠습니다.


위 그림은 이미 만들어 진 상태의 모습입니다. 새로 만들 때는 변수만들기를 누르면 보시는 것과 같은 창이 뜨고 변수이름을 치시면 변수 하나가 생성이 됩니다. 실험에서는 가변저항값을 현재 가변저항값과 이전 가변저항값을 비교하기 위해서 move, premove라는 변수를 만들었는데 이 부분은 나중에 설명 드릴께요. 두개 변수가 필요하니깐 우선 변수만 만들어 놓으세요.

그럼 변수를 만들었으면 그 변수에 실제 아두이노 가변저항값을 읽어 올까요.


제어, 동작, 변수 항목에서 표시한 블록들을 사용하여 읽게 됩니다. 어느 블록이 어느 위치에 있는지 잘 확인해 주세요. 첨에는 블록 위치가 햇갈려 할 수 있으며 색으로 구별하시면 아마 쉽게 구별이 가능 할 꺼에요. 총 4개의 블록으로 코딩을 하게 됩니다.

설계 :

  • 센서값 읽기 <= 계속 무한으로 읽어야겠죠.(실시간 조정을 위함)
  • 읽은 센서값 저장 <= move 변수를 만들었으니 여기에 저장해야겠죠.


끝! 위 블록 코딩으로 S4A 스크래치에서 이제 아두이노 가변저항값을 읽어와서 move 변수에 계속 실시간으로 저장하게 됩니다. 아무때나 move 변수값을 체크하면 현재 아두이노 가변저항값을 확인 할 수 있게 되었습니다.

고양이 좌/우 이동


아두이노의 가변저항기를 돌리면 고양이가 좌/우로 움직이게 하려면 어떻게 해야 할까요. 우선 고양이를 좌/우 이동을 시켜 봐야 합니다. 지난 시간에 고양이를 좌/우로 왔다 갔다 하는 동작을 샘플로 했었죠. 그 방법을 응용 할 거에요.


위 블록으로 x좌표로 좌/우로 이동을 했었습니다.


설계 :

  • 가변저항값을 x좌표로 변환 (0~1023을 x좌표 -200~200 값으로 변환)
  • 고양이 걷기 동작 만들기
  • 고양이 이동 (가변저항기를 돌리면 돌린 만큼 고양이를 이동시킨다)

가변저항값을 x좌표로 변환 (0~1023을 x좌표 양쪽 끝지점 -200~200 값으로 변환)

가변저항값을 어떤 특정값의 범위로 맞추기 위해서는 아두이노에서 map()함수를 사용했습니다.

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

위 식을 줄여서 그냥 0~400사이의 값으로 나오게 바꿨네요.

(move - 0) * (400 - 0) / (1023 - 0) + 0

=> move*400/1023

이렇게 줄였습니다. 그러면 가변저항기를 돌리면 0~400사이로 줄어 들게 됩니다.

그 다음 x 좌표는 양쪽 끝점 기준으로 -200~200사이가 됩니다. 그래서 가변저항값이 200일 때 0이 되어야 합니다. 그럼 식에 -200을 해주면 됩니다.

x좌표 : (move*400/1023) - 200

이렇게 해서 실제 고양이가 이동 할 x좌표를 구할 수 있게 되었습니다.



고양이 걷기 동작 만들기

가변저항기를 돌리게 되면 move값이 갱신이 되고 그 값을 기준으로 고양이를 이동시킨다고 했죠.

여기서, 고양이는 언제 걷기를 하나요. 바로 고양이가 이동 할 때 입니다. 즉, 가변저항기를 돌리는 순간 고양이는 걷는 동작을 해야 합니다. 이 표현을 블록 코딩 하면 다음과 같습니다.


이 원리는 딜레이 없이 딜레이 함수를 사용할 때 시간값을 비교할 때 코딩했던 로직과 유사한 원리입니다. 시간의 변화가 특정 조건에 만족할 때 그 동작을 수행하고 끝나는 시점에 현재 시간값을 저장하고 다음 시간을 비교하는 원리를 이용하였습니다. 여기에서는 가변저항기가 변화가 일어나면 그 변화한 만큼 고양이를 이동시킨 후 끝나는 시점에 현재 move(가변저항) 값을 premove(이전저항)값에 저장하여 새로운 가변저항값과 비교하여 변화가 일어나는지 체크하는 용도로 사용 하였습니다. 그래서 현재 가변값과 이전 가변값을 비교하기 위해서 premove 변수를 하나 더 만들어 사용 했네요.

위 블록코딩을 살펴보면 아래와 같은 C코딩으로 표현을 해보았습니다.

premove=0; //초기값

while(1){
  if(move<>premove){
   다음모양(고양이걷기);
   premove=move;
  }
}

여기서, 다음모양은 위 고양이 이미지 세팅에서 고양이 스프라이트에 2개의 이미지를 저장 했었죠. 이때 A, B 이미지가 있는데 다음모양 블록은 현재 이미지에서 다음 이미지로 무조건 바꾸라는 명령입니다. 참고로 다음 이미지는 순차적으로 이미지가 바뀝니다. 여기에서는 2장의 이미지인데 1번 이미지에서 다음모양블록을 만나면 2번 이미지로 바뀌게 됩니다.


위 그림에서 a가 현재 이미지면 다음모양 하면 b 이미지로 교체 됩니다. 현재 이미지가 b이면 다음모양 하면 a 이미지가 됩니다.

위 블록코딩은 가변저항기를 돌리는 순간 if문에서 이전 가변저항값과 현재 가변저항값이 다른지 체크하게 되고 다르면 가변저항기가 움직였다는 소리가 되고 그 순간 다음모양 블록으로 고양이 이미지를 다음 이미지로 바뀌고 고양이가 걷는 동작을 만들어 내게 됩니다.

[결과]


위 결과는 고양이를 x좌표로 이동하는 블록이 없어서 실제 x좌표로 이동하지 않고 가변저항기를 돌리면 제자리 걷는 동작만 수행하네요.


고양이 이동 (가변저항기를 돌리면 돌린 만큼 고양이를 이동시킨다)

사용 블록 :


위 블록에다가 위의 x좌표 구한 블록식을 x 위치에 배치하면 됩니다.


이렇게 배치하면 가변저항기가 움직이면 x좌표값이 바뀌고 해당 값의 위치로 고양이가 이동하게 됩니다.

종합


[아두이노 스프라이트 블록코딩]


[고양이 스프라이트 블록코딩]


[결과]

4. 자연스럽게 고양이 걷는 동작 만들기


이 내용은 안보셔도 됩니다. 스크래치 영역이고 아두이노를 다루는 것이 목적이지 고양이를 자연스럼게 움직이게 하는게 목적이 아니기 때문에 생략하셔도 됩니다. 그냥 뭔가 걷는게 부자연스럽게 보여서 블록 코딩을 수정한 것 뿐입니다. 수정 된 블록 코딩으로 하면 오늘 post의 의미 전달이 잘 안될 것 같아서 따로 분리 해서 설명합니다.

이 내용은 좀 더 자연스럽게 고양이가 오른쪽으로 걸을 때 오른 방향을 바라보도록 하고 왼쪽으로 걷게 되면 왼쪽을 바라보게 하는 방식입니다.


위 그림이 핵심 블록 코딩입니다. 우선 화살표가 가리키는 모양의 아이콘을 클릭해주세요. 좌우 이동시 회전 방향을 나타냅니다. 방향전환을 할 때 회전방향을 어떤 방식으로 회전 시키느냐에 따라서 고양이의 움직임이 바뀌게 됩니다. 좌/우 방향으로 바라보도록 회전 시키려면 화살표가 가리키는 모양의 아이콘을 클릭하면 됩니다.

여기서, 고양이의 방향 전환은 어쩔 때 일어나는지 알아야 합니다. 현재시점과 이전시점을 기준으로 비교하면 방향을 알아 낼 수 있는 두가지 방법이 있는데 그 중 하나를 선택하여 실험 했네요.

방향 찾기 :

  • 현재 가변저항값과 이전 가변저항값를 비교하여 방향을 정한다.
  • 현재 x좌표값과 이전 x좌표값을 비교하여 방향을 정한다.

가변저항값이든 x좌표값이든 선택은 여러분 몫입니다. 방향 전환을 할 때 예를 들면, 이전 가변저항값이 100일 때 현재 가변저항값이 110이면 어떻게 될까요. 고양이가 x좌표로 10만큼 이동하게 됩니다. 오른쪽으로 이동하는 것이기 때문에 고양이는 오른쪽 방향이 됩니다. 만약 현재 가병저항값이 90이면 x좌표는 왼쪽으로 10만큼 이동하게 되는데 고양이는 왼쪽 방향이 되겠죠.


위 코딩은 완성된 블록 코딩인데 x좌표 변수를 하나 더 만들었네요. 그리고 move와 premove변수가 기존에 있기 때문에 방향찾기는 가변저항값을 비교하여 방향을 결정했네요.

나머지 블록은 앞에서 설명 드렸기 때문에 생략합니다.

[결과]


영상을 보시면 가변저항기로 조정하면 깔금하게 해당 방향으로 고양이가 방향 전환을 하네요.

마무리


아! 이야기를 너무 풀어서 설명하다 보니 길어졌네요.


댓글()

[아두이노] S4A 스크래치로 아두이노 제어

IOT/아두이노|2019. 9. 30. 09:00

[아두이노] S4A 스크래치로 아두이노 제어



오늘은 여러 종류의 스크래치가 있으며 그 중에 S4A 스크래치를 이용하여 아두이노를 제어하는 방법을 간단히 살펴보는 시간을 갖도록 하겠습니다. 집에 S4A가 설치되어 있어서 그냥 이 S4A 스크래치 프로그램으로 아두이노를 제어했네요. 다른 스크래치 프로그램으로도 아두이노를 제어를 할 수 있으니 다른 스크래치 프로그램으로 제어하고 싶다면 해당 아두이노 펌웨어 소스로 아두이노에 프로그램을 이식 시키면 됩니다.

그러면 S4A 스크래치로 간단히 아두이노를 제어를 해봅시다.

1. S4A 스크래치


스크래치 프로그램은 아이들에게 그래픽 환경에서 코딩을 배우는 목적으로 설계된 교육용 소프트웨어입니다. 스크래치는 배경 이미지 위에 다수의 스프라이트라는 창에 있는 이미지를 겹쳐 쌓는 형태로 해서 한장의 이미지가 완성 됩니다. 여기서 개별 이미지는 움직이는 동작을 부여 할 수 있는데 이때 블록 코딩을 통해 이미지에 살아 움직이는 효과를 표현합니다. 쉽게말하면, 애니메이션과 같은 작업을 블록 코딩으로 한다고 생각하시면 됩니다. 애니메이션에서 각 장면 장면들을 그리면서 그림에 움직이는 효과를 표현하잖아요. 그와 마찬가지로 스크래치도 각 장면 장면들을 블록 코딩으로 통해 이미지를 그리거나 이동시켜서 애니메이션과 같은 움직이는 효과를 표현 한다고 생각하시면 됩니다.


위 그림처럼 배경 이미지 위에 개별 스프라이트 창에 고양이와 곤충 이미지 그림이 있습니다. 배경이 이미지 위에 고양이와 곤충이 배치 된 한장의 그림입니다. 여기서 고양이와 곤충을 개별적으로 블록 코딩이 하여 움직임을 부여 하여 애니메이션 효과로 표현 할 수 있습니다. 보면 이미지가 무대창, 스프라이트창으로 이미지가 개별적으로 나뉩니다. 그 이유는 각 창마다 블록 코딩을 개별적으로 하기 위해서 입니다. 진짜 이 프로그램이 대단한 것은 각 창마다 개별 코딩을 하는데 독립적인 동작을 개별적으로 처리 합니다. 우리가 프로그램 언어로 사용하여 이 개념을 코딩하려면 동시에 작업을 처리하는 코딩은 복잡해 지는데 이 복잡한 코딩을 스크래치는 내부에서 기본 바탕으로 세팅 되어 있어 동시 작업 처리에 대한 복잡한 생각을 할 필요가 없습니다. 각 이미지 별로 독립적인 개별 동작 코딩만 하면 되기 때문에 쉽게 코딩을 할 수 있습니다. 단점은 동시에 처리 시 우선 순위를 정하는 작업이 어렵습니다. 즉, 고양이와 곤충이 서로 충돌하는 장면을 연출한다고 해봅시다. 여기서 고양이와 곤충이 충돌 처리 동작 코딩이 복잡해 지는데 고양이가 곤충 충돌이 먼저 일어 났는지 곤충이 고양이와 충돌이 먼저 일어 났는지에 따라 결과가 달라지기 때문에 이 부분은 좀 복잡해 집니다. 스크래치도 동시 처리라고 하지만 실제 실행시키면 고양이와 곤충의 충돌 이벤트 시간이 다릅니다. 먼저 시작하는 쪽이 고양이 일지 곤충일지는 상황마다 다릅니다. 단지 인간이 감지했을 때 동시처리 되는 것처럼 보일 뿐이죠. 이게 왜! 단점이냐면요. 예를 들어 우주선 게임이 있는데 우주선에서 총알이 발사 됩니다 여기서 총알이미지가 몬스터와의 충돌 이벤트 처리가 어렵고 문제가 발생 할 수 있습니다. 총알은 몬스터에 충돌하면 사라지는 코딩을 넣고 몬스터는 총알과 총돌하면 피가 깍이거나 죽는 코딩을 넣는다고 상상해 봅시다. 이때 총알이 먼저 몬스터에 충돌하는 이벤트가 실행하면 총알이 사라질 때 몬스터 코딩에서는 총알이 충돌을 감지 못 할 수 있습니다. 총알은 몬스터에 공격하는데 몬스터는 총알이 총돌했는지 감지하기 전에 총알이 먼저 사라지기 때문에 몬스터 입장에서는 충돌 이벤트가 발생하지 않게 됩니다. 스크래치는 개별 코딩으로 동시처리 하지만 개별 코딩에서 서로 영향을 미치는 코딩에서는 처리하기가 복잡해 집니다.

사설은 이만하고, 이제 애니메이션 처럼 그림을 움직이게 해봅시다.


위 그림에서 보는 것 처럼 스크립트라는 창에다 왼쪽 블록들을 배치하여 고양이 스프라이트가 움직이게 합니다.

[블록 코딩]


블록 내용은 클릭이 되면 실행아래 블록들이 실행 됩니다. 여기서 제일 먼저 무한반복 블록이 실행된는데 무한 반복 블록 안에 잇는 동작을 순차적으로 실행하고 그 과정을 무한 반복하게 됩니다. 어떤 동작을 무한 반복하는지 볼까요. 현재 스프라이트를 x좌표로 20만큼 이동한 후 0.5초 후 다시 x좌표로 -20만큼 이동하고 0.5초 대기합니다. 이 과정을 무한 반복하라는 블록 코딩입니다. 그러면 배경이미지 기준으로 고양이 스프라이트 이미지가 x축으로 +20, -20으로 왔다 갔다하게 됨으로 고양이가 움직이는 애니메이션처럼 움직이게 됩니다. 여기서, 좀 더 디테일적으로 표현하면 고양이를 길이미지를 만들어 놓고 그 위에서 걸어가게도 할 수 있으며 고양이가 걷거, 뛰기, 점프(중력), 소리 효과도 부여할 수 있는데 그걸 넣으면 복잡해 보일 수 있기 때문에 단순히 좌/우로 움직이는 간단한 표현만 코딩했네요. 지금 스크래치 post가 아니고 아두이노를 제어하는 것이 목적임으로 이 내용은 생략합니다.

공부를 하고 싶으신 분들은 MIT 공대에서 만든 아래 스크래치 사이트에 가셔서 온라인 상에서 연습 해보세요. 튜토리얼이 잘 나와 있기 때문에 여러분들이 이곳에서 따라 연습해 보시면 이해하실 수 있을 꺼에요. 스크래치에 대해 post 한 것 같은데 기억이 잘 안나서 다시 이야기 합니다.



생활코딩 강좌에 가시면 이 강좌를 만드신 분이 아주 자세히 영상물로 설명하고 있어서 성인 기준 반나절이면 충분히 마스터 할 거라 생각됩니다.

추가로,



자격증 문제인데 샘풀문제를 한번 풀어보세요. 주기적으로 이전 시험 출제 문제들을 공개하는데 한번 문제를 풀어보는 것도 재밌을 꺼에요. 1급은 좀 난이도가 있더군요. 초등학생 수준은 3급 자격증이고 1~2급은 어느정도 연습과 코딩 능력을 갖춰야 할 수준이고요.

2. S4A 스크래치 설치 및 아두이노 펌웨어



위 사이트에 가셔서 다운로드 페이지로 넘어가시면 아래와 같은 창이 뜹니다.


설치 운영체제를 선택하는데 전 윈도우라서 윈도우 설치 프로그램 다운 받았으며 아두이노우노에 펌웨어 소스는 아래 표시된 곳에서 다운로드 받으시면 됩니다. 아두이노 소스가 다운로드 됩니다.

1) 아두이노우노에 펌웨어 시키기



위 S4A 공식 사이트에서 다운 받은 소스를 아두이노 IDE에서 위 그림처럼 S4AFirmware16이라는 소스를 업로드 시키면 됩니다. 이렇게 하면 아두이노우노 세팅은 끝납니다. 아주 간단하지요. 참고로 S4A 스크래치 프로그램을 실행 시킨 상태에서는 하지 마세요. 아두이노 IDE에서 먼저 세팅 해 놓고 나서 펌웨어가 성공하면 그다음에 S4A 스크래치 실행 시키기 바랍니다.

2) S4A 스크래치 실행


아두이노우노가 PC에 연결된 상태이면 아래 왼쪽 그림처럼 보드 검색 중인 상태 표시가 처음 표시 됩니다 그리고 자체적으로 인식 작업을 수행하고 아두이노우노가 인식을 하게 되면 오른쪽 그림처럼 아두이노우노가 일부 핀값들의 값들이 읽어와 표시 됩니다. 수치 변화가 실시간으로 이루어지면 정상적으로 아두이노우노가 인식했다고 보시면 됩니다. 이 수치는 아두이노칩 자체에 전류가 공급되면 각 핀마다 미세하지만 전류가 흐르게 됩니다. 일종의 노이즈가라고 생각하시면 돼요. 노이즈 값들이 실시간으로 읽어온다고 생각하시면 될 듯 싶네요.


3. S4A 스크래치에서 아두이노 우노 동작시키기


간단히 Blink 예제를 실행 시켜 볼까요.

[Blink 예제]

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

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

[S4A 스크래치 블록 Blink 예제]


두 코딩을 비교하면 아래 블록 코딩이 쉬워 보일꺼에요. 하지만 전 블록 코딩을 싫어 합니다. 제가 원하는 위치에 원하는 선언과 코딩을 하는데 약간 제약이 따르고 정해진 블록으로만 상상코딩을 해야 하기 때문에 상상코딩에 장애요인으로 저에게 오더군요. 익숙치 않는 원인도 있겠지만 왠지 이런식으로 코딩하면 뭔가 막힌 것 같은 코딩이 되어서 블록 코딩은 싫어 합니다. 하지만 비전공자나 아이들의 경우는 이런 코딩이 더 쉽고 편할 수 있습니다.

아무튼 스크래치로 아두이노를 제어 할 경우 실시간으로 반응을 체크 할 수 있는 장점이 있습니다. 방금 블록 코딩한 13번핀에 LED을 깜박이게 하는 동작을 수행 할 때 아두이노에 다시 프로그램을 이식할 필요 없이 바로 제어가 됩니다. A0핀에 센서를 읽고 싶다면 아날로그 읽기블록을 배치하면 바로 A0에 연결된 센서값을 읽어오게 됩니다. 실시간 코딩으로 실시간 반응을 확인할 수 있어 스크래치로 아두이노를 제어가 더 재밌을 수 있습니다. 실시간 처리가 가능한 이유는 이미 아두이노우노를 펌웨어 할 때 각 핀의 역할을 사전에 지정해 놓았기 때문입니다. 이미 디지털핀과 아날로그 핀 동작을 스크래치 블록에 맞게 세팅되어 활성화 된 상태이기 때문에 해당 블록을 사용하면 해당 핀 동작을 실시간으로 결과를 얻게되는 구조이지요. 문제는 특정 핀을 특정 동작만 하고 다른 동작을 수행할 수 없어 강제성을 갖고 있다는 점이 단점이라고 할 수 있습니다.

[결과]


추가로, tinkercad 가상시뮬레이터 실험


tinkercad 에서도 아두이노 우노를 위 그림처럼 블록 코딩이 가능합니다. 예전에 tinkecad 가상시뮬레이터를 소개 할때 이 부분을 설명했지만 이번 post내용에 연결되는 부분이라 다시 거론합니다.

[결과]


가상시뮬레이터에서도 연습이 되니깐 혹시 아두이노우노가 없으시다면 가싱시뮬레이터에서 블록 코딩을 해보세요.

마무리


스크래치에 그려진 이미지와 아두이노를 연동하여 재밌는 간단한 표현까지 post 하려고 했더니 잡이야기를 하다보니 post가 길어졌네요. 다음 post에서는 간단히 고양이 이미지를 만들고 고양이를 아두이노로 조정해보는 내용으로 post 하겠습니다. 고양이 움직임에 대해 간단히 상황을 설정하고 아두이노에서 조정하려면 몇가지 아두이노에서도 설정해야 하기 때문에 좀 내용이 애매하게 길어질 것 같아서 오늘 내용은 여기서 멈추겠습니다. 사실 하루치 post로 간단히 소개만 하고 넘어 가려고 했는데 좀 길어졌네요.

S4A와 연동한 아두이노는 스프라이트 이미지로 아두이노우노를 제어 할 수 있고 반대로 아두이노우노에서 스프라이트 이미지를 제어 할 수 있습니다. 쌍방 통신이 가능하여 상상하는 목적에 따라서 다양한 결과물을 얻을 수 있기 때문에 한번 사용해 보셨으면 합니다.

댓글()

[아두이노] 아두이노 전기 전도성 펜

IOT/아두이노|2019. 9. 6. 09:00

[아두이노] 아두이노 전기 전도성 펜



1. 전기 전도성 펜


전도성이란 "전기가 얼마나 잘 흐르는가를 나타내는 성질"을 말합니다. 전기가 통하는 금속으로 금, 은, 구리, 철, 백금, 주석, 알리미늄, 아연, 텅스텐, 니켈 등이 있습니다. 오늘 소개하는 전기 전도성 펜은 잉크에 전기 전동성 물질이 들어 있어서 펜으로 그림을 그리면 그림을 그린 선에는 전류가 흐르는 통로가 만들어 진다. 그림으로 그린 선이 일종의 회로도의 전선 부분을 담당하게 됩니다. 참고로, 전기 전동성 잉크펜은 일리노이 대학 제니퍼 교수가 처음 개발하였습니다.


위 전기 전도성 펜으로 아래 밧데리, LED, 저항이 세개 있다면 종이 위에 전도성 펜으로 선을 그리면 LED에 불이 들어오게 됩니다.


아니면, 위 그림처럼 표현하면 전기 전도성 펜을 사용 가치가 있을까라는 생각이 들꺼에요. 아래와 같이 이렇게도 표현해서 LED에 불이 들어 옵니다. 뭔가 카드 같은 걸 만들 때 사용하면 좋겠죠.


잉크 자체가 전기가 흐르는 성분이 들어 있기 때문에 잉크가 마르면 그림을 그린 선 자체가 전선이 됩니다. 그래서 공간적 제약이 없이 자유 자제로 그림을 그릴 수 있는 모든 사물이나 장소가 회로도가 될 수 있습니다.

전기 전도성 펜이 좋은 점은 회로도를 만들 때 기판에 전선을 연결하고 납땜을 해야 하는 불편함을 해결 됩니다 아이들도 쉽게 다룰 수 있어 상상력을 끌어 올리기 좋습니다. 아이들과 아두이노를 공부할 때 활용하면 아이들의 흥미를 유발할 수 있는 좋은 소재가 생각 되네요.

유튜브에서 전도성 펜이라는 단어로 검색하시면 진짜 다양한 작품들을 감상하실 수 있습니다. 간단한 표현에서 부터 고퀄리티 작품들도 쉽게 찾아 볼 수 있으니 한번 검색하셔서 전도성 펜이 어떤 펜인지 시각적으로 감상을 해보세요.

참조영상물 출처 : 서울시 · Seoul이라는 게시자가 올린 작품인데 아이들과 이런 걸 만들면 재밌을 거라 생각되네요.

서울시 · Seoul : https://www.youtube.com/watch?v=DWJMkZtY_Rw

아래 영상물은 영메이커와 KocoaFab에서 만든 영상물인데 아두이노 공부하신분들에게 볼만한 영상물입니다.

영메이커 : https://www.youtube.com/watch?v=N9c6-qic7y8
KocoaFab : https://www.youtube.com/watch?v=c9w3Uw8DPo0

제 영상물이 아니기 때문에 직접 올릴 수 없고 영상물 게시자와 출처내용과 링크 주소만 표시 합니다. 직접 해당 유튜브로 가셔서 확인하시거나 아니면 별도로 유튜브에서 전도성 펜이란 키워드로 검색하셔서도 쉽게 검색되고 링크한 영상물보다 더 멋진 영상물들이 수두룩 하니 직접 검색을 통해서 찾아보시기 바랍니다.

2. 전기 전도성 실



전기전도성 실은 스테인리스 스틸 재질의 섬유로서 일정 길이만큼 저항값을 가지고 있다고 합니다. 전자섬유는 섬유에 전기 신호를 전달 할 수 있기 때문에 웨어러블 기술과 접목한 전자 의류 연구가 국내에서 활발이 진행되고 있다고 하네요. 미래의 의류에는 웨어러블 전자의류로 다양한 기능이 탑재 되어 우리 생활에 많은 영향을 미칠 거라 생각되네요.

참조영상물 출처

김주현 : https://www.youtube.com/watch?v=efCwCIhTkAg
숙명여대 이지선 교수님의 딸 해나양이 직접 디자인해서 제작한 작품이라고 하네요.

제 영상물이 아니기 때문에 직접 올릴 수 없고 영상물 게시자와 출처내용과 링크 주소만 표시 합니다.

유튜브에서 전도성 실이라는 키워드로 검색하시면 다양한 작품들을 보실 수 있을 꺼에요. 위 유튜브 김주현님이 올린 영상물을 가셔서 보시면 토끼인형에 LED 불이 들어오게 하는 작품인데 귀여워서 링크 주소를 걸어 놨네요.

마무리


전기 전도성 펜은 그림을 그릴 수 있는 모든 곳이 회로도 됩니다. 카드나 종이모형에 LED 조명을 달면 시각적으로 재밌는 작품들을 만들 수 있습니다. 그리고 그림을 그릴 수 있는 모든 곳에 사용 할 수 있어 그림을 그리는 곳이 바로 전자회로가 됩니다. 전기 전도성 실의 경우도 마찬가지 입니다. 의류 같은 곳에다가 전기 전도성 실을 사용하면 옷에 실제 전선을 연결할 필요 없이 실로 그 역할을 대신하기 때문에 천에 실을 바느질을 하여 회로도를 만들어도 잘 티가 나지 않으면 옷의 불편함을 줄일 수 있습니다. 가령 의류에 LED를 달아 이퀄라이저를 표현하면 진짜 재밌을 것 같아 보입니다.

마지막으로, 이외에 전기 전도성 소재들이 많습니다. 어떤 것들이 있는지 한번 찾아보세요. 다양한 전기 전도성 소재을 가지고 아두이노와 접목하면 많은 것들을 할 수 있을 꺼에요. 상상코딩 소재에 이만한 좋은 소재는 없을거라 생각 됩니다.

댓글()

[아두이노] 아두이노 라이브러리 만들기

IOT/아두이노|2019. 9. 5. 09:00

[아두이노] 아두이노 라이브러리 만들기



지금까지 아두이노를 코딩 할 때 아두이노 표준 라이브러리 함수를 사용하거나 누군가 만들어 놓은 라이브러리 함수들을 가져다 편하게 코딩을 해왔습니다. 그런 라이브러리 함수는 어떻게 만들어지는 걸까 궁금한 적이 아마 있을거에요. 누군가 만들어 놓읗 라이브러리 함수만 쓰는 것은 재미가 없습니다. 한번 쯤 자신이 만든 라이브러리 함수를 사용해보고 싶은 생각을 가져 보셨을 거라 생각 합니다. 그리고 사용되는 부품에 따라서 뭔가 2% 부족한 함수이거나 이런 동작을 수행하는 함수가 있었으면 하고 원한 적이 있을 꺼에요. 이런 라이브러리 함수는 만드는 방법이 궁금하실 것 같아서 한번 라이브러리 함수를 만드는 방법을 알아두면 좋을 것 같아서 간단히 소개합니다.

1. 클래스


C언어에서 C++으로 넘어가면서 객체지향 프로그램에 대해 배우게 되는데 처음 클래스라는 개념을 배우게 되는데 클래스는 객체를 생성하기 위한 변수와 함수를 묶어 놓은 틀이라고 말합니다. 그리고 클래스의 정의와 특징들을 열거하자면 좀 복잡하고 쉽게 그 의미를 이해하기 쉽지 않습니다. 그냥 간단히 객체를 붕어빵이라고 하면 클래스는 붕어빵틀이라고 생각에서 출발해 주세요. 클래스는 완전 실체화 되지 않는 틀이라고 생각하고 객체는 실제 그 틀을 실체화 한 대상으로 생각하면 될 듯 싶네요.

그리고 클래스는 캡슐화 의미만 가지고 있으면 됩니다. 변수와 함수들을 하나의 주제로 묶어 만들어 놓은 틀로 생각하시면 됩니다.

예를 들어, 우리가 자동차를 코딩으로 비유해 봅시다.


자동차는 위 그림처럼 엔진, 핸들, 바퀴, 몸체, 의자, 창문 등등 여러가지 자동차 부품들이 모여서 한대의 자동차를 만들게 됩니다. 일반 코딩은 자동차 부품들을 한번에 하나의 틀로 일체화 된 코딩이라고 생각해 봅시다. 이런식의 코딩을 하게 되면 나중에 자동차 엔진이 맘에 안들어 다른 엔진으로 바꾸는 일이 생기면 이 엔진에 해당되는 코딩 위치와 이 엔진과 다른 부품과 연결된 위치를 전부 찾아내어 수정해야 합니다. 즉, 한번 뭔가를 업그레이드 할려면 전체 코딩 소스를 수정해야 한다는 복잡해 지겠죠. 여기서 자동차의 각 부품을 클래스 단위로 캡슐화 한다면 어떻게 될까요. 부품별로 나누고 객체화 시키면 나중에 엔진을 교체하고 싶을 때 해당 엔진 객체만 다른 객체로 바꾸면 쉽게 수정이 가능해 집니다.


위 그림에서 3개의 엔진이 있을 때 엔진을 교체한다면 엔진 클래스 A, B, C 중 자신이 원하는 클래스를 가져다가 사용하시면 됩니다. 즉, A엔진에서 C엔진으로 교체할 경우 C엔진 클래스로 변경만 하면 되기 때문에 코딩이 쉬워집니다. 전체 소스에서 클래스 접근 부분만 수정하면 되기 때문에 쉽게 코딩이 됩니다. 클래스 단위로 엔진이 만들어 지지 않았다면 어떤 현상이 발생할까요. 전체 소스에서 엔진이 어디서 부터 어디까지 인지 또는 엔진과 연결된 다른 부품에서 엔진과 다른 부품과의 경계를 구분하기가 어려워 엔진 코딩영역인지 다른 부품영역인지 나누는 것이 쉽지 않게 됩니다. 코딩을 길게 하다면 나사(변수)가 엔진에 사용하는 나사인지 바퀴에 사용하는 나사인지도 구별하기 힘들게 되는 문제점을 가지게 됩니다.

그래서 클래스라는 것을 이용합니다. 각 부품을 클래스화 하면 각 부품을 개별적으로 접근 제어 통제가 됩니다. 엔진에 대한 동작은 엔진 클래스에 안에서만 동작하고 바퀴에 대한 동작은 바퀴클래스 안에서만 동작하기 때문에 개별적 동작 제어가 되기 때문에 실제 프로그램을 설계할 때 클래스 단위로 접근 되기 때문에 그 경계가 명확하고 부품별 제어는 쉬워집니다. 왜 클래스를 배워야 하는지 아시겠지요.

이제 클래스에 대해 알아보도록 합시다.

2. 클래스 문법


클래스 기본 구조는 아래와 같습니다.

[클래스 구조]

class 클래스명
{
  private: //접근권한
    멤버변수1;  //내부접근
    멤버함수2;  //내부접근
  public: //접근권한
    멤버변수2;  //외부접근
    멤버함수2;  //외부접근
};

클래스명으로 하나의 클래스를 만드는 데 내부에서 private, public, protected 로 접근 권한을 부여합니다.

  • private : 내부에서만 접근 가능하고 외부에서는 접근 불가능
  • public : 내부에서 접근 가능할 뿐만 아니라 외부에서도 접근 가능
  • protected : 현재 클래스에서는 private 성격을 가지지만 다른 클래스에 상속 될 경우 다른 클래스에서 접근 불가능
    현재 클래스에서만 접근 가능한 제한 된 성격을 지니고 있음

private와 public만 기본적으로 알아두시면 됩니다. private은 클래스 내부에서만 접근되고, public은 클래스 밖에서도 접근 할 수 있다는 개념만 잡아 두세요. 우리가 러이브러리 함수를 호출하여 사용할 때 public 접근지정자에 선언된 함수들을 호출하여 사용되어 왔습니다.

클래스명 클래스객체;

클래스객체.멤버함수2();

이러헥 아두이노에서 사용되어 왔지요.

[생성자 & 소멸자 함수] : 생성자와 소멸자 함수는 클래스명과 동일해야 함.

  • 생성자 함수 : 클래스 객체가 생성과 동시에 호출되는 함수
  • 소멸자 함수 : 클래그 객체가 소멸과 동시에 호출되는 함수
class abc
{
  public:
    abc(){
          생성자함수;
    }
    ~abc(){
          소멸자함수;
    }       
}

abc 클래스를 객체변수를 다음과 같이 선언됩니다.

abc obj;
abc::abc(){
  생성자함수;
}

이렇게 abc()함수가 호출됩니다.

아두이노에서 LCD 라이브러리 함수를 사용할 때를 생각해 봅시다. 처음 객체선언 할 때 을 보면 다음과 같습니다.

예)

#include <LiquidCrystal.h>

//LiquidCrystal(rs, enable, d4, d5, d6, d7) 
LiquidCrystal lcd(3, 4, 8, 9, 10, 11);

위 처럼 lcd(3,4,8,9,10,11)로 객체변수가 선언되면 lcd()생성자 함수가 호출됩니다.

class LiquidCrystal
{
  public:
    LiquidCrystal(int a, int b, int c, int d, int e, int f){
      생성자함수 수행 명령 코딩;
    }
    ~LiquidCrystal(){
      소멸자함수 수행 명령 코딩;
    }
};

대충 a,b,c,d,e,f은 실제 변수명이 아니라 예를 든 것일 뿐 실제 따른 변수명이겠죠. 예를 들것 뿐입니다. 이렇게 클래스 객체변수를 선언하면 선언과 동시에 생성자 함수가 호출됩니다.

소멸자 함수는 이 클래스 객체변수가 delete 될 때 소멸자 함수가 호출됩니다.

이제는 쉽게 클래스를 이해하기 위해서 예를 들어 실험해 봅시다.

예) 두수의 합을 클래스로 만들기

Calc이라는 클래스를 만듭니다. 두 수 이니깐 2개의 멤버변수를 만드는데 해당 클래스 내에서만 접근하고 외부에서는 이 변수를 접근하지 못한다고 하면 다음과 같이 코딩합니다.

class Calc
{
  private:
    int a=0;
    int b=0;
};

여기서, 생성자 함수를 통해서 외부에서 a,b값을 받고, sum()함수로 입력받은 두수의 덧셈을 수행 해봅시다.

class Calc
{
  private:
    int a=0;
    int b=0;
  public:
    Calc(int val1, int val2){
      a=val1;
      b=val2;       
    }
    int sum();
};
int Calc::sum(){ //클래스 외부로 빼면
  return a+b;  
}

sum()함수는 생성자 함수처럼 클래스 내부에서 표현해도 되지만 외부로 빼면 위 코딩처럼 표현하시면 됩니다. 특정 동작 코딩이 꽤! 길어진다면 클래스 내부에서 코딩하면 지져분하게 보입니다. 그래서 외부로 빼서 클래스를 보기 편하게 최소화 코딩을 하면 좋습니다.

아무튼 이렇게 표현하고 아두이노 가상시뮬레이터에서 그 결과를 살펴볼까요.

[소스]

class Calc
{
  private:
    int a=0;
    int b=0;
  public:
    Calc(int val1, int val2){
      a=val1;
      b=val2;       
    }
    int sum();
};
int Calc::sum(){ //클래스 외부로 빼면
  return a+b;  
}

Calc obj(2,3); //객체변수 선언

void setup()
{  
  Serial.begin(9600);
  Serial.println(obj.sum());
}

void loop()
{
}

[결과]

5

위 예제를 보면 클래스 만들기가 그렇게 어렵지 않죠.

3. 라이브러리 만들기


아두이노 Blink 예제를 가지고 간단히 클래스를 만들어 볼까요.

[기본 틀]

#ifndef LED_H    
#define LED_H

클래스 코딩

#endif   

우선, 위 기본틀을 이해해 주세요. #ifndef ~ #endif 구조문을 기본 틀로서 해당 파일이 한번만 포함되도록 제한하는 방식으로 중복 인크루드 되는 걸 막는 구문입니다. 두번 포함 되지 않게 하는 표현으로 생각 하세요. #ifndef은 전처리기로 LED_H라는 정의된 식별자가 있는 지 체크하는데 없으면 처음 한번은 해당 코딩 소스를 인크루드 합니다. 안에 보시면 #define으로 LED_H가 정의하는 문장이 있죠. 처음에는 없으니깐 한번 인크루드하는데 안에서 정의를 하니깐 다음 번에는 인크루드하지 않습니다. 두번 참조되는 것을 막는 구문으로 정리하시면 됩니다.

Blink 예제로 실험 한다고 했죠. 클래스를 만들어 볼까요.

[Led.h 파일]

#ifndef LED_H    
#define LED_H

#include "arduino.h"

class Led
{
  private:
      int LedPin;
  public:
      Led(int Pin){ 
         LedPin = Pin;
         pinMode(LedPin, OUTPUT);         
      }
      ~Led(){
      }
public:
      void LedHigh();
      void LedLow();
};

#endif   

[Led.cpp 파일]

#include "Led.h"
void Led::LedHigh(){
  digitalWrite(LedPin,HIGH);
}
void Led::LedLow(){
  digitalWrite(LedPin,LOW);
}

여기서, PinMode(), DigitalWrite()함수 코딩을 직접해야 하는데 너무 길어서 인용했네요. 참고로 arduino.h 파일에 아두이노 표준 함수들이 들어 있기 때문에 선언해 주셔야 클래스 안에 아두이노 변수, 상수, 함수들을 사용할 수 있습니다.

간단히 위 클래스 함수에 대해 설명하면,

  • 생성자 Led()함수로 핀번호가 입력되면 무조건 해당 핀번호는 출력모드로 지정합니다.
  • LedHigh()와 LedLow()함수로 해당 핀번호로 High or Low 신호를 출력하게 됩니다.

이런식으로 자신만의 클래스를 만들 수 있습니다. 클래스 만드는 법이 간단하죠.



위 자료 출처에 가셔서 라이브러리 함수 내부 코딩을 보시면 꽤 긴 코딩을 보실 수 있을꺼에요 오늘 post는 의미 전달이 목적이라 실제 내부로직을 위 자료 출처의 소스처럼 코딩해야 합니다. 그러면 너무 복잡하고 의미전달도 안되겠죠. 간단히 클래스라는 개념만 오늘 배우는 시간이기 때문에 간단히 예제 클래스를 만들어 실험 했네요.

4. 라이브러리 추가하기


만든 클래스를 라이브러리에 추가하려면 아래와 같은 과정을 수행합니다.

먼저,


Led 클래스 이름을 전부 통일 시켜주세요.


위 그림처럼 아두이노 IDE가 깔려있는 폴더에서 라이브러리 폴더를 찾아주세요. 그안에 방금 만든 폴더를 추가하시면 끝납니다.


위그림에서 보시는 것 같이 라이브러리가 추가 된 것을 확인 할 수 있을 꺼에요.

5. 라이브러리 실행


1) 회로도


  • 준비물 : Red Led 1개, 저항 220옴 1개, 아두이노우노
  • 내용 : Led를 13번 핀에 연결하시오


2) 코딩


위에서 만든 라이브러리를 이용하면.

[실제 코딩]

#include <Led.h>

Led obj(13); //객체선언

void setup()
{   
}

void loop()
{
  obj.LedHigh(); //13번핀을 High상태로
  delay(1000);
  obj.LedLow(); //13번핀을 Low상태로
  delay(1000);
  
}

[가상시뮬레이터 코딩] : 인크루드를 할 수 없으니 해당 클래스를 복사해 와야 합니다.

class Led
{
  private:
      int LedPin;
  public:
      Led(int Pin){
         LedPin = Pin;
         pinMode(LedPin, OUTPUT);         
      }
      ~Led(){
      }
public:
      void LedHigh();
      void LedLow();
};

void Led::LedHigh(){
  digitalWrite(LedPin,HIGH);
}
void Led::LedLow(){
  digitalWrite(LedPin,LOW);
}

Led obj(13);

void setup()
{   
}
void loop()
{
  obj.LedHigh();
  delay(1000);
  obj.LedLow();
  delay(1000);
  
}

3)결과


Led 클래스를 인크루드 할 수 없기 때문에 클래스를 복사해서 가상시뮬레이터로 돌려 봤네요.


마무리


오늘은 클래스를 만들어 보는 시간을 가졌습니다. 아두이노를 코딩하다보면 많은 라이브러리 함수들을 사용합니다. 사용하다보면 뭔가 2% 부족한 함수들이 있습니다. 이 기능과 저 기능이 합쳐졌으면 하는 함수들이 있는가 하면은 자신이 뭔가 특정 동작을 수행하는 함수를 만들 때가 있습니다 .이 함수를 나중에 다른 곳에 사용하고 싶어지는 경우가 생길 때 직접 여러분들이 여러분들의 전용 클래스를 만들어 놓으면 나중에 해당 함수를 가져다 쓸 때 편하게 사용할 수 있습니다.

나중에 도움이 많이 되니깐 이번에 클래스를 만드는 연습을 해 놓으셨으면 합니다.

댓글()

[아두이노] 로봇 팔 관절 제어

IOT/아두이노|2019. 9. 4. 09:00

[아두이노] 로봇 팔 관절 제어



오늘은 마지막 시간으로 인터넷 로봇팔 키트로 판매하는 제품들의 일반적 특징들을 기반으로 해서 가상시뮬레이터에서 간단히 실험 해보는 시간을 갖도록 하겠습니다.

1. 로봇 팔


시중에 판매되는 로봇 팔 키트의 구조가 아래와 같은 형태로 디자인 되어 있더군요. 편의 상 원은 Servo Motor이고 회전되는 부위라고 가정한 디자인 입니다. 실제로는 좀 다르겠지요.


  • A 지점 : Servo Motor가 수평방향으로 회전하여 로봇팔의 몸통을 회전시키게 됩니다.
  • B, C지점 : Servo Motor가 수직방향으로 회전하여 로봇팔의 움직임을 만들어 냅니다.
  • D 지점 : Servo Motor가 집게를 제어합니다.

총 4개의 Servo Motor로 로봇팔 모양을 간단히 로봇팔 모형을 만들어 키트로 판매하더군요. 이걸 한번 가상시뮬레이터에서 실험해 보면 재밌을 것 같아서 실험을 하였습니다.

만약, 로봇 손이였다면 손가락 관절을 전부 다 제어해야 하기 때문에 너무 노가다 디자인을 해야 하기 때문에 간단한 집게 로봇팔을 실험 대상으로 했네요.

2. 로봇 팔


  • 준비물 : 가변 저항 4개, Servo Motor 4개, 아두이노우노, 외부전원
  • 내용 : 디지털Pin 4개를 Servo Motor 핀에 연결하고 가변저항도 A0~A3에 연결하시오


위 그림을 보면 지난시간에 6족 보행로봇 다리를 제어하는 실험을 가상시뮬레이터에서 했던 회로도와 같습니다. 관절 제어이기 때문에 회전만 제어하는 실험이라서 회로도는 같습니다. 같은 회로도이지만 어떻게 디자인 하느냐에 따라서 달라질 뿐이죠.

참고로 가변저항은 로봇팔을 제어하는 조종기가 됩니다. 몸통 회전 A와 로봇팔 움직임 B, C와 집게 D 제어로 총 4개의 제어값을 만들어야 합니다. 그래서 4개의 가변저항을 통해 조정하게 됩니다.

만약, 조이스틱으로 한다면 조이스틱은 X,Y 값을 만들어 내는데 4개의 제어값이 필요하니깐 조이스틱을 2개 연결하면 조정이 가능 합니다. 그리고 Bluetooth를 연결한다면 무선으로 스마트폰에서 조정이 가능합니다.

가상시뮬레이터에서는 가변 저항으로 조정했지만 실제로 제작해서 한다면 조이스틱이나 스마트폰으로 무선 조정을 하면 재미있겠죠.

3. 코딩


지난 시간의 6족 보행 로봇을 제어 하려면 보행 로봇의 움직임 패턴을 만들어야 하지만 로봇 팔은 그럴 필요가 없습니다. 집게 로봇 팔은 가변저항으로 간단히 제어가 가능하기 때문에 가변저항을 읽는 부분만 코딩하시면 됩니다.

가변저항 읽기 : analogRead()함수로 간단히 가변저항 값을 읽을 수 있습니다.

Servo Motor는 0~180도 회전을 할 수 있기 때문에 아날로그 읽기 0~1023값을 map()함수로 0~180으로 변환 시키야 합니다. 아래와 같이 가변저항값을 읽으면 됩니다.

int angle1 = map(analogRead(A0),0,1023,0,180);

A 모통 회전 : Servo Motor를 가변저항 값으로 회전 시키면 됩니다.

servo[0].write(angle1);

끝! 엄청 간단하죠.

종합해보면,

#include <Servo.h>

Servo servo[4];
const byte servoPin[4] = {2,3,4,5};

void setup()
{ 
  for(int i=0;i<4;i++){
    servo[i].attach(servoPin[i]);  
    servo[i].write(90);
    
  }
  delay(1000);
}

void loop()
{
  int angle1 = map(analogRead(A0),0,1023,0,180);
  int angle2 = map(analogRead(A1),0,1023,0,180);
  int angle3 = map(analogRead(A2),0,1023,0,180);
  int angle4 = map(analogRead(A3),0,1023,0,180);
  
  servo[0].write(angle1);
  servo[1].write(angle2);
  servo[2].write(angle3);
  servo[3].write(angle4);
  delay(100);  
}

위 코딩에서 중복되는 4번의 코딩 라인을 for문으로 처리하면 코딩 라인을 최소화 할 수 있습니다. 그 부분은 여러분들이 직접 수정해 보세요.

4. 결과


사실 집게 로봇팔에 대한 가상시뮬레이터 결과를 이해하기 위해서는 실제 모형을 보고 이해해야 하는데 단순히 Servo Motor회전으로 연상이 안될 수 있습니다. 아두이노 부품 판매 사이트에 가셔서 로봇팔 제품을 보시고 그래도 이해가 안되신다면 그 제품에 대한 영상물을 Youtube로 찾아 보시면 아마 있을꺼에요. 보고 움직임을 이해하시고 머리속에서 집게 로봇팔을 좌표계에 배치하고 움직이는 이미지와 가상시뮬레이터의 Servo Motor 회전을 같이 연결하여 상상하면서 보시기 바랍니다.


마무리


오늘 post 내용은 예전에 Servo Motor 제어편에서 간단히 가변저항을 이용하여 회전 시킨 회로도 입니다. 복습 post이지만 관절에서 빠질 수 없는 내용이기에 글을 쓰게 되었네요. 한개의 Servo Motor를 4개로 늘어 났을 뿐이고 코딩도 동일합니다. 재밌는 것은 Servo Motor를 가변저항으로 조정했던 원리가 오늘 로봇팔 제어가 되었다는 것이죠.

간단한 원리도 생각하는 관점에 따라 이렇게 재밌는 표현을 할 수 있습니다. 평소 사소한 원리일지라도 잘 정리 해놓으면 이렇게 상상력을 더해 재밌는 실험을 할 수 있습니다.

댓글()

[아두이노] 관절과 좌표계

IOT/아두이노|2019. 9. 3. 09:00

[아두이노] 관절과 좌표계



로봇팔이나 6족 보행로봇 같은 관절형 로봇은 Servo Motor나 Stepper Motor의 회전 각을 통해 관절의 움직임을 만들어 내게 됩니다. 처음 공부하시는 분들은 로봇팔이 Servo Motor의 회전각을 통해 어떻게 관절의 움직임을 만들어내는지 잘 연상이 안될 수 있습니다. 공감지각능력이 뛰어난 분들이나 관철력이 뛰어난 분들이라면 쉽게 이해할 수 있지만 약간 관절의 움직임에 대해 모르더라도 어려워 하지 마세요.

관절의 움직임을 이해하는데 좌표계를 머리속에 담아 놓으시면 쉽게 관절의 움직임을 이해 할 수 있습니다. 어떤 사물의 움직임을 표현한다면 그 움직임은 모두 좌표계에 배치되고 그 좌표계를 기준으로 회전한다고 머리속에 그려놓고 이해하시면 쉽게 이해 할 수 있습니다.

1. 관절



위 그림처럼 관절의 역활을 Servo Motor가 역할을 수행합니다. Servo Motor가 회전을 하게 되면 어떻게 될까요. 긴 막대기가 Servo Motor와 위치한 방향에서 그냥 원을 그리면 회전을 하게 됩니다. 이 회전이 관절형 로봇의 움직임을 만들어 낸다는 것이 잘 연상이 안되실거에요.

지난 시간에 6족 보행로봇에 대해 관찰 post를 썼는데 그때 다리 하나의 관절 제어를 다시 복습해 볼까요.


위 그림에서 각 관절 A, B, C를 방금 위에 Servo Motor와 합쳐진 원통막대 하나를 3개로 서로 연결되었을 때 다리 하나의 움직임을 만들어 냈습니다. 그림을 보면 A관절은 변화가 없고 B, C관절이 일정 각도로 위로 회전되었을 때 3관절의 다리가 그림처럼 움직임을 만들어 냈습니다.

다른 그림을 살펴볼까요.


손을 주먹형태로 쥐었을 때 손가락 하나의 움직임을 위 그림과 같은 모향을 만들어 냅니다. 주먹을 쥔 모양이니 위 그림에서 관절이 3개로 나뉘고 90도씩 회전했을 때 주먹이 쥐어지는 모습이 만들어 냅니다.

위 두 그림에서 관찰이 뛰어나신 분이라면 움직임을 이해 하셨을 꺼에요. Servo Motor의 회전과 위 그림에서의 원통막대기가 그 회전각만큼 움직였을 때 만들어내는 움직임을 머리속에서 그려 낼 수 있으면 관절 동작을 이해 할 수 있습니다.

혹시 이해가 안되신다면 이글을 보시는 여러분들이 직접 자신의 손을 주먹형태로 쥐어 보시고 관절이 Servo Motor라고 생각하시고 회전각도를 살펴보시기 바랍니다. 이해가 안될때는 실제 현실에서 그 움직임을 만들어 관찰하시면 됩니다.

그런데 복잡한 움직임을 만들기 위해 각 관절을 회전시킨다면 각 관절의 회전각을 쉽게 머리속에서 연상하기 어렵습니다. 즉, 손을 웨이브를 타는 동작으로 움직여 보세요. 아니면 직접 춤을 제자리에서 춰보세요. 그 때 손, 팔, 몸통, 다리 등 등의 각 관절에 기하학적인 움직임으로 춤을 출 때 각 춤의 동작에서 관절의 회전각을 머리속에 그리려고 할 때 쉽게 연상이 되 않습니다. 어떻게 하면 관절의 움직을 머리속에서 그려낼 수 있을까요. 바로 관절을 좌표계를 기준으로 관절의 움직임을 이해하시면 좀 더 쉽게 머리속에서 연상하실 수 있습니다. 그 방법에 대해 설명하겠습니다.

2. 좌표계


제가 처음 좌표계를 접했을 때가 컴퓨터그래픽스 과목을 배울 때였습니다. 그 때 OpenGl로 교수님이 컴퓨터라는 가상공간에 점을 찍고 선을 그리고 면을 만들고 3D 도형을 좌표계를 기준으로 그리는 방법을 배웠는데 이때부터 좌표계를 머리속에 담아두게 되었습니다. 의자를 컴퓨터 그래픽스로 표현할 때 현실에서의 의자를 좌표계를 기준으로 머리속에 현실 의자를 배치 할 수 있게 되니깐 의자의 모양을 좌표계 기준으로 그릴 수 있게 되었고 그 좌표계 기준으로 그려지 모양을 이동/회전을 통해 움직임을 만들어 낼 수 있게 되었습니다. 그 때 로봇손을 컴퓨터그래픽스로 그리게 되었고 호기심으로 로봇 손가락을 각 마디를 좌표계를 기준으로 그리게 되었는데 그 좌표계를 회전 시키니 그 좌표계을 기준으로 그려진 손가락 마디가 회전되는 것을 우연히 알게 되었습니다. 첨에는 잘 몰랐는데 그게 관절 제어를 한 것이였죠. 사실 교수님께서 가르쳐준것은 그냥 좌표계이 물체를 그리는 작업과 물체를 이동시키는 방법에 대해서만 설명을 했는데 로봇손을 OpenGl로 표현하고 손가락의 각 마디를 회전시킴으로 주먹을 쥐었다 펴는 동작을 만들게 되었는데 그 걸 보시고 교수님이 칭찬을 해 주신 기억이 나네요. 대단한 것은 아니였지만 각 마디 마다 개별 좌표계로 손가닥 마디마다 회전을 시켰는데 그게 나중에 관절 제어였다는 것을 알게 되었습니다.

관절제어는 좌표계를 머리속에 그릴 수 있으면 쉽게 제어를 할 수 있습니다. 그 방법을 설명하기 전에 우선 좌표계에 물체를 그려 낼 수 있어야 합니다.


좌표계는 x,y,z 3축으로 구성되어 있습니다. 모든 사물을 이 좌표계에 올려놓을 수 있습니다. 사각형을 올려 놓아 볼까요.


위 그림의 Box를 좌표계에 그려 보세요. 머리속에서 길이가 1인 Box를 좌표계에 그릴 수 있게 된다면 좌표계가 여러분의 머리속에 들어 있게 됩니다.

Box를 그릴 수 있게 된다면 의자를 그려보세요.


단, 그릴 때 각 부위 별로 개별 좌표계로 그려보세요.


위 좌표계로 다리와 앉는 부위를 좌표게로 그리게 됩니다. 그리고 다리 부위는 OpenGl에서 복사해서 4개의 다리를 만드는데 각 다리는 개별 좌표계가 기준이 됩니다.

이 때 전체 좌표계를 기준으로 방금 만든 다리와 앉는 부위를 배치하면 아래와 같이 완성이 됩니다.


여기서 각 다리는 개별 좌표계(0,0,0)을 기준을 4개의 다리와 앉는 부위가 그려지고 전체 좌표계에서 방금 그림 부위를 배치하면 위와 같은 의자가 완성이 됩니다.

물체를 좌표계 기준으로 그리고 그 물체를 또 다른 좌표계를 기준으로 배치하여 의자와 같은 특정 물체를 만드는 방법을 좌표계를 기준으로 머리속에서 그려 보세요. 이게 어느정도 머리속에서 완성이 되면 관절 제어에 대해 알아 봅시다.

관절 제어를 좌표계 기준으로 회전


위 그림처럼 원통 막대가 하나가 있다고 가정하고 좌표계 기준으로 그려 봅시다. 이걸 x축을 기준으로 회전 시키면 어떻게 될까요.


이처럼 좌표계에서 x축 기준으로 회전을 하게 됩니다. 다른 축으로 회전을 시킨다면 현실에서 여러분 주변있는 펜같은 것을 가지고 각 축별 회전을 시켜 보세요. 좌표계를 기준으로 물체의 회전을 이해 하실 수 있습니다.

다음으로 넘어가겠습니다.

좌표계의 부모-자식 관계 회전


A관절 좌표계는 부모 좌표계이고 B관절 좌표계는 A의 자식 관계입니다. A좌표계를 기준으로 회전하면 B 관절은 같이 따라서 회전하게 됩니다. 다음 B관절 좌표계를 기준으로 보면 C관절은 B관절의 자식 관계입니다 B관절을 회전하게 되면 C관절은 따라서 같이 회전을 하게 됩니다. C관절 회전에 경우는 A, B관절을 회전하지 않습니다. 즉, 부모 좌표계가 회전하면 자식좌표계는 따라서 같이 회전을 하고 자식 좌표계가 회전하면 부모 좌표계는 회전하지 않습니다. 이 개념을 머리속에 담아 주세요.

이제 3개의 원통을 하나의 좌표계를 기준으로 배치해서 좌표계로 살펴 봅시다.


위 그림처럼 개별적인 3개의 좌표계를 가지고 있습니다. 하지만 각 좌표계는 부모-자식 관계로 좌표계의 영역에 묶여 있는데 각 좌표계의 회전을 할 때 다른 좌표계도 영향은 부모-자식 관계로 영향을 받습니다.

정리하면,

  • 왼쪽 A좌표계를 회전하면 B,C좌표계가 같이 회전한다.
  • 가운데 B좌표계가 회전하면 A좌표계는 현재 상태를 그냥 유지하고 C좌표계가 회전합니다.
  • 오른쪽 C좌표계가 회전하면 A, B좌표계는 현재 상태를 그냥 유지한다.

각 물체를 좌표계에 올려놓고 각 좌표계는 부모-자식관계로 정의해놓고 좌표계를 회전하면 각 물체의 움직임을 만들어 낼 수 있게 됩니다.

좌표계로 물체를 배치할 수도 회전시킬 수도 있습니다.

이런 좌표계를 머리속에 담아 놓으셔야 합니다. 현재 여러분이 이 글을 보고 있는 전자기기가 스마트폰이면 스마트폰을 좌표계에 올려놓고 회전시켜보세요. 좌표계 기준으로 움직이는 각도가 몇도인지 계산해 보세요. 이 각도값을 좌표계 기준으로 몇도인지 알게 된다면 아두이노 관절 로봇의 관절 제어 코딩이 쉬워집니다.

좌표계의 회전각을 코딩화

A관절을 x축으로 45도 회전시킨다면.

Servo.write(45);

여기서 B, C관절은 현재 각도에서 A관절이 45도 회전된 각도의 위치로 움직이게 됩니다. 이게 머리속 좌표계에서 그려져야 합니다.

그래야 관절제어를 쉽게 할 수 있습니다.

정리하면,

  • 좌표계 기준으로 마디를 배치하고 각 마디는 개별 좌표계를 갖는다.
  • 좌표계 기준으로 각 마디의 부모-자식관계 구조로 되어 있다.
  • 좌표계 기준으로 마디의 회전각도를 계산한다.
  • 좌표계는 관절이고 그 회전각은 실제 Servo Motor의 회전 값이 된다.

마무리


관절제어는 좌표계를 기준으로 회전 하고 각 관절은 개별적 좌표계를 가지고 각 좌표계는 부모-자식 관계의 구조로 좌표계가 묶여 있습니다. 좌표계를 관절로 생각해서 물체를 회전 시키면 물체의 움직임을 만들어 낼 수 있습니다. 그리고 좌표계를 기준으로 바라보면 쉽게 그 움직임을 수치화 할 수 있습니다. 좌표계를 기준으로 특정 축을 기준으로 회전 된 각도는 Servo Motor의 회전각이 되어 관절의 움직임을 만들어 내게 됩니다.

그래서 관절제어를 할 때 좌표계를 머리속에 담아놓고 관절 제어를 하면 여러가지의 움직임을 어렵지 않게 만들어 낼 수 있습니다. 지난 시간에 가상시뮬레이터에서 Servo Motor 세개를 나란히 배치하고 이게 6족 보행로봇의 다리이고 전진/후진 동작이라고 했는데 사실 잘 연상이 안되셨을 꺼에요. 만약 그 Servo Motor가 여러분의 머리 속 좌표계에 배치되어 진다면 가상시뮬레이터에서 단순히 일렬로 3개의 Servo Motor가 회전 되었지만 머리 속 좌표계에서 이 회전이 실제 6족 보행 로봇의 다리 움직임으로 그려지게 될 것입니다.

댓글()

[아두이노] 아두이노 관련 자료 관찰 후 원리 실험

IOT/아두이노|2019. 9. 2. 09:00

[아두이노] 아두이노 관련 자료 관찰 후 원리 실험



핀터레스트에서 6족 보행로봇에 관련 이미지들을 한번 검색 중 가장 맘에 드는 ICStation 팀의 Hexapod4 Spider Robot 작품 post안에 Youtube 영상만 보고 움직임을 관찰하고 제 나름대로 한번 재해석 하는 시간을 지난 시간에 가졌었습니다. 마지막에 원리에 대한 실험에 대해 간단히 언급만 하고 끝냈는데 뭔가 좀 아쉬워서 가상시뮬레이터에서 동작 회전 원리에 대해 간단히 테스트 해볼 수 있는 방법에 대해 설명을 할까 합니다. 아주 간단한 한 동작만 실험해 봤네요.


위 그림처럼 6족 보행로봇에서 다리 하나만 간단히 회전을 시켜 동작 원리를 이해하는 시간을 갖도록 하겠습니다.

1. 검색 후 찾은 6족 보행로봇의 다리 한부분




위 그림에서 관절을 어떻게 회전 시켜야지 전진과 후진을 만들 수 있을까요. 위 출처에 가셔서 Youtube 동영상을 보고 오세요. 이걸 제작한 팀이 만든 영상물이 있는데 보행 움직임을 관찰하기 좋은 예제입니다.

ICStation 팀의 Hexapod4 Spider Robot 작품의 동영상을 보고 동작 코딩을 상항하시면 됩니다.

1) 전진



지난시간의 이미지 입니다.


여기서, 각 관절을 어떻게 회전해야지 위 그림처럼 전진 동작을 할 수 있을까요.


  • 1단계 : 초기다리 상태
  • 2단계 : 다리 전진하기 전 B, C관절 45도 위로 회전(다리 들어올리는 동작)
  • 3단계 : A관절을 수평 45도 앞으로 회전(다리의 진행방향)
  • 4단계 : 다리가 전진 상태가 되었을 때 B, C 관절을 45도 아래로 회전(다리를 내리는 동작)
  • 5단계 : A관절을 수평 45도 뒤로 회전(다리가 지탱하기 때문에 몸체가 앞으로 전진하게 됨)

Youtube 속 6족 보행로봇의 다리 움직임을 보면 대충 전진 동작 패턴이 위의 과정으로 진행되는 것 같더군요.

2) 전진 코딩


사실 전진 패턴을 만들면 패턴 변수를 만들어서 담아 놓으면 그 패턴변수값으로 컨트롤 하면 됩니다. 하지만 여러 관절의 패턴 동작을 일일히 만드는 과정은 시간이 좀 걸리고 오늘은 동작 회전에 대한 부분만 간단히 설명하기 때문에 패턴변수를 만들지 않겠습니다. 사실 패턴변수를 만들면 각 동작에 대한 Servo모터의 회전 딜레이 값을 따로 패턴변수로 만들어야 하는데 이 딜레이값은 실제로 Servo모터를 회전시키면서 보정해야 하는 작업이라서 가상으로는 짐작 코딩뿐이 할 수 없기 때문에 복잡한 패턴변수를 만드는 작업은 생략하고 단순하게 전진 동작 패턴에 대해 각 단계 별 동작 명령을 단순하게 코딩으로 전개 할 예정입니다.

원리 코딩이니깐 감안하고 머리속에서 상상하시면서 보시기 바랍니다. 실제는 다르게 동작할 수 있고 이 post는 의미 전달 post입니다.


위 그림의 좌표계를 이해하셔야 합니다. 각 관절의 좌표계를 기준으로 회전값을 줄 예정입니다.

[초기화] 1단계 상태입니다.

  for(int i=0;i<3;i++){
    servo[i].attach(servoPin[i]);  
    servo[i].write(90);
    
  }
  delay(1000);

Servo모터가 전부 90도로 회전 되었을 때 1단계 다리 모양이 만들어 진다고 가정하겠습니다.

[전진]

  servo[1].write(135);  //B관절 다리 올리기
  servo[2].write(135);  //C관절 다리 올리기   
  delay(500);
  servo[0].write(45);  //A관절 전진
  delay(500);
  servo[1].write(90);  //B관절 다리 내리기    
  servo[2].write(90);  //C관절 다리 내리기
  delay(500);
    
  //마지막 몸체이동
  servo[0].write(90);  //A관절 몸체 이동
  delay(1000);

패턴변수로 만들어서 했다면 위 코딩이 좀 복잡하게 설명 되었을 꺼에요. 대충 동작 회전 의미는 이해하셨죠. 실제 이 코딩으로 6족 보행로봇을 정상적으로 움직일 수 없습니다. 다리 하나의 관절에 대한 원리의 의미 동작을 코딩화 실험한 것일 뿐입니다.

실제로 전진하기 위해서는


위 그림에서 1, 4번 다리가 동시에 앞으로 전진 한 후 다음 2,5번 전진하고 마지막으로 3,6번이 전진 한 후에 마지막 몸체이동을 시키면 6족 보행로봇이 전진 시켜야 됩니다.. 사실 위 코딩은 원리를 이해하기 위한 코딩일 뿐 실제로는 다른 결과를 얻을 수 있기 때문에 더이상 깊게 코딩하지 않겠습니다.

위 코딩이 전진이 된다면 후진은 어떻게 해야 할까요. 반대로 코딩하면 됩니다.

[후진]

  servo[1].write(135);     
  servo[2].write(135);     
  delay(500);
  servo[0].write(135);  
  delay(500);
  servo[1].write(90);     
  servo[2].write(90);  
  delay(500);
    
  //마지막 몸체이동
  servo[0].write(90);  
  delay(1000);

원리는 간단하죠.

그러면 좌/후 회전은 어떻게 할까요. 앞명 다리와 후면 다리를 기준으로 다리의 각도를 만들어서 움직여야 하는데 약간 전진/후진과는 좀 더 다리의 회전 컨트롤이 복잡하지만 한번 상상력을 동원해서 동작 회전을 만들어 보셨으면 합니다.

2. 가상시뮬레이터 동작 실험


1) 회로도


  • 준비물 : Servo모터 3개, 아두이노우노, 외부전원
  • 내용 : 2,3,4번 핀을 Servo모터에 연결한다.


2) 코딩


#include <Servo.h>

Servo servo[3];
const byte servoPin[3] = {2,3,4}; //Servo Motor Pin

void setup()
{ 
  for(int i=0;i<3;i++){
    servo[i].attach(servoPin[i]);  
    servo[i].write(90);    
  }
  delay(1000);
}

void loop()
{
  //전진
  servo[1].write(135);     
  servo[2].write(135);     
  delay(500);
  servo[0].write(45);  
  delay(500);
  servo[1].write(90);     
  servo[2].write(90);  
  delay(500);
  servo[0].write(90);  
  delay(1000);
  
  //후진
  servo[1].write(135);     
  servo[2].write(135);     
  delay(500);
  servo[0].write(135);  
  delay(500);
  servo[1].write(90);     
  servo[2].write(90);  
  delay(500);
  servo[0].write(90);  
  delay(1000);  
}

3) 결과


아래 움짤을 보면 2번핀에 연결된 Servo모터는 A관절로 오른쪽으로 이동하면 전진이고 왼쪽으로 이동하면 후진이라고 상상을 해주세요. 그리고 3,4번 핀은 B, C 관절은 다리를 올리는 회전과 내리는 회전을 한다고 상상을 해주세요. 그러면 A관절로 전진/후진 하기전에 B, C 관절이 다리를 올리는 회전을 하고 A관절이 전진/후진 회전을 한 후 B, C 관절이 다리를 내리는 회전을 한다고 머리속에서 그려가면서 상상하시면 되겠습니다.


혹시 제작을 해보시겠다면 다음과 같은 준비물이 필요합니다.

  • Servo Motor - 16개
  • 16채널12비트 PWM/서보모터쉴드(I2C interface)
  • 아두이노우노
  • 외부전원장치

마무리


오늘은 특정 이미지나 영상을 보고 관찰했을 때 그 관찰을 토대로 가상시뮬레이터로 동작 원리를 실험하는 코딩을 해보았습니다. 하지만 위 코딩은 상상속에서 간단히 테스트 할거라 실제로 위 코딩이 정상적으로 보행을 만들어 낼지는 미지수입니다. 단지 동작 원리를 이해하기 위한 가상시뮬레이터에서 유사 실험으로 간단히 테스트를 한 것 뿐입니다. 가상시뮬에터에서 특정 대상을 관찰하고 얻는 원리를 이렇게 실험 할 수 있다는 것을 보여드리는게 오늘 목적이였네요.

마지막으로, 하나의 움직을 회전으로 가상시뮬레이터에서 실험 했는데 현실에서는 정상적으로 보행이 만들어지지 않을 것 같은 찜찜함이 남는 post네요.

댓글()

[아두이노] 핀터레스트에서 찾은 자료 관찰

IOT/아두이노|2019. 8. 30. 09:00

[아두이노] 핀터레스트에서 찾은 자료 관찰



핀터레스트에서 6족 보행로봇에 관련 이미지들을 한번 검색을 하였습니다. 그중에서 가장 맘에 드는 ICStation 팀의 Hexapod4 Spider Robot 작품 post를 발견했는데 자세한 내용은 보지 않고 그안에 Youtube 영상만 보고 움직임을 관찰하고 제 나름대로 한번 재해석 하는 시간을 가졌습니다. 해당 post의 글을 읽게 되면 상상력이 이 post를 쓰신 저자의 생각에 묶일 것 같아서 최대한 제 나름대로 해석하고 원리를 이해해 보고자 했네요.


오늘 post의 핵심은 아두이노 관련 자료를 핀터레스트에서 찾고 그 찾은 post를 보면서 관찰을 통해 원리를 이해하고 그걸 자신의 것으로 만드는 과정입니다.

1. 핀터레스트에서 찾은 6족 보행로봇



위 출처에 가시면 ICStation 팀의 Hexapod4 Spider Robot 작품이 나와 있습니다. 메인 사진을 보시면 다음과 같은데 Servo모터의 관절을 관찰해 봅시다.


출처 : ICStation 팀의 Hexapod4 Spider Robot 이미지

이걸 좀 더 보기 편하게 그려봤네요.


사진과 그림을 그리고 나니 대충 동작 제어가 어느정도 가늠이 되더군요. 그렇다면 ICStation 팀의 Hexapod4 Spider Robot 이 과연 어떻게 움직이게 했을지 궁금해지더군요. 다행히 Youtube로 6족 보행로봇의 움직이는 영상이 담겨져 있었네요.

관절의 움직임을 집중적으로 관찰했네요.

2. 6족 보행로봇 관절 동작 관찰


1) A관절 동작



위 그림에서 관절 A지점의 Servo모터가 수평으로 좌/우 움직이는 동작을 수행하더군요. 위 그림은 전진했을 때 각 관절이 앞쪽으로 45도 방향으로 움직인 상태이고 여기서 다시 몸체만 반대 방향으로 회전시키면 다리는 몸체를 지탱하는 중심축이 되고 몸체가 앞으로 전진하게 되고 다시 위 그림처럼 다리를 움직이고 45도 각도가 되면 몸체를 반대방향으로 회전시키면 몸체가 또 앞으로 전진하고 이런식으로 다리가 먼저 45도 앞으로 전진하고 몸체가 뒤 따라오는 식으로 영상을 보시면 A관절 움직임을 알 수 있을거에요. A관절은 수평으로 몸체을 움직이는 핵심이 됩니다.

2) B관절 동작



B관절은 다리를 들어올리는 동작을 담당하네요. 수직으로 위아래로 움직이면 진행 방향으로 다리를 움직이기 전에 다리를 올려서 해당 다리가 몸체를 지탱하는 중심축을 해제시킨다고 생각하시면 됩니다. 그리고 움직이기 편하게 다리가 올라간 상태를 만듭니다. 그리고 A관절의 회전시킨 방향이 진로 방향이 되고 그 방향에서 다시 B관절이 아래로 움직이고 해당 다리가 6족 보행로봇 몸체를 지탱하는 중심축으로 되돌아가게 됩니다. 다시 설명하면은 6개의 다리가 몸체를 지탱하는 중심축이 되는데 여기서 일부 다리는 중심축을 해제시키고 보행 방향으로 움직이고 다시 몸체를 지탱하는 중식축으로 돌아가는 동작 과정을 거치면서 보행하기 위한 움직임을 만들어 냅니다.

3) C관절 동작



B관절과 함꼐 몸체를 지탱하는 실제 중심다리입니다. 위 그림처럼 지면과 배치된다고 상상해보면 지면과의 몸체의 높이가 달라지고 딱딱한 움직임보다 좀 더 자연스럽게 움직이는 곤충과 유사한 움직임을 만들 어 낼 수 있는 다리 인 것 같아 보입니다. C관절이 없이 A, B관절이 움직인다고 상상을 해보세요. 뭔가 딱딱한 움직임이 연상 되실 꺼에요. 좀 더 자연스러운 움직임을 만들어내기 위해 C관절까지 표현한 것 같습니다. 보행 방향으로 움직이기 전 B관절을 들어올릴 때 C관절도 같이 들어올려서 움직임을 부드럽게 만들었네요. 그리고 지면과의 접촉에서도 C관절의 용도는 많아 보입니다. 제가 실제로 만들어 보지 못하고 잠깐 어제 우연히 검색해서 찾은 post라서 6족 보행로못에 대해 정확한 이야기를 할 수 없기 때문에 좀 설명이 애매하네요. 하지만 곤충과 흡사하게 다리의 움직임을 C관절을 통해서 좀 더 부드럽게 움직여진다는 것은 영상을 통해 알 수 있었습니다. 움직임의 패턴이 AxBxC 의 가지수로 많기 때문에 다른 6족 보행로봇보다는 꽤 흥미를 끄는 보행로봇 같아 보였습니다.

3. 전진 동작 관찰


동영상에 여러 동작 중 전진 동작을 한번 관찰해 봅시다.


위 그림에서 이미지 A가 초기 상태이고 위에서 관절 움직임을 정면 방향으로 전진 할 경우 이미지 B의 형태로 다리 관절이 전부 이동하게 됩니다. 그 때 몸체는 이미지 C처럼 관절을 움직이면 몸체는 앞으로 이동하게 됩니다. 이때 다리가 몸체를 지탱을 확실히 해야지 몸체가 앞으로 전진하겠죠. 순서는 A->B->C->B->C ... 이렇게 움직임으로서 앞으로 전진하는 것 같더군요.

4. 보행 동작 실험


가상시뮬레이터에서 실험을 한다면 Servo모터 3개를 이용하여 다리 하나의 관절 제어 코딩을 설계하시면 됩니다. 즉, 6개의 다리를 제어가 아닌 딱 하나의 다리만 제대로 보행동작 패턴 회전을 만들어 원리를 이해 하고 다리 1개를 동작 할 수 있게 된다면 똑같은 원리로 6개의 다리를 제어하면 됩니다.

아무튼 아래와 같이 가상시뮬레이터에서 3개의 Servo모터의 회전 패턴을 만들면 됩니다.


대충 이렇게 3개를 가상시뮬레이터서 준비하고 나머지 관찰한 관절 움직임을 코딩하면 됩니다. 관절 다리의 움직임은 이 세개의 Servo모터 회전을 순차적 회전 패턴을 만들어서 전진 보행을 만들어 내면 됩니다.

마지막으로, 제가 post하는 순서를 잘 읽어주시기 바랍니다. 특정 검색된 post의 이미지에서 어떻게 관찰을 했는지 그 관찰을 제가 어떻게 접근했는지를 보시고 다른 post에 대해 탐구하실 때 써먹으시면 합니다. 오늘 post의 관찰 핵심은 관절 다리 한개의 3개의 Servo모터 제어입니다. 이 3개의 Servo모터를 어떤식으로 패턴 회전을 시키느냐에 따라 6족 보행로봇이 움직이게 됩니다. 여러분들이 3개의 Servo모터를 회전 시킬 수 있으면 충분히 6족 보행로봇을 움직이게 할 수 있을거라 생각됩니다.

마무리


오늘 post는 아두이노와 관련 된 작품 하나를 관찰하는 과정을 간단히 이야기를 했네요. 참고로 실제로 제작을 한다면 다음과 같은 준비물이 필요합니다. 6족 보행 로봇은 총 18의 Servo모터를 필요 합니다. Servo모터를 많이 사용하기 때문에 그냥 아두이노로 제어 할 수 없습니다. Servo Motor Controller Driver가 필요 합니다. 다수의 Servo모터를 제어할 수 있습니다. 그리고 6족 보행로봇 뼈대, 아두이노, 외부전원 공급장치가 있으면 6족 보행로봇을 만들 수 있겠죠.

댓글()

[아두이노] 핀터레스트에서 아두이노 검색

IOT/아두이노|2019. 8. 29. 09:00

[아두이노] 핀터레스트에서 아두이노 검색



우연히 발견한 핀터레스트라는 사이트를 소개 합니다. 꽤 재밌는 사이트이더군요. 관심있는 주제로 검색을 하면 관련 이미지들을 모아 정리해서 보여주는데 자료 수집용으로 괜찮은 사이트 같아 보였습니다. 핀터레스트는 이용자들이 관련 이미지들을 스크랩하고 그 정보를 다른 사람들과 공유하는 소셜 네트워크 서비스를 제공한다고 하네요. 여기서 재밌는 것은 관련 검색어로 찾은 이미지를 클릭하면 해당 이미지의 post로 넘어 가기 전 해당 이미지와 유사한 다른 이미지들이 검색이 됩니다. 그리고 선택한 이미지를 보면 하단에 저정한 이용자 아디가 있는데 그 아디를 클릭하면 해당 블로그로 가고 그 블로그 안에 또다른 이미지 정보들을 확인 할 수 있어 이용자들 간의 수집 된 정보를 공유되고 있네요. 정보 공유 방식이 효율적이여서 원하는 정보를 수집할 때 유용할 것 같아서 소개합니다.

참고로, 아두이노 뿐만 아니라 다양한 주제의 post들을 공유되고 있는데 관련 단어로 검색을 하면 비슷한 개념의 이미지들을 검색이 되기 때문에 아두이노에 관심 있는 분들이나 다른 주제에 관심있는 분들도 사용하기에 괜찮은 사이트 같더군요. 특정 단어에 대한 관련 이미지들이 검색되는데 관련 이미지의 정확도가 높아서 유용한 사이트인 것 같네요.

1) 핀터레스트에서 아두이노 검색


아두이노 관련 이미지들이 수집 되어 아래 사진처럼 보여줍니다. 약간 포괄적인 검색이 되는데 사진들을 보면 아두이노의 상상력을 자극하는 이미지로 가득하네요.


위와 같이 아두이노를 검색하면 1차 검색으로 아두이노로 표현한 수많은 작품들이 포괄적으로 검색됩니다. 그런데 위에서 아무 이미지나 클릭해보시면 바로 해당 이미지의 post로 가는게 아니라 해당 이미지와 같은 주제로 2차 검색이 이러우 집니다.

그러면, 어떻게 2차 검색이 이루어지는 볼까요.

2) 특정 이미지 검색


아두이노 검색에서 6족 보행로봇 이미지가 마음에 들어서 한번 클릭 해봤네요. 그랬더니 아래 사진과 같이 6족 보행로봇과 비슷한 개념의 이미지들이 가득하네요.


즉, 아두이노->6족 보행로봇에 대한 관련 이미지들이 검색이 되었네요. 여기서 처음 클릭은 6족 보행로봇 이미지에서 다시 클릭하면 해당 6족 보행로봇 post로 최종적으로 넘어가서 정보를 확인 할 수 있게 되는 구조네요.

참고로 특정 이미지 클릭하여 위와 같은 이미지 창이 뜨면 하단에 이용자 아디가 표시 됩니다. 그 아디를 클릭하면 또 다른 공유 자료를 확인 할 수 있습니다.

한번 클릭해 봅시다.

3) 해당 이미지 저장한 이용자 클릭



위 사진처럼 이용자 아디를 클릭하면 해당 블로그로 넘어갑니다.


들어가보니 원하는 결과가 아니였지만 이렇게 이용자들 간의 정보를 공유가 이루어지네요.

이렇게 원하는 이미지를 클릭하고 그 이미지를 공유한 이용자 블로그에 들어가면 그 이미지를 수집한 이용자가 그 이미지와 관련 된 다른 수집 이미지를 검색 할 수 있다는 장점을 있네요. 즉, 누군가 특정 주제에 대해 자료를 수집하고 그 수집한 자료를 자신의 블로그에 정리되어 공유 되어 있다면 우리는 그 자료를 수집하는 시간을 절약 할 수 있습니다.

이제 이미지가 담겨져 있는 post가 대체 어떤 내용이 있는지 한번 살펴봅시다.

4) 특정 이미지 클릭


특정 이미지를 클릭하면 해당 post로 넘어 갑니다. 기대했던 정보는 아니지만 아래 사진처럼 정보를 얻을 수 있네요.


이렇게 원하는 정보를 수집할 수 있고 자신의 블로그에 스크랩하여 공유할 수 있어서 꽤 유용한 사이트 같네요.

마무리


우선 핀터레스트 사이트 자체가 최종 post까지 가지 않더라도 아두이노 관련 검색어로 검색 된 이미지만 보셔도 됩니다. 아두이노의 경우 상상력을 자극하는 이미지들이 많기 때문에 아두이노 공부하시는 분들에게 도움이 될 듯 싶네요.

댓글()