37款傳感器與執行器的提法,在網絡上廣泛流傳,其實Arduino能夠兼容的傳感器模塊肯定是不止這37種的。鑑於本人手頭積累了一些傳感器和執行器模塊,依照實踐出真知(一定要動手做)的理念,以學習和交流爲目的,這裏準備逐一動手嘗試系列實驗,不管成功(程序走通)與否,都會記錄下來—小小的進步或是搞不掂的問題,希望能夠拋磚引玉。
【Arduino】168種傳感器模塊系列實驗(資料代碼+仿真編程+圖形編程)
實驗一百:MAX30102血氧儀手腕心率脈搏檢測心跳傳感器模塊
實驗接線示意圖
硬件連接(MAX30102 到 Arduino):
-5V = 5V(允許 3.3V)
-接地 = 接地
-SDA = A4(或 SDA)
-SCL = A5(或 SCL)
-INT = 中斷腳未連接
MAX30102心率血氧傳感器模塊使用注意事項:
1、手指直接按壓可能會出現壓力變化,壓力變化會對傳感器數值產生影響。
2、佩戴部位爲手指,佩戴沒有方向區別。
3、本模塊並非專業醫療儀器,不能作爲輔助配件參與診斷和治療。
程序五:在 Arduino 的串口繪圖器上顯示用戶的心跳
Arduino參考開源代碼
/* 【Arduino】168種傳感器模塊系列實驗(資料代碼+仿真編程+圖形編程) 程序五:在 Arduino 的串口繪圖器上顯示用戶的心跳 下載庫: http://librarymanager/All#SparkFun_MAX30105 */ #include <Wire.h> #include "MAX30105.h" MAX30105 particleSensor; void setup() { Serial.begin(115200); Serial.println("正在初始化..."); // 初始化傳感器 if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //使用默認 I2C 端口,400kHz 速度 { Serial.println("沒有找到MAX30105,請檢查接線/電源。 "); while (1); } //設置以感應串口繪圖器上漂亮的曲線 byte ledBrightness = 0x1F; //亮度選項:0=關 到 255=50mA byte sampleAverage = 8; //樣本平均值選項:1、2、4、8、16、32 byte ledMode = 3; //工作方式選項:1 = 僅紅色,2 = 紅色 + IR,3 = 紅色 + IR + 綠色 int sampleRate = 100; //採樣率選項:50、100、200、400、800、1000、1600、3200 int pulseWidth = 411; //脈寬選項:69、118、215、411 int adcRange = 4096; //選項:2048、4096、8192、16384 //使用這些設置來配置傳感器 particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Arduino 繪圖儀令人討厭地自動縮放。爲了解決這個問題,預先填充 //繪圖儀的傳感器平均讀數爲 500 //在通電時取平均 IR 讀數 const byte avgAmount = 64; long baseValue = 0; for (byte x = 0 ; x < avgAmount ; x++) { baseValue += particleSensor.getIR(); //讀取IR值 } baseValue /= avgAmount; //預填充繪圖儀,使 Y 比例接近 IR 值 for (int x = 0 ; x < 500 ; x++) Serial.println(baseValue); } void loop() { Serial.println(particleSensor.getIR()); //將原始數據發送到繪圖器 delay(10); }
打開Arduino IDE——工具——串口繪圖器,查看實驗波形
實驗串口繪圖器返回情況
程序六:最簡輸出傳感器讀取的原始值(IR 和紅色讀數)
Arduino參考開源代碼
/* 【Arduino】168種傳感器模塊系列實驗(資料代碼+仿真編程+圖形編程) 程序六:最簡輸出傳感器讀取的原始值(IR 和紅色讀數) 下載庫: http://librarymanager/All#SparkFun_MAX30105 */ #include <Wire.h> #include "MAX30105.h"//導入驅動庫 MAX30105 particleSensor; void setup() { Serial.begin(9600);//初始化串口 Serial.println("MAX30102準備就緒"); // 初始化傳感器 if (particleSensor.begin() == false) { Serial.println("沒有找到MAX30102,請檢查接線/電源。"); while (1); } particleSensor.setup(); //配置傳感器,使用 6.4mA 進行 LED 驅動 } void loop() { Serial.print(" R[");//串口打印傳感器讀取的原始值 Serial.print(particleSensor.getRed()); Serial.print("] IR["); Serial.print(particleSensor.getIR()); Serial.println("]"); delay(1000); }
實驗串口返回情況
程序七:最簡繪製心率波形
Arduino參考開源代碼
/* 【Arduino】168種傳感器模塊系列實驗(資料代碼+仿真編程+圖形編程) 程序七:最簡繪製心率波形 下載庫: http://librarymanager/All#SparkFun_MAX30105 */ #include <Wire.h> #include "MAX30105.h"//導入驅動庫 MAX30105 particleSensor; void setup() { Serial.begin(9600);//初始化串口 Serial.println("MAX30102準備就緒"); // 初始化傳感器 if (particleSensor.begin() == false) { Serial.println("沒有找到MAX30102,請檢查接線/電源。"); while (1); } particleSensor.setup(); //配置傳感器,使用 6.4mA 進行 LED 驅動 } void loop() { Serial.print(particleSensor.getRed()); Serial.print(", "); Serial.println(particleSensor.getIR()); delay(6); }
打開Arduino IDE——工具——串口繪圖器,查看實驗波形
實驗串口繪圖器返回情況
在 Arduino IDE 中,選擇工具 > 串行繪圖儀。當您將手滑過傳感器時,您應該會看到類似於下圖的波浪。
程序八:以光學方式檢測心率的演示
說明:這種方法很棘手,容易給出錯誤的讀數。所以請不要將它用於實際的醫療診斷。
Arduino參考開源代碼
/* 【Arduino】168種傳感器模塊系列實驗(資料代碼+仿真編程+圖形編程) 程序八:以光學方式檢測心率的演示 說明:這種方法很棘手,容易給出錯誤的讀數。所以請不要將它用於實際的醫療診斷。 下載庫: http://librarymanager/All#SparkFun_MAX30105 */ #include <Wire.h> #include "MAX30105.h"//導入驅動庫 #include "heartRate.h" MAX30105 particleSensor; const byte RATE_SIZE = 4; //增加這個以獲得更多平均,4比較好。 byte rates[RATE_SIZE]; //心率數組 byte rateSpot = 0; long lastBeat = 0; //最後一個節拍發生的時間 float beatsPerMinute; int beatAvg; void setup() { Serial.begin(115200); Serial.println("Initializing..."); // 初始化傳感器 if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) { Serial.println("MAX30102 was not found. Please check wiring/power. "); while (1); } Serial.println("Place your index finger on the sensor with steady pressure."); particleSensor.setup(); //使用默認設置配置傳感器 particleSensor.setPulseAmplitudeRed(0x0A); //將紅色LED變爲低電平表示傳感器正在運行 particleSensor.setPulseAmplitudeGreen(0); //關閉綠色LED } void loop() { long irValue = particleSensor.getIR(); if (checkForBeat(irValue) == true) { //我們感覺到了節拍! long delta = millis() - lastBeat; lastBeat = millis(); beatsPerMinute = 60 / (delta / 1000.0); if (beatsPerMinute < 255 && beatsPerMinute > 20) { rates[rateSpot++] = (byte)beatsPerMinute; //將此讀數存儲在數組中 rateSpot %= RATE_SIZE; //包裝變量 //取讀數的平均值 beatAvg = 0; for (byte x = 0 ; x < RATE_SIZE ; x++) beatAvg += rates[x]; beatAvg /= RATE_SIZE; } } Serial.print("IR="); Serial.print(irValue); Serial.print(", BPM="); Serial.print(beatsPerMinute); Serial.print(", Avg BPM="); Serial.print(beatAvg); if (irValue < 50000) Serial.print(" No finger?"); Serial.println(); }
實驗串口返回情況
程序九:簡單測量血氧飽和度 (SpO2)
說明:將手指儘可能穩定地放在傳感器上,然後等待幾秒鐘以使讀數有意義。
Arduino參考開源代碼
/* 【Arduino】168種傳感器模塊系列實驗(資料代碼+仿真編程+圖形編程) 程序九:測量血氧飽和度 (SpO2) 說明:將手指儘可能穩定地放在傳感器上,然後等待幾秒鐘以使讀數有意義。 下載庫: http://librarymanager/All#SparkFun_MAX30105 */ #include <Wire.h> #include "MAX30105.h"//導入驅動庫 #include "spo2_algorithm.h" MAX30105 particleSensor; #define MAX_BRIGHTNESS 255 #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) //Arduino Uno 沒有足夠的 SRAM 來存儲 100 個 32 位格式的 IR LED 數據和紅色 LED 數據樣本 //爲了解決這個問題,採樣數據的16位MSB將被截斷。樣本變成 16 位數據。 uint16_t irBuffer[100]; //紅外LED傳感器數據 uint16_t redBuffer[100]; //紅色LED傳感器數據 #else uint32_t irBuffer[100]; //紅外LED傳感器數據 uint32_t redBuffer[100]; //紅色LED傳感器數據 #endif int32_t bufferLength; //數據長度 int32_t spo2; //SPO2值 int8_t validSPO2; //用於顯示 SPO2 計算是否有效的指標 int32_t heartRate; //心率值 int8_t validHeartRate; //顯示心率計算是否有效的指標 byte pulseLED = 11; //必須在PWM引腳上 byte readLED = 13; //每次讀取數據時閃爍 void setup() { Serial.begin(115200); // 以每秒 115200 位初始化串行通信 pinMode(pulseLED, OUTPUT); pinMode(readLED, OUTPUT); // 初始化傳感器 if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) // 使用默認 I2C 端口,400kHz 速度 { Serial.println(F("MAX30105 was not found. Please check wiring/power.")); while (1); } Serial.println(F("Attach sensor to finger with rubber band. Press any key to start conversion")); while (Serial.available() == 0) ; //等到用戶按下一個鍵 Serial.read(); byte ledBrightness = 60; //Options: 0=Off to 255=50mA byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32 byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200 int pulseWidth = 411; //Options: 69, 118, 215, 411 int adcRange = 4096; //Options: 2048, 4096, 8192, 16384 //使用這些設置配置傳感器 particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); } void loop() { bufferLength = 100; // 100 的緩衝區長度存儲以 25sps 運行的 4 秒樣本 //讀取前100個樣本,並確定信號範圍 for (byte i = 0 ; i < bufferLength ; i++) { while (particleSensor.available() == false) //我們有新數據嗎? particleSensor.check(); //檢查傳感器是否有新數據 redBuffer[i] = particleSensor.getRed(); irBuffer[i] = particleSensor.getIR(); particleSensor.nextSample(); //我們已經完成了這個樣本所以移動到下一個樣本 Serial.print(F("red=")); Serial.print(redBuffer[i], DEC); Serial.print(F(", ir=")); Serial.println(irBuffer[i], DEC); } //計算前 100 個樣本後的心率和 SpO2(前 4 秒樣本) maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate); //繼續從MAX30102採樣。每 1 秒計算一次心率和 SpO2 while (1) { //轉儲內存中的前25組樣本並將後75組樣本移到頂部 for (byte i = 25; i < 100; i++) { redBuffer[i - 25] = redBuffer[i]; irBuffer[i - 25] = irBuffer[i]; } //在計算心率之前取25組樣本 for (byte i = 75; i < 100; i++) { while (particleSensor.available() == false) //我們有新數據嗎? particleSensor.check(); //檢查傳感器是否有新數據 digitalWrite(readLED, !digitalRead(readLED)); //每次讀取數據時板載 LED 閃爍 redBuffer[i] = particleSensor.getRed(); irBuffer[i] = particleSensor.getIR(); particleSensor.nextSample(); // 我們已經完成了這個樣本所以移動到下一個樣本 //通過UART發送樣本和計算結果到終端程序 Serial.print(F("red=")); Serial.print(redBuffer[i], DEC); Serial.print(F(", ir=")); Serial.print(irBuffer[i], DEC); Serial.print(F(", HR=")); Serial.print(heartRate, DEC); Serial.print(F(", HRvalid=")); Serial.print(validHeartRate, DEC); Serial.print(F(", SPO2=")); Serial.print(spo2, DEC); Serial.print(F(", SPO2Valid=")); Serial.println(validSPO2, DEC); } //收集25個新樣本後重新計算HR和SP02 maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate); } }
實驗串口返回情況