使用带有Arduino uno的SIM900a,使用GPRS将GPS位置发送到服务器

时间:2017-01-01 12:15:31

标签: arduino gps gsm gprs

我一直试图这样做2天了。我能够将GPS lat,lang作为文本消息发送到接收号码。但是我现在想要的是使用GPRS发送它。我使用的是SIM900A GSM / GPRS模块。我是一名软件工程专业的学生,​​我对Arduino很新。这是我使用GSM的代码。

#include <SoftwareSerial.h>
#include <TinyGPS.h>

TinyGPS gps;
SoftwareSerial ss(5, 6);

static void smartdelay(unsigned long ms);

void setup()
{
  Serial.begin(115200);
  ss.begin(9600);
}

void loop()
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;

  gps.f_get_position(&flat, &flon, &age);
  sendLatLang(flat, flon);

  gps.stats(&chars, &sentences, &failed);
  Serial.println();

  smartdelay(1000);
}

static void smartdelay(unsigned long ms)
{
  unsigned long start = millis();
  do
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

static void sendLatLang(float lat, float lang)
{
  if (lat == TinyGPS::GPS_INVALID_F_ANGLE || lang == TinyGPS::GPS_INVALID_F_ANGLE) {
Serial.println("Searching for GPS fix...");
  } else {
    Serial.println("AT+CMGF=1");
    delay(1000);
    Serial.println("AT+CMGS=\"+94123445678\"");
    delay(1000);
    Serial.print("Latittude : ");
    Serial.println(lat);
    Serial.print("Longitude : ");
    Serial.println(lang);
    Serial.write(26);
    delay(1000);
  }
}

1 个答案:

答案 0 :(得分:2)

首先,SoftwareSerial非常非常低效。它会长时间禁用中断,这会干扰草图的其他部分。

总结this answer

  • AltSoftSerial是最好的,但它只适用于8针和8针。 9(在UNO上)。
  • NeoSWSerial是次佳选择。它适用于任何两个引脚,但它仅支持波特率9600,19200和38400

其次,因为您的程序与两个设备对话,您必须小心在程序的任何部分使用delay或“阻止”。当程序“卡在”delay时,没有其他任何东西正在被处理。 GPS字符继续进入,它们最终将溢出输入缓冲区(64个字符限制)。 smartDelay函数尝试解决该问题。

您应该使用Finite-state Machine来处理发送,而无需调用delay。每次通过loop时,FSM都会检查是否有时间进行下一步。对于发送过程的每个“步骤”(即当前的“状态”),使用switch语句和case非常容易实现。

这允许循环不断处理所有GPS字符,即使FSM“等待”一段时间过去。 FSM未使用delay,它会不断检查millis()以查看时间是否已过去。它每loop检查一次。

我还建议使用我的NeoGPS库。它比所有其他库更小,更快,更准确,并且可以配置为仅解析您真正使用的字段和NMEA消息。如果您想尝试一下,可以从Arduino IDE菜单中找到它 Sketch - &gt;包含图书馆 - &gt;管理图书馆

以下是草图的NeoGPS版本:

#include <NeoSWSerial.h>
#include <NMEAGPS.h>

NMEAGPS gps;
NeoSWSerial gps_port(5, 6);

enum state_t { WAITING_TO_SEND, SENDING_CMD1, SENDING_CMD2 }; // valid FSM states
state_t  state;     // current FSM state
uint32_t stateTime; // FSM timer for delays between states

bool     newData = false; // true when a fix with a location is ready
gps_fix  fixToSend;
const uint32_t SEND_INTERVAL = 60 * 1000UL; // once a minute

void setup()
{
  Serial.begin(115200);
  gps_port.begin(9600);
}

void loop()
{
  // Always process GPS characters so the latest fix is ready to go
  while (gps.available( gps_port )) {
    gps_fix newFix = gps.read();

    if (newFix.valid.location) {
      newData   = true;
      fixToSend = newFix;
    }
  }

  // FSM for sending fixes
  switch (state) {

    case WAITING_TO_SEND:
      //  Don't send new data too often.
      if (newData && (millis() - stateTime >= SEND_INTERVAL)) {
        Serial.println( F("AT+CMGF=1") );
        stateTime = millis();
        state     = SENDING_CMD1;
      }
      break;

    case SENDING_CMD1:
      //  Delay 1 second after the CMGF command
      if (millis() - stateTime >= 1000) {
        Serial.println( F("AT+CMGS=\"+94123445678\"") );
        stateTime = millis();
        state     = SENDING_CMD2;
      }
      break;

    case SENDING_CMD2:
      //  Delay 1 second after the CMGS command...
      if (millis() - stateTime >= 1000) {
        // ... then send the message
        sendFix( fixToSend );
        Serial.write(26); // no more data to send

        newData   = false;
        stateTime = millis();
        state     = WAITING_TO_SEND;
      }
      break;
  }
}


static void sendFix( const gps_fix &fix )
{
  //  Send only the fix pieces of interest
  //    (other pieces described on Data Model page)

  Serial.print( F("Latitude : ") );
  Serial.println( fix.latitude(), 6 );
  Serial.print( F("Longitude : ") );
  Serial.println( fix.longitude(), 6 );
}

您的原始程序使用了8896个字节的程序空间和564个字节的RAM。 NeoGPS版本使用 8562 字节的程序空间和 364 字节的RAM。

即使您不使用NeoGPS,也请务必阅读故障排除页面。它描述了许多常见问题,这些问题通常与程序结构和时序有关。

P.S。请注意, F 宏用于“双引号”字符串常量...这可以通过强制它们从FLASH存储器中使用来节省RAM。草图还有一个SENDING_INTERVAL,以避免每秒发送lat / long消息。 :P