SPRESENSE Wi-Fi Add-onボード iS110BでUDP通信

Qiita Advent calendar2021の記事です。

:::note
Spresenseの関係会社に勤務していますが、業務外の個人活動の紹介です。
当記事は会社と関係ありません。
:::

:::note alert
誤った基板上のピン接続により故障する可能性があります。
自己責任でお願いします。
:::

githubにWi-Fi Add-onボード iS110Bのサンプルプログラムが提供されています。
https://github.com/jittermaster/GS2200-WiFi

UDP通信するサンプルがなかったので、TCPClientを元に作ってみました。

####spresense側

<details><summary> AppFunc.cppの変更箇所だけ抜粋 </summary><div>

``` 
...

/*-------------------------------------------------------------------------*
   Globals:
  -------------------------------------------------------------------------*/
// この2行を追加
// udpパケットバッファサイズ
char UDP_Data[]="GS2200 UDP Client Data Transfer Test.";
const uint16_t UDP_PACKET_SIZE = 37; 
...
// このvoid App_UDPClient_Test(void)を追加
void App_UDPClient_Test(void)
{
  ATCMD_RESP_E resp;
  uint8_t server_cid = 0;
  bool served = false;
  uint32_t timer = 0;

  AtCmd_Init();
    
  App_InitModule();
  App_ConnectAP();

  while (1) 
  {
    if (!served) 
    {
      ATCMD_NetworkStatus networkStatus;
      resp = ATCMD_RESP_UNMATCH;

      ConsoleLog( "Start UDP Client");
      resp = AtCmd_NCUDP( (char *)UDPSRVR_IP, (char *)UDPSRVR_PORT, (char *)LocalPort, &server_cid);   // Create UDP Client; AT+NCUDP=<Dest-Address>,<Port>[<,Src-Port>]
      ConsolePrintf( "server_cid: %d \r\n", server_cid);
      
      AtCmd_CID();
      
      if (resp != ATCMD_RESP_OK) 
      {
        ConsoleLog( "No Connect!" );
        delay(2000);
        continue;
      }
      if (server_cid == ATCMD_INVALID_CID) 
      {
        ConsoleLog( "No CID!" );
        delay(2000);
        continue;
      }

      do 
      {
        resp = AtCmd_NSTAT(&networkStatus);         // AT+NSTAT=?
      } while (ATCMD_RESP_OK != resp);

      ConsoleLog( "Connected" );
      ConsolePrintf("IP: %d.%d.%d.%d\r\n\r\n",
                    networkStatus.addr.ipv4[0], networkStatus.addr.ipv4[1], networkStatus.addr.ipv4[2], networkStatus.addr.ipv4[3]);

      AtCmd_Time();

      served = true;
    }
    else 
    {
      ConsoleLog( "Start to send UDP Data");

      // Prepare for the next chunck of incoming data
      WiFi_InitESCBuffer();

      ConsolePrintf("\r\n");
              
      while ( 1 ) 
      {
        AtCmd_SendBulkData(server_cid, UDP_Data, UDP_PACKET_SIZE);

        resp = AtCmd_RecvResponse();  // Description: Wait for a response after sending a command. Keep parsing the data until a response is found.

        if ( ATCMD_RESP_BULK_DATA_RX == resp ) 
        {          
          if ( Check_CID( server_cid ) ) 
          {
              ConsolePrintf( "%d byte Recieved successfully. \r\n", ESCBuffer[0]);

              for(int i = 1; i < ESCBuffer[0] + 1; i++)
              {
                ConsolePrintf( "%c", ESCBuffer[i]);
              }
              ConsolePrintf( "\r\n");
          }
          WiFi_InitESCBuffer();
          
          delay(100);
        }

        if ( msDelta( timer ) > 100 ) 
        {
          timer = millis();
          led_effect();
        }
      }

    }
  }
}

``` 

</div></details>

<details><summary> config.hの変更箇所だけ抜粋 </summary><div>

``` 
/*-------------------------------------------------------------------------*
 * Configration
 *-------------------------------------------------------------------------*/
// 変更する
#define  AP_SSID        "{WiFiテザリングするスマホの名前}"
#define  PASSPHRASE     "{WiFiテザリングするスマホのパスワード}"

#define  UDPSRVR_IP     "{接続するPCのIPアドレス}"
#define  UDPSRVR_PORT   "{接続するPCのポート番号}" // 例えば8888

#define  LocalPort      "10001"

``` 
</div></details>

<details><summary> GS2200AtCmd.cppの変更箇所だけ抜粋 </summary><div>

ATCMD_RESP_E AtCmd_NCUDP(char *destAddress, char *port, char *srcPort, uint8_t *cid )
{
...
			// *cid = result[8];   // これだと動かない？
			*cid = (uint8_t)atoi(result[8]);   // こっちに変更
...

ATCMD_RESP_E AtCmd_SendBulkData(uint8_t cid, const void *txBuf, uint16_t dataLen)
{
...
	/*<Esc><'Z'><Cid><Data Length (4 byte ASCII)> <Data> */
	// sprintf( cmd, "%cZ%c%s", ATCMD_ESC, cid, digits );   // これだと動かない？ 
	sprintf( cmd, "%cZ%d%s", ATCMD_ESC, cid, digits );    // こっちに変更

</div></details>

そしてメインのスケッチのloopの中とAppFunc.hにあるApp_TCPClient_TestをApp_UDPClient_Testに変更します。

####接続するPC側
こちらのソースコードのserver.pyを拝借しました。

https://qiita.com/note-tech/items/c3e1e497d231ea1e7ca7

<details><summary> server.pyの変更箇所だけ抜粋 </summary><div>

```
# locaddr = (host, port)の前に、PCのIPアドレスとポート番号を入れる
host = '{PCのIPアドレス}' # '127.0.0.1' 
port = {PCのポート} # 8890 
```
</div></details>



####実行中の様子
エコーバックします。

https://youtu.be/Dg8FnpVUAAs