산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

정밀 GPS 기반 시계: 합리적인 가격으로 정확성과 신뢰성 확보

부품 및 소모품

아두이노 우노 (Arduino UNO) ×1
아다프루트 RGB 백라이트 LCD - 16x2 ×1
브레드보드 (일반) ×1
점퍼 와이어 (일반) ×1
GPS 수신기 (일반) ×1

앱 및 온라인 서비스

프로젝트 소개

지금까지 시계 프로젝트에는 다양한 RTC 모듈을 사용하거나 NTP 서버에서 시간을 가져왔습니다. 이 프로젝트에서는 전 세계 GPS 위성의 NMEA 문자열을 파싱하여 시간을 얻는 또 다른 소스를 소개합니다.

요즘 GPS 수신기가 얼마나 저렴한지 놀랐습니다. 하나 구입하세요 (제 경우 GY-GPS6Mv2, u-blox NEO-6M 사용).

정밀 GPS 기반 시계: 합리적인 가격으로 정확성과 신뢰성 확보

a) 선택 사항: 윈도우 PC에서 첫 테스트

u-blox에서 u-center 다운로드 설치. FTDI 어댑터로 GPS 브레이크아웃을 PC COM 포트에 연결하면 약 1분 후 위성 고정(Fix) 완료. 브레이크아웃의 빨간 LED가 깜빡임. F8 - Text Console에서 다양한 NMEA 문자열 확인 가능.

b) 무료 온라인 서비스에서 디코딩 테스트

https://rl.se/gprmc

이제 작동하는 GPS 수신기가 확인되었으니(하늘이 잘 보이는 곳 필수), 원하는 정보를 NMEA 문자열에서 추출할 수 있습니다.

정밀 GPS 기반 시계: 합리적인 가격으로 정확성과 신뢰성 확보

아두이노 IDE에 Adafruit GPS Library 설치 후 예제로 테스트해보세요.

c) 회로 구성

정밀 GPS 기반 시계: 합리적인 가격으로 정확성과 신뢰성 확보 정밀 GPS 기반 시계: 합리적인 가격으로 정확성과 신뢰성 확보 정밀 GPS 기반 시계: 합리적인 가격으로 정확성과 신뢰성 확보

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 20, 4); // LCD 주소, 보통 0x27 또는 0x3F

가지고 있는 디스플레이 사용 (16x2 등)

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>

// GPS 전원 핀 → 5V
// GPS 그라운드 핀 → 그라운드
// GPS TX(송신) → 디지털 8
// GPS RX(수신) → 디지털 7
SoftwareSerial mySerial(8, 7);
Adafruit_GPS GPS(&mySerial);

> GPS 수신기는 3.3V/5V 호환.

d) 우리 시계의 기능

시간, 날짜, 풍속 표시, 고도 표시. 위치는 고정되어 있으므로 불필요.

NMEA 문자열은 UTC 표준으로 시간을 제공. 로컬 타임존 변환은 직접 구현. 현재는 유럽 베를린 기준 +1 추가.

int timezone = +1; // Europe/Berlin (UTC +0100) > NMEA는 UTC 기준

타임존을 취향에 맞게 조정. 변수 hour를 GPS.hour 대신 LCD 출력에 사용.

// LCD 출력
lcd.setCursor(5, 0); // 0 = 첫 줄
int hour = (GPS.hour) + timezone; // UTC를 로컬 타임존으로 변환
if (hour < 10) { lcd.print('0'); }
lcd.print(hour, DEC); lcd.print(':');

유럽에서는 풍속 단위로 노트 대신 km/h 사용. 상수 곱해 변환 후 등급 분류. 1 노트 = 1.852 km/h

float speed = (GPS.speed) * 1.852; // 노트 → km/h 변환

위키피디아 기준 평가:

if (speed <= 1) {lcd.print(" Windstille");}
else if ((speed > 1) && (speed <= 9)) {lcd.print(" leiser Zug");}
else if ((speed > 9) && (speed <= 46)) {lcd.print(" Brise");}
else if ((speed > 46) && (speed <= 56)) {lcd.print(" starker Wind");}
else if ((speed > 56) && (speed <= 74)) {lcd.print(" stuerm. Wind");}
else if ((speed > 74) && (speed <= 83)) {lcd.print(" Sturm");}
else if ((speed > 83) && (speed <= 102)) {lcd.print(" schwerer Sturm");}
else if (speed > 102) {lcd.print(" Orkan");}
else {lcd.print(" ohne Bewertung");}

결과는 디스플레이에 다음과 같이 표시되며 원하는 대로 수정 가능:

정밀 GPS 기반 시계: 합리적인 가격으로 정확성과 신뢰성 확보

루프 업데이트 주기는 2초로 설정. 초와 고도 표시를 포기하면 16x2 디스플레이에도 적합.

정밀 GPS 기반 시계: 합리적인 가격으로 정확성과 신뢰성 확보 정밀 GPS 기반 시계: 합리적인 가격으로 정확성과 신뢰성 확보

다양한 GPS 옵션 탐험 즐기세요!

유럽에는 DCF77 전파 신호도 있지만 훨씬 비싸고 예민하다고 알려져 있습니다.

코드

C/C++

// Adafruit GPS 모듈 테스트 코드 (MTK3329/MTK3339 드라이버)
// 인터럽트 방식으로 GPS 모듈 리스닝하여 프로그램 자유도 확보
// 새 NMEA 문장 사용 가능할 때만 파싱, 필요할 때 데이터 접근
// Adafruit Ultimate GPS 모듈(MTK33x9 칩셋)과 호환 검증
// https://www.adafruit.com/products/746
// 2020.02.01 수정 - Ingo Lohs
// GPRMC & GPGGA 디코더: https://rl.se/gprmc

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 20, 4); // 16x2용 0x27, 제 경우 20x4용 0x3F

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>

// GPS 전원 → 5V, 그라운드 → 그라운드
// GPS TX → 디지털 8, GPS RX → 디지털 7
SoftwareSerial mySerial(8, 7);
Adafruit_GPS GPS(&mySerial);

#define GPSECHO true
int timezone = +1; // Europe/Berlin (UTC +0100)

void setup() {
  lcd.init();
  lcd.backlight();
  Serial.begin(115200);
  delay(5000);
  Serial.println("Adafruit GPS library basic test!");
  
  GPS.begin(9600); // UBLOX 6M: GY-GPS6Mv2 사용
  
  // RMC(권장 최소) + GGA(고정 데이터, 고도 포함) 활성화
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); // 최소 데이터만
  
  // 파싱을 위해 RMC만 또는 RMC+GGA 권장
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1Hz 업데이트
  GPS.sendCommand(PGCMD_ANTENNA); // 안테나 상태 요청
  delay(1000);
  mySerial.println(PMTK_Q_RELEASE); // 펌웨어 버전 요청
}

uint32_t timer = millis();

void loop() {
  char c = GPS.read();
  if ((c) && (GPSECHO)) Serial.write(c);
  
  if (GPS.newNMEAreceived()) {
    if (!GPS.parse(GPS.lastNMEA())) return;
  }
  
  if (timer > millis()) timer = millis();
  
  if (millis() - timer > 2000) {
    timer = millis();
    
    // 시리얼 출력
    Serial.print("\nTime: ");
    if (GPS.hour < 10) Serial.print('0');
    Serial.print(GPS.hour, DEC); Serial.print(':');
    if (GPS.minute < 10) Serial.print('0');
    Serial.print(GPS.minute, DEC); Serial.print(':');
    if (GPS.seconds < 10) Serial.print('0');
    Serial.print(GPS.seconds, DEC); Serial.print('.');
    if (GPS.milliseconds < 10) Serial.print("00");
    else if (GPS.milliseconds < 100) Serial.print("0");
    Serial.println(GPS.milliseconds);
    
    Serial.print("Date: ");
    Serial.print(GPS.day, DEC); Serial.print('/');
    Serial.print(GPS.month, DEC); Serial.print("/20");
    Serial.println(GPS.year, DEC);
    
    Serial.print("Fix: "); Serial.print((int)GPS.fix);
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
    
    // LCD 출력
    lcd.setCursor(5, 0);
    int hour = (GPS.hour) + timezone;
    if (hour < 10) { lcd.print('0'); }
    lcd.print(hour, DEC); lcd.print(':');
    if (GPS.minute < 10) { lcd.print('0'); }
    lcd.print(GPS.minute, DEC); lcd.print(':');
    if (GPS.seconds < 10) { lcd.print('0'); }
    lcd.print(GPS.seconds, DEC);
    
    lcd.setCursor(5, 1);
    if (GPS.day < 10) { lcd.print('0'); }
    lcd.print(GPS.day, DEC); lcd.print('.');
    if (GPS.month < 10) { lcd.print('0'); }
    lcd.print(GPS.month, DEC); lcd.print('.');
    lcd.print(GPS.year, DEC);
    
    if (GPS.fix) {
      Serial.print("Location: ");
      Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
      Serial.print(", "); Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
      Serial.print("Speed (knots): "); Serial.println(GPS.speed);
      Serial.print("Angle: "); Serial.println(GPS.angle);
      Serial.print("Altitude: "); Serial.println(GPS.altitude);
      Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
      
      lcd.setCursor(0, 2);
      float speed = (GPS.speed) * 1.852;
      // lcd.print("Speed km/h: ");
      lcd.print(speed);
      
      // 풍속 등급 (위키피디아 기준)
      if (speed <= 1) {lcd.print(" Windstille");}
      else if ((speed > 1) && (speed <= 9)) {lcd.print(" leiser Zug");}
      else if ((speed > 9) && (speed <= 46)) {lcd.print(" Brise");}
      else if ((speed > 46) && (speed <= 56)) {lcd.print(" starker Wind");}
      else if ((speed > 56) && (speed <= 74)) {lcd.print(" stuerm. Wind");}
      else if ((speed > 74) && (speed <= 83)) {lcd.print(" Sturm");}
      else if ((speed > 83) && (speed <= 102)) {lcd.print(" schwerer Sturm");}
      else if (speed > 102) {lcd.print(" Orkan");}
      else {lcd.print(" ohne Bewertung");}
      
      lcd.setCursor(0, 3);
      lcd.print("Hoehe: ");
      lcd.print(GPS.altitude);
    }
  }
}

제조공정

  1. DIY 저비용 장갑 컨트롤러 & 프로펠러 카 - 아두이노 핸드 컨트롤러 직접 만들기
  2. DHT11 온습도 센서 + LED 표시등 + 피에조 부저 프로젝트
  3. Azure IoT Hub에서 공간 분석 기능을 갖춘 GPS 데이터로거 구축
  4. 아두이노 DHT11 이더넷 실드 온습도 데이터 로거
  5. 아두이노 듀(Due) + 3.2″ TFT로 만드는 실시간 시계 & 온도 모니터
  6. 아날로그 스타일 LED POV 시계 - 아두이노 나노 DIY 프로젝트
  7. 아두이노로 만드는 빛과 소리의 생일 축하 DIY 프로젝트
  8. u-blox LEA-6H GPS 모듈: 아두이노 & 파이썬 연동 가이드
  9. 아두이노 나노 + 128x64 OLED로 실시간 셀룰러 오토마타 (생명 게임) 구현
  10. DIY 기타 스피드 픽 & 스톰프 페달 - 3D 프린팅 모터식 픽 직접 만들기