ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • MH Real Time으로부터 시각을 읽어서 7Segment x 4EA에 출력하기
    Arduino/MH Real Time 2020. 11. 3. 18:05

    우선 하드웨어의 연결은 아래를 보자.

    designatedroom87.tistory.com/278

     

    아두이노와 MH Real Time과 연결하고 간단한 문자열 함수 보기

    MHREAL TIME의 CLK은 아두이노의 A4번 핀에 연결 MHREAL TIME의 DAT은 아두이노의 A3번 핀에 연결 MHREAL TIME의 RST은 아두이노의 A2번 핀에 연결 나머지 핀은 GND와 VCC를 연결한다. 라이브러리는 DS1302를 추..

    designatedroom87.tistory.com

    아래는 아두이노와 7Segment x 4EA와의 연결이다.

    designatedroom87.tistory.com/273?category=900663

     

    7Segment x 4EA와 아두이노의 연결 & 숫자 출력하기

    테스트로 처음에 4자리 디지털 핀 중에서 맨 왼쪽의 a부분에만 LED를 켜려면 다음과 같이 연결하면 된다. 아두이노의 3.3볼트핀에 7Segment x 4EA의 11번핀을 연결하고 7Segment x 4EA의 12번핀에 220옴 저항

    designatedroom87.tistory.com

     

    7Segment는 자리 수가 4개이므로 시각은 제외하고 분(2자리)과 초(2자리)를 출력하도록 하자.

    여기서 한 가지 해결해야할 문제가 있는데, 시각의 반환하는 함수 rtc.getTimeStr()는 그 반환하는 값이

    "00:00:00" 과 같은 형태이다.

    즉, 문자열을 분리해야하는 과제가 있다.

     

    이는 3가지 방법으로 문자열을 분리할 수 있는데,

    첫 번째는 시각 쪽에 위치한 콜론의 위치(인덱스)와 초에 위치한 콜론의 위치(인덱스)를 찾아서

    substring함수를 이용해서 분과 초를 분리한다.

     

    두 번째는 rtc.getTimeStr()함수는 리턴형이 String인데 이를 배열로 저장을 해서

    분과 초가 저장된 위치를 찾아 각 자리 수를 정수로 변환하는 방법이 있다. 

     

    세 번째는 두 번째 방법과 같은 방법인데, charAt()함수를 써서 처리를 하는 방법이 있다.

    각 방법에 대한 함수들은 다음과 같다.

     

    Case1

     

    Case2

     

    Case3

     

    위의 각 함수들을 loop함수에서 하나씩 호출해보자.

    소스 코드

    더보기
    //  DS1302 라이브러리를 추가
    #include <DS1302.h>
    
    //  분과 초를 분리해서 하기
    #define    SCK_PIN   A4 //  클락(출력핀)
    #define    DAT_PIN   A3 //  데이터(입력핀 일 수도 출력핀일 수도)
    #define    RST_PIN   A2 //  리셋(출력핀)
    
    DS1302 rtc(RST_PIN,DAT_PIN,SCK_PIN);
    
    //  분에 있는 콜론의 위치 인덱스를 찾아 리턴하는 함수
    //  맨 앞에서 콜론의 위치를 찾는다.
    int GetMinuteColonIdx()
    {
       String l_time = rtc.getTimeStr();
    
       return l_time.indexOf(":");
    }
    
    //  초에 있는 콜론의 위치 인덱스를 찾아 리턴하는 함수
    //  맨 뒤에서 콜론의 위치를 찾는다.
    int GetSecondColonIdx()
    {
      String l_time = rtc.getTimeStr();
    
       return l_time.lastIndexOf(":");
    }
    
    //  rtc.getTimeStr함수로부터 분과 초를 분리하는 함수 
    void SplitTimeStr1()
    {
      String l_time = rtc.getTimeStr();
    
      //  substring은 찾는 문자의 시작 인덱스와 (마지막 인덱스 - 1)를 전달 
      String minutes = l_time.substring(GetMinuteColonIdx() + 1,GetMinuteColonIdx() + 3); 
      
      String seconds = l_time.substring(GetSecondColonIdx() + 1,GetSecondColonIdx() + 3 ); 
     
      Serial.println(minutes+seconds);
    }
    
    //  rtc.getTimeStr함수로부터 분과 초를 분리하는 함수 
    void SplitTimeStr2()
    {
      String realTime = rtc.getTimeStr();
    
      char rt[9]; //  널 문자를 포함해서 "00:00:00" 총 9칸이 필요
      
      realTime.toCharArray(rt,9); //  String을 문자열로 변환
       
      int irt[4];
    
      irt[0] = rt[3] - '0'; //  정수로 변환
      irt[1] = rt[4] - '0'; //  정수로 변환
      irt[2] = rt[6] - '0'; //  정수로 변환
      irt[3] = rt[7] - '0'; //  정수로 변환
    
      for (int i = 0; i < 4; i++)
      {
        Serial.println(irt[i]);
      }
    }
    
    void SplitTimeStr3()
    {
      String realTime=rtc.getTimeStr();
      int irt[4];
      
      irt[0]=realTime.charAt(3)-'0';
      irt[1]=realTime.charAt(4)-'0';
      irt[2]=realTime.charAt(6)-'0';
      irt[3]=realTime.charAt(7)-'0';
      for(int i=0;i<4;i++){
        Serial.println(irt[i]);
      }
    }
    
    void setup() {
      // put your setup code here, to run once:
      rtc.halt(false);          //  중지시키는 함수(중지 제거)
    
      rtc.writeProtect(false);  //  쓰기 방지 제거
    
      Serial.begin(9600);
    
      //  날짜 설정
      rtc.setDOW(TUESDAY);
    
      //  시,분,초 설정
      rtc.setTime(14,25,0);
    
      //  일,월,연도  
      rtc.setDate(3,11,2020);
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
      SplitTimeStr3();
    
      delay(1000);  //  1초 간격으로 출력
    }

     

     

     

    위의 내용을 그대로 가지고 와서 구현을 할 것이다.

    그런데 위에서 분과 초를 분리하는 함수는 하나만 남기고 지우도록 하자.

    여기서는 SplitTimeStr1함수를 쓰겠다.

    나머지 두 함수는 지우도록 한다.

    그리고, 아래에서 7Segment 에 LED를 출력하는데 필요한 모든 내용을 그대로 모두 가지고 올 것이다.

    designatedroom87.tistory.com/274?category=900663

     

    시리얼 통신을 이용해서 입력받은 수를 7Segment x4에 출력하기

    우선 시리얼 통신을 하기 전에, 문제를 좀 더 간단히 해보자. 시리얼 통신을 통해서 4자리 숫자 받았다고 가정해보자. 그런 이후에 FourDigitalNum라는 함수의 매개변수로 이 숫자를 전달하면 7Segment

    designatedroom87.tistory.com

     

    7Segment에 숫자를 표기하는 FourDigitalNum함수는 SplitTimeStr1함수에서 호출한다.

    분과 초를 분리한 이후에 이를 정수형으로 변환을 한 후에 출력한다.

    아래는 FourDigitalNum함수의 호출 부분이다.

    전체 소스 코드

    더보기
    //  분과 초를 LED에 출력
    
    //  DS1302 라이브러리를 추가
    #include <DS1302.h>
    
    //  MHREAL TIME의 CLK은 아두이노의 A4번 핀에 연결
    //  MHREAL TIME의 DAT은 아두이노의 A3번 핀에 연결
    //  MHREAL TIME의 RST은 아두이노의 A2번 핀에 연결
    
    #define    SCK_PIN   A4 //  클락(출력핀)
    #define    DAT_PIN   A3 //  데이터(입력핀 일 수도 출력핀일 수도)
    #define    RST_PIN   A2 //  리셋(출력핀)
    
    //  7Segment X 4EA
    #define   D1    10
    #define   D2    11
    #define   D3    12
    #define   D4    13
    
    #define   DIGIT   4   //  7SEGMENT에 표현할 수 있는 자리 수
    
    //  행의 수는 우리가 표현할 십진수의 개수이며, 
    //  열의 수는 십진수에 따른 수 표기에 필요한 세븐세그먼트핀의 수
    bool num[10][8] = {
        {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
    };
    
    DS1302 rtc(RST_PIN,DAT_PIN,SCK_PIN);
    
    void DigitalNum(int _num)
    {
      for (int i = 0; i < 8; i++)
      {
        digitalWrite(i + 2, num[_num][i]);
      }
      delay(1000);
    }
    
    //  디지털핀의 원하는 수를 표시한다.
    void DigitalNum(int Dpin, int _num)
    {
      digitalWrite(Dpin,LOW);
      
      for (int i = 0; i < 8; i++)
      {
        digitalWrite(i + 2, num[_num][i]);
      }
    }
    
    //  디지털 핀들을 초기화하는 함수
    void DigitalPinInit()
    {
      //  디지털 핀에 대한 초기화
      for (int i = 10; i < 14; i++)
      {
        pinMode(i, OUTPUT);
        digitalWrite(i,HIGH);
      }
    }
    
    //  0000에서 9999까지를 디지털 핀에 출력하는 함수
    //  매개변수는 디지털 핀에 출력할 수
    void FourDigitalNum(int _num)
    {
      int digit = 1000;
      int l_num = _num;
      int numArr[DIGIT] = {0,0,0,0};  //  디지털 핀에 출력할 숫자를 저장
      int quota;      //  l_num을 digit로 나눈 몫
      int remainer;   //  l_num을 digit로 나눈 나머지
      int i = 0;      //  numArr배열의 인덱스
    
      //  1. 숫자 분리
      while (l_num != 0)
      {
        quota = l_num / digit;    //  몫을 구한다.
        remainer = l_num % digit; //  나머지를 구한다.
    
        numArr[i++] = quota;      //  출력할 수의 맨 앞자리 부터 저장
    
        l_num = remainer;         //  그 다음 자리의 수를 찾기 위해 설정
        digit /= 10;              //  그 다음 자리의 수를 찾기 위해 설정
      }
    
      //  2. 분리한 수를 디지털 핀에 출력
      for (int i = 0; i < DIGIT; i++)
      {
        //  LED 출력
        DigitalNum(D1 + i, numArr[i]);
        delay(3);
        DigitalPinInit();
        
        Serial.println(numArr[i]);
      }
    }
    
    //  분에 있는 콜론의 위치 인덱스를 찾아 리턴하는 함수
    //  맨 앞에서 콜론의 위치를 찾는다.
    int GetMinuteColonIdx()
    {
       String l_time = rtc.getTimeStr();
    
       return l_time.indexOf(":");
    }
    
    //  초에 있는 콜론의 위치 인덱스를 찾아 리턴하는 함수
    //  맨 뒤에서 콜론의 위치를 찾는다.
    int GetSecondColonIdx()
    {
      String l_time = rtc.getTimeStr();
    
       return l_time.lastIndexOf(":");
    }
    
    //  rtc.getTimeStr함수로부터 분과 초를 분리하는 함수 
    void SplitTimeStr1()
    {
      String l_time = rtc.getTimeStr();
    
      //  substring은 찾는 문자의 시작 인덱스와 (마지막 인덱스 - 1)를 전달 
      String minutes = l_time.substring(GetMinuteColonIdx() + 1,GetMinuteColonIdx() + 3); 
      
      String seconds = l_time.substring(GetSecondColonIdx() + 1,GetSecondColonIdx() + 3 ); 
    
      int l_num = (minutes.toInt()*100) + seconds.toInt();
    
      //  7Segment에 표기
      FourDigitalNum(l_num);
    }
    
    void setup() {
      // put your setup code here, to run once:
      rtc.halt(false);          //  중지시키는 함수(중지 제거)
    
      rtc.writeProtect(false);  //  쓰기 방지 제거
    
      Serial.begin(9600);
    
      //  날짜 설정
      rtc.setDOW(TUESDAY);
    
      //  시,분,초 설정
      rtc.setTime(14,25,0);
    
      //  일,월,연도  
      rtc.setDate(3,11,2020);
    
      //  2번핀부터 9번핀까지 모두 설정
      for (int i = 2; i < 10; i++)
      {
        pinMode(i, OUTPUT);
        digitalWrite(i,LOW);
      }
    
      //  디지털 핀에 대한 초기화
      DigitalPinInit();
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
      SplitTimeStr1();
    }

     

     

    여기 까지만 해도 되나, 한 가지 아쉬운 점은 분과 초 사이에 dot 까지 찍어주면 완벽할 것 같다.

    7Segment의 출력에 관한 내용이니 FourDigitalNum함수에서 이에 대한 처리를 하면 된다.

    dot를 표현할 위치는 두 번째 글자이며, dot를 찍을 위치는 이차원 num배열의 맨 마지막 자리(7번 인덱스)이다.

    이는 결국 1번째 위치의 숫자를 출력하기 전에 dot 위치를 1로 설정해서 출력하면 숫자와 함께 dot가 출력된다.

    그리고 출력 후에,  dot 위치를 0로 설정해서 초기화를 하면 된다.

    이에 대한 내용을 추가할 부분은 FourDigitalNum함수의 내부이다.

     

    전체 소스 코드

    더보기
    //  분과 초를 LED에 출력
    
    //  DS1302 라이브러리를 추가
    #include <DS1302.h>
    
    //  MHREAL TIME의 CLK은 아두이노의 A4번 핀에 연결
    //  MHREAL TIME의 DAT은 아두이노의 A3번 핀에 연결
    //  MHREAL TIME의 RST은 아두이노의 A2번 핀에 연결
    
    #define    SCK_PIN   A4 //  클락(출력핀)
    #define    DAT_PIN   A3 //  데이터(입력핀 일 수도 출력핀일 수도)
    #define    RST_PIN   A2 //  리셋(출력핀)
    
    //  7Segment X 4EA
    #define   D1    10
    #define   D2    11
    #define   D3    12
    #define   D4    13
    
    #define   DIGIT   4   //  7SEGMENT에 표현할 수 있는 자리 수
    
    //  행의 수는 우리가 표현할 십진수의 개수이며, 
    //  열의 수는 십진수에 따른 수 표기에 필요한 세븐세그먼트핀의 수
    bool num[10][8] = {
        {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
    };
    
    DS1302 rtc(RST_PIN,DAT_PIN,SCK_PIN);
    
    void DigitalNum(int _num)
    {
      for (int i = 0; i < 8; i++)
      {
        digitalWrite(i + 2, num[_num][i]);
      }
      delay(1000);
    }
    
    //  디지털핀의 원하는 수를 표시한다.
    void DigitalNum(int Dpin, int _num)
    {
      digitalWrite(Dpin,LOW);
      
      for (int i = 0; i < 8; i++)
      {
        digitalWrite(i + 2, num[_num][i]);
      }
    }
    
    //  디지털 핀들을 초기화하는 함수
    void DigitalPinInit()
    {
      //  디지털 핀에 대한 초기화
      for (int i = 10; i < 14; i++)
      {
        pinMode(i, OUTPUT);
        digitalWrite(i,HIGH);
      }
    }
    
    //  0000에서 9999까지를 디지털 핀에 출력하는 함수
    //  매개변수는 디지털 핀에 출력할 수
    void FourDigitalNum(int _num)
    {
      int digit = 1000;
      int l_num = _num;
      int numArr[DIGIT] = {0,0,0,0};  //  디지털 핀에 출력할 숫자를 저장
      int quota;      //  l_num을 digit로 나눈 몫
      int remainer;   //  l_num을 digit로 나눈 나머지
      int i = 0;      //  numArr배열의 인덱스
    
      //  1. 숫자 분리
      while (l_num != 0)
      {
        quota = l_num / digit;    //  몫을 구한다.
        remainer = l_num % digit; //  나머지를 구한다.
    
        numArr[i++] = quota;      //  출력할 수의 맨 앞자리 부터 저장
    
        l_num = remainer;         //  그 다음 자리의 수를 찾기 위해 설정
        digit /= 10;              //  그 다음 자리의 수를 찾기 위해 설정
      }
    
      //  2. 분리한 수를 디지털 핀에 출력
      for (int i = 0; i < DIGIT; i++)
      {
        //  두 번째 자리의 숫자에 dot를 출력
        if (i == 1)
        {
          //  맨 마지막 자리에 1을 대입하면, dot를 화면에 출력하는 것으로 설정
          for (int j = 0; j < 10; j++)
          {
             num[j][7] = 1;
          }
        }
    
        //  LED 출력
        DigitalNum(D1 + i, numArr[i]);
        delay(3);
        DigitalPinInit();
        
        //  두 번째 자리의 숫자에 dot를 출력하던 것을 다시 초기화
        if (i == 1 )
        {
          for (int j = 0; j < 10; j++)
          {
            num[j][7] = 0;
          }
        }
        Serial.println(numArr[i]);
      }
    }
    
    //  분에 있는 콜론의 위치 인덱스를 찾아 리턴하는 함수
    //  맨 앞에서 콜론의 위치를 찾는다.
    int GetMinuteColonIdx()
    {
       String l_time = rtc.getTimeStr();
    
       return l_time.indexOf(":");
    }
    
    //  초에 있는 콜론의 위치 인덱스를 찾아 리턴하는 함수
    //  맨 뒤에서 콜론의 위치를 찾는다.
    int GetSecondColonIdx()
    {
      String l_time = rtc.getTimeStr();
    
       return l_time.lastIndexOf(":");
    }
    
    //  rtc.getTimeStr함수로부터 분과 초를 분리하는 함수 
    void SplitTimeStr1()
    {
      String l_time = rtc.getTimeStr();
    
      //  substring은 찾는 문자의 시작 인덱스와 (마지막 인덱스 - 1)를 전달 
      String minutes = l_time.substring(GetMinuteColonIdx() + 1,GetMinuteColonIdx() + 3); 
      
      String seconds = l_time.substring(GetSecondColonIdx() + 1,GetSecondColonIdx() + 3 ); 
    
      int l_num = (minutes.toInt()*100) + seconds.toInt();
    
      //  7Segment에 표기
      FourDigitalNum(l_num);
    }
    
    void setup() {
      // put your setup code here, to run once:
      rtc.halt(false);          //  중지시키는 함수(중지 제거)
    
      rtc.writeProtect(false);  //  쓰기 방지 제거
    
      Serial.begin(9600);
    
      //  날짜 설정
      rtc.setDOW(TUESDAY);
    
      //  시,분,초 설정
      rtc.setTime(14,25,0);
    
      //  일,월,연도  
      rtc.setDate(3,11,2020);
    
      //  2번핀부터 9번핀까지 모두 설정
      for (int i = 2; i < 10; i++)
      {
        pinMode(i, OUTPUT);
        digitalWrite(i,LOW);
      }
    
      //  디지털 핀에 대한 초기화
      DigitalPinInit();
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
      SplitTimeStr1();
    }

     

    댓글

Designed by Tistory.