Try   HackMD

南開科大 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 會自動產生下列程式碼
// 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 }
  1. 點選快捷鍵列的上傳鍵(右箭頭符號),此時程式就會開始編譯,完成後會自動上傳到開發板上。如果看到開發板上紅色LED以1秒亮1秒暗,即完成測試。
  2. 若無法上傳,快按開發板上RESET鍵二次,再重新選擇開發板及埠號,重新上傳即可。
  3. 以上程式 LED_BUILTIN (等同於LED_RED)可試著修改成其它顏色LED(紅色LED_RED, 綠色LED_GREEN, 藍色LED_BLUE),或修改延遲時間長度。

測試擴展板按鍵

  1. 點選選單 File > Examples > 02.Digital > Button 會自動產生下列程式碼
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 } }
  1. 修改使用者按鍵的接腳為D1,將 buttonPin = 2; 改成 buttonPin = D1;
  2. 修改輸入腳型式,將 INPUT 改成 INPUT_PULLUP
  3. 點擊「上傳」鍵編譯並上傳,當按下鍵時點亮LED,放開時LED熄滅。

測試擴展板蜂鳴器

以DIO方式驅動

結合LED閃爍及使用者按鍵程式範例,當按下按鍵時,令蜂鳴器產生1Khz頻率(500us ON + 500us OFF)。

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頻率。

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依此類推。

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!」
#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)範例。
#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(); } } }
  1. 點選快捷鍵列的上傳鍵(右箭頭符號) 完成編譯上傳。
  2. 點選選單 Tools > Serial Monitor 監看串列埠輸出字串,亦可點選 Tools > Serial Plotter 以圖形介面方式監看序列埠。

學習資源

  1. 歐尼克斯實境互動工作室,TinyML(MCU AI)系列發文
    https://hackmd.io/@OmniXRI-Jack/series_articles#TinyMLMCU-AI系列
  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