「樹莓派」3D打印製作,可全自動連發的諸葛神弩

連弩又稱”諸葛弩”,相傳為諸葛亮所制,可連續發射弩箭。但由於連弩用箭沒有箭羽,使鐵箭在遠距離飛行時會失去平衡而翻滾,且木製箭桿的製作要求精度高,人工製作難度大,不易大量製造使用。明朝以後,由於火器迅速發展,弩便不再受重視。


「樹莓派」3D打印製作,可全自動連發的諸葛神弩

今天我們使用建模軟件和3D打印技術製作一把可全自動連發的弩,使用樹莓派控制舵機運動,程序代碼全部為Python編寫,包括一個2個自由度的雲臺。上彈以及發射動作由兩個舵機和棘輪結構完成,可以通過增加橡皮筋的數量來改變射擊力量。

STL模型和程序已經開源,可以免費下載:

https://www.gewbot.com/learn/1070.html

彈藥為大約10x10x4的小方塊,由於3D打印機精度各不相同所以這裡不提供這個小方塊的模型。

實驗所用的代碼如下:

#!/usr/bin/python3
# File name : crossbow.py
# Author : William
# Date : 2019/10/09

import Adafruit_PCA9685
import time

import socket
import threading

pwm = Adafruit_PCA9685.PCA9685()
pwm.set_pwm_freq(50)

port_L = 0
port_R = 1

port_P = 2
port_T = 3

direction_L = 1
direction_R = -1

direction_P = -1
direction_T = -1

servo_middle_L = 290
servo_middle_R = 280

servo_middle_P = 300
servo_middle_T = 300
P_position = servo_middle_P
T_position = servo_middle_T

PT_speed = 1

P_command = ''
T_command = ''
CB_command = ''
nocked = 0

wiggle_f = 60
wiggle_b = 90
wiggle_loose = 60

steps_delay = 0.15
draw_steps = 5
time_delay = 0.001

def hold():
 pwm.set_pwm(port_L, 0, servo_middle_L)
 pwm.set_pwm(port_R, 0, servo_middle_R)


def draw(steps):
 global nocked
 for i in range(0, steps):
 pwm.set_pwm(port_L, 0, servo_middle_L + wiggle_f*direction_L)
 pwm.set_pwm(port_R, 0, servo_middle_R - wiggle_b*direction_R)
 time.sleep(steps_delay)

 pwm.set_pwm(port_L, 0, servo_middle_L - wiggle_b*direction_L)
 pwm.set_pwm(port_R, 0, servo_middle_R - wiggle_b*direction_R)
 time.sleep(steps_delay)

 pwm.set_pwm(port_L, 0, servo_middle_L - wiggle_b*direction_L)
 pwm.set_pwm(port_R, 0, servo_middle_R + wiggle_f*direction_R)
 time.sleep(steps_delay)

 pwm.set_pwm(port_L, 0, servo_middle_L - wiggle_b*direction_L)
 pwm.set_pwm(port_R, 0, servo_middle_R - wiggle_b*direction_R)
 time.sleep(steps_delay)
 hold()
 nocked = 1
 time.sleep(steps_delay)


def loose():
 global nocked
 if nocked:
 pwm.set_pwm(port_L, 0, servo_middle_L + wiggle_loose*direction_L)
 pwm.set_pwm(port_R, 0, servo_middle_R + wiggle_loose*direction_R)
 time.sleep(steps_delay)
 nocked = 0
 else:
 draw(draw_steps)
 pwm.set_pwm(port_L, 0, servo_middle_L + wiggle_loose*direction_L)
 pwm.set_pwm(port_R, 0, servo_middle_R + wiggle_loose*direction_R)
 time.sleep(steps_delay)
 nocked = 0

def up(speed_input):
 global T_position
 T_position+=speed_input*direction_T
 pwm.set_pwm(port_T, 0, T_position)


def down(speed_input):
 global T_position
 T_position-=speed_input*direction_T
 pwm.set_pwm(port_T, 0, T_position)


def left(speed_input):
 global P_position
 P_position-=speed_input*direction_P
 pwm.set_pwm(port_P, 0, P_position)


def right(speed_input):
 global P_position
 P_position+=speed_input*direction_P
 pwm.set_pwm(port_P, 0, P_position)


class PT_ctrl(threading.Thread):
 def __init__(self, *args, **kwargs):
 super(PT_ctrl, self).__init__(*args, **kwargs)
 self.__flag = threading.Event()
 self.__flag.set()
 self.__running = threading.Event()
 self.__running.set()

 def run(self):
 while self.__running.isSet():
 self.__flag.wait()
 if T_command == 'up':
 up(PT_speed)
 elif T_command == 'down':
 down(PT_speed)

 if P_command == 'left':
 left(PT_speed)
 print('11')
 elif P_command == 'right':
 right(PT_speed)

 if P_command == 'P_no' and T_command =='T_no':
 self.pause()
 time.sleep(time_delay)

 def pause(self):
 self.__flag.clear()

 def resume(self):
 self.__flag.set()

 def stop(self):
 self.__flag.set()
 self.__running.clear()


class CB_ctrl(threading.Thread):
 def __init__(self, *args, **kwargs):
 super(CB_ctrl, self).__init__(*args, **kwargs)
 self.__flag = threading.Event()
 self.__flag.set()
 self.__running = threading.Event()
 self.__running.set()

 def run(self):
 global goal_pos, servo_command, init_get, if_continue, walk_step
 while self.__running.isSet():
 self.__flag.wait()
 if CB_command == 'draw':
 draw(draw_steps)
 self.pause()
 elif CB_command == 'loose':
 loose()
 self.pause()
 time.sleep(time_delay)

 def pause(self):
 self.__flag.clear()

 def resume(self):
 self.__flag.set()

 def stop(self):
 self.__flag.set()
 self.__running.clear()


PT = PT_ctrl()
PT.start()
PT.pause()

CB = CB_ctrl()
CB.start()
CB.pause()


if __name__ == '__main__':
 HOST = ''
 PORT = 10223
 BUFSIZ = 1024
 ADDR = (HOST, PORT)

 tcpSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 tcpSerSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
 tcpSerSock.bind(ADDR)
 tcpSerSock.listen(5)
 print('waiting for connection...')
 tcpCliSock, addr = tcpSerSock.accept()
 print('...connected from :', addr)

 while True:
 data = ''
 data = str(tcpCliSock.recv(BUFSIZ).decode())
 if not data:
 continue

 elif 'draw' == data:
 CB_command = data
 CB.resume()

 elif 'loose' == data:
 CB_command = data
 CB.resume()

 elif 'P_no' in data:
 P_command = data

 elif 'T_no' in data:
 T_command = data

 elif 'left' == data:
 P_command = data
 PT.resume()

 elif 'right' == data:
 P_command = data
 PT.resume()

 elif 'up' in data:
 T_command = data
 PT.resume()

 elif 'down' in data:
 T_command = data
 PT.resume()

 print(data)


分享到:


相關文章: