Sunday, October 07, 2018

Skylab SKM52 - C&Q 84 - GPS module

Had this Skylab SKM52 GPS module for some time, in the past I tested it but nothing special made with it.


 Another ref/name for the module is: C&Q 84

Data-sheet here:

Original idea was to use the pps output to discipline another oscillator but no need for the moment.

This is the pps out:

Lat/Lon display:

Time display:

Interesting enough I could never see the $GPZDA (date and time) ever coming out of the module (during debug output) as on the spec data-sheet, this display of data is just taken from the normal output string. ZDA string would give the microseconds.... probably not implemented.

The code made will scroll alternately between the the values of position and time.

Connections and module view:

Vcc   - Arduino 3v3 output
RX    - Arduino D4 (softserial)
TX    - Arduino D3 (softserial)
GND - Arduino GND
PPS out: connect to a LED with a resistor. PPS only outputs when there's a stable GPS signal.
Pin 10 on Arduino to a 1k resistor then anode of LED, cathode to ground and this will indicate a GPS fix


////////////////// code here bellow
 // read the SKM52 Skylabe GPS module (C&Q 84) via softserial and dumps lat/lon/time on the Arduino nano USB
// pin D3 on Arduino to TX and D4 to RX on the GPS module
// power to module from the 3v3 output on arduino.
// CT2GQV 20180922

// initialize the library with the numbers of the interface pins
#define I2C_ADDR    0x27
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
LiquidCrystal_I2C       lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);


unsigned long fix_age;

SoftwareSerial GPS(3,4);
TinyGPS gps;
void gpsdump(TinyGPS &gps);
bool feedgps();
void getGPS();
long lat, lon;
float LAT, LON;

int fix_detected=0; // no fix yet

int year;
byte month, day, hour, minutes, second, hundredths;

//For the dual display
long previousMillis = 0;
long interval = 3000; // 3 seconds
int a = 60;

void setup(){
  pinMode(10, OUTPUT);
  lcd.begin(16, 2);
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE); // init the backlight
  lcd.setBacklight(1);        // Backlight on


void loop(){
  long lat, lon;
  unsigned long fix_age, time, date, speed, course;
  unsigned long chars;
  unsigned short sentences, failed_checksum;

  gps.get_position(&lat, &lon, &fix_age);
  gps.get_datetime(&date, &time, &fix_age);

  // do we have a fix or not
  if (fix_age == TinyGPS::GPS_INVALID_AGE) {
    Serial.println("No fix detected");fix_detected=0;
    digitalWrite(10, HIGH); delay (1); digitalWrite(10, LOW);
  } else if (fix_age > 5000) {
     Serial.println("Warning: possible stale data!");fix_detected=1;
    digitalWrite(10, HIGH); delay (10); digitalWrite(10, LOW);
  else  fix_detected=2; //Serial.println("Data is current.");
  // lcd.setCursor(0,1); lcd.print("fix: "); lcd.print(fix_detected);

  if (fix_detected==0 ||  fix_detected==1) {lcd.setCursor(0,0); lcd.print("WAITING FIX!!");};

// fix_detected=2; // for debug only to see output even without fix

  if (fix_detected==2) { // let's print gps data
    digitalWrite(10, HIGH); // set the green LED to allways on
   Serial.print("Lat : ");      Serial.print(LAT);
   Serial.print(" :: Lon : ");  Serial.print(LON);
   gps.crack_datetime(&year, &month, &day, &hour, &minutes, &second, &hundredths, &fix_age);
   Serial.print("::"); Serial.print(year);
   Serial.print("-"); Serial.print(month);
   Serial.print("-"); Serial.print(day);
   Serial.print("T"); Serial.print(hour);
   Serial.print(":"); Serial.print(minutes);
   Serial.print(":"); Serial.print(second);

   // every interval print the lat
   unsigned long currentMillis = millis();
   if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    lcd.setCursor(0,0); lcd.print("Lat:"); lcd.print(LAT);
    lcd.setCursor(0,1); lcd.print("Lon:"); lcd.print(LON);
   lcd.setCursor(0,0); lcd.print("                ");
   lcd.setCursor(0,1); lcd.print("                ");
   lcd.setCursor(0,0); lcd.print(year); lcd.print("-"); lcd.print(month); lcd.print("-"); lcd.print(day);
   lcd.setCursor(0,1); lcd.print(hour); lcd.print(":"); lcd.print(minutes); lcd.print(":"); lcd.print(second);
   // no NMEA sentences see where it displays the hundreths...
   // probably needs module programing, says on the manual that outputs the $GPZDA date and time...
   // manual
   //  Serial.print("."); Serial.print(hundredths);
  }; // endif fix detected

void getGPS(){
  bool newdata = false;
  unsigned long start = millis();
  // Every 1 seconds we print an update
  while (millis() - start < 1000)
    if (feedgps ()){
      newdata = true;
  if (newdata)

bool feedgps(){
  while (GPS.available())
    if (gps.encode(
      return true;
  return 0;

void gpsdump(TinyGPS &gps)
  gps.get_position(&lat, &lon);
  LAT = lat;
  LON = lon;
    feedgps(); // If we don't feed the gps during this long routine, we may drop characters and get checksum errors

//////////// Have a nice week!

No comments: