盒仔机器人_DFROBOT SEN0240 肌电传感器 OYMotion 产品资料 使用教程
簡介
這是由DFRobot與OYMotion合作推出的一款肌電傳感器模塊。本傳感器模塊通過檢測人體的表面肌電信號(sEMG),進而反應出人體肌肉和神經的活動情況。
本傳感器模塊集成了濾波、放大電路,將范圍在±1.5mV內的微弱人體表面肌電信號進行1000倍放大,并通過差分輸入、模擬濾波電路的方式對噪音(特別是工頻干擾)進行有效抑制。輸出信號為模擬量形式,以1.5V為基準電壓,0~3.0V量程的輸出。輸出信號的大小取決于選定肌肉的活動量,輸出信號的波形可顯著指示被觀察位置皮下肌肉的情況,方便做肌電信號的分析與研究,如使用Arduino作為控制器檢測肌肉活動情況,如肌肉是否緊繃,強度如何,是否疲勞等。
本產品是一種主動感應傳感器,能提供高質量的信號搜集,且易于使用。不論是被用到靜態還是動態的應用領域,僅需要一些極為簡單的準備工作即可。本產品使用干電極,無須導電凝膠也可得到良好的信號質量,因此具有壽命長、使用簡單方便等特點,更適合普通用戶。而采用凝膠探頭的醫用電極通常為一次性,使用起來較為麻煩。
本產品的測量具有非侵入性、無創傷、操作簡單等優點,可用于人機交互等相關應用。雖然測量肌肉活動歷來被用于醫學研究,然而隨著不斷縮小但功能更強大的微控制器和集成電路的完善,肌電圖電路和傳感器也逐漸被應用于各種控制系統。
供電電壓在3.3~5.5V之間,供電電流不小于20mA,紋波與其他噪音要小。推薦使用經過穩壓的直流電壓。
肌電信號的有效頻譜范圍為20Hz~500Hz,推薦采用分辨率不低于8bit、有效采樣頻率不低于1KHz的模數轉換器(ADC)進行采樣與數字化,以保留盡量多的原始信息。
采用配套的金屬干電極板,需將電極板保持和肌肉方向一致。
本品并非專業醫療儀器,不能作為輔助配件參與診斷和治療。
技術規格
信號處理板供電電壓:+3.3V~5.5V
工作電壓:+3.0V
檢測范圍:+/-1.5mV
電極接口:PJ-342
模塊接口:PH2.0-3P
輸出范圍:0~3.0V
工作溫度:0~50℃
板子尺寸:22 * 35 mm
干電極板電極接口:PJ-342
電極線長:50cm
板子尺寸:22 * 35 mm
重量:36g
引腳說明
肌電傳感器信號處理板管腳定義
標號
名稱
功能描述
1
A
模擬信號輸出端(0~3.0V)
2
+
電源輸入正極(3.3~5.5V)
3
-
電源輸入負極
4
PJ-342
電極連線接口
肌電傳感器信號處理板管腳定義
使用教程
本教程將演示如何使用這款肌電傳感器,通過Arduino IDE的Serial Plotter打印出肌電波形。
準備
硬件1 x Arduino UNO控制板(或類似)
1 x 肌電傳感器信號處理板
1 x 肌電傳感器干電極
1 x 干電極連接線
1 x 3P模擬信號線
若干 杜邦線
軟件Arduino IDE(推薦1.8.2及以上), 點擊下載Arduino IDE
接線圖
樣例代碼
本樣例代碼需要EMGFilters庫文件,請先下載庫文件后并安裝。
如何安裝庫?
/*
* Copyright 2017, OYMotion Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*/
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "EMGFilters.h"
#define TIMING_DEBUG 1
#define SensorInputPin A0 // input pin number
EMGFilters myFilter;
// discrete filters must works with fixed sample frequence
// our emg filter only support "SAMPLE_FREQ_500HZ" or "SAMPLE_FREQ_1000HZ"
// other sampleRate inputs will bypass all the EMG_FILTER
int sampleRate = SAMPLE_FREQ_1000HZ;
// For countries where power transmission is at 50 Hz
// For countries where power transmission is at 60 Hz, need to change to
// "NOTCH_FREQ_60HZ"
// our emg filter only support 50Hz and 60Hz input
// other inputs will bypass all the EMG_FILTER
int humFreq = NOTCH_FREQ_50HZ;
// Calibration:
// put on the sensors, and release your muscles;
// wait a few seconds, and select the max value as the threshold;
// any value under threshold will be set to zero
static int Threshold = 0;
unsigned long timeStamp;
unsigned long timeBudget;
void setup() {
/* add setup code here */
myFilter.init(sampleRate, humFreq, true, true, true);
// open serial
Serial.begin(115200);
// setup for time cost measure
// using micros()
timeBudget = 1e6 / sampleRate;
// micros will overflow and auto return to zero every 70 minutes
}
void loop() {
/* add main program code here */
// In order to make sure the ADC sample frequence on arduino,
// the time cost should be measured each loop
/*------------start here-------------------*/
timeStamp = micros();
int Value = analogRead(SensorInputPin);
// filter processing
int DataAfterFilter = myFilter.update(Value);
int envlope = sq(DataAfterFilter);
// any value under threshold will be set to zero
envlope = (envlope > Threshold) ? envlope : 0;
timeStamp = micros() - timeStamp;
if (TIMING_DEBUG) {
// Serial.print("Read Data: "); Serial.println(Value);
// Serial.print("Filtered Data: ");Serial.println(DataAfterFilter);
Serial.print("Squared Data: ");
Serial.println(envlope);
// Serial.print("Filters cost time: "); Serial.println(timeStamp);
// the filter cost average around 520 us
}
/*------------end here---------------------*/
// if less than timeBudget, then you still have (timeBudget - timeStamp) to
// do your work
delayMicroseconds(500);
// if more than timeBudget, the sample rate need to reduce to
// SAMPLE_FREQ_500HZ
}
校準
推薦每次使用時都校準一次,因為即使是同一個人,不同位置的肌電信號也是不同的。
1. 將樣例代碼中的Threshold變量改成0,即:static int Threshold = 0;
2. 上傳樣例代碼至arduino控制板中,然后打開arduino IDE的串口監視器,觀察打印的數值。
3. 放松手臂上的肌肉,觀察串口打印的數值。身心平靜,讓肌肉放松一會,觀察串口監視器打印的最大數值,并記錄之。如果數值太大,比如1000以上,可嘗試微調干電極的放置位置。
4. 將樣例代碼中的Threshold變量改成剛才記錄的最大數值,重新上傳樣例代碼至arduino主控板。5. 打開arduino IDE的Serial Plotter,即可看到肌電波形。一般情況下,肌肉放松時,是一條值始終為0的直線,如下圖所示。如偶爾有幾個尖峰波形出現,也屬正常現象。
用力握拳的過程中,可看到明顯的肌電波形,如下圖所示。
基礎應用演示
本應用通過對握拳次數進行計數的演示,來說明如何識別是否有肌電信號產生。識別是否有肌電信號,是對肌肉活動進行計數,可用于俯臥撐計數、啞鈴計數等場合,也可用于人機交互,如用握拳產生的肌電信號玩Flappy Bird游戲等。
本應用使用的硬件連接、傳感器位置放置可參考本維庫中第四章的“4.1 準備”與“4.2 接線圖”。
本樣例代碼需要EMGFilters庫文件,如還沒有下載,請先下載庫文件后并安裝。
如何安裝庫?
/*
Copyright 2017, OYMotion Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "EMGFilters.h"
#define SensorInputPin A0 //sensor input pin number
/*
Define the `threshold` variable as 0 to calibrate the baseline value of input sEMG signals first.
After wiring the sEMG sensors to the Arduino board, wear the sEMG sensors. Relax your muscles for a few seconds,
you will be able to see a series of squared sEMG signals values get printed on your serial terminal.
Choose the maximal one as the baseline by setting the `threshold` variable. Then rebuild this project.
The `envelope`, which is the squared sEMG signal data, will be printed to the serial line.
The developer can plot it using the Arduino SerialPlotter.
Note:
After calibration, Any squared value of sEMG sigal below the baseline will be treated as zero.
It is recommended that you do calibration every time you wear the sEMG sensor.
*/
unsigned long threshold = 0; // threshold: Relaxed baseline values.(threshold=0:in the calibration process)
unsigned long EMG_num = 0; // EMG_num: The number of statistical signals
EMGFilters myFilter;
/*
Set the input frequency.
The filters work only with fixed sample frequency of
`SAMPLE_FREQ_500HZ` or `SAMPLE_FREQ_1000HZ`.
Inputs at other sample rates will bypass
*/
SAMPLE_FREQUENCY sampleRate = SAMPLE_FREQ_500HZ;
/*
Set the frequency of power line hum to filter out.
For countries with 60Hz power line, change to "NOTCH_FREQ_60HZ"
*/
NOTCH_FREQUENCY humFreq = NOTCH_FREQ_50HZ;
void setup()
{
myFilter.init(sampleRate, humFreq, true, true, true);
Serial.begin(115200);
}
void loop()
{
int data = analogRead(SensorInputPin);
int dataAfterFilter = myFilter.update(data); // filter processing
int envelope = sq(dataAfterFilter); //Get envelope by squaring the input
envelope = (envelope > threshold) ? envelope : 0; // The data set below the base value is set to 0, indicating that it is in a relaxed state
/* if threshold=0,explain the status it is in the calibration process,the code bollow not run.
if get EMG singal,number++ and print
*/
if (threshold > 0)
{
if (getEMGCount(envelope))
{
EMG_num++;
Serial.print("EMG_num: ");
Serial.println(EMG_num);
}
}
else {
Serial.println(envelope);
}
delayMicroseconds(500);
}
/*
if get EMG signal,return 1;
*/
int getEMGCount(int gforce_envelope)
{
static long integralData = 0;
static long integralDataEve = 0;
static bool remainFlag = false;
static unsigned long timeMillis = 0;
static unsigned long timeBeginzero = 0;
static long fistNum = 0;
static int TimeStandard = 200;
/*
The integral is processed to continuously add the signal value
and compare the integral value of the previous sampling to determine whether the signal is continuous
*/
integralDataEve = integralData;
integralData += gforce_envelope;
/*
If the integral is constant, and it doesn't equal 0, then the time is recorded;
If the value of the integral starts to change again, the remainflag is true, and the time record will be re-entered next time
*/
if ((integralDataEve == integralData) && (integralDataEve != 0))
{
timeMillis = millis();
if (remainFlag)
{
timeBeginzero = timeMillis;
remainFlag = false;
return 0;
}
/* If the integral value exceeds 200 ms, the integral value is clear 0,return that get EMG signal */
if ((timeMillis - timeBeginzero) > TimeStandard)
{
integralDataEve = integralData = 0;
return 1;
}
return 0;
}
else {
remainFlag = true;
return 0;
}
}
推薦每次使用時都校準一次,因為即使是同一個人,不同位置的肌電信號也是不同的。
1. 本代碼中,threshold變量的值默認為0,表示處于校準模式。改成非零值,則退出校準模式。因此,如要重新進行校準,將代碼中的threshold變量改成0即可,即:unsigned long threshold = 0;
2. 上傳代碼至arduino控制板中,然后打開arduino IDE的Serial Plotter,觀察y軸數值的最大值。
3. 輕輕的握緊拳頭,再輕輕的松開拳頭,如此循環。觀察Serial Plotter中y軸出現的最大值并記錄之。將如下圖,最大值為400左右。
4. 將代碼中的threshold變量改成剛才記錄的最大數值。推薦改成:最大值+100,提升抗干擾能力。重新上傳樣例代碼至arduino主控板。
5. 打開arduino IDE的Serial Monitor,用力握拳并松開一次,即可看到打印出的計數。輕輕的握拳是不會計數的。用力緊握拳不放,計數也不會累加,必須握緊后并松開才能計數。通過這種方式,就實現了對握拳進行精確計數。
如發現松拳時,計數多次累加,則是閥值設置的較低,引起誤判。可將代碼中的threshold變量值再加100,重新上傳樣例代碼至arduino主控板,再次查看效果,直到把threshold變量加到滿意效果為止。
將傳感器放置在需要檢測肌肉活動的位置,再進行校準,就可對肌肉活動進行精確計數,如用于俯臥撐計數、啞鈴計數等健身場合,也可用于人機交互,如用握拳產生的肌電信號玩Flappy Bird游戲等。
除了這個基礎功能,該傳感器也能通過判斷每次信號的強度來檢測肌肉活動強度。更多應用,請參考本維庫下方的“更多資料”。
常見問題
Q1. 手臂上什么地方可以放置干電極?有什么要求嗎?
A. 一般來說,采用配套的三金屬干電極板,無需關注參考電平,只需將電極板保持和肌肉方向一致即可。放置位置可參考下圖:
更多問題及有趣的應用,可以 訪問論壇 進行查閱或發帖。
更多資料
總結
以上是生活随笔為你收集整理的盒仔机器人_DFROBOT SEN0240 肌电传感器 OYMotion 产品资料 使用教程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅谈管理数据平台的一些想法
- 下一篇: 【机器学习】 关联规则Apriori和m