Arduino에서 GPS 모듈 (GMS7-CR6)에서 날짜 및 시간 획득

소개



RandyHoo( @RandyHoo_ )라고 합니다.
닉시 관 시계를 만들거나하는 임베디드 프로그래머입니다.

닉시 관 시계를 만들 때 빠진 부분이므로 전개합니다.

이번 해설하는 코드는 GitHub 에서 공개하고 있습니다.

실장·해설



이번에 사용한 GPS 모듈은 GMS7-CR6 입니다.

Nixcie_Clock.ino
#include <SoftwareSerial.h>
#include <string.h>
#include <stdlib.h>
#include <MsTimer2.h>
#include <Wire.h>

int CalenderArray[6] = {}; //0:Year1桁目, 1:Year2桁目, 2:Month1桁目, 3:Month2桁目, 4:Day1桁目, 5:Day2桁目

int ClockArray[6] = {}; //0:Hour1桁目, 1:Hour2桁目, 2:Min1桁目, 3:Min2桁目, 4:Sec1桁目, 5:Sec2桁目
boolean data_get_flag = false; //GPSデータ取得確認用フラグ

void loop() {
  data_get_flag = GPSDataCatch();//初期値設定用のデータ取得
}

GPSDataCatch.ino
int GPSDataCatch(){
  String year_1; //現在の年1桁目
  String year_2; //現在の年2桁目
  String month_1; //現在の月1桁目
  String month_2; //現在の月2桁目
  String day_1; //現在の日1桁目
  String day_2; //現在の日2桁目
  String hour_1; //現在の時1桁目
  String hour_2; //現在の時2桁目
  String min_1; //現在の分1桁目
  String min_2; //現在の分2桁目
  String sec_1; //現在の秒1桁目
  String sec_2; //現在の秒2桁目

  char GPS_Rx_buf[256]; //受信用バッファ(255文字分)
  char GPS_Rx_count; //受信データカウンタ

  String want_frame = "$GPRMC"; //データを取り出したいフレーム
  String WantStatus = "A"; //ステータス判別用

  char data_read_count = 0; //データ読み出しカウンタ
  int data_get_flag = false; //データ取得結果

GPS로부터 수신한 데이터를 해석해 갑니다.
문자 변환을 실시하기 위해(때문에), String형으로 취급합니다.

GPSDataCatch.ino
  //Ackフレームを受信するまでループを回す
  do {
    if ( sGps.available() ) {
      GPS_Rx_buf[ GPS_Rx_count ] = sGps.read();
      GPS_Rx_count++;
    }
    //バッファが溢れそうなら
    if ( GPS_Rx_count > 250 ) {
      break;
    }
  } while ( GPS_Rx_buf[ GPS_Rx_count - 1 ] != 0x0A );
  GPS_Rx_buf[ GPS_Rx_count ] = '\0'; //一番最後の要素に改行を入れる
  String buf_str = GPS_Rx_buf; //Stringで処理するために変換

데이터는 「,」로 단락지어지고 있으므로, 「,」의 위치를 ​​취득해, 필요한 데이터만을 취득해 갑니다.
일시를 취득할 수 없었던 경우에는 이 함수의 반환값으로 false 를 돌려줍니다.

GPSDataCatch.ino
  //欲しいデータかどうか調べる
 //LogSample : $GPRMC,142152.000,A,3247.4679,N,12957.0161,E,0.00,36.32,250116,,,A*5A
  if ( want_frame == buf_str.substring( 0, 6 ) && WantStatus == buf_str.substring( 18, 19 ) ) {
    data_read_count = buf_str.indexOf( ",", data_read_count ); //1つ目の区切り文字を探す
    data_read_count++; //不要データなので次のデータへ

    data_read_count = buf_str.indexOf( ",", data_read_count ); //2つ目の区切り文字を探す(時刻)
    data_read_count++; //時計・カレンダーでは文字列位置を直指定するので次のデータへ

시각은 UTC(협정 세계시)로 취득하므로, 일본 시간에 수정합니다.
또, 10 이하의 숫자를 「0X」 표시하기 위해서 변환 처리를 씹고 있습니다.

GPSDataCatch.ino
    String UTC_time = buf_str.substring( 7, 9 ); //時刻修正処理の為にHourを抜き出す
    int JP_time = atoi( UTC_time.c_str() ) + 9; //日本時間に修正
    //変換した際に24時以上になった場合
    if ( JP_time > 23 ) {
      JP_time -= 24;
    }
    String JP_time_str = String( JP_time ); //日本時間に差し換えるためにStringに変換
    //時刻が1桁だった場合
    if ( JP_time < 10) {
      String change_double_digit_calc = JP_time_str.substring( 0, 1 ); //1桁目を保持
      JP_time_str = "00"; //JP_time_strのデータ長を2に増設する
      char hoge_cddc = *change_double_digit_calc.c_str(); //1桁目に0を差し込むためにchar型に変換
      JP_time_str.setCharAt( 0, '0' ); //1桁目を0に差し替える
      JP_time_str.setCharAt( 1, hoge_cddc ); //2桁目に1桁目を差し込む
      String JP_time_str = String( JP_time ); //もう一度Stringに変換
    }

    String JP_time_first_digit = JP_time_str.substring( 0, 1 ); //1桁目を取り出す
    char hoge_1 = *JP_time_first_digit.c_str(); //char型に変換
    String JP_time_second_digit = JP_time_str.substring( 1, 2 ); //2桁目を取り出す
    char hoge_2 = *JP_time_second_digit.c_str(); //char型に変換
    buf_str.setCharAt( 7, hoge_1 ); //1桁目を差し替える
    buf_str.setCharAt( 8, hoge_2 ); //2桁目を差し替える

일시를 취득할 수 있었으므로 각각 int형으로 변환해 배열에 넣어 갑니다.

GPSDataCatch.ino
    //時1桁目を取得
    hour_1 = buf_str.substring( 7, 8 );
    ClockArray[0] = hour_1.toInt();
    //時2桁目を取得
    hour_2 = buf_str.substring( 8, 9 );
    ClockArray[1] = hour_2.toInt();
    //分1桁目を取得
    min_1 = buf_str.substring( 9, 10 );
    ClockArray[2] = min_1.toInt();
    //分2桁目を取得
    min_2 = buf_str.substring( 10, 11 );
    ClockArray[3] = min_2.toInt();
    //秒1桁目を取得
    sec_1 = buf_str.substring( 11, 12 );
    ClockArray[4] = sec_1.toInt();
    //秒2桁目を取得
    sec_2 = buf_str.substring( 12, 13 );
    ClockArray[5] = sec_2.toInt();

    //3~9つ目までの区切り文字をスキップする
    for (int i = 0; i < 7; i++) {
      data_read_count = buf_str.indexOf( ",", data_read_count ); //3つ目の区切り文字を探す
      data_read_count++; //不要データなので次のデータへ
    }

    //日1桁目を取得
    day_1 = buf_str.substring( data_read_count, data_read_count + 1 );
    CalenderArray[4] = day_1.toInt();
    data_read_count++;
    //日2桁目を取得
    day_2 = buf_str.substring( data_read_count, data_read_count + 1 );
    CalenderArray[5] = day_2.toInt();
    data_read_count++;
    //月1桁目を取得
    month_1 = buf_str.substring( data_read_count, data_read_count + 1 );
    CalenderArray[2] = month_1.toInt();
    data_read_count++;
    //月2桁目を取得
    month_2 = buf_str.substring( data_read_count, data_read_count + 1 );
    CalenderArray[3] = month_2.toInt();
    data_read_count++;
    //年1桁目を取得
    year_1 = buf_str.substring( data_read_count, data_read_count + 1 );
    CalenderArray[0] = year_1.toInt();
    data_read_count++;
    //年2桁目を取得
    year_2 = buf_str.substring( data_read_count, data_read_count + 1 );
    CalenderArray[1] = year_2.toInt();

이상입니다.

좋은 웹페이지 즐겨찾기