airpocket が 2022年08月23日21時59分51秒 に編集
初版
タイトルの変更
Wi-SUN Add-onボード SPRESENSE-WiSUN-EVK-701 を使ってみる
タグの変更
spresense
Wi-SUN
メイン画像の変更
記事種類の変更
セットアップや使用方法
ライセンスの変更
(MIT) The MIT License
本文の変更
# はじめに ただいま、2022年 SPRESENSE™ 活用コンテストに向けて絶賛開発中なのですが、RohmさんのWi-SUN Add-onボード SPRESENSE-WiSUN-EVK-701のモニター品をいただいたので使い方の覚書です。 このボードを選定した理由は、省電力で動きそう(イメージ)、Wi-SUNって聞いたことがあるけど触ったことない、メインボードだけで動かせる、といったあたりです。 ただしちょっと想定外だったこともあり、使用例やドキュメント類が少ない、受信用に使用するUSBドングルが高価と言った点は、個人でやるには少し手を出しにくい部分です。 参考にさせていただいた情報もあり、デバイスプラスさんの[この記事](https://deviceplus.jp/mc-general/weather-station-with-wisun-01/)をベースにセットアップを進めましたがちょっと詰まったところもあったので蛇足かとも思いましたが覚書程度に。 とりあえず動いたよ、程度なので基本は元資料にあたってください。 # 参考 ## デバイスプラスさんの記事 https://deviceplus.jp/mc-general/weather-station-with-wisun-01/ https://deviceplus.jp/mc-general/weather-station-with-wisun-02/ https://deviceplus.jp/mc-general/weather-station-with-wisun-03/ WiSUN-EVK-701の使い方は第3回、第4回に詳しく解説されてる(予定)ですが、第4回はまだ公開されてません。お待ちしてますmm ## GitHub https://github.com/RohmSemiconductor/Arduino/tree/master/SPRESENSE-WISUN-EVK-701 RohmさんのGitHubに、サンプルコードとライブラリとドキュメントがあります。 ## ボードの回路図 https://www.rohm.co.jp/documents/11401/6353165/SPRESENSE-WiSUN-EVK-701-schematic.pdf セットアップには直接関係ありませんが、ボードの回路図が公開されています。 @spresense さん、情報共有ありがとうございます。 @[twitter](https://twitter.com/spresense/status/1560677061945044992) # 使用する部品 ## Spresense メインボード メインボードだけで動かします。 https://www.switch-science.com/catalog/3900/ ## Wi-SUN Add-onボード SPRESENSE-WiSUN-EVK-701 今回はモニター品としていただきました。core staff onlineさん、chip 1 stopさんで在庫確認できました。 https://www.zaikostore.com/zaikostore/stockDetail?productIdOfHitotsukara=pr14922577&productName_forFind=SPRESENSE%2dWISUN%2dEVK%2d701&typeStock_forFind=all ## Wi-SUN USBドングル BP35C2 core staff onlineさんで購入しました。私が調べた限りでは最安値、でも15800円(税抜き)・・・。 https://www.zaikostore.com/zaikostore/stockDetail?productIdOfHitotsukara=pr11257823&productName_forFind=BP35C2&typeStock_forFind=all # USBドングルの設定 USBドングルは、PCに接続して初期設定をすると通信ができる様になります。 この部分はデバイスプラスさんの3回目記事の通りです。 RPiで使用するため、USBドングルの初期設定用pythonスクリプトにちょっと追加して、ボード側の設定に必要な情報も確認しています。 ```python # /usr/bin/env python3 # -*- coding: utf-8 -*- import serial from time import sleep con=serial.Serial('/dev/ttyUSB0',115200) print(con.portstr) def sendcmd(cmd_str): con.write(cmd_str.encode()) while True: str_bf=con.readline() if str_bf !="": print(str_bf) if str_bf == b'OK\r\n': break sleep(0.5) sendcmd('SKSREG SF0 1\r\n') sendcmd('SKSREG S2 23\r\n') sendcmd('SKSREG S3 5678\r\n') sendcmd('SKSREG SA9 1\r\n') sendcmd('SKSREG SA2 1\r\n') sendcmd('SKSTART\r\n') sendcmd('SKSETHPWD 001D12910003584C 1111222233334444\r\n') #通信先のadd-on ボードのmacアドレスとパスワード設定 sendcmd('SKINFO\r\n') #add-on ボードの設定に必要なUSBドングルの情報を確認 con.close() ``` sendcmd()で、USBドングルにコマンドを送っています。送信したコマンドの詳細は[公式ドキュメント](https://github.com/RohmSemiconductor/Arduino/blob/master/SPRESENSE-WISUN-EVK-701/documents/SPRESENSE-WiSUN-EVK-701_%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E8%AA%AC%E6%98%8E%E6%9B%B8_ROHC.pdf)をご確認ください。下2行がポイントで、SKSETHPWD以降に通信先のadd-onボードのmacアドレスと新たに設定したパスワードを指定しています。add-onボードのマックアドレスは、ボードのシールに記載されています。パスワードは任意の文字列でOKですが、add-onボードの設定時に使用します。 私の場合は「001D12910003584C」がmacアドレスで、「1111222233334444」がパスワードです。 SKINFOは、USBドングルの情報を出力させるコマンドです。このスクリプトを実行すると次のような出力が出るはずです。最後から2行目の「b'EINFO FE80:0000:0000:0000:021D:1291:0002:2E8B 001D129100022E8B 23 5678 1 \r\n'」の部分はadd-onボードの設定時に通信先の情報として使用します。 ```sh >>> %Run wisun_init.py /dev/ttyUSB0 b'SKSREG SF0 1\r\n' b'OK\r\n' b'SKSREG S2 23\r\n' b'OK\r\n' b'SKSREG S3 5678\r\n' b'OK\r\n' b'SKSREG SA9 1\r\n' b'OK\r\n' b'SKSREG SA2 1\r\n' b'OK\r\n' b'SKSTART\r\n' b'OK\r\n' b'SKSETHPWD 001D12910003584C 1111222233334444\r\n' b'OK\r\n' b'SKINFO\r\n' b'EINFO FE80:0000:0000:0000:021D:1291:0002:2E8B 001D129100022E8B 23 5678 1 \r\n' b'OK\r\n' ``` # Spresenseのプログラム Spresense側にはadd-onボードを使用するためのプログラムを書き込みます。 動作テストには、[Rohmさんのサンプルプログラム](https://github.com/RohmSemiconductor/Arduino/tree/master/SPRESENSE-WISUN-EVK-701/examples/SPRESENSE-WISUN-EVK-701)を一部変更して使用します。 合せて、[RohmさんのGitHub](https://github.com/RohmSemiconductor/Arduino/tree/master/SPRESENSE-WISUN-EVK-701)からbp35c0-j11.hとbp35c-j.cppをダウンロードし、メインプログラムと同じフォルダに保存してください。 ## メインプログラム まずはメインプログラムからですが、任意の文字列を送信できる様に一部修正しています。 ```arduino /* SPRESENSE-WISUN-EVK-701 Copyright (c) 2019 ROHM Co.,Ltd. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "bp35c0-j11.h" unsigned char state = 0 ; BP35C0J11 bp35c0j11; void setup() { boolean rc = FALSE ; bp35c0j11.j11_init(); rc = bp35c0j11.wait_msg(); if(rc == TRUE){ state = 1 ; // hardware reset end }else{ state = 0 ; } } void loop() { unsigned char msg_length = 0 ; boolean rc = 0 ; #ifdef DEBUG Serial.print("State = "); Serial.println(state, DEC); #endif delay(500); switch (state) { case(0): // need hardware reset rc = bp35c0j11.cmd_send(CMD_RESET); rc = bp35c0j11.wait_msg(); if(rc == TRUE){ state = 1 ; } break; case(1): // init state rc = bp35c0j11.cmd_send(CMD_INI); rc = bp35c0j11.wait_msg(); if(rc == TRUE){ state = 2; } break; case(2): // HAN PANA setting rc = bp35c0j11.cmd_send(CMD_PANA_SET); rc = bp35c0j11.wait_msg(); if(rc == TRUE){ state = 4; } break; case(3): // active scan rc = bp35c0j11.cmd_send(CMD_SCAN); rc = bp35c0j11.wait_msg(); if(rc == TRUE){ rc = bp35c0j11.wait_msg(); if(rc == TRUE){ state = 4; } } break; case(4): // HAN act rc = bp35c0j11.cmd_send(CMD_HAN); rc = bp35c0j11.wait_msg(); if(rc == TRUE){ state = 5; } break; case(5): // HAN PANA act rc = bp35c0j11.cmd_send(CMD_PANA); rc = bp35c0j11.wait_msg(); if(rc == TRUE){ rc = bp35c0j11.wait_msg(); if(rc == TRUE){ state = 7; } } break; case(6): // rcv mode change rc = bp35c0j11.cmd_send(CMD_CON_SET); rc = bp35c0j11.wait_msg(); if(rc == TRUE){ state = 7; } break; case(7): // my_port open rc = bp35c0j11.cmd_send(CMD_PORTOPEN); rc = bp35c0j11.wait_msg(); if(rc == TRUE){ state = 8; } break; case(8): // UDP send bp35c0j11.radiodata = "send data"; //<====この一行を追加するだけ。""内に送信する文字列を記入 rc = bp35c0j11.cmd_send(CMD_UDPSEND); rc = bp35c0j11.wait_msg(); if(rc == TRUE){ delay(5000); } break; default: // error state = 0 ; break; } } ``` 変更点は、case(8)内に、 bp35c0j11.radiodata = "send data"; の一行を追加しているのみです。'' ''内に、送信する文字列を入力します。 ## bp35c0-j11.h 合せて、bp35c0-j11.hを変更します。 ```arduino /* bp35c0-j11.h Copyright (c) 2019 ROHM Co.,Ltd. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _BP35C0J11_H_ #define _BP35C0J11_H_ #define DEBUG #define CMD_HDR_LEN ((unsigned char)8) #define UNI_CODE_LEN ((unsigned char)4) #define CMD_RESET (0x00D9) #define CMD_INI (0x005F) #define CMD_HAN (0x000A) #define CMD_PANA (0x003A) #define CMD_PANA_SET (0x002C) #define CMD_CON_SET (0x0025) #define CMD_UDPSEND (0x0008) #define CMD_SCAN (0x0051) #define CMD_PORTOPEN (0x0005) #define NORT_WAKE (0x6019) #define RES_INI (0x205F) #define RES_HAN (0x200A) #define RES_PANA (0x203A) #define RES_PANA_SET (0x202C) #define RES_CON_SET (0x2025) #define RES_UDPSEND (0x2008) #define RES_SCAN (0x2051) #define NORT_SCAN (0x4051) #define RES_PORTOPEN (0x2005) #define NORT_PANA (0x6028) #define TIMEOUT ((unsigned short)10000) #define PIN_ENABLE (PIN_D20) // level shifter enable pin #define PIN_RESET (PIN_D21) // wisun module reset pin #define TRUE 1 #define FALSE 0 typedef struct { unsigned char uni_code[4]; unsigned char cmd_code[2]; unsigned char msg_len[2]; unsigned char hdr_chksum[2]; unsigned char dat_chksum[2]; unsigned char data[128]; }CMD_FORMAT; class BP35C0J11 { public: char* radiodata = "test"; <===この行を追加する。 BP35C0J11(void); void j11_init(void); boolean wait_msg(void); boolean cmd_send(unsigned short cmd); void static msg_create(unsigned short cmd , unsigned short msg_length ,unsigned short hdr_chksum , unsigned short dat_chksum, unsigned char *pdata , unsigned char *psend_data ); private: void static debugmsg(unsigned short datalength , unsigned char *psend_data); }; #endif //_BP35C0J11_H_ ``` class BP35C0J11のpublic直下に char* radiodata = "test"; の一行を追加しています。メンバ変数をpublicにするのはお行儀が悪いことのようですが許してつかーさい。 ## bp35c0-j11.cpp bp35c0-j11.cpp には、通信先となるUSBドングルの情報を記入し、任意のデータを送信するためのコード変更を行います。 変更する部分は、30,31,35,325行目の合計4行です。長いプログラムですので、arduinoIDEなどに貼りつけて行数を表示させて確認してください。 ```arduino /******************************************************************************** bp35c0-j11.cpp Copyright (c) 2019 ROHM Co.,Ltd. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *********************************************************************************/ #include <Arduino.h> #include "bp35c0-j11.h" unsigned const char uni_req[4] = {0xD0 , 0xEA , 0x83 , 0xFC}; unsigned const char uni_res[4] = {0xD0 , 0xF9 , 0xEE , 0x5D}; unsigned const char ini_data[4] = {0x03 , 0x00 , 0x05 , 0x00}; // エンドデバイス/Sleep 非対応/922.9MHz/20mW出力 unsigned const char pair_id[8] = {0x00 , 0x1D , 0x12 , 0x91 , 0x00 , 0x02 , 0x2E , 0x8B}; // 接続先MACアドレス<==USBドングルから読み取ったパラメータ unsigned const char mac_adr[16] = {0xFE , 0x80 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x02 , 0x1D , 0x12 , 0x91 , 0x00 , 0x02 , 0x2E , 0x8B}; // 接続先IPv6アドレス<USBドングルから読み取ったパラメータ unsigned const char my_port[2] = { 0x01 , 0x23 }; // オープンするUDPポート unsigned const char dist_port[2] = { 0x0E , 0x1A }; // 送信先UDPポート unsigned const char password[16] = { '1' , '1' , '1' , '1' , '2', '2' , '2' , '2' , '3' , '3' , '3' , '3' , '4' , '4' , '4' , '4' }; // PANA認証時のパスワード //unsigned const char radiodata[4] = { 'T' , 'E' , 'S' , 'T'}; // <=== bp35c0-j11.hでpublic変数として宣言したためコメントアウト CMD_FORMAT cmd_format; BP35C0J11::BP35C0J11(void) { } /******************************************************************************** * Name : j11_init * Function : initial setting bp35c0-j11 * input : - * return : - *********************************************************************************/ void BP35C0J11::j11_init(void) { // configure output D20/D21 pinMode(PIN_ENABLE, OUTPUT); pinMode(PIN_RESET, OUTPUT); digitalWrite(PIN_ENABLE, HIGH); delay(1000); // Serial port initial Serial2.begin(115200); Serial.begin(115200); Serial.write("RESET"); Serial.println(""); digitalWrite(PIN_RESET, LOW); // reset delay(500); digitalWrite(PIN_RESET, HIGH); } /******************************************************************************** * Name : wait_msg * Function : wait for response from bp35c0-j11 * input : - * return : TRUE/FALSE *********************************************************************************/ boolean BP35C0J11::wait_msg(void) { unsigned long start_time; unsigned long current_time; unsigned char rcvdata[128] = {0} ; unsigned char cnt = 0 ; start_time = millis(); while (Serial2.available() == 0) { current_time = millis(); if ((current_time - start_time) > TIMEOUT) { Serial.println("receive timeout"); return FALSE; } } while (Serial2.available() > 0 ) { delay(5); rcvdata[cnt] = Serial2.read(); #ifdef DEBUG Serial.print(rcvdata[cnt] , HEX); #endif cnt++; if (cnt >= 128) { Serial.println("receive data over flow"); return FALSE; } } if (rcvdata[0] == uni_res[0] && rcvdata[1] == uni_res[1] && rcvdata[2] == uni_res[2] && rcvdata[3] == uni_res[3]) { // RESPONSE/NORTIFICATION switch (rcvdata[4] << 8 | rcvdata[5]) { case (NORT_WAKE): break; case (RES_INI): if (rcvdata[12] == 0x01) { Serial.println("Init Success"); } else { Serial.println("Init Error"); return FALSE; } break; case (RES_PANA_SET): if (rcvdata[12] == 0x01) { Serial.println("PANA Password set Success"); } else { Serial.println("PANA Password set Error"); return FALSE; } break; case (RES_SCAN): break; case (NORT_SCAN): break; case (RES_HAN): if (rcvdata[12] == 0x01) { Serial.println("HAN Act Success"); } else { Serial.println("HAN Act Error"); return FALSE; } break; case (RES_PANA): if (rcvdata[12] == 0x01) { Serial.println("PANA Act Success"); } else { Serial.println("PANA Act Error"); return FALSE; } break; case (NORT_PANA): if (rcvdata[12] == 0x01) { Serial.println("PANA Connect Success"); } else { Serial.println("PANA Connecgt Error"); return FALSE; } break; case (RES_CON_SET): if (rcvdata[12] == 0x01) { Serial.println("Normal connect mode"); } else { Serial.println("connect mode change error"); return FALSE; } break; case (RES_PORTOPEN): if (rcvdata[12] == 0x01) { Serial.println("UDP port open Success"); } else { Serial.println("UDP port open Error"); return FALSE; } break; case (RES_UDPSEND): if (rcvdata[12] == 0x01) { Serial.println("UDP send Success"); } else { Serial.println("UDP send Error"); return FALSE; } break; case (0x2FFF): Serial.println("checksum error"); return FALSE; break; default: Serial.println("uni code error"); return FALSE; break; } } else { Serial.println("recv data error"); return FALSE; } return TRUE; } /******************************************************************************** * Name : cmd_send * Function : REQUEST command to bp35c0-j11 * input : cmd - REQUEST command * return : TRUE/FALSE *********************************************************************************/ boolean BP35C0J11::cmd_send(unsigned short cmd) { unsigned short hdr_chksum = uni_req[0] + uni_req[1] + uni_req[2] + uni_req[3] ; unsigned short dat_chksum = 0 ; unsigned short msg_length = 0 ; unsigned short dat_length = 0 ; unsigned short send_dat_size = 0 ; unsigned char data[128] = {0}; unsigned char send_data[128] = {0} ; unsigned char cnt = 0 ; switch (cmd) { case (CMD_RESET): dat_length = 0; msg_length = (unsigned short)(4 + dat_length); hdr_chksum += CMD_RESET + msg_length; dat_chksum = 0 ; msg_create(CMD_RESET , msg_length , hdr_chksum , dat_chksum, data , send_data ); Serial2.write(send_data, (msg_length + CMD_HDR_LEN)); #ifdef DEBUG debugmsg( msg_length + CMD_HDR_LEN , send_data); #endif break; case (CMD_INI): dat_length = (unsigned short)4; msg_length = (unsigned short )( 4 + dat_length); hdr_chksum += CMD_INI + msg_length ; for (cnt = 0 ; cnt < dat_length ; cnt++ ) { data[cnt] = ini_data[cnt] ; } for (cnt = 0 ; cnt < dat_length ; cnt++) { dat_chksum += data[cnt]; } msg_create(CMD_INI , msg_length , hdr_chksum , dat_chksum, data , send_data ); Serial2.write(send_data, (msg_length + CMD_HDR_LEN)); #ifdef DEBUG debugmsg( msg_length + CMD_HDR_LEN , send_data); #endif break; case (CMD_PANA_SET): dat_length = (unsigned short)16 ; msg_length = (unsigned short)(4 + dat_length); hdr_chksum += CMD_PANA_SET + msg_length; for (cnt = 0 ; cnt < dat_length ; cnt++ ) { data[cnt] = password[cnt] ; } for (cnt = 0 ; cnt < dat_length ; cnt++) { dat_chksum += data[cnt]; } msg_create(CMD_PANA_SET , msg_length , hdr_chksum , dat_chksum, data , send_data ); Serial2.write(send_data, (msg_length + CMD_HDR_LEN)); #ifdef DEBUG debugmsg( msg_length + CMD_HDR_LEN , send_data); #endif break; case (CMD_SCAN): break; case (CMD_HAN): dat_length = (unsigned short)8 ; msg_length = (unsigned short)(4 + dat_length); hdr_chksum += CMD_HAN + msg_length; for (cnt = 0 ; cnt < dat_length ; cnt++ ) { data[cnt] = pair_id[cnt] ; } for (cnt = 0 ; cnt < dat_length ; cnt++) { dat_chksum += data[cnt]; } msg_create(CMD_HAN , msg_length , hdr_chksum , dat_chksum, data , send_data ); Serial2.write(send_data, (msg_length + CMD_HDR_LEN)); #ifdef DEBUG debugmsg( msg_length + CMD_HDR_LEN , send_data); #endif break; case (CMD_PANA): dat_length = 0; msg_length = (unsigned short)(4 + dat_length); hdr_chksum += CMD_PANA + msg_length; dat_chksum = 0 ; msg_create(CMD_PANA , msg_length , hdr_chksum , dat_chksum, data , send_data ); Serial2.write(send_data, msg_length + CMD_HDR_LEN); #ifdef DEBUG debugmsg( msg_length + CMD_HDR_LEN , send_data); #endif break; case (CMD_CON_SET): dat_length = 1; msg_length = (unsigned short)(4 + dat_length); hdr_chksum += CMD_CON_SET + msg_length; data[0] = 0x02 ; dat_chksum = data[0] ; msg_create(CMD_CON_SET , msg_length , hdr_chksum , dat_chksum, data , send_data ); Serial2.write(send_data, msg_length + CMD_HDR_LEN); #ifdef DEBUG debugmsg( msg_length + CMD_HDR_LEN , send_data); #endif break; case (CMD_PORTOPEN): dat_length = 2; msg_length = (unsigned short)(4 + dat_length); hdr_chksum += CMD_PORTOPEN + msg_length; for (cnt = 0 ; cnt < dat_length ; cnt++ ) { data[cnt] = my_port[cnt] ; } for (cnt = 0 ; cnt < dat_length ; cnt++) { dat_chksum += data[cnt]; } msg_create(CMD_PORTOPEN , msg_length , hdr_chksum , dat_chksum, data , send_data ); Serial2.write(send_data, msg_length + CMD_HDR_LEN); #ifdef DEBUG debugmsg( msg_length + CMD_HDR_LEN , send_data); #endif break; case (CMD_UDPSEND): send_dat_size = strlen(radiodata); //<======送信データサイズを固定長の 4 から、変数のサイズに変更する。 dat_length = 22 + send_dat_size ; msg_length = (unsigned short)(4 + dat_length); hdr_chksum += CMD_UDPSEND + msg_length; for (cnt = 0 ; cnt < 16 ; cnt++ ) { data[cnt] = mac_adr[cnt] ; } data[16] = my_port[0] ; data[17] = my_port[1] ; // 送信元UDPポート :0x0123 data[18] = dist_port[0] ; data[19] = dist_port[1] ; // 送信先UDPポート:0x0E1A data[20] = (unsigned char)(send_dat_size >> 8); data[21] = (unsigned char)(send_dat_size & 0xFF); // send data length for (cnt = 0 ; cnt < send_dat_size ; cnt++) { data[22 + cnt] = radiodata[cnt]; // data } for (cnt = 0 ; cnt < dat_length ; cnt++) { dat_chksum += data[cnt]; } msg_create(CMD_UDPSEND , msg_length , hdr_chksum , dat_chksum, data , send_data ); Serial2.write(send_data, msg_length + CMD_HDR_LEN); #ifdef DEBUG debugmsg( msg_length + CMD_HDR_LEN , send_data); #endif break; default: break; } return TRUE; } /******************************************************************************** * Name : msg_create * Function : create Request command format * input : cmd - Request command * msg_length - message data length * hdr_chksum - header checksum dat_chksum - data checksum *pdada - wireless data *psend_data- request command format data * return : - *********************************************************************************/ void static BP35C0J11::msg_create(unsigned short cmd , unsigned short msg_length , unsigned short hdr_chksum , unsigned short dat_chksum, unsigned char *pdata , unsigned char *psend_data ) { unsigned char cnt = 0 ; for (cnt = 0 ; cnt < 4 ; cnt++) { psend_data[cnt] = uni_req[cnt]; } psend_data[4] = (unsigned char)((cmd & 0xFF00) >> 8); psend_data[5] = (unsigned char)(cmd & 0xFF); psend_data[6] = (unsigned char)((msg_length & 0xFF00) >> 8); psend_data[7] = (unsigned char)(msg_length & 0xFF); psend_data[8] = (unsigned char)((hdr_chksum & 0xFF00) >> 8); psend_data[9] = (unsigned char)(hdr_chksum & 0xFF); psend_data[10] = (unsigned char)((dat_chksum & 0xFF00) >> 8); psend_data[11] = (unsigned char)(dat_chksum & 0xFF); if (msg_length > 4) { for (cnt = 0 ; cnt < msg_length - 4 ; cnt++) { psend_data[12 + cnt] = pdata[cnt]; } } } /******************************************************************************** * Name : debugmsg * Function : output serial console for debug * input : datalength - output data lengh psend_data - output data pointer * return : - *********************************************************************************/ void BP35C0J11::debugmsg(unsigned short datalength , unsigned char* psend_data) { unsigned char cnt = 0 ; for ( cnt = 0 ; cnt < datalength ; cnt++) { Serial.print(psend_data[cnt] , HEX); Serial.print(" "); } Serial.println(""); } ``` 変更部分だけ抜き出してみます。 30、31行目には接続先のUSBドングルのパラメータを記入します。 実際には29~34行目まではすべて設定すべきパラメータですが、USBドングル側の設定をすでに反映させているため今回は変更の必要はありません。必要に応じて任意の値に変更してください。 ```arduino unsigned const char pair_id[8] = {0x00 , 0x1D , 0x12 , 0x91 , 0x00 , 0x02 , 0x2E , 0x8B}; // 接続先MACアドレス unsigned const char mac_adr[16] = {0xFE , 0x80 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x02 , 0x1D , 0x12 , 0x91 , 0x00 , 0x02 , 0x2E , 0x8B}; // 接続先IPv6アドレス ``` ここで 設定するpair_id[8]と、mac_adr[16]は、RPi側のプログラムで出力したUSBドングルのパラメータを使用します。 それぞれの値は以下のパラメータに対応しています。 **USBドングルから出力されたパラメータ** ``` b'EINFO FE80:0000:0000:0000:021D:1291:0002:2E8B 001D129100022E8B 23 5678 1 \r\n' ``` このパラメータのうち、「FE80:0000:0000:0000:021D:1291:0002:2E8B」がmac_adr[16]に、「001D129100022E8B」がpair_id[8]に対応しているのが判るかと思います。 35行目は、送信するデータと格納する変数を定義していますが、bp35c0_j11.hで定義しているためコメントアウトします。 ```arduino //unsigned const char radiodata[4] = { 'T' , 'E' , 'S' , 'T'}; // コメントアウト ``` 325行目は、送信するデータサイズを定義していますが、任意のデータを送信するため、送信するデータに合わせてデータサイズの定義を変更するように書き換えています。。 ```arduino send_dat_size = strlen(radiodata); ``` 以上の変更により、メインプログラムで指定したradiodataを送信できます。 # RPiで受信したデータを読む RPiでデータを読むためには、USBドングルを初期化プログラムで初期化したうえで、次のプログラムを実行してください。 ```python #!/usr/bin/env python # -*- coding: utf-8 -*- #Wi-SUN Rx program import serial import datetime con=serial.Serial('/dev/ttyUSB0',115200) print(con.portstr) while True: str_bf=con.readline() if str_bf !="": print(str_bf) ``` このプログラムは受信したデータをだらだらと表示するだけのプログラムです。 よく探すと、Spresens側で送信したradiodataと同じ文字列が見つかるはずです。 下の画像は、RPi上のThonnyで受信用スクリプトを動かした様子です。多くのデータの最後に「send data」の文字が見えます。 ![キャプションを入力できます](https://camo.elchika.com/f0e6a51f273efbbd886d5b949400e0a89a5bf76c/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38666662353561372d373433312d346234382d383832642d3565323665663534343465652f36626639356237632d643264372d343264612d383737342d356265633432623230356665/) ややこしいデータのなかから、ラベルをつけたデータを拾い出すプログラムは、デバイスプラスさんの[第三回目の記事で紹介されています](https://deviceplus.jp/mc-general/weather-station-with-wisun-03/)ので参考にしてください。 # まとめ ちょっと情報量の少ないボードだったため、当初は戸惑いもありましたがデバイスプラスさんの記事のお掛けでWi-SUN Add-onボード SPRESENSE-WiSUN-EVK-701を動かすことができました。ヨカッタ。