22浏览
查看: 22|回复: 2

[项目] 【Arduino 动手做】LittleArm:Arduino 机械臂

[复制链接]
LittleArm 是一款 3D 打印可训练 Arduino 机械臂,适合 STEM 学生和制造商。

这是LittleArm网站,您可以在此找到其他购买 Littlearm 套件或获取文件、教程和其他资源来构建您自己的套件。

LittleArm 最初是由 Slant 创始人 Gabe Bentz 的一个周末项目发起的。Gabe 当时正在寻找一款低成本的 3D 打印机械臂来配合 Arduino 进行实验。由于找不到合适的,他便用自己的 3D 打印机制作了 LittleArm 的第一个原型。

朋友和老师们不断请加布为他们制作工具,以便他们能组装这只假肢。从那时起,它就成了Slant的一个项目。

如今,LittleArm 由一支热爱科技的设计师团队提供支持。用户可以免费下载所有软件,开始训练他们的 LittleArm。拥有 3D 打印机的用户可以下载 STL 文件,没有打印机的用户则可以购买套件。

Slant 团队非常热爱 LittleArm 的设计。它是市面上少数几个需要 3D 打印的设计之一,而且其他任何制造工艺都无法实现。

【Arduino 动手做】LittleArm:Arduino 机械臂图2

【Arduino 动手做】LittleArm:Arduino 机械臂图3

【Arduino 动手做】LittleArm:Arduino 机械臂图1

驴友花雕  中级技神
 楼主|

发表于 昨天 16:16

【Arduino 动手做】LittleArm:Arduino 机械臂

项目代码

  1. #This program has a complete set of commands for most behaviors
  2. #an improvement to the software would be for the arduino to wait until completion of the execution of the command before sending a ready signal
  3. from Tkinter import *
  4. import tkFileDialog
  5. import tkMessageBox
  6. import time
  7. import serial
  8. import serial.tools.list_ports
  9. import copy
  10. #+++++++++++++Global Variables+++++++++++++++++++++
  11. currentSequence = "motion_recording.txt"        #the file name of recording prei-intialized to the default
  12. currentDirectoy = "/"                                                #defines the working directory of the user
  13. loopStartStop = False
  14. #This line of code is a manual alternative should the Arduino search function below fault
  15. #To use Comment out the below While loop and change the COM# to the port the arduino is connected to based on the Device Mananger
  16. #ser = serial.Serial('COM3', 9600, timeout = .1)
  17. checker = 0  #Loop control
  18. while checker == 0:
  19.     #Find the serial port that the arduino is connected to
  20.     ports = list(serial.tools.list_ports.comports())
  21.     print ports
  22.        
  23.     for p in ports:
  24.         
  25.         print "Searching for Port ..."
  26.         
  27.         if "CH340"  in p[1]:
  28.            
  29.             print p[1]
  30.             ser = serial.Serial(p[0], 9600, timeout = .5)
  31.             checker = 1
  32.             break
  33.                        
  34.         if "Arduino" in p[1]:
  35.             print "hello1"
  36.             ser = serial.Serial(p[0], 9600, timeout = .5)
  37.             checker = 1
  38.             #print "Found the Arduino"
  39.                             
  40.         else:
  41.                 print ("No Arduino Device was found connected to the computer")
  42. #++++++++++++++++Functions+++++++++++++++++++++++
  43. colors = {
  44.     "spacer": "black",
  45.     "background": "black",
  46.     "frame": "black",
  47.     "label": "gray",
  48.     "speed": "#3366ff",
  49.     "arm": "#00b300",
  50.     "gripper": "red"
  51. }
  52. if sys.platform != "win32":
  53.     colors["spacer"] = "black"
  54.     colors["background"] = "white"
  55.     colors["frame"] = "white"
  56. def move_it(aCommand):
  57.     #this function sends the command of joint angles to the arduino to move the servos to the desired positions in real time with the GUI
  58.    
  59.     aCommand = 0  #unused holder to allow function to work live with scale bar
  60.     ser.flushInput()
  61.     ser.flushOutput()
  62.     command = str(base.get()) + ',' + str(shoulder.get()) +   ',' + str(elbow.get())+','+ str(gripper.get())+','+ str(21 - theSpeed.get()) + '\n'
  63.     print command
  64.     ser.write(command)
  65.     #wait until a repsonse if found from the arduino
  66.     OK = 'no'
  67.     while (OK != 'd'):
  68.         OK = ser.read(1)
  69.    
  70. def recordArmPos():
  71.     #This function records the current positions of the GUI and places them in a TXT file in the same directory as this program
  72.     readPosCommand = str(base.get()) + ',' + str(shoulder.get()) +   ',' + str(elbow.get())+','+ str(gripper.get()) +','+ str(21 -theSpeed.get())+'\n'
  73.     recordFile = open(currentSequence, 'a')
  74.     print (currentSequence)
  75.     recordFile.write(readPosCommand)
  76.     recordFile.close()
  77. def recordPause():
  78.     #This function records the current positions of the GUI and places them in a TXT file in the same directory as this program
  79.     pauseCommand = "pause" + '\n'
  80.     recordFile = open(currentSequence, 'a')
  81.     recordFile.write(pauseCommand)
  82.     recordFile.close()   
  83. def playback():
  84.    #This function reads the record file created in recordArmPos() and send the commands to the arm so that a sequence may be repeated.
  85.    recordFile = open(currentSequence, 'r')
  86.    Count = 1
  87.    for line in recordFile:
  88.        Count = Count + 1
  89.        recordedCommand = line
  90.        #send the command to the arduino using another function
  91.        sendCommand(recordedCommand)
  92.    print ('Done')
  93.    recordFile.close()
  94. def sendCommand(anotherCommand):
  95.     #this is a basic command function. It recieves the generic command in the form base,shoulder,elbow,effector\n and send it to the arduino and then waits to recieve confirmations that the arduino has processed it.
  96.         #this function is a variation of move_it for the playback function
  97.     ser.flushInput()
  98.     ser.flushOutput()
  99.     theCommand = anotherCommand
  100.     print theCommand
  101.     if theCommand == "pause\n":
  102.         time.sleep(1)
  103.         return
  104.    
  105.     ser.write(theCommand)
  106.     #wait until a repsonse if found from the arduino
  107.     OK = 'no'
  108.     while (OK != 'd'):
  109.         OK = ser.read(1)
  110.                        
  111. def goHome():
  112.     #This function returns the robot to its initial positions and changed the GUI positions to match
  113.     homePos = str(108) + ',' + str(154) + ',' + str(30)+ ',' + str(10) + ',' + str(4) + '\n'
  114.     base.set(108)
  115.     shoulder.set(154)
  116.     elbow.set(30)
  117.        
  118.     sendCommand(homePos)
  119.        
  120. def clearFile():
  121.     #this clears the file for a new sequence
  122.     open(currentSequence, 'w').close()
  123.        
  124. def saveFileAs():
  125.     #This function is called by the menubar
  126.     #this function opens the current set of commands in the file motion_recording.txt and saves the contents to a new
  127.     print "Saving a File I see"
  128.     global currentSequence                        #aacess the gloabl value of the current sequence
  129.        
  130.         #open the current file and copy its contents
  131.     file = open(currentSequence, 'r')   
  132.     textoutput = file.readlines()
  133.     file.close()
  134.        
  135.         #open the new files and insert the contents
  136.     theNewFile = tkFileDialog.asksaveasfilename(initialfile='Untitled.txt',defaultextension=".txt",filetypes=[("All Files","*.*"),("Text Documents","*.txt")])
  137.     file = open(theNewFile, 'w')
  138.     file.writelines(textoutput)                #not the writelines. write does not enter the data correctly from readlines
  139.     file.close()
  140.        
  141.         #update the working file
  142.     currentSequence = theNewFile        #update the file that is being used universally
  143. def openFile():
  144.     #this function sets the file that is being edited and recorded into
  145.     global currentSequence
  146.     currentSequence = tkFileDialog.askopenfilename(initialdir = "/",title = "Select file",filetypes = (("txt files","*.txt"),("all files","*.*")))
  147.     print (currentSequence)
  148.        
  149. def newFile():
  150.     #this function created a new .txt file to hold imput commands
  151.     global currentSequence
  152.        
  153.         #open a new fle
  154.     theNewFile = tkFileDialog.asksaveasfilename(initialfile='Untitled.txt',defaultextension=".txt",filetypes=[("All Files","*.*"),("Text Documents","*.txt")])        #names the file and sets the location
  155.     file = open(theNewFile, 'a')   #creates the file
  156.     file.close()
  157.    
  158.     currentSequence = theNewFile        #update the file that is being used universally
  159. def looper( ):
  160.     #this function loops through a the current sequence repeatedly.
  161.     #startStop is the boolean bit that stats looping
  162.     if loopStartStop == 1:
  163.         playback()
  164.     root.after(1000, looper)       
  165. def startLooper():
  166.     global loopStartStop
  167.     loopStartStop = 1
  168. def stopLooper():
  169.     global loopStartStop       
  170.     loopStartStop = 0
  171.        
  172. #++++++++++++++++++++The GUI++++++++++++++++++++++
  173. root = Tk()
  174. root.wm_title("LittleArm")
  175. root.configure(background = colors["background"])
  176. #++++++++++++++++++Menu+++++++++++++++++++++++++
  177. menubar = Menu(root)
  178. filemenu = Menu(menubar, tearoff = 0)
  179. filemenu = Menu(menubar, tearoff=0)
  180. filemenu.add_command(label="Open", command=openFile)
  181. filemenu.add_command(label= "New Sequence", command=newFile)
  182. filemenu.add_command(label="Save Sequence As", command=saveFileAs)
  183. filemenu.add_separator()
  184. filemenu.add_command(label="Exit", command=root.quit)
  185. menubar.add_cascade(label="File", menu=filemenu)
  186. # display the menu
  187. root.config(menu=menubar)
  188. #+++++++++++++++++++++++spacer frame++++++++++++++++++++++++++++++++++
  189. spacerFrameLeft = Frame(root, bg = colors["frame"])
  190. spacerFrameLeft.grid(row = 0, column = 0 )
  191. spacerLabel6 = Label(spacerFrameLeft,  bg = colors["spacer"], padx = 10)
  192. spacerLabel6.grid(row = 0, column = 0 )
  193. #+++++++++++++++++ARM+++++++++++++++++++++++++
  194. # The scroll bars
  195. armControl = Frame(root, background = colors["frame"])
  196. armControl.grid(row = 0, column = 1 )
  197. #armLabel = Label(armControl, text = "Arm Components", font = ("ARIAL", 24),relief = GROOVE, padx = 100)
  198. #armLabel.pack()
  199. spacerLabel = Label(armControl,  bg = colors["spacer"], padx = 100)
  200. spacerLabel.grid(row = 1, column = 1 )
  201. #++++++++++++++++++++++++BASE+++++++++++++++++++++++++++
  202. baseLabel = Label(armControl, text = "Base", font = ("ARIAL", 16), relief = GROOVE, padx = 100, width = 9, bg = colors["arm"])
  203. baseLabel.grid(row = 2, column = 1 )
  204. base = Scale(armControl, from_= 5, to = 175, length = 306, orient = HORIZONTAL, troughcolor = colors["arm"], showvalue = 0, command = move_it)
  205. base.set(108)
  206. base.grid(row = 3, column = 1 )
  207. #++++++++++++++++++++++++Shoulder+++++++++++++++++++++++++
  208. shoulderLabel = Label(armControl, text = "Shoulder", font = ("ARIAL", 16),relief = GROOVE, padx = 100, width = 9, bg = colors["arm"])
  209. shoulderLabel.grid(row = 4, column = 1 )
  210. shoulder = Scale(armControl, from_= 5, to = 175, length = 306, orient = HORIZONTAL, troughcolor = colors["arm"], showvalue = 0,command = move_it)
  211. shoulder.set(100)
  212. shoulder.grid(row = 5, column = 1 )
  213. #++++++++++++++++++++++ELBOW++++++++++++++++++++++++++++
  214. elbowLabel = Label(armControl, text = "Elbow",font = ("ARIAL", 16), relief = GROOVE, padx = 100, width = 9, bg = colors["arm"])
  215. elbowLabel.grid(row = 6, column = 1 )
  216. elbow = Scale(armControl, from_= 5, to = 175, length = 306, orient = HORIZONTAL,troughcolor = colors["arm"], showvalue = 0, command = move_it)
  217. elbow.set(30)
  218. elbow.grid(row = 7, column = 1 )
  219. #++++++++++++++++++++++++++++Gripper+++++++++++++++++++
  220. gripperLabel = Label(armControl, text = "Gripper",font = ("ARIAL", 16), relief = GROOVE, padx = 100, width = 9, bg = colors["gripper"])
  221. gripperLabel.grid(row = 8, column = 1 )
  222. gripper = Scale(armControl, from_= 5, to = 75, length = 306, orient = HORIZONTAL, troughcolor = colors["gripper"], showvalue = 0,  command = move_it)
  223. gripper.grid(row = 9, column = 1 )
  224. #++++++++++++++++++++++++++Speed++++++++++++++++++++++++
  225. spacerLabel2 = Label(armControl,  bg = colors["spacer"], padx = 100)
  226. spacerLabel2.grid(row = 10, column = 1 )
  227. speedLabel = Label(armControl, bg = colors["speed"], font = ("Arial", 16), text = "Speed", relief = GROOVE, padx = 100, width = 9)
  228. speedLabel.grid(row = 11, column = 1 )
  229. theSpeed = Scale(armControl, from_= 3, to = 20, length = 306, orient = HORIZONTAL, troughcolor = colors["speed"] ,command = move_it)
  230. theSpeed.grid(row = 12, column = 1 )
  231. spacerLabel3 = Label(armControl,  bg = colors["spacer"], padx = 100)
  232. spacerLabel3.grid(row = 13, column = 1 )
  233. pauseButton = Button(armControl, font = ("ARIAL", 16), text= "Pause for 1 Sec", width = 20, command = recordPause)
  234. pauseButton.grid(row = 14, column = 1 )
  235. homeButton = Button(armControl, font = ("ARIAL", 16), text= "Go Home", width = 20, command = goHome)
  236. homeButton.grid(row = 15, column = 1 )
  237. spacerLabel8 = Label(armControl,  bg = colors["spacer"], padx = 100)
  238. spacerLabel8.grid(row = 16, column = 1 )
  239. #+++++++++++++++++++++++space frame++++++++++++++++++++++++++++++++++
  240. spacerFrame = Frame(root, bg = colors["frame"])
  241. spacerFrame.grid(row = 0, column = 2 )
  242. spacerLabel6 = Label(spacerFrame,  bg = colors["spacer"], padx = 20)
  243. spacerLabel6.grid(row = 0, column = 0 )
  244. #+++++++++++++++++++++++RECORD++++++++++++++++++++++++++++
  245. recordButtons = Frame(root, bg = colors["frame"])
  246. recordButtons.grid(row = 0, column = 3 )
  247. spacerLabel4 = Label(recordButtons,  bg = colors["spacer"], padx = 100)
  248. spacerLabel4.grid(row = 1, column = 2 )
  249. recordButton = Button(recordButtons, font = ("ARIAL", 16),text = "Record Position", width = 20, command = recordArmPos)
  250. recordButton.grid(row = 2, column = 2 )
  251. spacerLabel9 = Label(recordButtons,  bg = colors["spacer"], padx = 100)
  252. spacerLabel9.grid(row = 3, column = 2 )
  253. playButton = Button(recordButtons, font = ("ARIAL", 16), text = "Play Sequence", width = 20, command = playback)
  254. playButton.grid(row = 4, column = 2 )
  255. clearButton = Button(recordButtons, font = ("ARIAL", 16), text = "Clear Sequence", width = 20, command = clearFile)
  256. clearButton.grid(row = 5, column = 2 )
  257. spacerLabel5 = Label(recordButtons,  bg = colors["spacer"], padx = 100)
  258. spacerLabel5.grid(row = 6, column = 2 )
  259. #++++++++Looping+++++++++++++++++++
  260. loopStartButton = Button(recordButtons, font = ("ARIAL", 16), text = "Start Loop", width = 20, command = startLooper)
  261. loopStartButton.grid(row = 7, column = 2 )
  262. loopStopButton = Button(recordButtons, font = ("ARIAL", 16), text = "Stop Loop", width = 20, command = stopLooper)
  263. loopStopButton.grid(row = 8, column = 2 )
  264. #+++++++++++++++++++++++space frame++++++++++++++++++++++++++++++++++
  265. spacerFrameRight = Frame(root, bg = colors["frame"])
  266. spacerFrameRight.grid(row = 0, column = 4 )
  267. spacerLabel7 = Label(spacerFrameRight,  bg = colors["spacer"], padx = 10)
  268. spacerLabel7.grid(row = 0, column = 0 )
  269. #+++++++++++++++++++++++++++Primary Loop+++++++++++++++++
  270. root.after(1000, looper)
  271. root.mainloop()
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 昨天 16:20

【Arduino 动手做】LittleArm:Arduino 机械臂

附录
【Arduino 动手做】LittleArm:Arduino 机械臂
项目链接:https://www.hackster.io/slantcon ... no-robot-arm-401fe2
项目作者:Slant Concepts

项目视频 :
https://www.youtube.com/watch?v=RSenq1iEZ_M
https://www.youtube.com/watch?v=xU3S6d1WIh4
项目代码:
https://www.hackster.io/code_files/82889/download
LittleArm 图形用户界面:
https://github.com/slantconcepts/LittleArmOne-Desktop-GUI

【Arduino 动手做】LittleArm:Arduino 机械臂图1

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail