Arduino 没有将完整的 NMEA 语句写入 SD 卡文件

Arduino not writing full NMEA sentence to SD-card file

我目前正在构建一个小型 GPS 盒,它可以跟踪我的位置并将完整的 NMEA 语句写入 SD 卡。
(我想在我的电脑上解析它)
我正在使用 Arduino Nano 和 NEO-6M GPS Module 来获取数据。

有效方法:从模块获取 NMEA 数据,写入 SD 卡。
通过 Serial.write 将数据输出到串行输出工作正常。

现在我遇到的问题是 Arduino 似乎无法足够快地将数据写入 SD 卡并与 GPS 模块不同步。这偶尔会产生这样的东西:$G3,3,09,32,20,248,*4D

我对如何解决这个问题有一些想法:
1.写入数据更快
2. 始终等到数据完全写入后再获取下一个修复
3. 只写每秒 GPS 定位
4. 首先写入缓冲区,然后一次性写入SD卡

我尝试实现这些但每次都失败了(抱歉我是新手)。

这是我当前的代码:

#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>

SoftwareSerial GPS_Serial(4, 3); // GPS Module’s TX to D4 & RX to D3
File GPS_File;
int NBR = 1;  //file number

void setup() {
  Serial.begin(9600);
  GPS_Serial.begin(9600);
  SD.begin(5);

  //write data to a new file
  bool rn = false;
  while (rn == false) {
    if (SD.exists(String(NBR) + ".txt")) {
      NBR = NBR + 1;
    }
    else {
      GPS_File = SD.open(String(NBR) + ".txt", FILE_WRITE);
      GPS_File.write("START\n");
      GPS_File.close();
      rn = true;
    }
  }
}

void loop() {                                               
  GPS_File = SD.open(String(NBR) + ".txt", FILE_WRITE);

  while (GPS_Serial.available() > 0) {
    GPS_File.write((byte)GPS_Serial.read());
  }
  GPS_File.close();
}

在尝试了不同的方法后,我决定将其简化为最基本的水平。
没有任何花哨的编码或缓冲区,我现在只是将数据直接写入 SD 卡并每 15 秒刷新一次,这有可能丢失多达 15 秒的数据,即切割时 15 个 GPS 定位(每秒 1 个)关闭电源。

唯一可能发生数据丢失的其他时间是在程序将累积数据刷新到 SD 时。不过,这并非每次都会发生。

为了将 NMEA 句子解析为可用数据,我使用了 GPSBabel。它会自动忽略虚线。转换为 .gpx 后,我用 Google Earth 查看它。

这是 "finished" 代码:

#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>

SoftwareSerial GPS_Serial(4, 3);  // GPS Module’s TX to D4 & RX to D3
File GPS_File;
int NBR = 1;                      //file number

unsigned long TimerA;             //save timer
bool sw = false;                  //save timer switch

void setup() {
  Serial.begin(9600);
  GPS_Serial.begin(9600);
  SD.begin(5);                    //SD Pin

  //write data to a new file
  bool rn = false;
  while (rn == false) {
    if (SD.exists(String(NBR) + ".txt")) {
      NBR = NBR + 1;
    }
    else {
      GPS_File = SD.open(String(NBR) + ".txt", FILE_WRITE);
      GPS_File.write("START\n");
      rn = true;
    }
  }
}

void loop() {
  while (GPS_Serial.available() > 0) {
    GPS_File.write(GPS_Serial.read());
  }

  //set up timer
  if ( sw == false) {
    TimerA = millis();
    sw = true;
  }

  //save every 15 seconds
  if (millis() - TimerA >= 15000UL) {
    GPS_File.flush();
    sw = false;
  }
}