This software is a test tool for the XBee Library 'XBee Coord API'. I'll check to pass the test when release the library.
Dependencies: TextLCD mbed xbee
Please refer to the following site for the details:
- http://developer.mbed.org/users/bokunimowakaru/code/xbee/wiki/Homepage (English)
- http://www.geocities.jp/bokunimowakaru/diy/xbee/xbee-nucleo.html (Japanese)
Diff: main.cpp
- Revision:
- 0:60ca8c579d80
- Child:
- 3:e815df43e269
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Sep 21 10:15:44 2014 +0000 @@ -0,0 +1,625 @@ +#define ARM_MBED +//#define DEBUG // D8(PA_9)からログをUART(38400baud)出力します +/********************************************************************* +XBee ライブラリ・自動システム試験ツール + + 元々、XBeeライブラリ「ZB Coord API」のリリース用のテストツールとして + 作成して、使用していたものです。 + XBeeライブラリを用いた時の評価用に公開することにいたしました。 + 電波環境が悪いと100%になりません。 + Arduino用PC用ともにキーを押すとエラー数と合格回数、テスト回数、最後の + エラーの内容を表示します。 + +本ソースリストおよびソフトウェアは、ライセンスフリーです。 +利用、編集、再配布等が自由に行えますが、著作権表示の改変は禁止します。 + + Copyright (c) 2010-2014 Wataru KUNINO + http://www.geocities.jp/bokunimowakaru/ +*********************************************************************/ + +/********************************************************************* + +●試験項目● + ①ローカルATコマンド試験 + ②ローカルxbeeライブラリ用コマンド試験 + ③リモートATコマンド試験 + ④リモートxbeeライブラリ管理コマンド試験 + ⑤リモートxbeeライブラリ応答待ちコマンド試験 + ⑥ループバック試験 + +●試験環境● + ○本ソフトを動かす親機用ArduinoまたはPC + ○親機用XBee ZBモジュール【ファーム=ZIGBEE COORDINATOR API】 + ○子機用XBee ZBモジュール【ファーム=ZIGBEE ROUTER AT】 + ○子機のUARTはループバック接続が必要です。(DINとDOUTを接続) +*/ + +// #define DEBUG //DEBUGをdefineするとライブラリの動作ログが出力されます。 +// #define DEBUG_TX //送信データ表示 +// #define ERRLOG +#define EASY_SENSOR +#define XBEE_ERROR_TIME +#define PASSED 0 +#define FAILED 1 +#ifdef ARDUINO + #define SIZEOF_LOG_S 36 // 33以上 +#else + #ifdef ARM_MBED + #define SIZEOF_LOG_S 80 + #else // PC + #define SIZEOF_LOG_S 80 + #endif +#endif + +#ifdef ARDUINO + #include <xbee.h> + #include <Wire.h> + #include <Adafruit_MCP23017.h> + #include <Adafruit_RGBLCDShield.h> + Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield(); +#else + #ifdef ARM_MBED + #include <xbee.h> + #include "TextLCD.h" + #include <ctype.h> + TextLCD lcd(PA_9, PC_7, PB_5, PB_4, PB_10, PA_8); // rs, e, d4-d7 + DigitalIn mybutton(USER_BUTTON); + #else // PC + #include "../libs/xbee.c" + #include <ctype.h> // isgraph + #include "../libs/kbhit.c" + #endif +#endif + +byte dev[8]; +byte my[8]; +byte myt[8]; +byte panid[8]; +byte panidt[8]; +byte TEST_COUNT=0; +byte ERROR_COUNT=0; +byte ERROR_TOTAL=0; +char ERROR_S[SIZEOF_LOG_S]; +unsigned int pan; +byte nc,rnc=0xFF,dd=0xFF; + +static const char UARTDATA[] = "0123456789ABCDEF"; +char *sprint_FAIL(char *s,const char *text){ + sprintf(s,"%s:FAIL####",text); + return s; +} + +void aging_delay(unsigned int ms){ + #ifdef ARDUINO + delay((unsigned long)ms); + #else + #ifdef ARM_MBED + wait((float)ms/1000.); + #else // PC + wait_millisec(ms); + #endif + #endif +} + +#if defined(ARDUINO) +void prints(char *s){ + byte x,y; + byte c=1; + for(y=0;y<2;y++){ + lcd.setCursor(0, y); + for(x=0;x<16;x++){ + if(s[16*y+x]=='\0') c=0; + if(isgraph(s[16*y+x]) && c) lcd.print(s[16*y+x]); + else lcd.print(' '); + } + } +} +#endif +#if defined(ARM_MBED) +void prints(char *s){ + byte x,y; + byte c=1; + for(y=0;y<2;y++){ + lcd.locate(0, y); + for(x=0;x<16;x++){ + if(s[16*y+x]=='\0') c=0; + if(isgraph(s[16*y+x]) && c) lcd.printf("%c",s[16*y+x]); + else lcd.printf(" "); + } + } +} +#endif + +void aging_key(void){ + #ifdef ARDUINO + if( lcd.readButtons() ){ + lcd.clear(); + lcd.print(ERROR_COUNT,DEC); // 3 + lcd.print("errs "); // 5 + lcd.print((TEST_COUNT-ERROR_TOTAL),DEC); // 3 + lcd.print('/'); // 1 + lcd.print(TEST_COUNT,DEC); // 3 + lcd.setCursor(0, 1); + if(ERROR_COUNT || ERROR_TOTAL){ + lcd.print(ERROR_S); + } + delay(100); + while( lcd.readButtons() ); + delay(100); + while( !lcd.readButtons() ); + prints(ERROR_S); + delay(3000); + while( lcd.readButtons() ); + } + #else + #ifdef ARM_MBED + if( mybutton==0 ){ // Button is pressed + lcd.cls(); + lcd.printf("%d",ERROR_COUNT); // 3 + lcd.printf("errs "); // 5 + lcd.printf("%d",TEST_COUNT-ERROR_TOTAL); // 3 + lcd.printf("/"); // 1 + lcd.printf("%d",TEST_COUNT); // 3 + lcd.locate(0, 1); + if(ERROR_COUNT || ERROR_TOTAL){ + lcd.printf(ERROR_S); + } + aging_delay(100); + while( !mybutton ); + aging_delay(100); + while( mybutton ); + prints(ERROR_S); + aging_delay(3000); + while( !mybutton ); + } + #else // PC + if( kbhit() ){ + getchar(); + printf("----------------------------------------------------------------\n"); + printf("ERROR=%d(TEST:%d/%d) ",ERROR_COUNT,TEST_COUNT-ERROR_TOTAL,TEST_COUNT); + if(ERROR_COUNT || ERROR_TOTAL){ + printf("%s",ERROR_S); + } + printf("\n----------------------------------------------------------------\n"); + aging_delay(3000); + } + #endif + #endif +} + +void aging_log(char *s){ + #if defined(ARDUINO) || defined(ARM_MBED) + prints(s); + #else // PC + time_t error_time; + struct tm *error_time_st; + + time(&error_time); + error_time_st = localtime(&error_time); + printf("%4d/%02d/%02d %02d:%02d:%02d %s\n", + error_time_st->tm_year+1900, + error_time_st->tm_mon+1, + error_time_st->tm_mday, + error_time_st->tm_hour, + error_time_st->tm_min, + error_time_st->tm_sec, + s + ); + #endif + aging_key(); +} + +void error_log(char *s){ + #ifndef ARDUINO + #ifndef ARM_MBED // PC + FILE *fp; + time_t error_time; + struct tm *error_time_st; + + time(&error_time); + error_time_st = localtime(&error_time); + if( (fp=fopen("err.log","a")) != NULL ){ + fprintf(fp,"%4d/%02d/%02d %02d:%02d:%02d %s\n", + error_time_st->tm_year+1900, + error_time_st->tm_mon+1, + error_time_st->tm_mday, + error_time_st->tm_hour, + error_time_st->tm_min, + error_time_st->tm_sec, + s + ); + fclose(fp); + } + #endif + #endif + aging_log(s); + strcpy(ERROR_S,s); + ERROR_COUNT++; + aging_delay(1000); + aging_key(); +} + +void aging_results(void){ + char s[SIZEOF_LOG_S]; + TEST_COUNT++; + if(ERROR_COUNT==0){ + // 012345678901234567890123456 28~30bytes + sprintf(s,"###TEST:PASSED (%d/%d)####",TEST_COUNT-ERROR_TOTAL,TEST_COUNT); + aging_log(s); + }else{ + ERROR_TOTAL++; + // 01234567890123456789012345678 30~33bytes + sprintf(s,"###TEST:FAILED %d(%d/%d)####",ERROR_COUNT,TEST_COUNT-ERROR_TOTAL,TEST_COUNT); + aging_log(s); + #ifndef ARDUINO + #ifndef ARM_MBED // PC + strcpy(s,ERROR_S); + aging_log(s); + #endif + #endif + ERROR_COUNT=0; + } + aging_delay(3000); +} + +void aging_print(char *text,byte ret,byte target,byte judge){ + char s[SIZEOF_LOG_S]; + if( (judge==PASSED && target == ret) || + (judge==FAILED && target != ret) + ){ + sprintf(s,"%s:PASS(%02X)",text,ret); + aging_log(s); + }else{ + // 0-789012345678901--234-- 26bytes + sprintf(s,"%sret=%02X:%02X",sprint_FAIL(s,text),ret,target); + error_log(s); + } +} + +void aging_rx_resp(char *text,char *at,byte n){ + XBEE_RESULT xbee_result; + byte data; + byte i,j; + char s[SIZEOF_LOG_S]; + for(i=0;i<n;i++){ + data=xbee_rx_call( &xbee_result ); + if( ( xbee_result.MODE==MODE_RESP && + xbee_result.STATUS == STATUS_OK && + xbee_result.AT[0] == 'I' && + xbee_result.AT[1] == 'S' && + bytecmp(dev,xbee_result.FROM,8)==0 + ) + // || ( + // xbee_result.MODE==MODE_GPIN && + // bytecmp(dev,xbee_result.FROM,8)==0 + // ) + ){ + sprintf(s,"%s:PASS(%02X)",text,data); + for(j=0;j<8;j++){ + if( (data>>(7-j))&0x01 ) s[16+j]='1'; + else s[16+j]='0'; + } + s[24]='\0'; + aging_log(s); + return; + } + } + error_log(sprint_FAIL(s,text)); +} + +void aging_rx_uart(char *text,const char *uart,byte n){ + XBEE_RESULT xbee_result; + byte i,j; + byte len; + char s[SIZEOF_LOG_S]; + byte data[SIZEOF_LOG_S]; + + for(i=0;i<n;i++){ + len=xbee_rx_call( &xbee_result ); + if( xbee_result.MODE==MODE_UART && + bytecmp(dev,xbee_result.FROM,8)==0 + ){ + for(j=0;j<SIZEOF_LOG_S;j++) data[j]=(byte)uart[j]; + if(len>SIZEOF_LOG_S) len=SIZEOF_LOG_S; + if(bytecmp(data,xbee_result.DATA,len)==0){ + sprintf(s,"%s:PASS(%02d) ",text,len); + for(j=16;j<32;j++){ + if(isgraph(xbee_result.DATA[j-16])){ + s[j]=(char)xbee_result.DATA[j-16]; + }else s[j]=' '; + } + s[32]='\0'; + aging_log(s); + if(len!=strlen(uart)){ + sprintf(s,"%s:WARNING txLen=%d,rx=%d",text,strlen(uart),len); + aging_log(s); + } + return; + }else{ + sprintf(s,"%s:FAIL(%02d)################",text,len); + for(j=16;j<24;j++){ + if(xbee_result.DATA[j-16]>16){ + s[j]=(char)xbee_result.DATA[j-16]; + }else s[j]=' '; + } + error_log(s); + return; + } + } + } + error_log(sprint_FAIL(s,text)); +} + +byte s2bytes(byte *bytes,const char *s){ + byte i; + for(i=0;i<strlen(s);i++) bytes[i]=s[i]; + return(i); +} + +void aging_rx_batt(char *text,byte n){ + XBEE_RESULT xbee_result; + byte i; + char s[SIZEOF_LOG_S]; + for(i=0;i<n;i++){ + xbee_rx_call( &xbee_result ); + if( xbee_result.MODE==MODE_BATT && + xbee_result.STATUS == STATUS_OK && + bytecmp(dev,xbee_result.FROM,8)==0 && + xbee_result.ADCIN[0] > 1000 + ){ + sprintf(s,"%s:PASS(00)%d[mV]",text,xbee_result.ADCIN[0]); + aging_log(s); + return; + } + } + error_log(sprint_FAIL(s,text)); +} + +char byte2a(byte in, byte i){ + char ret; + if(i) in /= 16; + ret = (char)(in%16); + if(ret<10) ret += '0'; + else ret += 'A' -10; + return( ret ); +} + +byte pairing(byte *dev,byte n){ + XBEE_RESULT xbee_result; + char s[SIZEOF_LOG_S]; + + byte i,len; + for(i=0;i<n;i++){ + xbee_rx_call( &xbee_result ); + if( xbee_result.MODE==MODE_IDNT ){ + sprintf(s,"Pairing:PASS(%02X)",xbee_result.STATUS); + len=strlen(s); + for(i=0;i<8;i++){ + dev[i]=xbee_result.FROM[i]; + s[len] =byte2a(dev[i],1); + s[len+1]=byte2a(dev[i],0); + len+=2; + } + s[len]='\0'; + aging_log(s); + return(1); + } + } + return(0); +} + +void aging_rx_none(char *text,byte n){ + XBEE_RESULT xbee_result; + byte i; + char s[SIZEOF_LOG_S]; + for(i=0;i<n;i++){ + xbee_rx_call( &xbee_result ); + if( xbee_result.MODE != 0x00 ){ + sprintf(s,"%smode=%02X stat=%02X",sprint_FAIL(s,text),xbee_result.MODE,xbee_result.STATUS); + error_log(s); + return; + } + } + sprintf(s,"%s:PASS",text); + aging_log(s); +} + +void aging_init(void){ + char s[SIZEOF_LOG_S]; + byte i; + + xbee_atnj(0xFF); + aging_delay(1000); + aging_log("Press Commiss.SW"); + /* ペアリング&宛先アドレス取得 */ + while(pairing(dev,100)==0); + sprintf(s,"DestAdr:"); + for(i=0;i<4;i++){ + s[8+2*i]=byte2a(dev[i+4],1); + s[9+2*i]=byte2a(dev[i+4],0); + } + s[16]='\0'; + aging_log(s); + xbee_atnj(0); + aging_delay(1000); + /* 自分のアドレス */ + xbee_myaddress(my); + sprintf(s,"MyAdr :"); + for(i=0;i<4;i++){ + s[8+2*i]=byte2a(my[i+4],1); + s[9+2*i]=byte2a(my[i+4],0); + } + s[16]='\0'; + aging_log(s); + aging_delay(1000); + /* PAN ID */ + pan=xbee_atop(panid); + sprintf(s,"PAN ID :%d ",pan); + for(i=0;i<8;i++){ + s[16+2*i]=byte2a(panid[i],1); + s[17+2*i]=byte2a(panid[i],0); + } + s[32]='\0'; + aging_log(s); + aging_delay(1000); + /* 子機数など */ + nc=xbee_atnc(); + while(rnc==0xFF){ + rnc=xbee_ratnc(dev); + } + while(dd==0xFF){ + dd=xbee_ping(dev); + } + sprintf(s,"nOfChld:%d,%d,%02X",10-nc,12-rnc,dd); + aging_log(s); + aging_delay(1000); +} + +void loop(){ + byte data[SIZEOF_LOG_S]; + byte i,len; + + aging_log("Started:========"); + + // ①ローカルATコマンド試験 + #ifndef ARDUINO + #ifndef ARM_MBED // PCのみ試験 + for(i=0;i<10;i++){ + aging_print("LocAt L",xbee_at("ATP004"),STATUS_OK,PASSED); + aging_print("LocAt H",xbee_at("ATP005"),STATUS_OK,PASSED); + } + #endif + #endif + aging_print("LocAt -",xbee_at("ATP001"),STATUS_OK,PASSED); + + // ②ローカルxbeeライブラリ用コマンド試験 +// aging_print("reset ",xbee_reset(),0,FAILED); + aging_print("atcb ",xbee_atcb(1),0,PASSED); + for(i=0;i<3;i++){ + aging_print("myAdr ",xbee_myaddress(myt),0,FAILED); + aging_print("myAdCmp",bytecmp(my,myt,8),0,PASSED); + aging_print("atvr ",xbee_atvr(),ZB_TYPE_COORD,PASSED); + aging_print("atai ",xbee_atai(),0,PASSED); + aging_print("atop ",(byte)xbee_atop(panidt),(byte)pan,PASSED); + aging_print("atopCmp",bytecmp(panid,panidt,8),0,PASSED); + aging_print("atnc ",xbee_atnc(),nc,PASSED); // ncと一致すること + } + + // ③リモートATコマンド試験 + #ifndef ARDUINO + #ifndef ARM_MBED // PCのみ試験 + for(i=0;i<10;i++){ + aging_print("RemAt L",xbee_rat(dev,"ATP104"),STATUS_OK,PASSED); // 0xFF=ERROR + aging_print("RemAt H",xbee_rat(dev,"ATP105"),STATUS_OK,PASSED); // 0xFF=ERROR + } + #endif + #endif + aging_print("LocAt -",xbee_at("ATP100"),STATUS_OK,PASSED); + + // ④リモートxbeeライブラリ管理コマンド試験 + aging_print("ratd ",xbee_ratd(dev, my),0xFF,FAILED); // 0xFF=ERROR + aging_print("ratdMyA",xbee_ratd_myaddress(dev),0xFF,FAILED); // 0xFF=ERROR + aging_print("ratnc ",xbee_ratnc(dev),rnc,PASSED); // rncと一致すること + aging_print("ping ",xbee_ping(dev),dd,PASSED); // ddと一致すること + aging_print("batt ",(byte)(xbee_batt(dev)<0),0,PASSED); + aging_print("gpioIni",xbee_gpio_init(dev),dd,PASSED); // ddと一致すること + #if defined(ARDUINO) || defined(ARM_MBED) + aging_print("gpi 1 ",xbee_gpi(dev,1),0xFF,FAILED); + aging_print("adc 1 ",(byte)(xbee_adc(dev,1)==0xFFFF),0,PASSED); + #else // PCのみ試験 + for(i=0;i<3;i++){ + aging_print("gpi 1 ",xbee_gpi(dev,1),0xFF,FAILED); + aging_print("gpi 2 ",xbee_gpi(dev,2),0xFF,FAILED); + aging_print("gpi 3 ",xbee_gpi(dev,3),0xFF,FAILED); + } + for(i=0;i<3;i++){ + aging_print("adc 1 ",(byte)(xbee_adc(dev,1)==0xFFFF),0,PASSED); + aging_print("adc 2 ",(byte)(xbee_adc(dev,2)==0xFFFF),0,PASSED); + aging_print("adc 3 ",(byte)(xbee_adc(dev,3)==0xFFFF),0,PASSED); + } + for(i=0;i<3;i++){ + aging_print("sensorL",(byte)(xbee_sensor(dev,LIGHT)<0),0,PASSED); + aging_print("sensorT",(byte)(xbee_sensor(dev,LIGHT)<0),0,PASSED); + aging_print("sensorH",(byte)(xbee_sensor(dev,LIGHT)<0),0,PASSED); + } + #endif + + // ⑤リモートxbeeライブラリ応答待ちコマンド試験 + for(i=0;i<3;i++){ + aging_print("force ",xbee_force(dev),0x00,FAILED); + aging_rx_resp("rxResp ","IS",200); // STATUS_OKのIS応答を200受信分、待つ + aging_print("batForc",xbee_batt_force(dev),0x00,FAILED); + aging_rx_batt("rxBatt ",200); + // aging_print("ratForc",xbee_rat_force(dev,"ATIS"),0x00,FAILED); + // aging_rx_resp("rxResp ","IS",200); // STATUS_OKのIS応答を200受信分、待つ + } + for(i=0;i<5;i++){ + aging_print("gpo11,0",xbee_gpo(dev,11,0),0,FAILED); + aging_rx_none("rxNo110",10); + aging_print("gpo11,1",xbee_gpo(dev,11,1),0,FAILED); + aging_rx_none("rxNo111",10); + #ifndef ARDUINO + #ifndef ARM_MBED // PCのみ試験 + aging_print("gpo12,0",xbee_gpo(dev,12,0),0,FAILED); + aging_rx_none("rxNo120",10); + aging_print("gpo12,1",xbee_gpo(dev,12,1),0,FAILED); + aging_rx_none("rxNo121",10); + #endif + #endif + } + aging_rx_none("rxNone ",100); + + // ⑥ループバック試験 + for(i=0;i<3;i++){ + aging_print("uartTx ",xbee_uart(dev,UARTDATA),0,FAILED); + aging_rx_uart("rxUart ",UARTDATA,200); // UART応答を200受信分、待つ + len=s2bytes(data,UARTDATA); + aging_print("byteTx ",xbee_bytes(dev,data,len),0,FAILED); + aging_rx_uart("rxByte ",UARTDATA,200); // UART応答を200受信分、待つ + } + + // 試験結果 + aging_results(); +} + +#ifdef ARDUINO + void setup(){ + byte i; + + lcd.begin(16, 2); + lcd.clear(); + lcd.print("XBee Aging"); + lcd.setCursor(0, 1); + lcd.print(COPYRIGHT); + xbee_init(0); + aging_init(); + for(i=0;i<SIZEOF_LOG_S;i++) ERROR_S[i]='\0'; + } +#endif + +#ifndef ARDUINO + #ifdef ARM_MBED + int main() + #else + int main(int argc,char **argv) + #endif + { + byte port=0; + byte i; + + #ifdef ARM_MBED + lcd.cls(); + lcd.printf("XBee Aging"); + lcd.locate(0, 1); + lcd.printf(COPYRIGHT); + #else + if( argc==2 ) port = (byte)(atoi(argv[1])); + #endif + xbee_init( port ); // XBee用COMポートの初期化(引数はポート番号) + aging_init(); + for(i=0;i<SIZEOF_LOG_S;i++) ERROR_S[i]='\0'; + + while(1)loop(); + exit(1); + } +#endif