• 締切済み

ESP-WROOM-02で応答文字を受信したい

現在ESP-WROOM-02というwifiモジュールをH8S2368マイコンに接続してでAPに接続して、サーバにクライアントで接続してデータを送信するというプログラムを作成しています。 サーバと接続してデータ送信できるプログラムを作り、実際にサーバに送信できるようになりました。 ただ、 ESP8266 ATコマンド 一覧 jumpwire.io http://ja.docs.jumpwire.io/ESP8266Reference/ATCommands/ こちらの ”使用例 シングルコネクション (TCPクライアント)” この項目のTCPクライアント接続方法を使用しているのですが、各ATコマンド送信後にESP-WROOT-02から返される応答キャラクタは正確に取れず、現在は無視している状態です。 これを正確に取得してフラグとして使用したいと考えています。 例えば、サーバに接続する際のATコマンドコード sprintf(cmd,"AT+CIPSTART=\"TCP\",\"192.168.1.158\",8000\r\n"); wifiModuleSendAT(cmd,0,1000); memset(cmd,0,50); このコードを使用して、サーバに正常に接続できているのですが、このコードを利用して、コネクションが成功しているのかどうかを判定するため返答の”OK”を受信して使用したいと考えています。 そのため関数の返り値を追加して”OK”を受信したらTRUEを返し、受信できなかったら”FALSE”を返すようにしたのですが、これができない状態です。 u8 wifiModuleSendAT( const u8 * cmd,u16 len,int timeOutTime) { int i; u8 err; u8 * pC; int checkLen; memset(g_wire_rx_buf,0,MAX_WIRELESS_BUF); if(len==0) { for(i = 0 ; i < strlen(cmd) ; i++) wireless_put_for_Wifi_data(cmd[i]); } else { for(i = 0 ; i < len ; i++) wireless_put_for_Wifi_data(cmd[i]);    } OSSemPend(WifiRxData, timeOutTime, &err); memset(g_wire_cmd,0,sizeof(g_wire_cmd)); if(err != 0) { memset(g_wire_rx_buf,0,MAX_WIRELESS_BUF); return false; //continue; } { pC = strtok(g_wire_rx_buf," "); i=0; while(pC != NULL) { strcpy(&g_wire_cmd[i][0],pC); pC = strtok(NULL," "); i++; } //memset(g_wire_rx_buf,0,MAX_WIRELESS_BUF); } if(err == 0) { if(strstr(cmd,"AT+CIPSTART") != NULL) { for(i=0;i<5;i++) { if(strstr(g_wire_cmd[i],"OK") != NULL) { return true; } } } return false; } ”if(strstr(cmd,"AT+CIPSTART") != NULL)”こちらのコードの次のコードでブレイクポイントを作っておいて、”AT+CIPSTART”コマンド実行時に”OK”の返答を取得できるようにしているのですが、ブレイク発生時に”g_wire_rx_buf”やg_wire_rx_bufをコマンド毎に分割するように配列したg_wire_cmd[i][0]の中身を確認しても”OK”というアスキーコードが全く入っておらず”true”が返らない状態になってしまっていることを確認しました(※ AT+CIPSTART=\"TCP\",\"192.168.1.158\",8000\” のアスキーコードや”0”しか格納されていない時があります。) 受信割り込み時はg_wire_rx_bufの配列にデータを入れるようにしています。 u8 ddddd; __interrupt(vect=89) void INT_RXI0_SCI0(void) { OSIntEnter(); SCI0.SSR.BIT.RDRF = 0; ddddd = SCI0.RDR; g_wire_rx_buf[g_wire_front++] = ddddd; if(g_wire_front > (MAX_WIRELESS_BUF-1)) g_wire_front =0; if(ddddd==0x0d) { g_wire_length = g_wire_front; g_wire_rx_buf[g_wire_front] = 0; g_wire_front = 0; OSSemPost(WifiRxData); } OSIntExit(); } プログラムでuCOSというOSプログラムを動作させています。”if(ddddd==0x0d) ”でdddddに改行文字があったらその時点で OSSemPost(WifiRxData); でWifiRxDataコードでペンディングしている他のタスクコードをポストしています。 なぜ、サーバへの接続は現在問題ないのですが、”OK”という返答をg_wire_rx_bufの配列に収納できないのかや、もっと効率のよいプログラムのやり方などありましたら、ぜひご教示頂きますよう、よろしくお願い致します。

みんなの回答

  • MSZ006
  • ベストアンサー率38% (390/1011)
回答No.1

回答にはなっていませんが、ヒントになるかもしれないので何となく思った点について書きます。 (1)g_wire_rx_buf に、マイコンからwifiモジュールに送信したコマンド(AT+CIPSTART= ・・・)入っている場合があるというのが謎。送信コマンドは変数cmdに格納しているので、cmdをg_wire_rx_bufに入れるような操作がどこかにないか、確認してみる。 (2)wifiモジュールにATコマンドを送信してから応答が返ってくるまでに、いくらかのタイムラグがあると思われるが、その点については考慮されているのか? 応答がある前に(g_wire_rx_bufに文字列が全部セットされる前に)、g_wire_rx_bufの内容の吟味をしていないか。 (3)wifiモジュールからの応答文字列の最後は0x0Dとなっているのは確かか?0x00ではないのか?(応答文字列のフォーマットの確認)

関連するQ&A

  • ESP-WROOM-02の透過モード時のデータ長

    現在wifiモジュール基板のESP-WROOM-02で、今までイーサネットポートしかもっていなかった端末機の残っていたUARTポートを利用してwifi通信を行えるようにしたいと考えています。 現在、端末側からESP-WROOM-02に対してwifi APの設定と接続先サーバの設定を完了して、30秒に1回程度送信するための1.2kByte程度のパケットデータをESP-WROOM-02の透過送信モードを使用して送信しようとしています。 受信側のサーバPCでWiresharkを起動して、データの受信状況を確認したのですが、 イーサーネット側で送信していた場合は1.2Kbyte程度のパケットデータ長だったのですが、ESP-WROOM-02で送信してみるとなぜか48Byteのパケットデータ長になってしまい、1.2Kbyteで構成されているデータの頭の4バイトのみしか送信できていないことが分かりました。 1.2KByteの”Packet”というデータパケットは、イーサネットポートからパケットを出力している際には send(s+1,(BYTE *)Packet,sizeof(TEST_PACKET)); このように送信していたところを wifiModuleSendAT((BYTE *)Packet,200); 今回wifi送信のための関数として作成した”wifiModuleSendAT”に入れて送信しました。200という引数は、この端末で使用しているucosのペンディング時のエラーとしてのポストのタイムアウト時間です。 send関数の場合、引数としてパケットサイズを見るsizeof(TEST_PACKET)を渡している部分がありますが、wifiModuleSendAT関数ではこの部分がないのですが、パケットサイズを引数として渡さなくてはいけませんでしょうか? どうぞ、ご教示頂きますようよろしくお願い致します。 wifiModuleSendAT関数のコード u8 wifiModuleSendAT(u8 * cmd,int timeOutTime) { int i; u8 err; u8 * pC; int checkLen; checkLen = strlen(cmd); for(i = 0 ; i < strlen(cmd) ; i++) wireless_put_for_Wifi_data(cmd[i]); OSSemPend(WifiRxData, timeOutTime, &err); memset(g_wire_cmd,0,sizeof(g_wire_cmd)); if(err != 0) { memset(g_wire_rx_buf,0,MAX_WIRELESS_BUF); return false; //continue; } pC = strtok(g_wire_rx_buf," "); i=0; while(pC != NULL) { strcpy(&g_wire_cmd[i][0],pC); pC = strtok(NULL," "); i++; } memset(g_wire_rx_buf,0,MAX_WIRELESS_BUF); if(err == 0) { if(strstr(cmd,"AT+CIPSEND") != NULL) { return TRUE; } if(strstr(cmd,"AT+CWJAP") != NULL) { return TRUE; } if(strstr(cmd,"AT+CIPSTART") != NULL) { return TRUE; } if(strstr(cmd,"AT+CIFSR") != NULL) { return TRUE; } if(strstr(g_wire_cmd[0],"OK") != NULL) { return TRUE; } } return FALSE; }

  • 一番大きい奇数を表示する

    scanf関数を使って数字を10回入力して一番大きなものを表示させるプログラムをつくったのですが、 さらに一番大きな奇数を表示するにはどうすればいいのでしょうか? 偶数=割り切れる 奇数=割り切れない というところまでは分かるのですが、以下のプログラムに奇数を判別するソースを追加するのにはどうすればいいのでしょうか。 #include <stdio.h> int main(void) { char str[1024]; char buf[10]; int i; int w; printf("文字列を10回入力して下さい:\n"); memset(str, 0, sizeof(str)); for (i = 0; i < 10; i++) { memset(buf, 0, sizeof(buf)); printf("input>\n"); scanf("%s", buf); } for (i = 0; i < 10; i++) { if ((buf[i] & 1) == 1) /* 奇数であるか */ { if (strcmp(buf, str) > 0) { strcpy(str, buf); } } } printf("output>\n%s\n" , str); getchar(); }

  • TCP/IP通信型大文字・小文字変換プログラム

    TCP/IP通信型大文字・小文字変換プログラムを作りたいです。 しかし、うまく2つのプログラムが接続されません。 恐らく、IPアドレスやホスト名の問題だと思います。 超初心者でそこのところをあまり理解していません。 どなたかプログラムの補足をお願いします。 概要は ・クライアント キーボードから文字列を入力し、サーバーに送信。 サーバーから送信された文字列を画面に出力。 ・サーバー クライアントから送信された文字列に対し、 大文字は小文字に、小文字は大文字に変換して返す。 クライアント側プログラム #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #define SOCK_NAME "./socket" int main() { struct sockaddr_in saddr; int soc; char buf[1024]; if ( (soc =socket(AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { perror("socket"); exit(1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr=inet_addr("192.168.1.1"); saddr.sin_port=htons(1357); if(connect(soc, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("connect"); exit(1); } fprintf(stderr, "Connection established: socket %d used.\n", soc); while(fgets(buf, 1024, stdin)){ if(buf[strlen(buf) -1] == "\n") buf[strlen(buf) -1] = "\0"; write(soc, buf, 1024); read(soc, buf, 1024); fprintf(stdout, "%s\n", buf); } close(soc); return 0; } サーバー側プログラム #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #define SOCK_NAME "./socket" int main() { int i; int fd1, fd2; struct sockaddr_in saddr; struct sockaddr_in caddr; int len; int ret; char buf[1024]; if((fd1 =socket(AF_INET, SOCK_STREAM, 0)) < 0 ){ perror("socket"); exit(1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr=INADDR_ANY; saddr.sin_port=htons(1357); unlink(SOCK_NAME); if(bind(fd1, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind"); exit(1); } if(listen(fd1,5) < 0 ) { perror("listen"); exit(1); } while(1){ len = sizeof(caddr); if((fd2 = accept(fd1, (struct sockaddr *)&caddr, &len)) < 0){ perror("accept"); exit(1); } fprintf(stderr, "Connection established: socket %d used.\n", fd2); while((ret = read(fd2, buf, 1024)) > 0 ){ fprintf(stderr, "read: &s\n", buf); for(i=0; i<ret; i++) if(islower(buf[i])) buf[i] = toupper(buf[i]); if(isupper(buf[i])) buf[i] = tolower(buf[i]); fprintf(stderr, "write: %s\n", buf); write(fd2, buf, 1024); } close(fd2); } close(fd1); return 0; }

  • 同じコードがある初期化について教えてください。

    シューティングゲームのサンプルを勉強しています。 下記のこの部分のコードが二つあります。 memset(buf,0,sizeof(buf)); 気になっています。 なぜ二つあるのかを意味を知りたいです。 よろしくお願いします。 コードは以下に記述します。 CONTROL::CONTROL() { player = new PLAYER; back = new BACK; FILE *fp; ENEMYDATA data[ENEMY_NUM]; char buf[100]; int c; int col=1; int row=0; memset(buf,0,sizeof(buf)); fp = fopen("enemydata1.csv","r"); while(fgetc(fp)!='\n'); while(1){ while(1){ c=fgetc(fp); if(c==EOF) goto out; if(c!=','&& c!='\n') strcat(buf,(const char*)&c); else break; } switch(col){ case 1: data[row].type=atoi(buf); break; case 2: data[row].stype=atoi(buf); break; case 3: data[row].m_pattern=atoi(buf); break; case 4: data[row].s_pattern=atoi(buf); break; case 5: data[row].in_time=atoi(buf); break; case 6: data[row].stop_time=atoi(buf); break; case 7: data[row].shot_time=atoi(buf); break; case 8: data[row].out_time=atoi(buf); break; case 9: data[row].x=atoi(buf); break; case 10: data[row].y=atoi(buf); break; case 11: data[row].speed=atoi(buf); break; case 12: data[row].hp=atoi(buf); break; } memset(buf,0,sizeof(buf)); ++col; if(c=='\n'){ col=1; ++row; } } out: for(int i=0;i<ENEMY_NUM;++i){ enemy[i]=new ENEMY( data[i].type, data[i].stype, data[i].m_pattern, data[i].s_pattern, data[i].in_time, data[i].stop_time, data[i].shot_time, data[i].out_time, data[i].x, data[i].y, data[i].speed, data[i].hp, data[i].item); } }

  • 一番大きい奇数を表示する

    scanf関数を使用して、文字列を10回入力し一番大きい文字列を表示するプログラムを作ったのですが、 一番大きい「奇数」を表示するように条件を加えた場合どうすればよいのでしょうか? 偶数=割り切れる 奇数=割り切れない ということまでは分かるのですがその先が分かりません。 一応一番大きい文字列を表示するプログラムを貼っておきます。 #include <stdio.h> int main(void) { char str[1024]; char buf[10]; int i; printf("文字列を10回入力して下さい:\n"); memset(str, 0, sizeof(str)); for (i = 0; i < 10; i++) { memset(buf, 0, sizeof(buf)); printf("input>\n"); scanf("%s", buf); } if (strcmp(buf, str) > 0) { strcpy(str, buf); } printf("output>\n%s\n" , str); getchar(); }

  • xmegaのstrstr関数で文字検索

    現在ATMEL社のATxmega128A1というCPUでプログラミングを行っております。 テンキーパネルでのコマンド操作機能というのを設置しているのですが、テンキー操作で、”#”ボタンが押されると u8 key_proc(u8 * buf,int length) この関数が必ず呼ばれます。 bufという引数に”#”ボタンが押されるまでに押されたボタンのキャラクタデータが収納されたSRAMの番地が格納されています。 例えば、端末の設定などを変更したい場合に使用する4文字のキーがEEPROMに格納されていて、それを変更したい場合のコマンドを追加したいと思っています。 そのEEPROMに格納されている4文字キーというのは (u16)gEnv.main_set.key; というEEPROMに”1234”というデータが入っているのですが、 bufというSRAMのメモリに例えば”1234Z4321#” このようなコマンドが来たらもともと”1234”という現在のkeyと合致して、なおかつ次の文字が”Z”という文字が来たら、次の”4321”というデータに(u16)gEnv.main_set.key;のEEPROMの内容を変更するというプログラムが作りたいと思っています。 現在このようなプログラムでこの機能を実現しています。 #if 1 pass16 = (u16)gEnv.main_set.key; sprintf((char *)str,"%04d",pass16); str[4] = 0; memcpy(value,buf,4); if(strstr((char *)value,(char *)str) != 0) { if(buf[4] == 'Z' && buf[9] == '#') { value[0] = buf[5]; value[1] = buf[6]; value[2] = buf[7]; value[3] = buf[8]; gEnv.main_set.key = strtoul(value,NULL,10); env_save(&gEnv); return true; } } #endif このプログラムを作ったことで疑問に思っていることなのですが、 buf[4] == 'Z' であるかどうかをstrstrとは別のコードで判定しているのですが、 sprintf((char *)str,"%04dZ",pass16); このようなコードで"1234Z"という文字列をstrstr検索して判定することはできないのでしょうか? 現在”sprintf((char *)str,"%04dZ",pass16);”としてしまうと、プログラムが暴走したような状態になり、正常な動作ができなくなってしまう現象が出てしまいます。 どうぞ、ご教示よろしくお願い致します。

  • Excel VBA セル選択

    Sub 全角() Dim i As Long, buf As String For i = 1 To Len(ActiveCell.Value) If Mid(ActiveCell.Value, i, 1) Like "[ア-ン]" Then buf = buf & StrConv(Mid(ActiveCell.Value, i, 1), vbWide) Else buf = buf & Mid(ActiveCell.Value, i, 1) End If Next i ActiveCell.Value = buf End Sub このコードだと一つのセルしか変換できません。 選択した範囲全部を変換できるようにしたいです。

  • C++のファイルの読み込みの部分で質問があります。

    fp = fopen("enemydata.csv","r");の部分のコードで "enemydata.csv"のファイルを読み込むのですが "r"の部分が何を意味しているのがわかりません。 以下のコードの他にも enemy.cpp enemy.h がありますが関連するものが見あたりません。 "r"の部分のコードは以下に表示します。 よろしくお願いします。 control.cpp #include "pch.h" #include "control.h" CONTROL::CONTROL() { player = new PLAYER; back = new BACK; FILE *fp; ENEMYDATA data[ENEMY_NUM]; char buf[100]; int c; int col=1; int row=0; memset(buf,0,sizeof(buf)); ここの部分→fp = fopen("enemydata.csv","r"); //ヘッダ読み飛ばし while(fgetc(fp)!='\n'); while(1){ while(1){ c=fgetc(fp); //末尾ならループを抜ける。 if(c==EOF) goto out; //カンマか改行でなければ、文字としてつなげる if(c!=','&& c!='\n') strcat(buf,(const char*)&c); //カンマか改行ならループ抜ける。 else break; } //ここにきたということは、1セル分の文字列が出来上がったということ switch(col){ //1列目は敵種類を表す。atoi関数で数値として代入。 case 1: data[row].type=atoi(buf); break; //2列目は弾種類。以降省略。 case 2: data[row].stype=atoi(buf); break; case 3: data[row].m_pattern=atoi(buf); break; case 4: data[row].s_pattern=atoi(buf); break; case 5: data[row].in_time=atoi(buf); break; case 6: data[row].stop_time=atoi(buf); break; case 7: data[row].shot_time=atoi(buf); break; case 8: data[row].out_time=atoi(buf); break; case 9: data[row].x=atoi(buf); break; case 10: data[row].y=atoi(buf); break; case 11: data[row].speed=atoi(buf); break; case 12: data[row].hp=atoi(buf); break; case 13: data[row].item=atoi(buf); break; } //バッファを初期化 memset(buf,0,sizeof(buf)); //列数を足す ++col; //もし読み込んだ文字が改行だったら列数を初期化して行数を増やす if(c=='\n'){ col=1; ++row; } } out: //敵クラス生成 for(int i=0;i<ENEMY_NUM;++i){ enemy[i]=new ENEMY( data[i].type, data[i].stype, data[i].m_pattern, data[i].s_pattern, data[i].in_time, data[i].stop_time, data[i].shot_time, data[i].out_time, data[i].x, data[i].y, data[i].speed, data[i].hp, data[i].item); } } void CONTROL::All() { //int count = 0; //描画領域を指定 SetDrawArea(MARGIN,MARGIN,MARGIN+380,MARGIN+460); back->All(); //プレイヤークラスのAll関数実行 player->All(); for(int i=0;i<ENEMY_NUM;++i){ if(enemy[i]!=NULL){ if(enemy[i]->All()){ delete enemy[i]; enemy[i]=NULL; } } } ++g_count; } CONTROL::~CONTROL() { //プレイヤークラスの解放 delete player; delete back; for(int i=0;i<ENEMY_NUM;++i){ if(enemy[i]!=NULL){ delete enemy[i]; } } }

  • メッセージを受信したら受信終了したい

    TCPでスループットを測定するプログラムを作っています。 データの受信を終了するには、送信側がソケットをクローズして、 受信側のread()メソッドが-1を返すのが主流だと考えていますが、 私のプログラムでは、受信した後に受信側から送信側へデータを返信したいため、 ソケットをクローズすることで受信終了というようにしたくないです。 また、受信したバイト数をread(buf,int,int)の戻り値で取得したいです。 私が考えている方法としては、送信側で「finish」というメッセージを送信したら、 受信側で受信を終了させようと考えました。 read(buf,int,int)はbufに受信したバイトを格納すると思います。格納されたバイトの最後から6個を確認させ、 finishならば受信終了にすればよいと考えました。 送信側のコードは下のようにしました。 String signal = "finish"; byte[] signal_buf = signal.getBytes(); send_start = System.nanoTime(); for (int i = 0; i < Data-6; i++) {   try {     out.write(i);     out.flush();   } catch (IOException e) {     System.err.println(e);   } } out.write(signal_buf); out.flush(); send_stop = System.nanoTime(); System.out.println("送信完了"); 受信側は、finishを読み込んだらループを抜けるようにしたいです。 recv_start = System.nanoTime(); for(;;){   part = in.read(buf);   if(part > 0)     total += part;   if(finishを読み込んだら){     break;   } } recv_stop = System.nanoTime(); どのようにしてfinishを読み込んだことを認識させれば良いでしょうか? ・合図となるメッセージにより受信を終了すること、 ・read(buf,int,int)の戻り値で読み込んだバイト数を取得すること、 この2点を絶対に削りたくないのです。 どうすればよいか、アドバイスをいただけないでしょうか?

    • ベストアンサー
    • Java
  • 【MATLAB】任意の多次元配列からの配列の抽出

    ベクトルvから複数の要素を抽出し,新しいベクトルuを生成する方法には,以下のようにインデックスを指定する方法があります. idx = [3 10 15 28]; u = v(idx); この方法を拡張し,以下のようにN次元配列Aのi次元目のインデックスを指定することで複数の配列を抽出し,新しい配列Bを得ようと考えています. idx = [3 10 15 28]; B = A(:,:, ・・・ ,:,idx,:, ・・・ ,:,:); Aの次元Nはi以上の任意の値で,iは予め指定された値である場合, 配列Bを得る方法はございますでしょうか. 現在,私は以下のような方法で計算しておりますが,コマンド「eval」を用いて力技でしのいでいる感じで,最適な方法が他にあるのでは,と考えております. N = length(size(A)); idx = [3 10 15 28]; i = 3; buf = 'A('; for s = 1:N if s == i buf = [buf 'idx']; else buf = [buf ':']; end if s < N buf = [buf ',']; end end buf = [buf ')']; B = eval(buf);