「树莓派」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)


分享到:


相關文章: