電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>電子資料>使用EMG的機(jī)械手控制

使用EMG的機(jī)械手控制

2022-11-07 | zip | 0.07 MB | 次下載 | 2積分

資料介紹

描述

我們的團(tuán)隊(duì)在機(jī)器人手方面有著悠久的歷史。有一段時(shí)間我們?cè)噲D制作一個(gè)可靠的假手,但對(duì)于這個(gè)項(xiàng)目,我使用了現(xiàn)有開源手的一個(gè)很好的例子:inMoov 。

我不會(huì)詳細(xì)介紹手動(dòng)組裝 - 在項(xiàng)目網(wǎng)站上對(duì)此進(jìn)行了很好的描述,并且非常復(fù)雜。我將在這里專注于控制,因?yàn)檫@是全新的 :)
另外,在下一個(gè)項(xiàng)目中查看這項(xiàng)技術(shù)如何隨著時(shí)間的推移而發(fā)展

1.信號(hào)處理

控制基于 EMG - 肌肉的電活動(dòng)。EMG 信號(hào)由三個(gè) uECG 設(shè)備獲得(我知道,它應(yīng)該是 ECG 監(jiān)視器,但由于它基于通用 ADC,它可以測(cè)量任何生物信號(hào) - 包括 EMG)。對(duì)于 EMG 處理,uECG 有一個(gè)特殊的模式,它發(fā)出 32 段頻譜數(shù)據(jù)和“肌肉窗口”平均值(平均頻譜強(qiáng)度在 75 和 440 Hz 之間)。光譜圖像如下所示:

?
pYYBAGNkdPqAYcO_AAEoqq6LtHs787.png
?

這里的頻率在垂直軸上(在 3 個(gè)圖的每一個(gè)上,底部的低頻,頂部的高頻率 - 從 0 到 488 Hz,步長(zhǎng)約為 15 Hz),時(shí)間在水平軸上(左側(cè)的舊數(shù)據(jù)總體在這里屏幕上大約 10 秒)。強(qiáng)度用顏色編碼:藍(lán)色 - 低,綠色 - 中,黃色 - 高,紅色 - 甚至更高。為了可靠的手勢(shì)識(shí)別,需要對(duì)這些圖像進(jìn)行適當(dāng)?shù)?PC 處理。但是對(duì)于機(jī)器人手指的簡(jiǎn)單激活,僅使用 3 個(gè)通道上的平均值就足夠了 - uECG 可以方便地在某些數(shù)據(jù)包字節(jié)處提供它,以便 Arduino 草圖可以解析它。這些值看起來(lái)要簡(jiǎn)單得多:

?
pYYBAGNkdP2AAC8VAABg2rR0G6M637.png
?

當(dāng)我相應(yīng)地?cái)D壓拇指、無(wú)名指和中指時(shí),紅色、綠色、藍(lán)色圖表是來(lái)自不同肌肉群的 uECG 設(shè)備的原始值。在我們看來(lái),這些情況顯然是不同的,但我們需要以某種方式將這些值轉(zhuǎn)換為“手指分?jǐn)?shù)”,以便程序可以將值輸出到手動(dòng)伺服系統(tǒng)。問題是,來(lái)自肌肉群的信號(hào)是“混合的”:在第一種和第三種情況下,藍(lán)色信號(hào)強(qiáng)度大致相同 - 但紅色和綠色不同。在第 2 和第 3 種情況下,綠色信號(hào)是相同的 - 但藍(lán)色和紅色是不同的。為了“解開”它們,我使用了一個(gè)相對(duì)簡(jiǎn)單的公式:

S0=V0^2 / ((V1 *a0 +b0)(V2 * c0+d0))

其中 S0 - 通道 0、V0、V1、V2 的得分 - 通道 0、1、2 和 a、b、c、d 的原始值 - 我手動(dòng)調(diào)整的系數(shù)(a 和 c 從 0.3 到 2.0,b 和d 分別為 15 和 20,無(wú)論如何您都需要更改它們以適應(yīng)您的特定傳感器位置)。為通道 1 和 2 計(jì)算了相同的分?jǐn)?shù)。在此之后,圖表變得幾乎完全分離:

?
poYBAGNkdQCAa3dpAABQFQpQbQs363.png
?

對(duì)于相同的手勢(shì)(這次是無(wú)名指、中指和拇指),信號(hào)很清晰,只需與閾值比較即可輕松轉(zhuǎn)換為伺服運(yùn)動(dòng)。

2. 原理圖

?
poYBAGNkdQOAA9RNAAETk8qAb6Y619.png
?

原理圖非常簡(jiǎn)單,您只需要 nRF24 模塊、PCA9685 或類似的 I2C PWM 控制器,以及足以同時(shí)移動(dòng)所有這些舵機(jī)的高安培 5V 電源(因此它需要至少 5A 的額定功率才能穩(wěn)定運(yùn)行)。

連接列表:
nRF24 pin 1 (GND) - Arduino 的 GND
nRF24 pin 2 (Vcc) - Arduino 的 3.3v
nRF24 pin 3 (Chip Enable) - Arduino's D9
nRF24 pin 4 (SPI:CS) - Arduino's D8
nRF24 pin 5 (SPI: SCK) - Arduino 的 D13
nRF24 引腳 6 (SPI:MOSI) - Arduino 的 D11
nRF24 引腳 7 (SPI:MISO) - Arduino 的 D12
PCA9685 SDA - Arduino 的 A4
PCA9685 SCL - Arduino 的 A5
PCA9685 Vcc - Arduino 的 5v
PCA9685 GND - Arduino 的 GND
PCA9685 V+ -高放大器 5V
PCA9685 GND - 高放大器 GND
手指伺服:到 PCA 通道 0-4,在我的符號(hào)中拇指 - 通道 0,食指 - 通道 1 等。

3. EMG 傳感器放置

為了獲得合理的讀數(shù),將記錄肌肉活動(dòng)的 uECG 設(shè)備放置在正確的位置非常重要。雖然這里有許多不同的選項(xiàng),但每個(gè)選項(xiàng)都需要不同的信號(hào)處理方法 - 所以我分享我用過的東西:

?
pYYBAGNkdQqAM3HtAAqxomsPJeU308.jpg
?

這可能違反直覺,但拇指肌肉信號(hào)在手臂的另一側(cè)更明顯,因此將其中一個(gè)傳感器放置在那里,并且所有傳感器都放置在靠近肘部的位置(肌肉的大部分身體都在那個(gè)區(qū)域,但是您想檢查您的確切位置-個(gè)體差異很大)

4. 代碼

在運(yùn)行主程序之前,您需要找出特定 uECG 設(shè)備的單元 ID(通過取消注釋第 101 行并逐個(gè)打開設(shè)備來(lái)完成)并將它們填充到 unit_ids 數(shù)組中(第 37 行)。

#include 
#include 24.h>
#include 
#include 01.h>
#include 
#include 
#define SERVOMIN  150 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  600 // this is the 'maximum' pulse length count (out of 4096)
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
int rf_cen = 9; //nRF24 chip enable pin
int rf_cs = 8; //nRF24 CS pin
RF24 rf(rf_cen, rf_cs);
//pipe address - hardcoded on uECG side
uint8_t pipe_rx[8] = {0x0E, 0xE6, 0x0D, 0xA7, 0, 0, 0, 0};
uint8_t  swapbits(uint8_t a){ //uECG pipe address uses swapped bits order
// reverse the bit order in a single byte
uint8_t v = 0;
if(a & 0x80) v |= 0x01;
if(a & 0x40) v |= 0x02;
if(a & 0x20) v |= 0x04;
if(a & 0x10) v |= 0x08;
if(a & 0x08) v |= 0x10;
if(a & 0x04) v |= 0x20;
if(a & 0x02) v |= 0x40;
if(a & 0x01) v |= 0x80;
return v;
}
long last_servo_upd = 0; //time when we last updated servo values - don't want to do this too often
byte in_pack[32]; //array for incoming RF packet
unsigned long unit_ids[3] = {4294963881, 4294943100, 28358}; //array of known uECG IDs - need to fill with your own unit IDs
int unit_vals[3] = {0, 0, 0}; //array of uECG values with these IDs
float tgt_angles[5]; //target angles for 5 fingers
float cur_angles[5]; //current angles for 5 fingers
float angle_open = 30; //angle that corresponds to open finger
float angle_closed = 150; //angle that corresponds to closed finger
void setup() {
//nRF24 requires relatively slow SPI, probably would work at 2MHz too
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
for(int x = 0; x < 8; x++) //nRF24 and uECG have different bit order for pipe address
pipe_rx[x] = swapbits(pipe_rx[x]);
//configure radio parameters
rf.begin();
rf.setDataRate(RF24_1MBPS);
rf.setAddressWidth(4);
rf.setChannel(22);
rf.setRetries(0, 0);
rf.setAutoAck(0);
rf.disableDynamicPayloads();
rf.setPayloadSize(32);
rf.openReadingPipe(0, pipe_rx);
rf.setCRCLength(RF24_CRC_DISABLED);
rf.disableCRC();
rf.startListening(); //listen for uECG data
//Note that uECG should be switched into raw data mode (via long button press)
//in order to send compatible packets, by default it sends data in BLE mode
//which cannot be received by nRF24
Serial.begin(115200); //serial output - very useful for debugging
pwm.begin(); //start PWM driver
pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates
for(int i = 0; i < 5; i++) //set initial finger positions
{
tgt_angles[i] = angle_open;
cur_angles[i] = angle_open;
}
}
void setAngle(int n, float angle){ //sends out angle value for given channel
pwm.setPWM(n, 0, SERVOMIN + angle * 0.005556 * (SERVOMAX - SERVOMIN));
}
float angle_speed = 15; //how fast fingers would move
float v0 = 0, v1 = 0, v2 = 0; //filtered muscle activity values per 3 channels
void loop()
{
if(rf.available())
{
rf.read(in_pack, 32); //processing packet
byte u1 = in_pack[3];//32-bit unit ID, unique for every uECG device
byte u2 = in_pack[4];
byte u3 = in_pack[5];
byte u4 = in_pack[6];
unsigned long id = (u1<<24) | (u2<<16) | (u3<<8) | u4;
//Serial.println(id); //uncomment this line to make list of your uECG IDs
if(in_pack[7] != 32) id = 0; //wrong pack type: in EMG mode this byte must be 32
int val = in_pack[10]; //muscle activity value
if(val != in_pack[11]) id = 0; //value is duplicated in 2 bytes because RF noise can corrupt packet, and we don't have CRC with nRF24
//find which ID corresponds to current ID and fill value
for(int n = 0; n < 3; n++)
if(id == unit_ids[n])
unit_vals[n] = val;
}
long ms = millis();
if(ms - last_servo_upd > 20) //don't update servos too often
{
last_servo_upd = ms;
for(int n = 0; n < 5; n++) //go through fingers, if target and current angles don't match - adjust them
{
if(cur_angles[n] < tgt_angles[n] - angle_speed/2) cur_angles[n] += angle_speed;
if(cur_angles[n] > tgt_angles[n] + angle_speed/2) cur_angles[n] -= angle_speed;
}
for(int n = 0; n < 5; n++) //apply angles to fingers
setAngle(n, cur_angles[n]);
//exponential averaging: prevents single peaks from affecting finger state
v0 = v0*0.7 + 0.3*(float)unit_vals[0];
v1 = v1*0.7 + 0.3*(float)unit_vals[1];
v2 = v2*0.7 + 0.3*(float)unit_vals[2];
//calcualting scores from raw values
float scor0 = 4.0*v0*v0/((v1*0.3 + 20)*(v2*1.3 + 15));
float scor1 = 4.0*v1*v1/((v0*2.0 + 20)*(v2*2.0 + 20));
float scor2 = 4.0*v2*v2/((v0*1.2 + 20)*(v1*0.5 + 15));
//print scores for debugging
Serial.print(scor0);
Serial.print(' ');
Serial.print(scor1);
Serial.print(' ');
Serial.println(scor2);
//compare each score with threshold and change finger states correspondingly
if(scor2 < 0.5) //weak signal - open finger
tgt_angles[0] = angle_open;
if(scor2 > 1.0) //strong signal - close finger
tgt_angles[0] = angle_closed;
if(scor1 < 0.5)
{
tgt_angles[1] = angle_open;
tgt_angles[2] = angle_open;
}
if(scor1 > 1.0)
{
tgt_angles[1] = angle_closed;
tgt_angles[2] = angle_closed;
}
if(scor0 < 0.5)
{
tgt_angles[3] = angle_open;
tgt_angles[4] = angle_open;
}
if(scor0 > 1.0)
{
tgt_angles[3] = angle_closed;
tgt_angles[4] = angle_closed;
}
}
}

5. 結(jié)果

通過一些大約 2 小時(shí)的實(shí)驗(yàn),我能夠獲得相當(dāng)可靠的運(yùn)行(視頻顯示了一個(gè)典型案例):

?

它的行為并不完美,通過這種處理只能識(shí)別張開和閉合的手指(甚至不能識(shí)別 5 個(gè)手指中的每一個(gè),它只檢測(cè)到 3 個(gè)肌肉群:拇指、食指和中指,無(wú)名指和小指)。但是分析信號(hào)的“AI”在這里需要 3 行代碼,并使用來(lái)自每個(gè)通道的單個(gè)值。我相信可以通過在 PC 或智能手機(jī)上分析 32-bin 光譜圖像來(lái)完成更多工作。此外,此版本僅使用 3 個(gè)uECG設(shè)備(EMG 通道)。有了更多的通道,應(yīng)該可以識(shí)別真正復(fù)雜的模式——但是,這就是項(xiàng)目的重點(diǎn),為任何有興趣的人提供一些起點(diǎn):) 手控絕對(duì)不是這種系統(tǒng)的唯一應(yīng)用。


下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評(píng)論

查看更多

下載排行

本周

  1. 1華為硬件工程師手冊(cè)目前最全版本
  2. 1.02 MB   |  7次下載  |  2 積分
  3. 2STM32單片機(jī)無(wú)人機(jī)設(shè)計(jì)
  4. 8.81 MB   |  2次下載  |  免費(fèi)
  5. 3TTL通往RS232神奇之黑盒(一)(可下載)
  6. 515.72 KB  |  2次下載  |  免費(fèi)
  7. 4TP4336 線性充電,同步升壓1A 同步移動(dòng)電源解決方案
  8. 764.17 KB  |  1次下載  |  免費(fèi)
  9. 5直流有刷電機(jī)驅(qū)動(dòng)PCB設(shè)計(jì)注意事項(xiàng)講解(可下載)
  10. 1.01 MB  |  1次下載  |  免費(fèi)
  11. 6晶體諧振器的工作原理
  12. 736.44 KB  |  1次下載  |  免費(fèi)
  13. 7LLC的死區(qū)時(shí)間對(duì)DS波形的影響(可下載)
  14. 675.86 KB  |  1次下載  |  免費(fèi)
  15. 8電子產(chǎn)品設(shè)計(jì)與調(diào)試
  16. 14.66 MB   |  次下載  |  8 積分

本月

  1. 1STM32CubeMX用于STM32配置和初始化C代碼生成
  2. 21.90 MB   |  631次下載  |  免費(fèi)
  3. 2STM32開發(fā)板教程之STM32開發(fā)指南免費(fèi)下載
  4. 24.88 MB   |  176次下載  |  3 積分
  5. 3EN60335-1安規(guī)標(biāo)準(zhǔn) 中文版本
  6. 1.86 MB   |  53次下載  |  1 積分
  7. 4OAH0428最新規(guī)格書(中文)
  8. 2.52 MB   |  28次下載  |  10 積分
  9. 5UHV系列雷電沖擊電壓發(fā)生器試驗(yàn)裝置詳細(xì)說明使用
  10. 1.07 MB   |  17次下載  |  免費(fèi)
  11. 6介紹一些常用的電子元器件
  12. 3.20 MB   |  8次下載  |  免費(fèi)
  13. 7麻將機(jī)升降電路
  14. 0.12 MB   |  7次下載  |  1 積分
  15. 8華為硬件工程師手冊(cè)目前最全版本
  16. 1.02 MB   |  7次下載  |  2 積分

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935124次下載  |  10 積分
  3. 2開源硬件-PMP21529.1-4 開關(guān)降壓/升壓雙向直流/直流轉(zhuǎn)換器 PCB layout 設(shè)計(jì)
  4. 1.48MB  |  420063次下載  |  10 積分
  5. 3Altium DXP2002下載入口
  6. 未知  |  233088次下載  |  10 積分
  7. 4電路仿真軟件multisim 10.0免費(fèi)下載
  8. 340992  |  191371次下載  |  10 積分
  9. 5十天學(xué)會(huì)AVR單片機(jī)與C語(yǔ)言視頻教程 下載
  10. 158M  |  183336次下載  |  10 積分
  11. 6labview8.5下載
  12. 未知  |  81583次下載  |  10 積分
  13. 7Keil工具M(jìn)DK-Arm免費(fèi)下載
  14. 0.02 MB  |  73814次下載  |  10 積分
  15. 8LabVIEW 8.6下載
  16. 未知  |  65988次下載  |  10 積分