私は GSM モデムを 2 つのうちの 1 つに使用するアプリケーションに取り組んできました。GET 要求をサーバーに送信するか、(UDP を使用して) サーバーにデータを送信することにより、組み込みの HTTP スタックを使用してステータスを確認します。これを可能な限り信頼できるものにするために、いくつかの異なる方法を試しましたが、ついに助けを求める準備が整いました。
私のアプリケーションは、SIMCOM908 モジュールと PIC18 プラットフォーム用に作成されています (開発には PIC18 Explorer を使用しています)。
そのため、問題は、モデムが何かをしているときにビジー状態になり、コマンドを見逃してしまうことがあります。人間として、私はそれを見て、コマンドを再送信します. MCU がタイムアウトして再送信するための機能を追加することは問題ではありません。
問題は、モデムがさまざまなイベントの後に未承諾の応答を送信することです。+CGREG: 1, ...
モデムが (セル タワーで) 登録ステータスを変更すると、または GPS の準備ができたときに応答しGPS Ready
ます。これらの応答は、コマンドの途中 (IP 接続の作成など) を含め、いつでも発生する可能性があります。
これに対処する方法を考えていなかったので、これは問題です。私のアプリケーションはコマンドを送信する必要があります (たとえば、サーバーに接続するためAT+CIPSTART="UDP","example.com",5000
)。このコマンドは「OK」で応答し、コマンドが完了すると「CONNECT OK」と応答します。ただし、他の多くの可能な応答に対応できるようにする必要があり、これを行う方法がわかりません。コードで何をする必要がありますか。モデムからの応答を待ち、応答を確認し、その応答に基づいてアクションを実行しますか?
私はコードに制限があり (8 ビットのマイクロコントローラーです!)、keep の繰り返しを最小限に抑えたいと考えています。GSM モジュールからの応答 (要求されたものまたは現在のもの) を取得し、プログラムの残りの部分に何が起こっているかを知らせる応答関数を作成するにはどうすればよいですか?
理想的には、それらの応答で何かをしたいと思います。内部状態を維持するのと同じように ( を聞くGPS Ready
と、GPS などに電力を供給できることがわかります。
考えなければならないことがいくつかあるのでしょうか、それともこの問題をすでに解決しているオープンソース プロジェクトがあるのでしょうか?
これが私がこれまでに持っているものです:
/* Command responses */
enum {
// Common
OK = 0,
ERROR,
TIMEOUT,
OTHER,
// CGREG
NOT_REGISTERED,
// CGATT
NOT_ATTACHED,
// Network Status
NO_NETWORK,
// GPRS status
NO_ADDRESS,
// HTTP ACTION
NETWORK_ERROR,
// IP Stack State
IP_INITIAL,
IP_STATUS,
IP_CONFIG,
UDP_CLOSING,
UDP_CLOSED,
UDP_CONNECTING
} gsmResponse;
int gsm_sendCommand(const char * cmd) {
unsigned long timeout = timer_getCurrentTime() + 5000;
uart_clearb(GSM_UART); // Clear the input buffer
uart_puts(GSM_UART, cmd); // Send the command to the module
while (strstr(bf2, "\r") == NULL) { // Keep waiting for a response from the module
if (timeout < timer_getCurrentTime()) { // Check we haven't timed out yet
printf("Command timed out: %s\r\n", cmd);
return TIMEOUT;
}
}
timer_delay(100); // Let the rest of the response be received.
return OK;
}
int gsm_simpleCommand(const char * cmd) {
if (gsm_sendCommand(cmd) == TIMEOUT)
return TIMEOUT;
// Getting an ERROR response is quick, so if there is a response, this will be there
if (strstr(bf2, "ERROR") != NULL)
return ERROR;
// Sometimes the OK (meaning the command ran) can take a while
// As long as there wasn't an error, we can wait for the OK
while (strstr(bf2, "OK") == NULL);
return OK;
}
単純なコマンドは、具体的に探している、OK
またはERROR
応答している任意の AT コマンドです。のようなものAT
。ただし、より高度なコマンドにも使用します。AT+CPIN?
これは、応答全体をキャプチャし、+CPIN: READY
. ただし、これらのいずれも、未承諾の応答に対する実際の応答ではありません。実際、gsm_sendCommand()
未承諾の応答が受信されると、関数は早期に戻ります。
このような複雑で、場合によっては未承諾のステータス メッセージを管理するには、どのような良い方法があるでしょうか? このアプリケーションは C で書かれており、8 ビットのマイクロコントローラーで動作することに注意してください。