Arduino Scripted GPS Simulator

Portland Internation Raceway

Here is the basis of the Arduino program for my scripted GPS simulator. It works with the following test data file loaded into dataflash (see: Serial Transfer of Text File from PC to Arduino).

Sample Data File:

045.593980122.690800292.10084.22
245.593980122.690800292.15084.97
445.594090122.691100291.01092.06
645.594120122.691200291.11087.55
845.594120122.691400290.66086.93
045.594160122.691400290.80087.32
245.594180122.691500290.87088.52
445.594230122.691600290.80089.22
645.594260122.691600290.97089.33
845.594260122.691700291.00089.61
045.594300122.691900291.17090.19
245.594330122.692000291.05090.54
445.594330122.692200291.30091.07
645.594370122.692200291.31091.81
845.594400122.692200291.34092.36
045.594440122.692500291.39093.13
245.594470122.692500291.36093.46
445.594470122.692500291.32093.98
645.594470122.692700291.63094.25
845.594520122.692700291.55094.90
045.594530122.692700291.62095.70
245.594590122.692900291.37095.85
445.594600122.693000291.60096.31
645.594600122.693100291.37096.69
845.594650122.693300291.34097.10
045.594670122.693300291.40097.46
245.594730122.693400291.35098.05
445.594740122.693500291.25098.51
645.594800122.693700291.10098.84
845.594810122.693800291.23099.47
045.594810122.693800291.32099.96
245.594870122.693900291.38100.34

Scripted GPS Simulator:

/*
  Arduino Scripted GPS Simulator
  James M. Eli
  3/12/2012
  All Rights Reserved.
  
Note: No checksum calculation for the NMEA sentences (checksum output is XX). 
      If you need a cs, it’s just a hex representation of the XOR of all characters 
      in the sentence between (not including) the $ and the * character.
      //XOR the received data
      checksum ^= gprmc[i];
 
Sentence format:
  $GPRMC,184331.200,V,45.59462,N,122.692900,W,68.39,63.60,80212,,,A*xx
Specific GPS data is extracted from dataflash:
                2     45.594620  122.692900   068.39063.60
  245.594620122.692900068.39063.60 (32 chars)
*/
#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <DataFlash.h>

//dataflash page size (bytes)
#define PAGE_SIZE 512
#define BYTES_PER_LINE 32
#define MAX_LINES 32
 
char sec[2];
char lat[10];
char lng[11];
char hdg[7];
char spd[7];
volatile uint8_t t4 = 10;
volatile uint8_t t3 = 30;
volatile uint8_t t2 = 0;
volatile uint8_t t1 = 0;
volatile boolean _5Hz_flag = 0;
uint32_t lines;
char gprmc[96];

void TimerInit() {
  cli();
  //allow oscillator to stabilize
  _delay_ms(1000);
  //disable the timer 1 and 2 interrupts
  TIMSK1 &= ~((1<<OCIE1A) | (1<<OCIE1B) | (1<<TOIE1));
  //select prescaler: 16MHz/64/50000 = 5Hz per overflow
  TCCR1A = 0;
  TCCR1B = (1<<CS11) | (1<<CS10);
  TCCR1C = 0;
  TIFR1 = ((1<<OCF1A) | (1<<OCF1B) | (1<<TOV1));
  //65536 – 15536 = 50000
  TCNT1 = 0x3cb0;
  TIMSK1 |= (1<<TOIE1);
}
 
void IncrementTime() {
  t1++;
  if (t1 > 4) {
    t1 = 0;
    t2++;
  }	
  if (t2 > 59) {
    t2 = 0;
    t3++;
  }	
  if (t3 > 59) {
    t3 = 0;
    t4++;
  }
  if (t4 > 23)
    t4 = 0;
}	
 
//
ISR(TIMER1_OVF_vect) {
  TCNT1 = 0x3cb0;
  _5Hz_flag = true;
}

//
void ReadDataFlash(void) {
  uint8_t i;
  
  //time
  sec[0] = DataFlash.ReadByte();
  //latitude
  for (i=0; i<9; i++)
    lat[i] = DataFlash.ReadByte();
  //longitude
  for (i=0; i<10; i++)
    lng[i] = DataFlash.ReadByte();
  //heading
  for (i=0; i<6; i++)
    hdg[i] = DataFlash.ReadByte();
  //speed
  for (i=0; i<6; i++)
    spd[i] = DataFlash.ReadByte();
  //lines of data read
  if (++lines >= MAX_LINES) {
    DataFlash.StartRead(1);
    lines = 0;
  }
}

void setup() {
  cli();
  _5Hz_flag = false;
  sec[0] = '0';
  sec[1] = '\0';
  lat[10] = '\0';
  lng[11] = '\0';
  hdg[7] = '\0';
  spd[7] = '\0';
  lines = 0;
  //set pins here
  //
  Serial.begin(19200);
  TimerInit();
  DataFlash.Init();
  DataFlash.StartRead(1);
  sei();
}

void loop() {
  ReadDataFlash();
  while (1) {
    if (_5Hz_flag) {
      IncrementTime();
      //format $GPRMC sentence
      sprintf(gprmc,"$GPRMC,%2.2u%2.2u%2.2u.%1s00,A,%9s,N,%10s,W,%s,%s,080112,,,S*XX", t4, t3, t2, sec, lat, lng, hdg, spd);
      Serial.println(gprmc);
      ReadDataFlash();
      _5Hz_flag = false;
    }
  }
}

Advertisements

About Jim Eli

µC experimenter
This entry was posted in Uncategorized and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s