0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何制作和控制一只仿生手

电子发烧友论坛 2025-04-15 11:52 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

这个项目介绍了如何制作和控制一只仿生手。作者最初受到Instagram上一个视频的启发,该视频展示了使用MPU6050传感器追踪手部动作并在屏幕上显示3D模型。作者决定将这个想法进一步发展,使用OpenCV来控制一只真实的仿生手。

0b4603de-19ad-11f0-9434-92fbcf53809c.png

大家好,在这篇教程中,我想和大家分享一下如何制作并控制一只自己的仿生手。这个想法源于我在无意中刷Instagram时,看到一段短视频:一个人通过MPU6050传感器来跟踪手部运动,并在屏幕上显示手的3D模型。因为我之前也使用过这个传感器,所以觉得这个我也能完成。我一直喜欢将编程与现实世界结合起来,于是我想,为什么不将这些测量数据传输到一个真实的仿生手上呢?后来我决定,使用OpenCV代替MPU6050会更加高效,部分原因也是我想借此机会学习另一种技能。

特别感谢Gaël Langevin,他在InMoov项目[1]中设计了这个手的模型,并慷慨地分享了出来。

效果展示


所需材料

InMoov手及前臂

  • 3D打印机
  • 焊接工具
  • 约1公斤的耗材(PETG 或 ABS 或 PLA)
  • 3米钓鱼线(能承重约20公斤)
  • 5根扩展弹簧(3/16″ x 1-3/4)
  • RTV硅胶 Ecoflex 00-10

螺丝、螺母和螺栓

  • 10个M2x4平头木螺丝
  • 10个M3x4mm平头螺丝
  • 4个M3x12mm平头木螺丝
  • 20个M3x12mm平头螺丝
  • 25个M3x16mm平头螺丝
  • 10个M3x20mm平头螺丝
  • 35个M3螺母

电子元件

  • 1块ESP32 38-pin 开发模块
  • 1根micro USB数据线
  • 5个线性霍尔传感器(49E)
  • 5个直径2.5mm x 1mm的磁盘磁铁
  • 1根16芯彩排线
  • 5个1k电阻
  • 5个2k电阻
  • 6个伺服电机(JX PDI-6225MG-300)
  • 1块定制PCB(可选)
  • 1个电源(理想情况下为6V或5V,功率约100W,因为每个伺服电机的电流可达3A)

步骤1:3D打印手部

0b5e7144-19ad-11f0-9434-92fbcf53809c.png

0b8f7c80-19ad-11f0-9434-92fbcf53809c.png

3D打印文件见文末。

0be4ea12-19ad-11f0-9434-92fbcf53809c.png

打印时,建议使用稍高的填充率(约30%),以提高部件的耐用性。关于材料,InMoov使用的是ABS,不过如果你没有稳定打印ABS的设备,PETG或PLA同样可以使用。

步骤2:3D打印前臂

0c029256-19ad-11f0-9434-92fbcf53809c.png

同样地,手部所需的文件如下,并且也在inmoov STL零件库[2]中。请注意,在inmoov零件库中有原版inmoov机器人的文件。这个手是i2版本,因此你只需要前臂部分的一些零件。另外一个需要注意的是,当打印Bolt_entretoise7时,你只需要中间的螺栓和夹子(其他部分是为旧版手设计的)。

0c203f22-19ad-11f0-9434-92fbcf53809c.png

3D打印文件文末下载。

你还可以打印一个我自己在Fusion 360中设计的小展示支架。

0c334568-19ad-11f0-9434-92fbcf53809c.png

链接:https://www.printables.com/model/593999-inmoov-hand-stand?lang=cs

步骤3:组装

0c4decd8-19ad-11f0-9434-92fbcf53809c.png

在组装时,可以参考InMoov提供的hand i2[3]前臂[4]的教程,这些教程非常详细,提供了所有必要的信息。

0c70319e-19ad-11f0-9434-92fbcf53809c.png0c946bf4-19ad-11f0-9434-92fbcf53809c.png0cbcc392-19ad-11f0-9434-92fbcf53809c.png

初始部件的组装相对简单,只需用螺丝将整个设计固定在一起。稍微复杂的部分是确保钓鱼线的布置不打结,以及将霍尔传感器正确安装在指尖。

步骤4:硅胶指尖

0cd5237e-19ad-11f0-9434-92fbcf53809c.png0cf043ca-19ad-11f0-9434-92fbcf53809c.png0d11d9cc-19ad-11f0-9434-92fbcf53809c.png

对于指尖来说,使用非常柔软的硅胶是很重要的,因为霍尔传感器的读取有一定的不确定性。硅胶越软,内部的磁铁运动幅度越大,从而更容易从数据中识别。将硅胶部分粘到3D打印出的部件上之后,可以用它来调整霍尔传感器的突出程度。

0d33ffb6-19ad-11f0-9434-92fbcf53809c.png

在这一切设置好之后,强烈建议将霍尔传感器固定在手指的末端,否则在手指运动过程中,霍尔传感器可能会稍微移动,从而影响测量结果。

步骤5:电路

0d607c12-19ad-11f0-9434-92fbcf53809c.png0d71021c-19ad-11f0-9434-92fbcf53809c.png

电路方面,使用16路舵机驱动模块会带来显著的效果,但也存在一些缺点。该驱动模块有两种不同的版本,虽然它们几乎相同,但在反极性保护电路(用于电容)所使用的晶体管上有区别,一个版本可承受约8A电流,而另一个版本仅可承受约0.5A,这远低于舵机实际需要的电流。因此,最好不要让伺服电机通过驱动模块供电,或者按照视频[5]中所述进行小改动,并在使用电容时要格外小心。

关于霍尔传感器,我们需要使用一个电压分压器,因为它输出的电压范围在0V到5V之间,而ESP32只能正确读取0V到3.3V的ADC值。

对于整个电路,可以选择使用面包板,或者更好的是使用定制PCB(作者版本的GitHub链接[6])。

步骤6:测试


由于每个伺服电机和霍尔传感器都略有不同,所以需要对它们进行测试。

最重要的是测试霍尔传感器,因为它们测量的值将决定仿生手是否施加了足够的压力。我建议使用Arduino IDE的绘图功能来绘制数据,以观察数值何时超过自然不确定性范围。

为此,我们可以使用这个非常简单的代码片段:

inthall="Pinnumberyourhallsensorisconnectedto";

voidsetup(){
Serial.begin(115200);
pinMode(hall,INPUT);
}

voidloop(){
Serial.println(analogRead(hall));
delay(10);
}

步骤7:代码

OpenCV(在VSCode中运行的Python代码)

就运行在带有网络摄像头的PC上的代码而言,我们需要完成两个主要任务:

第一个任务是使用OpenCV追踪手部及其元素。基于这些元素我们可以计算每根手指的位置。

第二个任务是通过串口将数据发送到ESP32,以便控制伺服电机。这些数据可以相对简化,因为我们不需要发送精确的角度值,而只需发送每个手指是否弯曲的信息。因此,我们可以发送五个0或1,并在末尾加一个符号以便后续识别每个数字的索引

这种方法将手部追踪和数据传输简化为一个二进制状态系统,使得数据处理和传输更加高效,同时仍能提供足够的信息来控制仿生手的动作。

首先,我们需要为Python代码导入以下库:

importcv2
importmediapipeasmp
importtime
importserial

然后,我们需要创建一个用于处理摄像头数据的类:

classHandDetector():
#Constructoroftheclasswithparametersforthemeasurement
def__init__(self,mode=False,maxHands=1,detectionCon=0.5,trackCon=0.5):
self.mode=mode
self.maxHands=maxHands
self.detectionCon=detectionCon
self.trackCon=trackCon

self.mpHands=mp.solutions.hands
self.hands=self.mpHands.Hands()
self.mpDraw=mp.solutions.drawing_utils

#Functionforfindinganddrawingthehand
deffindHands(self,frame,draw=True):
imgRGB=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
self.results=self.hands.process(imgRGB)

ifself.results.multi_hand_landmarks:
forhandLmsinself.results.multi_hand_landmarks:
ifdraw:
self.mpDraw.draw_landmarks(frame,handLms,self.mpHands.HAND_CONNECTIONS)
returnframe

#Functionforfindingeachhandlandmarkanddrawingitsposition
deffindPosition(self,frame,handNo=0,draw=False):
lmList=[]

ifself.results.multi_hand_landmarks:
myHand=self.results.multi_hand_landmarks[handNo]

forid,lminenumerate(myHand.landmark):
h,w,c=frame.shape
cx,cy=int(lm.x*w),int(lm.y*h)

lmList.append([id,cx,cy])

ifdrawandid==0:
cv2.circle(frame,(cx,cy),15,(255,0,255),-1)
returnlmList

接下来定义主函数:

defmain():
#TheprevTimeandcurrentTimeareusedtocalculatetheFPSlater
prevTime=0
currentTime=0

#Arrayforstoringtheinfoaboutthehand
hand=[["Wrist",False],["Index",False],["Middle",False],
["Ring",False],["Thumb",False],["Pinky",False]]

#InitializingtheSerialandopencv
ser=serial.Serial(port="ThenameoftheporttheESP32isconnectedto")
#Ihadtoincludethe"cv2.CAP_DSHOW"becauseIhadissueswiththewebcamloadingonmylinuxmachine
cap=cv2.VideoCapture(0,cv2.CAP_DSHOW)
detector=HandDetector()

#MAINLOOPOFTHECODE#

#Releasingthestuffallocatedforopencv
cap.release()
cv2.destroyAllWindows()

main()

以及代码的主循环:

while(True):
#Findingthehandsandreadingthepositionofhtelandmarks
ret,frame=cap.read()
frame=detector.findHands(frame)
lmList=detector.findPosition(frame)

iflen(lmList)>0:

j=1
change=False
#Loopwhichchecksifthetopofthefingerisbelowthesecondmosttop
foriinrange(1,6):
ifi==1andlmList[4][1]< lmList[3][1]andnothand[4][1]:
#Incasethatitistrueitchangesalltheneededdata
hand[4][1]=True
change=True
print(hand[4][0],hand[4][1])
elifi==1andlmList[4][1]>lmList[3][1]andhand[4][1]:
hand[4][1]=False
change=True
print(hand[4][0],hand[4][1])
elifi!=1:
iflmList[i*4][2]>lmList[(i*4)-2][2]andnothand[j][1]:
hand[j][1]=True
change=True
print(hand[j][0],hand[j][0])
eliflmList[i*4][2]< lmList[(i*4)-2][2]andhand[j][1]:
hand[j][1]=False
change=True
print(hand[j][0],hand[j][0])
ifj==3:
j+=2
else:
j+=1

#Iftherehasbeenanychangeinthestateofthehandthiscodeblockwillrun
ifchange:
msg=""
#Convertsthebooleanvaluesto0sand1s
foriinrange(6):
ifhand[i][1]:
msg+="1"
else:
msg+="0"

#AddstheendingsymbolandsendsthedataovertotheESP32
msg+='\n'
print(msg)
ser.write(msg.encode("Ascii"))

#CalculatestheFPSanddisplaysitontheframe
currentTime=time.time()
fps=1/(currentTime-prevTime)
prevTime=currentTime
cv2.putText(frame,str(int(fps)),(10,70),cv2.FONT_HERSHEY_SIMPLEX,3,(255,0,255),3)

#Showswhatthewebcamseesonaframe
cv2.imshow("frame",frame)

#Ifwepress"q"itquitsrunningtheprogram
ifcv2.waitKey(1)&0xFF==ord("q"):
break

整个代码 OpenCV:

importcv2
importmediapipeasmp
importtime
importserial

classHandDetector():
def__init__(self,mode=False,maxHands=2,detectionCon=0.5,trackCon=0.5):
self.mode=mode
self.maxHands=maxHands
self.detectionCon=detectionCon
self.trackCon=trackCon

self.mpHands=mp.solutions.hands
self.hands=self.mpHands.Hands()
self.mpDraw=mp.solutions.drawing_utils

deffindHands(self,frame,draw=True):
imgRGB=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
self.results=self.hands.process(imgRGB)

ifself.results.multi_hand_landmarks:
forhandLmsinself.results.multi_hand_landmarks:
ifdraw:
self.mpDraw.draw_landmarks(frame,handLms,self.mpHands.HAND_CONNECTIONS)
returnframe

deffindPosition(self,frame,handNo=0,draw=False):
lmList=[]

ifself.results.multi_hand_landmarks:
myHand=self.results.multi_hand_landmarks[handNo]

forid,lminenumerate(myHand.landmark):
h,w,c=frame.shape
cx,cy=int(lm.x*w),int(lm.y*h)

lmList.append([id,cx,cy])

ifdrawandid==0:
cv2.circle(frame,(cx,cy),15,(255,0,255),-1)
returnlmList

defmain():
prevTime=0
currentTime=0
hand=[["Wrist",False],["Index",False],["Middle",False],
["Ring",False],["Thumb",False],["Pinky",False]]


ser=serial.Serial(port="COM3")
cap=cv2.VideoCapture(0,cv2.CAP_DSHOW)
detector=HandDetector()

while(True):
ret,frame=cap.read()
frame=detector.findHands(frame)
lmList=detector.findPosition(frame)

iflen(lmList)>0:

j=1
change=False
foriinrange(1,6):
ifi==1andlmList[4][1]< lmList[3][1]andnothand[4][1]:
hand[4][1]=True
change=True
print(hand[4][0],hand[4][1])
elifi==1andlmList[4][1]>lmList[3][1]andhand[4][1]:
hand[4][1]=False
change=True
print(hand[4][0],hand[4][1])
elifi!=1:
iflmList[i*4][2]>lmList[(i*4)-2][2]andnothand[j][1]:
hand[j][1]=True
change=True
print(hand[j][0],hand[j][0])
eliflmList[i*4][2]< lmList[(i*4)-2][2]andhand[j][1]:
hand[j][1]=False
change=True
print(hand[j][0],hand[j][0])
ifj==3:
j+=2
else:
j+=1

ifchange:
msg=""
foriinrange(6):
ifhand[i][1]:
msg+="1"
else:
msg+="0"

msg+='\n'
print(msg)
ser.write(msg.encode("Ascii"))

currentTime=time.time()
fps=1/(currentTime-prevTime)
prevTime=currentTime

cv2.putText(frame,str(int(fps)),(10,70),cv2.FONT_HERSHEY_SIMPLEX,3,(255,0,255),3)

cv2.imshow("frame",frame)

ifcv2.waitKey(1)&0xFF==ord("q"):
break

cap.release()
cv2.destroyAllWindows()

main()

ESP32(Arduino IDE)

我们可以充分利用ESP32是双核这一特点,类似于PC的代码,我们同样需要完成两项主要工作。

首先是接收来自PC的数据。正如前面提到的,数据基本上是一个带有六位二进制数和结束符的字符串。此外,由于只有在状态变化时才会传输数据,我们可以立即将这些值(转换为true或false)分配给相应的变量。将这个任务分配给核心0,而主循环则在核心1上运行。

第二项工作就是控制手部运动。为此,我们需要不停地检查这些变量的状态是否发生变化,一旦有变化,伺服电机就会按小步长进行线性移动。在每一步后,首先需要检查变量是否没有再次变化,并且还要测量霍尔传感器读取的值。如果霍尔传感器的值过高,意味着磁铁距离手指核心太近,此时也要停止伺服电机的运动。

最初,我们需要用于伺服驱动的库,并且还将包含用于I2C通信的Wire库:

#include
#include

之后,我们需要定义脉冲长度的值,这些值因伺服类型而异,所以强烈建议查找特定伺服的信息或者像这样测试[7]它们。

//OperatingSpeedofmyServo(6V):0.21sec/60°

#defineSERVOMIN"Yourvalue(minewas70)"//Thisisthe'minimum'pulselengthcount(outof4096)
#defineSERVOMAX"Yourvalue(minewas510)"//Thisisthe'maximum'pulselengthcount(outof4096)
#defineSERVO_FREQ50//Analogservosrunat~50Hzupdates

现在我们必须定义其余要使用到的变量:

//Initializingservodriverobject
Adafruit_PWMServoDriverpwm=Adafruit_PWMServoDriver();

//Index,Middle,Ring,Thumb,Pinky
//"state0"isthestatethehandonthewebcamisinand"state"
//isthestuffhappeningontheactualhand
boolstate0[6]={false,false,false,false,false,false};
boolstate[6]={false,false,false,false,false,false};

//Variablewhichindicatesiftherehasbeenanychangemadetothestate
boolchange=false;

//VariablesneededforreadingthedatafromSerial
charsData;
Stringstate;

//Variableforthehallsensor
//Index,Middle,Ring,Thumb,Pinky
//{pin,measuredvalue,maximumvalue}
//ALLOFTHEMAXVALUESWEREMEASUREDBYMETHUSTHEYWILLMOSTLIKELYNOTBESAMEFORYOU
inthall[5][3]={{26,0,2200},{27,0,2400},{14,0,2300},{25,0,2200},{12,0,2300}};

//Settingtheindexnumbersofeachmotor
intwrist=0;
intthumb=4;
intindex=1;
intmiddle=2;
intring=3;//IMPORTANTthismotorwillrotateintheopositedirection
intpinky=5;//IMPORTANTthismotorwillrotateintheopositedirection

//FunctionforcalculatingthePWMbasedonthedegreeyouwant
intdegToPwm(intdegree){
returnmap(degree,0,320,SERVOMIN,SERVOMAX);
}

//Settingthedegreethresholdsused
intdeg=degToPwm(75);
intdeg1=degToPwm(95);
intdeg2=degToPwm(85);
intstartDeg=degToPwm(180);

接下来,需要定义我们将要使用的函数:

//Initializationofthetask
TaskHandle_trecieveData;

//FunctionwhichreadsthedatafromSerial
voidrecieveDataCode(void*parameter){
for(;;){
//Loopwhichrunswhenthereisamessagesent
while(Serial.available()){
//Readingbyeachcharacter
sData=Serial.read();

//Ifthecharacteristhelineendingsymbolweknowitistheendofthemessage
if(sData=='\n'){
//Loopforconvertingthestring0sand1stoboolean
for(inti=0;i< 6;i++){
state0[i]=state.substring(i,i+1).toInt();
}

//Resetingthestatetemporaryvariable
state="";
//Showingachangeinstatehappened
change=true;
break;
}else{//Ifthecharacterisnotthelineendingsymbolweaddittothetemporarystate
state+=sData;
}
}
delay(10);
}
}

//Functionforactuallymovingtheservos
voidmoveFinger(intfingerId,boolflex,intiteration){
//Becausetheringandpinkymotorsmoveinoppositedirection
//wehavetocheckwhichmotorswearemoving
if(fingerId!=ring&&fingerId!=pinky){
//Wealsoneedtocheckifwewantthefingertoflexorstraighten
if(flex){
//Moreoverthethumbmovesalittlelesssowealsocheckforthat
if(fingerId==thumb){
//Becausewewanttobeabletocontrolthemovementthroughoutwehaveto
//divideitintosmallerparts
floatfPwm=SERVOMIN+(float(103)*float(iteration))/float(130);
//Butwealsohavetomakesuretoconvertbacktointbecausefloatwould
//notbeacceptedbypwmfunction
intiPwm=round(fPwm);
pwm.setPWM(fingerId,0,iPwm);
}else{//Ifthefingerisnotthethumbwejustmoveit
pwm.setPWM(fingerId,0,SERVOMIN+iteration);
}
}else{//Forthecasethatisretractingwehavetojustdotheopposite
if(fingerId==thumb){
floatfPwm=deg-(float(103)*float(iteration))/float(130);
intiPwm=round(fPwm);
pwm.setPWM(fingerId,0,iPwm);
}else{
pwm.setPWM(fingerId,0,deg1-iteration);
}
}
}elseif(fingerId==ring||fingerId==pinky){
//Inthecaseoftheringorpinkyfingerwedoagainthesame
if(flex){
pwm.setPWM(fingerId,0,startDeg-iteration);
}else{
pwm.setPWM(fingerId,0,deg2+iteration);
}
}
}

补上设置和循环功能:

voidsetup(){
//StartingSerialonthesamefrequencyasonthePC
Serial.begin(9600);

//AssigningthepinModetoallpinsconnectedtohallsensor
for(inti=0;i< 5;i++){
pinMode(hall[i][0],INPUT);
}

//Setupandstartingtheservodriver
pwm.begin();
pwm.setOscillatorFrequency(27000000);
pwm.setPWMFreq(SERVO_FREQ);

delay(10);

//Pinningthecreatedtasktocore0
xTaskCreatePinnedToCore(
recieveDataCode,
"recieveData",
10000,
NULL,
0,
&recieveData,
0);
delay(500);
}

voidloop(){
//Oncetherehasbeenachangeinthestatethiscodeblockwillrun
if(change){
//Loopingfirstlythroughthetotalstepsoftheservos
for(inti=5;i< 135;i+=5){

//Secondlythroughallofthehallsensorsandreadingthevalues
for(intk=0;k< 5;k++){
hall[k][1]=analogRead(hall[k][0]);
//Ifthemeasuredvalueisgreaterthanmaximumvaluewestopthemovement
if(hall[k][1]>hall[k][2]){
state1[k+1]=state0[k+1];
}
}

//Thirdlythroughalltheservomotors
for(intj=0;j< 6;j++){
if(state0[j]!=state1[j]){
//IfthestateonthePCdoesnotmatchtheoneontheesp32we
//callthefunctionformovingtherespectivefinger
moveFinger(j,state0[j],i);
}
}
//Thisdelayisveryimportantasitsetsthespeedofthemovements
delay(17);
}

//Attheandwemakethestatevariablesequalagain
for(inti=0;i< 6;i++){
state1[i]=state0[i];
}
}

delay(100);
}

ESP32的完整代码:

#include
#include

#defineSERVOMIN"Yourvalue"
#defineSERVOMAX"Yourvalue"
#defineSERVO_FREQ50

Adafruit_PWMServoDriverpwm=Adafruit_PWMServoDriver();

boolstate0[6]={false,false,false,false,false,false};
boolstate1[6]={false,false,false,false,false,false};

boolchange=false;

charsData;
Stringstate;

inthall[5][3]={{26,0,2200},{27,0,2400},{14,0,2300},{25,0,2200},{12,0,2300}};

intwrist=0;
intthumb=4;
intindex=1;
intmiddle=2;
intring=3;
intpinky=5;

intdegToPwm(intdegree){
returnmap(degree,0,320,SERVOMIN,SERVOMAX);
}

intdeg=degToPwm(75);
intdeg1=degToPwm(95);
intdeg2=degToPwm(85);
intstartDeg=degToPwm(180);

TaskHandle_trecieveData;

voidrecieveDataCode(void*parameter){
for(;;){
while(Serial.available()){
sData=Serial.read();
if(sData=='\n'){
for(inti=0;i< 6;i++){
state0[i]=state.substring(i,i+1).toInt();
}
state="";
change=true;
break;
}else{
state+=sData;
}
}
delay(10);
}
}

voidmoveFinger(intfingerId,boolflex,intiteration){
if(fingerId!=ring&&fingerId!=pinky){
if(flex){
if(fingerId==thumb){
floatfPwm=SERVOMIN+(float(103)*float(iteration))/float(130);
intiPwm=round(fPwm);
pwm.setPWM(fingerId,0,iPwm);
}else{
pwm.setPWM(fingerId,0,SERVOMIN+iteration);
}
}else{
if(fingerId==thumb){
floatfPwm=deg-(float(103)*float(iteration))/float(130);
intiPwm=round(fPwm);
pwm.setPWM(fingerId,0,iPwm);
}else{
pwm.setPWM(fingerId,0,deg1-iteration);
}
}
}else/*if(fingerId==ring||fingerId==pinky)*/{
if(flex){
pwm.setPWM(fingerId,0,startDeg-iteration);
}else{
pwm.setPWM(fingerId,0,deg2+iteration);
}
}
}

voidsetup(){
Serial.begin(9600);

for(inti=0;i< 5;i++){
pinMode(hall[i][0],INPUT);
}

pwm.begin();
pwm.setOscillatorFrequency(27000000);
pwm.setPWMFreq(SERVO_FREQ);

delay(10);

xTaskCreatePinnedToCore(
recieveDataCode,
"recieveData",
10000,
NULL,
0,
&recieveData,
0);
delay(500);
}

voidloop(){
if(change){
for(inti=5;i< 135;i+=5){
for(intk=0;k< 5;k++){
hall[k][1]=analogRead(hall[k][0]);
if(hall[k][1]>hall[k][2]){
state1[k+1]=state0[k+1];
}
}
for(intj=0;j< 6;j++){
if(state0[j]!=state1[j]){
moveFinger(j,state0[j],i);
}
}
delay(17);
}

for(inti=0;i< 6;i++){
state1[i]=state0[i];
}
}

delay(100);}


原文地址:https://www.instructables.com/Bionic-Hand-Controlled-by-OpenCV/

项目作者:bloudakm

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 传感器
    +关注

    关注

    2574

    文章

    54414

    浏览量

    786251
  • OpenCV
    +关注

    关注

    33

    文章

    651

    浏览量

    44427
  • 仿生手
    +关注

    关注

    0

    文章

    15

    浏览量

    10298
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    意大利新型仿生手,体验“逼真”的触感!

    意大利研制成功款新型仿生手,不仅能够完成复杂的动作,而且能够通过与患者神经系统的衔接来让患者体验到“逼真”的触感。
    发表于 02-25 11:12 3490次阅读

    【开源项目】做一只由 OpenCV 控制仿生手

    这个项目介绍了如何制作和控制一只仿生手。作者最初受到Instagram上个视频的启发,该视频展示了使用MPU6050传感器追踪手部动作并在
    发表于 11-18 10:07

    帧头查找程序,初学小制作,菜鸟一只~

    帧头查找程序,初学小制作,菜鸟一只~哈哈,希望大家都能在这里有所收获哈~
    发表于 07-26 09:17

    分享仿生手的设计方案

    是模仿人类自然手的机械假手。它可以做人手可以做的事情。这只手是用塑料作为原材料进行 3D 打印的。对于 PCB,将边框直接放置在具有精确尺寸的仿生手上,它有个 arduino nano 作为控制
    发表于 07-04 08:01

    一只电容救活显象管

    一只电容救活显象管笔者家中有台老式的14英寸的黑白电视机,使用十年来,
    发表于 04-17 22:26 799次阅读

    一只单连开关控制三盏灯

    一只单连开关控制三盏灯
    发表于 09-10 08:57 3297次阅读
    <b class='flag-5'>一只</b>单连开关<b class='flag-5'>控制</b>三盏灯

    一只单连天关控制盏灯并另外连接一只插座

    一只单连天关控制盏灯并另外连接一只插座
    发表于 09-10 08:58 1054次阅读
    <b class='flag-5'>一只</b>单连天关<b class='flag-5'>控制</b><b class='flag-5'>一</b>盏灯并另外连接<b class='flag-5'>一只</b>插座

    Youbionic仿生手变身多臂超人不再是梦!

    器人,那么家叫做Youbionic的公司可以助你圆梦。根据《每日邮报》报道,Youbionic声称,公司最新的仿生手设计可以赋予你“神奇能力”。 方面,该奇妙装置通过移动你的手指来控制
    发表于 02-13 03:48 1760次阅读
    Youbionic<b class='flag-5'>仿生手</b>变身多臂超人不再是梦!

    如何制作一只用蒸汽驱动的能航行的小船?

    制作一只蒸汽驱动的能航行的小船,似乎是很难的件事情,但是我们设计的这个套件让它变得非常简单。您只需要简单的工具和材料,就能在家里跟孩子起完成这个任务,共同
    的头像 发表于 08-07 15:43 2.5w次阅读

    触控手机可穿戴仿生手将投入量产

    近日,微博大号“黑客师”曝光了款可穿戴仿生手设备的谍照。据“黑客师”透露,这是他从京东数科内部拿到的最新款智能可穿戴仿生手,目前已经完成了前期研发工作并已进入样机测试阶段。
    的头像 发表于 06-07 11:29 4552次阅读

    3D打印定制仿生手臂,仅需10小时即可完成

    WMG和华威大学的工程师团队在其他公司的协助下创建了3D打印仿生手,可在10小时内生产。
    的头像 发表于 05-19 15:57 3117次阅读

    英国游戏玩家在厂商帮助下获得新仿生手

    据外媒CNET报道,英国游戏玩家Daniel Melville天生没有右手,由于电子游戏发行商 Konami(科乐美)和Open Bionics的帮助,他现在拥有了一只超酷的新仿生手臂,它是基于《合金装备》中毒蛇(Venom Snake)
    的头像 发表于 11-18 14:58 1971次阅读

    中国科学家研发新型仿生手术缝线

    基于“藕断丝连”这自然现象,中国科学家再次秀出了令人侧目的研究成果,而它就是新型仿生手术缝线。
    的头像 发表于 01-21 09:26 2097次阅读

    arduino nano作为控制器的仿生手

    电子发烧友网站提供《arduino nano作为控制器的仿生手.zip》资料免费下载
    发表于 07-07 10:47 5次下载
    arduino nano作为<b class='flag-5'>控制</b>器的<b class='flag-5'>仿生手</b>

    通过基于CNN的EMG识别进行实时仿生手控制

    电子发烧友网站提供《通过基于CNN的EMG识别进行实时仿生手控制.zip》资料免费下载
    发表于 10-24 10:03 4次下载
    通过基于CNN的EMG识别进行实时<b class='flag-5'>仿生手</b>臂<b class='flag-5'>控制</b>