프로젝트

나도 메이커! 메이커스 여러분들의 작품/프로젝트를 공유하는 공간입니다.

초음파 센서와 LCD를 이용해 헬스 Counter 만들기

2016-01-14 16:05:49

개요

 

추운 겨울이라서 실외에 나가서 헛둘헛둘~ 나가서 운동하기는 싫고,

눈에보인게 아두이노인데 , 몇가지 센서는 별로 없어서

지니어스 키트에 있던  푸쉬업/스쿼트의 거리를 측정해줄 초음파센서와, 푸쉬업/스쿼트 갯수를 측정한 것을 보여줄 LCD 를 이용해서 

푸쉬업 및 스쿼트가 가능한  health 카운터를 만들어 보았어요~!

추운겨울 집에만 있지말고, 

아두이노 헬스 카운터를 만들어서 실내 몸짱왕이 되보아요~ㅎㅅㅎ

 

 

사전 지식

 

-초음파 거리센서

-LCD 사용

 

 

미리 보기

 

 

초음파센서, 가변저항, LCD 를 이용한 모델링까지 더해 보았습니다. 사람의 얼굴처럼 나와보이게 하였는데요,

 

 

<모델링 앞면>

 

 

<모델링 전체적인 모습>

 

 

<모델링 옆모습>

 

 

 

그럼 모델링에 필요한 센서들과 과정들을 알아볼까요?

 

 

<푸시업 거리를 측정해줄 초음파 센서>

 

<측정된 푸쉬업갯수와 칼로리를 보여주는 LCD>

 

 

<모드를 선택할 가변저항과 풀업 버튼>

 

<가변저항과 풀업버튼 고정>

 

 

<나머지도 연결중>

 

 

<앞 조립>

 

 

<앞 연결>

 

 

 

초기 화면은 다음과 같습니다.

 

<초기 화면>

 

왼쪽에 연결해 두엇던 가변저항을 돌리면 (0~500) 값이면 Squart 모드임을 알려줍니다.

 

<스쿼트 모드>

 

왼쪽에 연결해 두엇던 가변저항을 돌리면 (500~1023) 값이면 Push up 모드임을 알려줍니다.

버튼을 누르면, Push up mode가 실행됩니다.

<푸쉬업 모드>

 

 

가까울때는 카운트가 증가하지 않습니다. 

가까울때는 down-flag가 true가 되고, up_flag는 false 입니다.

 

<가까울때>

 

멀어질때는 up_flag가 true가 되고, 

down_flag와 up_flag 모두 true 이니 카운트가 올라갑니다.

 

<멀 때-카운트 증가>

 

 

헉헉 카운트를 2번이나 해서 운동을 다하였으니 운동을 정지시켜 볼까요?

 

<헉헉 끝>

 

버튼을 다시 누르면 ,FINAL Score가 나오며,

<파이널 스코어>

 

마지막으로 했던  운동했던 점수가 3초동안 보여집니다.

<마무리 스코어>

 

 

 

 

부품목록

 

NO

부품명

수량

상세설명

1

오렌지보드

1

아두이노 우노 호환 보드

2

초음파 센서

1

초음파 센서

3

브레드보드

1

브레드보드

4

점퍼케이블

N

점퍼케이블

5

LCD

1

LCD

6

100KΩ 저항

1

100KΩ 저항

7 가변저항 2

가변저항

8 푸쉬버튼 1

푸쉬버튼

 

 

부품명

오렌지보드

초음파 센서

브레드보드

점퍼케이블

파트

x1

x1

x1

x N

부품명

LCD

100KΩ 저

가변저항 푸쉬버튼

파트

  x1

x1

x2 x1

 

 

 

 

하드웨어 Making

 

 

브레드보드 레이아웃

 

 

 

아두이노 브레드 보드 레이아웃은 이렇게 구성 되어있습니다. 

LCD 아랫부분에 있는 가변저항은 LCD의 밝기를 조절하기 위한 가변저항이고,

버튼은 운동의 시작/끝을 나타내는 기능을가진 것입니다.

버튼 아랫쪽의 가변저항은 운동의 모드 스쿼트 및 푸시업을 결정하는 가변저항입니다.

 

 

* 직접 외관을  3D 프린터로 디자인을 해서, 아두이노를 넣고 싶으시다면 9v 건전지와 connector 가 필요하니 참조해 주세요.^^

 

 

전자 회로도

 

 

 

 

 

 

 

소프트 웨어 코딩

 

함수는 LCD 화면에 내용을 출력해 주는 함수인 Print 함수와 

초음파 센서를 이용해 거리를 측정해 주는 함수인 Distance 함수

운동한 시간을 측정해주는 Time 함수

두가지 운동인 Squart와 PushUp 함수 두가지가 있습니다.

Time 함수는 시리얼 모니터에만 출력하도록 설정 해 놓았으니,

출력하고 싶으시다면 LCD 화면에 출력하도록 코드를 바꾸어 보세요~

 

  // LCD를 쉽게 제어하기 위한 라이브러리를 추가합니다.
#include <LiquidCrystal.h>
//LCD 화면에 내용을 출력해 주는 함수
void Print();
//초음파 센서를 이용해 거리를 측정해 주는 함수
float Distance();
//운동한 시간을 측정해 주는 함수
void Time();
//운동 종류별 함수
void Squart();
void PushUp();

// 오렌지보드의 4, 5, 6, 7, 8, 9 번핀을 사용하도록 지정된 lcd객체를 생성합니다.
LiquidCrystal lcd(4, 5,6,7,8,9);
//게임상태여부 버튼
const int buttonPin=10;
//초음파센서 셋팅
int trigPin = 12;
int echoPin = 13;


//가변저항의 값에 따라 모드를 고르는 기능
int modeSet=A0;
//가변저항의 값을 읽어 들여온 mode 변수
int mode=analogRead(modeSet);

//운동 상태여부를 나타내 주는 변수들
boolean buttonStatus; //버튼상태
int Flag;                       //상태 여부
int finish;                    //운동 종료

//운동을 계속하고 있는지, 아닌지 확인하는 변수(가까이 엎드려 있는지 유무)
boolean up_flag=false;
boolean down_flag=false; 

int count=0;                // 푸시업/스쿼트 운동 갯수 
float kcal=0;                //소모된 칼로리

//시간 변수
long previousMillis = 0;            // LED에 마지막으로 수정된 내용을 저장할 변수
long startTime ;                    // 스탑워치의 시작 시간
long elapsedTime ;                  // 스탑워치의 지연된 시간
int fractional;                     // 시간의 소수점 아래 부분


// LCD 화면에 COUNT와 Kcal를 출력해 주는 함수
void Print(){
    // 0번째 줄 0번째 셀부터 입력하게 합니다.
    lcd.setCursor(0,0);
    // 아래의 문장을 출력합니다.
    lcd.print("COUNT:");
    lcd.print(count);    
    
    // 1번째 줄 0번째 셀부터 입력하게 합니다.
    lcd.setCursor(0,1);
    // 아래의 문장을 출력합니다.
    lcd.print("Kcal:");
    lcd.print(kcal);
    delay(400);   
}


//초음파 센서를 이용해 거리를 측정해 주는 함수
float Distance(){  
        
  //초음파 센서를 이용한 거리 값 측정
  float duration, distance;
  digitalWrite(trigPin, HIGH);
  delay(10);
  digitalWrite(trigPin, LOW);
  // 초음파를 보낸다. 다 보내면 echo가 HIGH 상태로 대기하게 된다.
  
  duration = pulseIn(echoPin, HIGH); // echoPin 이 HIGH를 유지한 시간을 저장 한다.
  distance = ((float)(340 * duration) / 10000) / 2;  // HIGH 였을 때 시간(초음파가 보냈다가 다시 들어온 시간)을 가지고 거리를 계산 한다.

  // cm 값으로 변환한 값을 반환
  return distance;
 }

 
//운동한 시간을 측정해 주는 함수
void Time(){  
   
    //푸쉬업 카운트가 0이면,
    if(count==0){      
      startTime = millis();                    //시작 시간을 저장
      }

    //푸쉬업 카운트가 1이상이면, 운동한 시간을 계산하기 시작
      if(count>=1){
         elapsedTime =   millis() - startTime;              //지연 시간을 저장

         //소수점 윗부분
         Serial.print( (int)(elapsedTime / 1000L));         //초로 변환하기 위해 1000으로 나누어 준다.그리고, print 하기위해 int형으로 캐스팅 해준다
         
        //소수점  아래 출력
        Serial.print(".");                           
        //시간의 소수점 부분을 구하기위한 모듈러 연산자를 사용.모듈러 연산자(%)란 나머지를 반환해 주는 함수이다.
       fractional = (int)(elapsedTime % 1000L);

       //모듈러 연산자의 갯수에 따라서 0을 덧붙여 준다.
       if (fractional == 0)
          Serial.print("000");      // add three zero's
       else if (fractional < 10)    // if fractional < 10 the 0 is ignored giving a wrong time, so add the zeros
          Serial.print("00");       // add two zeros
       else if (fractional < 100)
          Serial.print("0");        // add one zero
       Serial.println(fractional);  // 소수점 부분 출력
    
           //시간이 경과되었다면,
           if ( (millis() - previousMillis > 100) ) {
          previousMillis = millis();           //이전 시간을 최근 시간으로 업데이트 해준다.
           }
       

        }//푸쉬업 카운트가 1이상이면의 끝
  
  }//운동한 시간을 출력해 주는 함수의 끝


//스쿼트 함수
void Squart(){
    //초음파 센서로부터 측정한 거리를 가져온다.
  float distance=Distance();
  //시리얼 모니터에 측정한 거리 출력
  Serial.print(distance);
  Serial.print("cm ");
  
  //거리가 40<distance<70 이면 아래로 움직인 것이므로 down_flag를 true로 설정
    if ((40<distance) && (distance<70) ){
    down_flag=true;
    up_flag=false;                        //다운을 한후, up을 해줘야 카운트가 올라가게끔!
    }    
    
//70~75 사이의 값을 넣지 않은이유 : 70근방에서 부르르 떨경우, 운동한 갯수가 올라가므로 제외해 주었다.

 //거리가 75<distance<100 이면 위로 움직인 것이므로 up_flag를 true로 설정    
    else if( (75<distance) && (distance<100) ){
    up_flag=true;
    }
 //그밖의 경우 플래그를 변경해 주지 않는다.
    else{      
  }   
   
//down_flag와 up_flag가 true 라면         
    if( (down_flag==true) && (up_flag==true) ){
    //푸쉬업 카운트,kcal를 증가,
    count++;
    kcal=kcal+0.05;    
   
    //다시 down_flag와 up_flag를 false로 설정해준다.
        down_flag=false;
        up_flag=false;        
     // LCD를 초기화 합니다.
    lcd.clear();
    }
     Serial.print("Squart_count  ");
     //스쿼트 갯수와 kcal를 시리얼 모니터에 출력
    Serial.println(count);    
    //스쿼트 갯수와 kcal를 LCD 화면에 출력
    Print();          
  }
  

//푸쉬업 함수
void PushUp(){
    //초음파 센서로부터 측정한 거리를 가져온다.
  float distance=Distance();
  //시리얼 모니터에 측정한 거리 출력
  Serial.print(distance);
  Serial.print("cm ");
  
//거리가 0<distance<15이면 아래로 움직인 것이므로 down_flag를 true로 설정
    if ((0<distance) && (distance<15) ){
    down_flag=true;
    up_flag=false;                        //다운을 한후, up을 해줘야 카운트가 올라가게끔!
    }    
//15~20 사이의 값을 넣지 않은이유 : 15근방에서 부르르 떨경우, 운동한 갯수가 올라가므로 제외해 주었다.

 //거리가 20<distance<50이면 위로 움직인 것이므로 up_flag를 true로 설정    
    else if( (20<distance) && (distance<50) ){
    up_flag=true;
    }
 //그밖의 경우 플래그를 변경해 주지 않는다.
    else{      
  }      
//down_flag와 up_flag가 true 라면         
    if( (down_flag==true) && (up_flag==true) ){
    //푸쉬업 카운트,kcal를 증가,
    count++;
    kcal=kcal+0.825;    
     //다시 down_flag와 up_flag를 false로 설정해준다.
        down_flag=false;
        up_flag=false;        
     // LCD를 초기화 합니다.
    lcd.clear();
    }
     Serial.print("Pushup_count  ");
     //푸쉬업 갯수와 kcal를 시리얼 모니터에 출력
    Serial.println(count);    
    //푸쉬업 갯수와 kcal를 LCD 화면에 출력
    Print();        
  }



// 실행시 가장 먼저 호출되는 함수이며, 최초 1회만 실행됩니다.
// 변수를 선언하거나 초기화를 위한 코드를 포함합니다.
void setup() {
 //시리얼 모니터 시작
  Serial.begin(9600);  
  // 초음파 센서 trig를 출력모드로 설정, echo를 입력모드로 설정  
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);  
  //가변저항으로 모드를 받아오는것을 입력모드로 설정
  pinMode(modeSet,INPUT);
  // 16개의 셀과 2줄을 사용하도록 설정합니다.
  lcd.begin(16,2);  
}




// setup() 함수가 호출된 이후, loop() 함수가 호출되며,
// 블록 안의 코드를 무한히 반복 실행됩니다.
void loop(){
//버튼이 눌리면 시작하도록 설정
if(digitalRead(buttonPin)==HIGH)
{
  if(Flag==0)
  {
    Flag=1;
    buttonStatus=!buttonStatus;        
    lcd.clear();
  }
}
//초기화면 
else if(digitalRead(buttonPin)==LOW && Flag==0 && buttonStatus==0){  
    Flag=0;                  
       //운동 모드 측정
      mode=analogRead(modeSet);
     Serial.println(mode);   
    //lcd에 안내출력
    lcd.setCursor(0,0);
    lcd.print("SetMode-resistor");
    lcd.setCursor(0,1);
    lcd.print("Start-Button");   
   delay(2000);
                      //가변저항값이 0이상 500미만이면 Squart Mode 라는것을 안내
                      if( (0<=mode) && (mode<500) ){
                          lcd. clear();
                          lcd.setCursor(0,0);
                          lcd.print("Squart Mode");
                          delay(500);
                          lcd.clear();              

                         //카운트,시작시간,kcal를 0으로 초기화
                         count=0;
                         startTime=0;
                         kcal=0;
                               
                    }    

                       //아닐경우, 가변 저항 값이 500<mode<1023 이면 PushUp Mode라는 것을 안내    
                   else{
                            lcd. clear();
                            lcd.setCursor(0,1);
                            lcd.print("PushUp Mode");
                             delay(500);
                            lcd.clear();
                            
                         //카운트,시작시간,kcal를 0으로 초기화
                         count=0;
                         startTime=0;
                         kcal=0;
                  }
}        
else if(digitalRead(buttonPin)==LOW && Flag==0 && buttonStatus==0){
  Flag=0;
  }
else{
    Flag=0;            
}

//버튼이 눌렸으면 운동 시작!
    if(buttonStatus){          
                           
                    //운동한 시간을 측정
                   Time();    

                      //가변 저항 값이 0<mode<500 이면 Squart Mode가 실행 됩니다.                      
                  if( (0<=mode) && (mode<500) ){
                          Squart();               
                    }
                                                  
                      //아닐경우, 가변 저항 값이 500<mode<1023 이면 PushUp Mode가 실행 됩니다.          
                   else if((500<=mode) && (mode<=1023)){         
                    PushUp();
                  }             

                delay(300);
                                
               //버튼을 다시 누르면, 운동 종료         
              if(digitalRead(buttonPin)==HIGH){

                finish = true;
                buttonStatus=0;   
        
                    if(finish==1 && buttonStatus==0){
                      lcd.clear();
                      lcd.setCursor(0,0);
                      lcd.print("Final Score");
                      delay(1000);
                      lcd.clear(); 
                      Print();
                      delay(3000);
                      finish= false; 
                      lcd.clear();
                      }//if 의 끝
                 } //버튼의 눌림여부의 끝
                 
    }      
 }


 

 

김연주충북대학교