# 南開科大 Seeed Xiao nRF52840 Sense 實驗 2023/12/08 Jack OmniXRI整理製作 ## Seeed官方文件: 開發板資訊:Getting Started with Seeed Studio XIAO nRF52840 Sense https://wiki.seeedstudio.com/XIAO_BLE/ 擴展板資訊:Expansion Board Base for XIAO https://wiki.seeedstudio.com/Seeeduino-XIAO-Expansion-Board/ ## 連接開發板 以 USB Type C纜線連接電腦和開發板,檢查「裝置管理員」下「連接埠(COM和LPT)」是否有多一個「USB序列裝置(COMxx)」。xx即為埠號,會隨電腦即插入USB位置每次都會隨機配置。若沒有產生序列裝置,則可快速按開發板「Reset」鍵二次,令其進入模式。 ## 安裝開發環境 1. 安裝 Arduino 2.x (Windows Win 10 and newer, 64 bits) https://www.arduino.cc/en/software 2. 開啟Arduino 3. 點選選單 File > Preference ... ,並於 "Additional Boards Manager URLs" 項目填入 **https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json** 4. 點選選單 Tools > Board > Boards Manager... , 輸入 **nRF52840** 搜尋 Seeed nRF52840 開發板相關函式庫。 安裝下列二個函式庫。版本選最新即可,按下「INSTALL」鍵後開始安裝 4.1. **Seeed nRF52 Boards** 4.2. **Seeed nRF52 mbed-enabled Boards** 5. 指定好欲工作的開發板名稱及埠號,點選選單 Tools > Board > Seeed nRF52 Boards > Seeed XAIO nRF52840 Sense 並選擇 Port。可點選 Tools > Get Board Info 來檢查連線是否正確。 ## 測試程式編譯及上傳(LED閃爍) 1. 點選選單 File > Examples > 01.Basics > Blink 會自動產生下列程式碼 ```c++= // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); } // the loop function runs over and over again forever void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } ``` 2. 點選快捷鍵列的**上傳鍵(右箭頭符號)**,此時程式就會開始編譯,完成後會自動上傳到開發板上。如果看到開發板上紅色LED以1秒亮1秒暗,即完成測試。 3. 若無法上傳,快按開發板上RESET鍵二次,再重新選擇開發板及埠號,重新上傳即可。 4. 以上程式 **LED_BUILTIN** (等同於LED_RED)可試著修改成其它顏色LED(紅色LED_RED, 綠色LED_GREEN, 藍色LED_BLUE),或修改延遲時間長度。 ## 測試擴展板按鍵 1. 點選選單 File > Examples > 02.Digital > Button 會自動產生下列程式碼 ```c++= const int buttonPin = D1; // 設定擴展板使用者按鍵腳位 const int buzzerPin = PIN_A3; // 設定擴展板蜂鳴器腳位 int buttonState = 0; // 設定按鍵狀況初始值 void setup() { // 初始化設定 pinMode(buzzerPin , OUTPUT); // 指定擴展板蜂鳴器接腳為輸出 pinMode(buttonPin, INPUT_PULLUP); // 指定擴展板按鍵為具上拉輸入 } void loop() { // 無限迴圈 buttonState = digitalRead(buttonPin); // 讀取按鍵狀態 if (buttonState == LOW) { // 若按鍵按下 digitalWrite(buzzerPin, HIGH); // 蜂鳴器ON delayMicroseconds(500); // 等待時間500us digitalWrite(buzzerPin, LOW); // 蜂鳴器OFF delayMicroseconds(500); // 等待時間500us } } ``` 2. 修改使用者按鍵的接腳為D1,將 buttonPin = 2; 改成 buttonPin = D1; 3. 修改輸入腳型式,將 INPUT 改成 INPUT_PULLUP 4. 點擊「上傳」鍵編譯並上傳,當按下鍵時點亮LED,放開時LED熄滅。 ## 測試擴展板蜂鳴器 ### 以DIO方式驅動 結合LED閃爍及使用者按鍵程式範例,當按下按鍵時,令蜂鳴器產生1Khz頻率(500us ON + 500us OFF)。 ```c++= const int buttonPin = D1; // 設定擴展板使用者按鍵腳位 const int buzzerPin = PIN_A3; // 設定擴展板蜂鳴器腳位 int buttonState = 0; // 設定按鍵狀況初始值 void setup() { // 初始化設定 pinMode(buzzerPin , OUTPUT); // 指定擴展板蜂鳴器接腳為輸出 pinMode(buttonPin, INPUT_PULLUP); // 指定擴展板按鍵為具上拉輸入 } void loop() { // 無限迴圈 buttonState = digitalRead(buttonPin); // 讀取按鍵狀態 if (buttonState == LOW) { // 若按鍵按下 digitalWrite(buzzerPin, HIGH); // 蜂鳴器ON delayMicroseconds(500); // 等待時間500us digitalWrite(buzzerPin, LOW); // 蜂鳴器OFF delayMicroseconds(500); // 等待時間500us } } ``` ### 以PWM方式驅動 使用PWM方式,當按下按鍵後從蜂鳴器產1KHz頻率。 ```c++= const int buttonPin = D1; // 設定擴展板使用者按鍵腳位 int buttonState = 0; // 設定按鍵狀況初始值 void setup() { // 初始化設定 pinMode(buttonPin, INPUT_PULLUP); // 指定擴展板按鍵為具上拉輸入 } void loop() { // 無限迴圈 buttonState = digitalRead(buttonPin); // 讀取按鍵狀態 if (buttonState == LOW) { // 若按鍵按下 tone(PIN_A3, 1000, 100); // A3接腳以PWM方式發出1000Hz持續100ms delay(100); // 延遲100ms } } ``` ### 以蜂鳴器播放音樂 生日快樂歌曲,notes[]定義音高,beats[]定義節奏(音長),names[]定義音高名稱C代表DO依此類推。 ```c++= int speakerPin = A3; int length = 28; // the number of notes char notes[] = "GGAGcB GGAGdc GGxecBA yyecdc"; int beats[] = { 2, 2, 8, 8, 8, 16, 1, 2, 2, 8, 8, 8, 16, 1, 2, 2, 8, 8, 8, 8, 16, 1, 2, 2, 8, 8, 8, 16 }; int tempo = 150; void playTone(int tone, int duration) { for (long i = 0; i < duration * 1000L; i += tone * 2) { digitalWrite(speakerPin, HIGH); delayMicroseconds(tone); digitalWrite(speakerPin, LOW); delayMicroseconds(tone); } } void playNote(char note, int duration) { char names[] = {'C', 'D', 'E', 'F', 'G', 'A', 'B', 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'x', 'y' }; int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956, 834, 765, 593, 468, 346, 224, 655 , 715 }; int SPEE = 5; // play the tone corresponding to the note name for (int i = 0; i < 16; i++) { if (names[i] == note) { int newduration = duration / SPEE; playTone(tones[i], newduration); } } } void setup() { pinMode(speakerPin, OUTPUT); } void loop() { for (int i = 0; i < length; i++) { if (notes[i] == ' ') { delay(beats[i] * tempo); // rest } else { playNote(notes[i], beats[i] * tempo); } // pause between notes delay(tempo); } } ``` ## 測試擴展板OLED SSD1306 1. 目前擴展板之 0.96" OLED是採用SSD1306晶片驅動,具有128x64像素(單色/白色)。 2. u8g2 函式庫,這是一個支援多種OLED/LCD的單色點矩陣字形及顯示函式庫。完整介紹請參考: https://github.com/olikraus/u8g2/wiki 3. 開啟Arduino IDE左側之Library Manager,輸入 u8g2 ,選擇最新版本,點擊「INSTALL」進行安裝。 4. 輸入下列程式並編譯上傳,即可看到OLED上顯示「Hello World!」 ```c++= #include <Arduino.h> #include <U8x8lib.h> #include <Wire.h> // 設定OLED I2C接腳 U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* clock=*/ PIN_WIRE_SCL, /* data=*/ PIN_WIRE_SDA, /* reset=*/ U8X8_PIN_NONE); void setup(void) { // 初始化設定 u8x8.begin(); // 初始化u8x8函式 u8x8.setFlipMode(0); // 設定螢幕顯示翻轉方式,1為翻轉180度 } void loop(void) { // 無限迴圈 u8x8.setFont(u8x8_font_chroma48medium8_r); // 設定顯示字形 u8x8.setCursor(0, 0); // 設定起始座標(X, Y) u8x8.print("Hello World!"); // 設定顯示字串 } ``` ## 測試運動感測器 Seeed官方文件:The 6-Axis IMU Usage on Seeed Studio XIAO nRF52840 Sense (LSM6DS3) https://wiki.seeedstudio.com/XIAO-BLE-Sense-IMU-Usage/ 1. 下載 LSM6DS3 函式庫,進入下列網址,點擊網頁右上角「<>Code」按鍵,按下「Download ZIP」,取得 Seeed_Arduino_LSM6DS3-master.zip 。 https://github.com/Seeed-Studio/Seeed_Arduino_LSM6DS3 2. 開啟 Arduino IDE 3. 點選選單 Sketch > Include Library > Add .ZIP Library... 加入剛才下載的ZIP檔案。 4. 點選選單 File > Examples > Seeed Aruino LSM6DS3 > IMU_capture 開啟運動感測器(IMU)範例。 ```c++= #include <LSM6DS3.h> #include <Wire.h> LSM6DS3 myIMU(I2C_MODE, 0x6A); // 建立LSM6DS3實例並設定I2C裝置位址 float aX, aY, aZ, gX, gY, gZ; // 儲存三軸加速度及陀螺儀數值變數 const float accelerationThreshold = 2.5; // 加速度門檻值 const int numSamples = 119; // 樣本數量 int samplesRead = numSamples; // 讀取樣本數量 void setup() { // 初始化設定 Serial.begin(9600); // 設定串例通信速度(bps) while (!Serial); // 等待串列埠初始化完成 if (myIMU.begin() != 0) { // 初始化運動感測器 Serial.println("Device error"); } else { Serial.println("aX,aY,aZ,gX,gY,gZ"); } } void loop() { // 無限迴圈 // 等待取得足夠數量樣本 while (samplesRead == numSamples) { // 讀取加速度計值 aX = myIMU.readFloatAccelX(); aY = myIMU.readFloatAccelY(); aZ = myIMU.readFloatAccelZ(); // 求得加速度值總合 float aSum = fabs(aX) + fabs(aY) + fabs(aZ); // 檢查是否超過門檻值,若是重置已讀樣本數量 if (aSum >= accelerationThreshold) { samplesRead = 0; break; } } // 檢查自上次檢測到顯著運動以來是否已讀取所有必需的樣本 while (samplesRead < numSamples) { samplesRead++; // 已讀取樣本數加1 // print the data in CSV format Serial.print(myIMU.readFloatAccelX(), 3); Serial.print(','); Serial.print(myIMU.readFloatAccelY(), 3); Serial.print(','); Serial.print(myIMU.readFloatAccelZ(), 3); Serial.print(','); Serial.print(myIMU.readFloatGyroX(), 3); Serial.print(','); Serial.print(myIMU.readFloatGyroY(), 3); Serial.print(','); Serial.print(myIMU.readFloatGyroZ(), 3); Serial.println(); // 若已讀樣本數已足夠則列印換行 if (samplesRead == numSamples) { Serial.println(); } } } ``` 5. 點選快捷鍵列的**上傳鍵(右箭頭符號)** 完成編譯上傳。 6. 點選選單 Tools > Serial Monitor 監看串列埠輸出字串,亦可點選 Tools > Serial Plotter 以圖形介面方式監看序列埠。 ## 學習資源 1. 歐尼克斯實境互動工作室,TinyML(MCU AI)系列發文 https://hackmd.io/@OmniXRI-Jack/series_articles#TinyMLMCU-AI%E7%B3%BB%E5%88%97 2. CAVEDU教育團隊技術部落格,TinyML https://blog.cavedu.com/?s=tinyml 3. 【iCShop開箱趣】ep7 Seeed Studio XIAO nRF52840 Sense Review | 把神經網路放到MCU原來這麼簡單? TinyML Tutorial 範例教學 https://youtu.be/Faka_ahto0o 4. 林士允(Felix Lin), 【Maker 玩 AI】 XIAO nRF52840 Sense-入門 TinyML 就靠它! https://vmaker.tw/archives/65534 ## 參考文獻 1. Seeed, Getting Started with Seeed Studio XIAO nRF52840 (Sense) https://wiki.seeedstudio.com/XIAO_BLE/ 2. Seeed, Expansion Board Base for XIAO https://wiki.seeedstudio.com/Seeeduino-XIAO-Expansion-Board/ 3. Seeed XIAO BLE nRF52840 Sense Speech Recognition Powered by Edge Impulse https://youtu.be/Ss8L94170B0 4. 許哲豪(史蒂芬周), tinyML這個球不是這麼踢滴系列 https://ithelp.ithome.com.tw/users/20141396/ironman/5860 --- ###### tags: `XIAO` `Edge AI`