# 南開科大 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`