0

我正在做一个 GPS 记录器项目。我有一个带有发射器和接收器以及 GPS 和 GSM 模块的Arduino Mega 。我还有一个带有发射器、接收器和蜂鸣器的Arduino Uno 。

当两个设备相距太远时,GPS 数据会被提取并使用 GSM 模块发送到我的网络服务器。当我将文件发送到服务器时,它会创建一个文本文件,当我移动到另一个位置时,它会覆盖以前的位置。

我试图弄清楚如何附加文本文件而不是覆盖它。我发现了很多使用 SD 卡屏蔽的东西,但没有它就什么都没有。

#define GPS_PIN_1       9       // GPS serial pin RX
#define GPS_PIN_2       8       // GPS serial pin TX
#define CHECKPIN        13      // Pin that lights up when things are checked
#define GPSRATE         4800    // GPS baud rate

#include <SoftwareSerial.h>
#include <Flash.h>
#include <Streaming.h>

// How many bytes of input to buffer from the GPS?
#define BUFFERSIZE      100      
#define ENDLN           

int rx1Pin=31; 
int txPin=30;  
int tx1Pin=11;  
int onModulePin = 2;
int rxPin=12;
SoftwareSerial mySerial = SoftwareSerial(GPS_PIN_1, GPS_PIN_2);  //(rx,tx)
SoftwareSerial txSerial = SoftwareSerial(rxPin, txPin);
SoftwareSerial rxSerial = SoftwareSerial(rx1Pin, tx1Pin);
char sendChar ='H';
char incomingChar = 0;
int counter=0;

//GPS variables
int numSats = 0;
int fixType = 0;
int time[] = {
  0, 0, 0};
double latitude = 0.0;
double longitude = 0.0;
long altitude = 0;
long maxAlt = 0;
int speed = 0;
int txCount = 0;
int ExOnce = 0;
int FalcomCheck = 0;
int LogCheck =0;
unsigned long GpsOffTime = 0;  
unsigned long SmsStart = 0;     // SMS-time
char buffer[BUFFERSIZE];

void switchModule(){            // Function to switch the module ON;
  digitalWrite(onModulePin,HIGH);
  delay(2000);
  digitalWrite(onModulePin,LOW);
  delay(2000);
}

void setup(){
  pinMode(rxPin, INPUT);
  pinMode(txPin,OUTPUT);
  pinMode(rx1Pin, INPUT);
  pinMode(tx1Pin,OUTPUT);
  pinMode(GPS_PIN_1, INPUT);
  pinMode(GPS_PIN_2, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(13, OUTPUT);
  digitalWrite(7, HIGH);
  pinMode(onModulePin, OUTPUT);

  txSerial.begin(4800);
  rxSerial.begin(4800);
  mySerial.begin(4800);
  Serial.begin(19200);      // The GPRS baud rate
  switchModule();           // Switch the module ON

  for (int i=0;i<2;i++){    // Wait 20 sec for connection
    delay(10000);                        
  } 
}

void loop(){
  txSerial.println(sendChar);
  Serial.println(sendChar);

  for(int i=0; i<6; i++) {
    incomingChar = rxSerial.read(); //Read incoming message from TX.

    if (incomingChar =='L') {
      GPS();//Serial.println("It Works");
    }
  }
}

void GPS(){
  Serial.flush();

  // Get a GGA string from the GPS, and
  // check if it's a valid fix, and extract the data.
  getNMEA("$GPGGA");    
  delay(100);
  numSats = getSats();
  fixType = getFixType();
  // Make sure we have a valid fix
  if (fixType != 0) {
    getTime(time);
    latitude = getLat();
    longitude = getLong();
    altitude = getAlt();

    // Keep track of the maximum altitude
  }     

  // Convert latitude and longitude into strings.
  char latString[12]; 
  char longString[12];
  doubleToString(latitude, 4, latString);
  doubleToString(longitude, 4, longString);

  sprintf(buffer, "%02d:%02d:%02d,%s,%s,%ld", 
    time[0], time[1], time[2], latString, longString, altitude);
  Serial.println(buffer);

  if (fixType > 0) {
    if (ExOnce==0){
      digitalWrite(13, HIGH);
      //ExOnce=1;
      sendsms();
      logftp();
      // for (int i=0; i<3; i++) {    // Wait 30 sec for a connection.
      //   delay(10000);                        
      // } 
    }
  }

  delay(200);
}

void sendsms(){ 
  Serial.println("AT+CMGF=1");         // Set the SMS mode to text. 
  delay(500);
  Serial.print("AT+CMGS=");            // Send the SMS the number.
  Serial.print(34,BYTE);               // Send the " char.
  Serial.print("**********");          // Send the number change ********* 
                                       // by the actual number.
  Serial.println(34,BYTE);             // Send the " char.
  delay(1500); 
  Serial.print("Hi this is the General text testing."); // The SMS body
  delay(500);
  Serial.print(0x1A,BYTE);             // End of message command 1A (hex)

  delay(20000);
 }

void logftp(){ 
  Serial.println("AT&k3");         // Flow activate

  delay(1000);
  Serial.print("AT+KCNXCFG=0,");     // Connect to GPRS
  Serial.print(34,BYTE);
  Serial.print("GPRS");
  Serial.print(34,BYTE);
  Serial.print(",");
  Serial.print(34,BYTE);
  //Serial.print("wap.cingular");
  Serial.print("epc.tmobile.com");
  Serial.print(34,BYTE);
  Serial.print(",");
  Serial.print(34,BYTE);
  Serial.print(34,BYTE);
  Serial.print(",");
  Serial.print(34,BYTE);
  Serial.println(34,BYTE);

  delay(1000);
  Serial.println("AT+KCNXTIMER=0,60,2,70");   // Set timers

  delay(1000);
  Serial.println("AT+CGATT=1");               // Network check

  delay(1000);
  Serial.print("AT+KFTPCFG=0,");    //FTP configuration/connect
  Serial.print(34,BYTE);
  Serial.print("ftp.insertaddress.com");  //FTP address
  Serial.print(34,BYTE);
  Serial.print(",");
  Serial.print(34,BYTE);
  Serial.print("username");     //Username
  Serial.print(34,BYTE);
  Serial.print(",");
  Serial.print(34,BYTE);
  Serial.print("password");       //Password
  Serial.print(34,BYTE);
  Serial.println(",21,0");        //Port         

  delay(500);
  Serial.print("AT+KPATTERN=");     
  Serial.print(34,BYTE);
  Serial.print("--EOF--Pattern--");
  Serial.println(34,BYTE);

  delay(500);
  Serial.print("AT+KFTPSND=0,,");
  Serial.print(34,BYTE);
  Serial.print("log");          //Directory folder of FTP
  Serial.print(34,BYTE);
  Serial.print(",");
  Serial.print(34,BYTE);
  Serial.print("pol.txt");      //Text file
  Serial.print(34,BYTE);
  Serial.println(",0");

  delay(12000);       

  Serial.print(buffer);   
  Serial.println("--EOF--Pattern--"); 
  delay(12000);

  Serial.println("AT+KTCPCLOSE=1,1"); 
  delay(1000);
} 

// ------- GPS Parsing ----------

// Reads a line from the GPS NMEA serial output
// Give up after trying to read 1000 bytes (~2 seconds)
int readLine(void) {
  char c;
  byte bufferIndex = 0;
  boolean startLine = 0;
  byte retries = 0;
  while (retries < 20) {
    c = mySerial.read();

    if (c == -1) { 
      delay(2); 
      continue; 
    }

    if (c == '\n') continue;
    if (c == '$') startLine = 1;
    if ((bufferIndex == BUFFERSIZE-1) || (c == '\r')) {
      if (startLine) {
        buffer[bufferIndex] = 0;
        return 1;
      }
    }
    if (startLine)
      buffer[bufferIndex++] = c;
    //} 
    else {
      retries++;
      delay(50);
    }
  }
  return 0;
}

// Returns a specific field from the buffer
void getField(int getId, char *field, int maxLen) {
  byte bufferIndex = 0;
  byte fieldId = 0;
  byte i = 0;
  while (bufferIndex < sizeof(buffer)) {
    if (fieldId == getId) {
      // End of string, or string overflow
      if (buffer[bufferIndex] == ',' || i > (maxLen - 2)) {
        field[i] = 0;   // Null terminate
        return;
      }
      // Buffer chars to field
      field[i++] = buffer[bufferIndex++];
    } 
     else {
      // Advance field on comma
      if (buffer[bufferIndex] == ',') {
        bufferIndex++;          //Advance in  buffer
        fieldId++;              // Increase field     position counter
      } 
      else {
        bufferIndex++;          // Advance in  buffer
      }
    }
  }
  // Null terminate incase we didn't already..
  field[i] = 0;
}

// Polls for an NMEA sentence of type requested
// Validates checksum, silently retries on failed checksums
int getNMEA(char *getType) {
  char type[7];
  byte retries = 0;
  while (retries < 2) {
    if (readLine() && validateChecksum()) {
      ;
      getField(0, type, sizeof(type));
      if (strcmp(type, getType) == 0) {
        return 1;
      }
    } 
    else {
      retries++;
     }
  }
  Serial.println("Failed to read GPS");

  return 0;
}

// Validates the checksum on an NMEA string
// Returns 1 on valid checksum, 0 otherwise
int validateChecksum(void) {
  char gotSum[2];
  gotSum[0] = buffer[strlen(buffer) - 2];
  gotSum[1] = buffer[strlen(buffer) - 1];
  // Check that the checksums match up
  if ((16 * atoh(gotSum[0])) + atoh(gotSum[1]) == getCheckSum(buffer))
    return 1;
  else
    return 0;
}

// Calculates the checksum for a given string
// returns as integer
int getCheckSum(char *string) {
  int i; 
  int XOR;  
  int c;
  // Calculate checksum ignoring any $'s in the string
  for (XOR = 0, i = 0; i < strlen(string); i++) {
    c = (unsigned char)string[i];
    if (c == '*') break;
    if (c != '$') XOR ^= c;
  }
  return XOR;
}

// Returns the groundspeed in km/h
int getSpeed(void) {
  char field[10];
  getField(7, field, sizeof(field));
  int speed = atoi(field);
  return speed;
}

// Return the fix type from a GGA string
int getFixType(void) {
  char field[5];
  getField(6, field, sizeof(field));
  int fixType = atoi(field);
  return fixType;
}

// Return the altitude in meters from a GGA string
long getAlt(void) {
  char field[10];
  getField(9, field, sizeof(field));
  long altitude = atol(field);
  return altitude;
}

// Returns the number of satellites being tracked from a GGA string
int getSats(void) {
  char field[3];
  getField(7, field, sizeof(field));
  int numSats = atoi(field);
  return numSats;
}

// Read the latitude in decimal format from a GGA string
double getLat(void) {
  char field[12];
  getField(2, field, sizeof(field));   // read the latitude
  double latitude = atof(field);       // convert to a  double (precise)
  int deg = (int) latitude / 100;      // extract the number of degrees
  double min = latitude - (100 * deg); // work out the number of minutes
  latitude = deg + (double) min/60.0;  // convert to decimal format
  getField(3, field, sizeof(field));   // get the hemisphere (N/S)

  // sign the decimal latitude correctly
  if (strcmp(field, "S") == 0)
    latitude *= -1;

  return latitude;
}

// Read the longitude in decimal format from a GGA string
double getLong(void) {
  char field[12];
  getField(4, field, sizeof(field));    // read the longitude
  double longitude = atof(field);       // convert to a double
  int deg = (int) longitude / 100;      // extract the number of degrees
  double min = longitude - (100 * deg); // work out the number of minutes
  longitude = deg + (double) min/60.00; // convert to decimal format
  getField(5, field, sizeof(field));    // get the E/W status

  // sign decimal latitude correctly
  if (strcmp(field, "W") == 0) 
    longitude *= -1;

  return longitude;
}

// Converts UTC time to the correct timezone
void convertTime(int *time) {
  // How many hours off GMT are we?
  float offset = -5;
  long sectime = ((long)(time[0]) * 3600) + (time[1] * 60) + time[2];
  sectime += (offset * 3600.0);
  // Did we wrap around?
  if (sectime < 0) sectime += 86400;
  if (sectime > 86400) sectime -= 86400;
  // Convert back to time
  time[0] = (int)(sectime / 3600);
  time[1] = (int)((sectime % 3600) / 60);
  time[2] = (int)((sectime % 3600) % 60);
}

// Parses a time field from a GGA string
void parseTime(char *field, int *time) {
  char tmp[3]; 
  tmp[2] = 0; // Init tmp and null terminate
  tmp[0] = field[0]; 
  tmp[1] = field[1]; 
  time[0] = atoi(tmp); // Hours
  tmp[0] = field[2]; 
  tmp[1] = field[3]; 
  time[1] = atoi(tmp); // Minutes
  tmp[0] = field[4]; 
  tmp[1] = field[5]; 
  time[2] = atoi(tmp); // Seconds
}

// Gets the hours, minutes and seconds from a GGA string
void getTime(int *time) {
  char field[12];
  getField(1, field, sizeof(field));
  parseTime(field, time);
  convertTime(time);
}


// ------ MISC ----------

// Returns a string with a textual representation of a float
void doubleToString(double val, int precision, char *string){

  // Print the int part
  sprintf(string, "%d", (int)(val));
  if(precision > 0) {
    // Print the decimal point
    strcat(string, ".");
    unsigned long frac;
    unsigned long mult = 1;
    int padding = precision -1;
    while (precision--) { 
      mult *=10; 
    }
    if (val >= 0)
      frac = (val - (int)(val)) * mult;
    else
      frac = ((int)(val)- val ) * mult;
    unsigned long frac1 = frac;
    while (frac1 /= 10) { 
      padding--; 
    }
    while (padding--) { 
      strcat(string, "0"); 
    }

    // Convert and print the fraction part
    sprintf(string+strlen(string), "%d", (int)(frac));
  }
}


// Converts a HEX string to an int
int atoh(char c) {
  if (c >= 'A' && c <= 'F')
    return c - 55;
  else if (c >= 'a' && c <= 'f')
    return c - 87;
  else
    return c - 48;
}
4

1 回答 1

2

If the server is where the text file is received via SMS/GSM, that server program controls how the file is written or appended. Your posted Arduino code would not need to be changed. On the server, where you now open the file - first check if the file exists and if it does, change the open function to add append mode. Exactly how depends on the OS/language of your server program. But you should be able to figure it out from reading the documentation on the open call.

于 2012-04-19T18:03:52.303 回答