我一直试图这样做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);
}
}
答案 0 :(得分:2)
首先,SoftwareSerial非常非常低效。它会长时间禁用中断,这会干扰草图的其他部分。
总结this answer:
其次,因为您的程序与两个设备对话,您必须小心在程序的任何部分使用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