FatFs problem saving gps data

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm still struggling with my gps logger. I want to save the gps data from a NEO-6M and save it to an SD card as a .gpx. I can save the content without error:

    <trkpt lat="48.191566" lon="15.202584">
      <ele>246.1</ele>
      <time>2019-11-08T12:09:53Z</time>
    </trkpt>

But the GPX file itself needs a header, which would be this: 

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<gpx version="1.1" creator="GPS Visualizer https://www.gpsvisualizer.com/" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<trk>
  <name>Logging</name>
  <trkseg>

 

When I try to write the header before the endless loop cycle, something goes wrong, because the avr keeps resetting. At this case the only thing has been written on the card is the header string. I'm using the FatFs ( http://elm-chan.org/fsw/ff/00index_e.html ). I know that many things can goes wrong, but at first glance do you have any idea what can be the problem? Maybe I'm just simply using the FatFs wrong. Here is the code: 

 

const char header[] = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n"
					  "<gpx version=\"1.1\" xmlns=\"http://www.topografix.com/GPX/1/1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
					  " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n<trk>\n"
					  "  <name>Logging</name>\n"
					  "  <trkseg>";
const char ending[] = "  </trkseg>\n</trk>\n</gpx>";

void FormatGPXData(char* input, float lat, float lon, char* alt, char* speed, char* time, char* date)
{
    float intpart = 0;
    float latitude = modff(lat / 100.0 , &intpart) / 60 * 100 + intpart;
    float longitude = modff(lon / 100.0 , &intpart) / 60 * 100 + intpart;

    sprintf(input, "    <trkpt lat=\"%f\" lon=\"%f\">\n      <ele>%s</ele>\n      <time>%sT%sZ</time>\n      <speed>%s</speed>\n    </trkpt>\n", latitude, longitude, alt, date, time, speed);
}

int main(void)
{
	uint8_t i = 0;
	uint8_t status = D_ERROR;
	char sentence[100U];
    char sd_data[160U];
    char c = '\0';

    FRESULT fr;
    FATFS fs;
    FIL fil;

	UART_Init(9600);
	RingBuffer_InitBuffer(&Buffer);
	LCDInit(LS_NONE);

	LCDClear();
	LCDWriteStringXY(0, 0, "Welcome");

 	f_mount(&fs, "", 0);
 	fr = open_append(&fil, "logfile.gpx");
 	if(fr == FR_OK)
 	{
 		f_printf(&fil, header);
 		f_close(&fil);
 	}

	sei(); 

	while(1)
	{
        while (c != '$')
        {
            while(RingBuffer_IsEmpty(&Buffer)); // wait until chars arrive
            {
                c = RingBuffer_Remove(&Buffer);
            }
        }
        sentence[i++] = c;

        while (c != '\n')
        {
            while(RingBuffer_IsEmpty(&Buffer)); // wait until chars arrive
            {
                c = RingBuffer_Remove(&Buffer);
                sentence[i++] = c;
            }
        }

        sentence[i] = '\0';
        i = 0;

		status = proc_sentence(sentence);

        if(status == OK)
		{
            f_mount(&fs, "", 0);
            fr = open_append(&fil, "logfile.gpx");

            if (fr == FR_OK)
            {
                if(gpgll_datas.data_arrive == TRUE)
                {
                    FormatGPXData(sd_data, gprmc_datas.latitude, gprmc_datas.longitude, gpgga_datas.altitude, gpvtg_datas.speed_kmh, gprmc_datas.time, gprmc_datas.date);
					f_printf(&fil, sd_data);
                    fr = f_close(&fil);
                    LCDClear();
                    LCDWriteStringXY(0, 0, gpgga_datas.satellites);
                    LCDWriteStringXY(8, 0, gpgga_datas.altitude);
                    LCDWriteStringXY(0, 1, gpvtg_datas.speed_kmh);
                    gpgll_datas.data_arrive = FALSE;
                }
            }

            status = D_ERROR;
        }
        else
        {
            LCDClear();
            LCDWriteStringXY(0, 0, "StatErr");
        }  

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't know the implementation of f_printf() but might it require:

	f_printf(&fil, "%s", header);

?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good catch, regarding the documentation, I forgot it

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Where do you check ‘sentence’ for overrun? Bad things happen if you exceed 100 bytes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmm, there is no overrun check, but the remark is true, definetly need one to avoid overrun.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

‘Defensive programming’ - you have no control of what data comes in. Ensure you validate the input. There’s plenty of examples of nmea parsers on the internet for you to choose from.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

yoman91 wrote:
When I try to write the header before the endless loop cycle, something goes wrong, because the avr keeps resetting.

So what have you done to identify what, exactly, goes wrong?

 

It could be something trivial like the string is just too long - have you tried writing a shorter string?

 

You haven't said what AVR you're using - does it have on-chip debug?

 

If it does, then use it to step through the code & see where it's going wrong.

 

If it doesn't, then instrument your code so that you can see what's happening.

 

A UART is probably the best way to do this; failing that, the LCD could be used in a pinch.

 

See: https://www.avrfreaks.net/commen...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried to shorten the header string, but when it was containing only 10 characters, it was still not working stable. I think I have memory issues, but because I have no one-wire debugger for the Atmega328p, I cannot be sure about it. I cannot use the UART for debugging, because the GPS module is using it. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I corrected it, but nothing changed. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yoman91 wrote:
I cannot use the UART for debugging, because the GPS module is using it. 

Do you have a spare pin, if so then use softuart to gain a serial output you can use for debug!

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looks like I had some memory problem. I moved every constants to the eeprom territory, and looks like it is working now. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sounds like wishful thinking. I night be wise to identify the root cause and understand the problem so that you avoid the same issue next time. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When avr-size runs at the end of the build what percentage of SRAM usage does it show? You probably don't want that figure to be much above 70% as there needs to be room for the stack frame. (If you use autos heavily it might need to be even lower).