網頁最後修改時間:2017/08/15
為了測試掃描器是否能正常動作,藉由切換無線路由器的無線頻道可以很方便的檢驗,並且更換使用外接天線的無線模組進行接收靈敏度的測試。雖然它不是一個非常高檔的 2.4G 訊號掃描器,但是為了之後要查詢還有哪些 2.4GHz ISM 頻段可以做為通訊來說,夠用了 !
掃描器無線模組使用 nRF24L01+ 負責掃描(接收)不同頻率的訊號,因為 LCD 只有 16 的字元寬度,所以根據下表可得知 WiFi 頻道由中心頻率 2.412 GHz 開始,每間隔 5 MHz 為一個頻道;由於頻率 (範圍 2.400 GHz ~ 2.525 GHz,1 MHz 間隔,共 126 個頻率) 可自己設定,所以可大概產生一個產生 WiFi 頻道的公式:
channel[i] = 12 + i * 5; // i = 0 ... 15
由 Michael Gauthier, Wireless Networking in the Developing World - I created this work based on Image:2.4_GHz_Wi-Fi_channels_(802.11b,g_WLAN).png, 創用CC 姓名標示-相同方式分享 3.0, 連結
nRF24L01+ 通電之後,由微控制器 (這裡指的是 Arduino Nano) 先進行基本初始化後進入到 Standy 模式。將上面設定好的通道頻率依順序設定入 nRF24L01+ 後,進入 RX 模式準備接收訊號。接收時間到之後切換回 standy 模式,這時若之前有接收到該頻率且訊號強度大於 -64 dBm 以上的話,nRF24L01+ 的暫存器 0x09 的最低位元 RPD 會被設定為 1;讀取這個值並記錄下來。
重複上面的流程數次,紀錄訊號被檢測到的次數,就可以得到各通道在一個完成循環的訊號強度,最後將這些訊號強度轉換到整合型 LCD 上做顯示就得到下面影片中的結果。
[備註]
無線路由器無線頻道:Channel 10 (2.457 GHz [頻率範圍:2.446 GHz ~ 2.468 GHz),涵蓋到 Channel 9 (2.452 GHz) 和 Channel 11 (2.462 GHz),所以 channel 9 / 10 / 11 訊號會較強;相對於其他頻道的微小訊號,不用去管!除非有其他 2.4GHz 裝置在旁邊且訊號很強,不然結果會類似 !
*********************************************************************************
現在,我們就可以開始動手作!
參考接線圖:
2.4GHz 訊號掃描器參考接線圖 |
* 材料:
- Arduino Nano / Uno
- 一些杜邦線
- Arduino Nano 擴充底板
- NRF24L01+ (功率加強版本) 無線模組 (含轉接板)
- NRF24L01+ + PA+LNA 遠距離無線模組(含轉接板與 SMA 天線)
- {5V} 整合型 LCD (1602)
實際接線完成示意圖 |
我們使用的函式庫對於 nRF24L01+ 支援很好,經過幾個版本的更新之後更臻完善,而且以此為基礎支援 Network layout 和 Mesh Network ... 等,推薦大家下載此一支援 nRF24L01 和 nRF24L01+ 的函式庫來用
推薦函式庫下載
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 整合型 LCD 的長條圖顯示函式庫:
這裡使用到整合型 LCD 自訂字元的功能,相關的函式庫與程式碼都在{ 單晶片 + Arduino + 樹莓派 } 整合型 LCD ( @ I2C 模式 ) 的漂亮數字顯示 ( 自訂字型或圖案 ) 部落格網頁裡,裡面有說明也有範例;另外有 {5V} 整合型 LCD 雲端資料夾 ( { 5V } 整合型 1602 LCD 螢幕 / codes / Arduino / 整合型 LCD 長條圖標頭檔 (for nRF24l01+ scanner) / iiclcdbar.h )可直接下載使用。
長條圖顯示函式庫與大型數字顯示函式庫基本上相同,改變的如下所述:
- 移除 void displayNumeric() 函式宣告與程式碼
- 移除 const unsigned char Numerics[][] 陣列
- 移除 const int nix[] 和 const int pix[] 兩個陣列
- -------------------------------------------------------------------
- 修改 const unsigned char CGRAM_block[] 陣列如下
- 加入 void displayBarOnLCD() 函式如下
1 2 3 4 5 6 7 8 9 10 | const unsigned char CGRAM_block[]={ 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F, // 0, 0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0X1F, // 1, 0X00,0X00,0X00,0X00,0X00,0X1F,0X1F,0X1F, // 2, 0X00,0X00,0X00,0X00,0X1F,0X1F,0X1F,0X1F, // 3, 0X00,0X00,0X00,0X1F,0X1F,0X1F,0X1F,0X1F, // 4, 0X00,0X00,0X1F,0X1F,0X1F,0X1F,0X1F,0X1F, // 5, 0X00,0X1F,0X1F,0X1F,0X1F,0X1F,0X1F,0X1F, // 6, 0X1F,0X1F,0X1F,0X1F,0X1F,0X1F,0X1F,0X1F, // 7, }; |
1 2 3 4 5 6 7 8 9 10 11 | void displayBarOnLCD( unsigned char pos, unsigned char lev ) { if( lev > 7 ) { displayCGRAM( lev - 8, 1, pos ); displayCGRAM( 7, 2, pos ); } else { displayCharOnLCD( 1, pos, " ", 1 ); displayCGRAM( lev, 2, pos ); } } |
程式碼:
2.4GHz 訊號掃描器是參考函式庫裡面的範例程式,不過我們進行了一些小修改,先將它載進來吧 !
打開 Arduino IDE,選擇 "File/Examples/RF24/scanner" 載入程式碼,載入完成後先另存新檔,並且複製 iiclcdbar.h 這個檔案到目錄中
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 標頭檔:
在原有程式的標頭檔,新增兩個標頭檔宣告,如下所示
1 2 3 4 5 6 | #include <Wire.h> // <---- 加入此標頭檔 #include <SPI.h> #include "nRF24L01.h" #include "RF24.h" #include "printf.h" #include "iiclcdbar.h" // <---- 加入此標頭檔 |
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 全局宣告區:
setup() 函式往上至 #include "iiclcdbar.h 之間所有的程式碼刪掉,插入下面程式碼
1 2 3 4 5 6 7 8 9 10 11 | /** nRF24L01+ */ #define CEPIN 7 #define CSNPIN 8 const uint8_t num_channels = 16; // for 1602 LCD //---------------------------------------------------- // 設定 channel ( CH = 0 ~ 125, 2.4Ghz ~ 2.525Ghz) uint8_t channel[num_channels]; // 在程式中指定,可依固定間隔跳頻 // uint8_t carrierCount[num_channels] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; uint8_t carrierCount[num_channels]; // 載波檢測到的次數 //---------------------------------------------------- RF24 rf24( CEPIN, CSNPIN ); |
在這裡重新定義連接 nRF24L01+ <CE> 和 <CSN> 的接腳;掃描的頻率頻道修改為 16 (原本的 128 也是錯的!最多只有 126 個頻率頻道可使用)
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 新增一個函示:
在 loop() 函式的後面,插入下面的程式碼新增一個函式
1 2 3 4 5 6 | bool checki2cdevice( uint8_t i2caddr ) { // 呼叫此函示之前, Wire 必須先初始化 Wire.beginTransmission( i2caddr ); if( Wire.endTransmission() == 0 ) return true; return false; } |
藉由這個函式,可偵測 I2C 裝置是否有接好或是是否有接上,只需要相關裝置的 I2C 位址。
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 變更 radio 為 rf24:
我將原本的 RF24 radio() 宣告改為 RF24 rf24(),所以在做進一步修改之前,先將整個程式使用到 radio 的全部變更為 rf24。
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* setup():
移除掉 // Print out header, high then low digit 開始至 setup() 函式最後面這幾行程式碼,未修改前的 setup() 函式程式碼如下所示。基本上,這幾行程式碼是之後修改的主架構,只是加入了我們新增的程式碼。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | void setup(void) { // // Print preamble // Serial.begin(57600); printf_begin(); printf("\n\rRF24/examples/scanner/\n\r"); // // Setup and configure rf radio // rf24.begin(); rf24.setAutoAck(false); // Get into standby mode rf24.startListening(); rf24.stopListening(); } |
有兩個部分需要新增,首先是整合型 LCD 初始化相關程式碼。複製下面程式碼插入到 printf() 下面 ( setup(), line10 下面找一處)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /** 整合型 LCD (IIC 模式) */ Wire.begin(); // 檢查整合型 LCD 是否接上與接好 ? if( !checki2cdevice( IIC_ADDR_LCD1 ) ) { Serial.println( "LCD not found!" ); while(1) delay(1); } // 初始化 initLCD(); delay(100); clearLCD(); delay(100); // 自訂字元寫入 writeCGRAM( &CGRAM_block[0], 3, 1 ); writeCGRAM( &CGRAM_block[24], 3, 4 ); writeCGRAM( &CGRAM_block[48], 2, 7 ); displayCharOnLCD( 1, 1, "**IIC LCD ready*", 16 ); delay( 500 ); |
接著,在 rf24.begin() 的下一行,插入下面的程式碼
1 2 3 4 5 6 7 8 9 10 | //檢查 RF24 是否接上與接好 ? if( !rf24.isChipConnected() ) { Serial.println( "nRF24L01/+ not found!" ); while(1) delay(1); } //----- RF 掃描頻道設定 ----- for( int i = 0; i < num_channels; i++ ) channel[i] = 12 + i * 5; // 2.412, 2.417, 2.422, ... displayCharOnLCD( 2, 1, "RF channel ready", 16 ); //--------------------------- |
如此,插入這兩部份的程式碼之後,在每一個連接的週邊模組初始化之前都會先檢查連接的正確性或是否有接上 ? 若是程式開始一段時間之後沒有動作,就可以打開 Serial Monitor 看看輸出的情況,由此來判斷哪裡出錯了!另外,程式在一開始的時候也會在 LCD 上輸出,每完成一個週邊初始化就會輸出一行文字,只要其中一行沒輸出 ... ready 那麼也可以判斷出哪裡出了問題!
setup() 完成程式碼修改之後,下面進行 loop() 函式的修改!
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* loop():
loop() 函式在進行修改前基本的樣子如下所示。特別注意 line 4 ~ 6,原本有的那一行要刪掉;while( rep_counter--) {} 後面接的 //Print out... 什麼的,全部刪除掉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | // // Loop // void loop(void) { // Clear measurement values memset(values,0,sizeof(values)); // Scan all channels num_reps times int rep_counter = num_reps; while (rep_counter--) { int i = num_channels; while (i--) { // Select this channel rf24.setChannel(i); // Listen for a little rf24.startListening(); delayMicroseconds(128); rf24.stopListening(); // Did we get a carrier? if ( rf24.testCarrier() ) ++values[i]; } } } |
上面就是處理掃描的基本程式架構,等一下會變更幾個變數名稱以及新增整合型 LCD 顯示和 Serial 輸出的部分。
首先,改變一下 loop() 基本架構變數宣告與編排,修改之後如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | void loop(void) { uint8_t sweeps = 200; uint8_t maxCount = 0; uint8_t i = 0, j = 0; // Clear measurement values memset(carrierCount, 0, sizeof(carrierCount)); // Scan all channels num_reps times while (sweeps--) { for( i = 0; i < num_channels; i++ ) { // Select this channel rf24.setChannel(i); // Listen for a little rf24.startListening(); delayMicroseconds(128); rf24.stopListening(); // Did we get a carrier? if ( rf24.testCarrier() ) ++carrierCount[i]; } } } |
最後要插入下面的程式碼到 loop() 函式裡的最後面,將掃描之後的結果輸出到 Serial 和整合型 LCD 上 (不要對下面程式碼有所疑慮,只要編譯通過就表示可以用)
1 2 3 4 5 6 7 8 9 10 | for( j = 0; j < num_channels; j++ ) if( maxCount < carrierCount[j]) maxCount = carrierCount[j]; /** 顯示各頻道的載波值 */ for( i = 0; i < num_channels; i++ ) { uint8_t level = map( carrierCount[i] , 0, maxCount, 0, 15 ); displayBarOnLCD( i + 1, level ); printf_P( PSTR("%02d "), level ); } printf_P( PSTR( "| %02d\n" ), maxCount ); |
完成上面的步驟之後,程式碼基本就完成修改可進行編譯與上傳,實際動作結果就如網頁前面的影片。
能夠成功上傳程式之後,接著讓我們來做一些小測試,看看效果如何 ?
測試:
我們測試的重點有兩個:第一個,是測試整個電路與程式是否能正常運作;第二個,則是在第一個測試 OK 之後,更換使用外接天線的的無線模組進行測試,看看兩者之間究竟有何不同 ?
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 頻道頻率測試:
因為要測試,所以頻率不能亂選擇,畢竟現在不是用在傳送與接收數據上,由於無線網路大多家中都有,而且設定也很方便,所以就選擇無線網路頻段來做測試 (這部份的一些訊息可上 WIKIPEDIA, WLAN 信道列表查看)
WLAN 頻道頻率列表 |
如下所示,手動選擇無線頻道為 4
WLAN 使用的無線頻道 (Channel 4) |
板載天線無線模組,WLAN Channel = 4, 掃描過程中其中的一次結果畫面 |
WLAN 使用的無線頻道 (Channel 10) |
板載天線無線模組,WLAN Channel = 10, 掃描過程中其中的一次結果 |
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* PA+LNA 外接天線模組:
緊接著上面的測試,將無線模組換成 PA+LNA 外接天線式的無線模組 (程式與硬體接腳都是相容的),兩者使用相同的 nRF24L01+ 晶片,在這邊只是順便做測試,測試一下它接收的能力 (當然它的發射功率也是相當不錯的 ! ),而且從下圖也可以看到接收能力比板載天線的無線模組好多了。
PA+LNA 外接天線無線模組,WLAN Channel = 10, 掃描過程中其中的一次結果 |
結論:
這是個簡易且實用的二點四GHz 訊號掃描器,做為 nRF24L01+ 無線模組在部落格網頁的起頭,我覺得不錯 ! 即便手邊沒有整合型 LCD,也可以換成其他的液晶螢幕來用,來顯示更多的頻道頻率。
接下來,就要進入到 nRF24L01+ 傳送與接收的部分了,不過還不會太深入!要先來加強板載天線的無線模組傳送與接收的能力,要利用這些改裝的無線模組來做穿牆的測試,為了更後面的多節點無線溫濕度環境監控作準備,所以有興趣的就繼續看下去吧 !
<< 部落格相關網頁 >>
- *0*nRF24L01+*0* Arduino 二點四GHz 訊號掃描器
- *1*RF24L01+*1* 如何提高 nRF24L01+ 板載天線無線模組的傳輸距離與穿牆效果 ? 加碼:不同天線形式的穿牆測試
- *2*nRF24L01+*2* SHT31 單點無線溫溼度傳輸
- 初遇 Blynk ( 物聯網手機 APP ) - 如何使用 Arduino 和 AT 韌體 ( Ai-Mod, AT v1.2.0.0 based on SDK v1.5.4.1 ) 的 ESP8266 (ESP-01, ESP-01S) 連上 Blynk 伺服器和儲存數據 {*2_1*nRF24L01+*2_1*}
- *3*nRF24L01+*3* 初遇 Blynk - 建立從 nRF24L01+ 到 ESP8266 再到 Blynk 的 SHT31 單點無線溫溼度傳輸物聯網
沒有留言:
張貼留言
留言屬名為"Unknown"或"不明"的用戶,大多這樣的留言都會直接被刪除掉,不會得到任何回覆!
發問問題,請描述清楚你(妳)的問題,別人回答前不會想去 "猜" 問題是什麼?
不知道怎麼發問,請看 [公告] 部落格提問須知 - 如何問問題 !