2017-01-01 14 views
2

저는 2 일 동안이 작업을 시도했습니다. 수신 번호로 문자 메시지로 GPS lat, lang을 보낼 수 있습니다. 그러나 내가 지금 원하는 것은 GPRS를 사용하여 이것을 보내는 것입니다. SIM900A GSM/GPRS 모듈을 사용하고 있습니다. 저는 소프트웨어 공학 학생이며 Arduino를 처음 접했습니다. 이것은 GSM을 사용하는 코드입니다.GPU를 사용하여 서버에 GPS 위치를 전송하기 위해 Arduino uno가있는 SIM900a를 사용합니다.

#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); 
    } 
} 

답변

2

우선 SoftwareSerial은 매우 비효율적입니다. 스케쥴의 다른 부분을 방해하는 장시간 동안 인터럽트를 비활성화합니다.

  • AltSoftSerial 가장이지만, 그것은 단지 (AN UNO에) 핀 8 & 9 일 :

    this answer을 요약합니다.

  • NeoSWSerial 다음으로 좋습니다. 그것은 어떤 두 개의 핀에 작동하지만, 그것은 단지 전송 속도를 9600, 19200 및 38400

둘째를 지원하여 두 장치에 프로그램 회담 있기 때문에, 당신은 어떤 부분에서 delay를 사용하거나 "차단"에 대한 조심해야 귀하의 프로그램의. 프로그램이 delay에 "붙어있는"동안 다른 것은 처리되지 않습니다. GPS 문자가 계속 입력되고 결국에는 입력 버퍼 (64 문자 제한)를 오버플로합니다. smartDelay 함수는이를 해결하려고합니다.

을 호출하지 않고 Finite-state Machine을 사용하여 송신을 처리해야합니다. loop을 통해 매 FSM은 다음 단계를 수행 할 시간인지 확인합니다. 이는 전송 프로세스의 각 "단계"(즉, 현재 "상태")에 대해 switch 문과 case 문을 사용하여 구현하기가 매우 쉽습니다.

이렇게하면 FSM이 일정 시간 동안 "대기 중"인 경우에도 루프가 모든 GPS 문자를 계속 처리 할 수 ​​있습니다. FSM은 delay을 사용하지 않고 시간이 경과했는지 계속 확인하기 위해 항상 millis()을 확인합니다. loop마다 한 번 확인합니다.

NeoGPS 라이브러리를 사용하는 것이 좋습니다. 다른 모든 라이브러리보다 작고 빠르며 정확하며 실제 사용하는 필드와 NMEA 메시지 만 구문 분석하도록 구성 할 수 있습니다. 시험해보고 싶다면 Arduino IDE 메뉴 스케치 -> 라이브러리 포함 -> 라이브러리 관리에서 사용할 수 있습니다.

#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 바이트 RAM의 564 바이트를 사용 :

여기 스케치의 NeoGPS 버전입니다. NeoGPS 버전은 바이트의 프로그램 공간과 바이트의 RAM을 사용합니다.

NeoGPS를 사용하지 않더라도 문제 해결 페이지를 반드시 읽으십시오. 일반적으로 프로그램 구조 및 타이밍과 관련된 많은 일반적인 문제를 설명합니다.

P. F 매크로는 "큰 따옴표"문자열 상수에 사용됩니다.이 옵션을 사용하면 FLASH 메모리에서 강제로 RAM을 절약 할 수 있습니다. 스케치에는 매초/분 메시지를 보내지 않으려면 SENDING_INTERVAL도 있습니다.: P

+0

답장을 보내 주셔서 대단히 감사합니다! 내가 언급 한 모든 것을 시도하고 곧 다시보고 할 것입니다. –