亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

Talking Portal 2 Turret Gun

组件和用品

Arduino Nano R3
× 1

必要的工具和机器

3D 打印机(通用)

关于这个项目

故事

今年圣诞节,我决定从游戏 Portal 2 中设计和建造一个可用的 Portal 炮塔枪 .对我来说,这是在构建任何东西之前,首先在 Fusion 360 中正确建模整个装配体的练习。此设计使用 Arduino Nano、MP3 播放器芯片、距离传感器、伺服系统、LED 和 3D 打印部件。

此处的目标是使其在 3 个“轴”中移动,并使用游戏中的语音和 LED 模拟射击。

  • 如果它感觉到前面有人,就打开“翅膀”。使用带有滑块的曲柄机构,只是因为。
  • 如果人在打开后还在那里,开火直到他们倒下。 LED 灯和机枪声。
  • 如果此人不在,请运行一些扫描搜索程序。
  • 闭上眼睛睡觉,直到有其他人出现。
  • 使用游戏中的传送门炮塔声音和声音。

我在设计上有一些自由,试图使它与游戏中看到的完全相同,但功能齐全且可打印。在网上找到了一些基本的草图,我开始建模和规划......

声音存储在 microSD 卡上,可从背面访问该卡,以便以后更新或更改声音。它与黑色填充条对齐,安装后基本上不可见。本轮使用了 18 个单独的表达和声音。

激光雷达传感器(飞行时间)位于具有矩形轮廓的芯片上。组装后,从正面几乎看不到该传感器。

第 1 步:Fusion 360 建模

设计从网上找到的草图开始。使用这些图像作为画布,我开始绘制 3 个视图的轮廓。然后就是将它们挤压成 3D,然后对一般形状进行脱壳并进行切割。所有电子设备都在 Fusion 中构建,作为插入并放置在我认为有意义的地方的组件。驱动参数为:

  • Arduino Nano 必须有连接器才能在完全组装后进行更新
  • MicroSD 卡必须以相同的方式访问,并且安装后最好不可见
  • 飞行时间传感器也应该不可见
  • 背面有一个 2.1 毫米的电源连接器
  • 打印的零件尽可能大(不是很多小零件)
  • 无支撑打印

在将组件(纳米、其他芯片、伺服系统)添加到基本形状后,它们会根据需要四处移动和定位,并构建支撑结构以将它们支撑在外壳内。

机翼打开机构是曲柄和滑动机构。为什么?因为我想使用曲柄机构,这就是原因!这增加了一些复杂性,但也有好处;一旦确定了几何形状,就可以确保操作的可重复性,并且几乎可以保证最小和最大限制。

一旦构建了整个模型并且我确信它可以工作,并且可以构建(打印)和组装,我继续打印出零件并构建原型。确定后,我回到模型并进行了一些调整以改善外观和可组装性(这是一个词吗?)。这个模型就是这些变化的结果。

这非常费力,因为这东西真的没有多少四四方方的形状,而且它闭合得非常紧密,一旦放在一起就没有真正的调整机会。我在这个项目中学到了很多东西,比如在其他组件中使用嵌入式组件。这使得操作和保持子组件链接以便快速访问。最后,值得努力!

第 2 步:3D 打印部件

传送门炮塔 v4.zip 已更新,应包含构建最新炮塔所需的所有打印部件。

---新的“后测试腿”。不是原装的,但它在后面,并且允许直接使用直的迷你 USB 连接器。 ---

这些是在 Prusa Mk2 上打印的,所有部件都使用 PLA。打印方向应该很明显。身体以垂直位置打印,没有支撑。侧面有很大的间隙需要弥合,但除了凹凸之外,我对非常标准的设置真的没有什么大问题。使用良好的灯丝和一些良好的打印设置几乎可以消除前后的颠簸。我发现 0.2 毫米在切片机中效果很好,并产生了不错的结果。填充条附近的身体开始出现任何更大的开口。

通道和突起的设计采用45度倒角,因此“悬空”元素将最小化。

我几乎没有清理工作要做将组件组装在一起。滑入通道的填充条现在非常简单,宽度减小,厚度一致。我认为人们可以使用切成条状的黑色薄材料,而不是使用这些印​​刷件(印刷在边缘)。

确实需要技巧的一个区域是间距框架中的滑块销。钻孔中的直销(钉子)用 1/8" 钻头和一些润滑油钻出,会有很长的路要走。

镜头%2Bv3b.stl 正文-RHS%2Bv4.stl 正文-LHS%2Bw%2Bcomponents%2Bv4.stl Wing%2BRH%2Bbottom%2Bv4.stl Wing%2BRH%2Btop%2Bv4.stl Wing%2BLH%2Bbottom%2Bv4.stl Wing%2BLH%2Btop%2Bv4.stl Pitch%2BFrame%2Bv4.stl Leg%2B-%2BREAR%2Bv4.stl 填充%2Bstrips%2Bv3.stl Leg%2B-%2BREAR%2Btest.stl Pitch%2BFrame%2B-%2Bmodified%2B1.stl 翅膀%2Bv6.zip Arduino%2BBase%2Bw%2BRadio.stl 传送门%2BTurret%2Bv4.zip

第 3 步:组件

V4(红色炮塔)有较小的桥接,需要 v4 机翼和 Pitch 框架。

v6 翅膀 一个 选项 那个 允许 不同 彩色“枪”。 我个人没有做过这样的,但它应该可以正常工作。

模型完成后,我对我的原型很满意,我用塑料组件打印了 rev 2,如图所示。这里的一切都是 PLA,黑色和设计色(在这种情况下为蓝色),以及用于中央“镜头”或激光眼的一点点半透明 PLA。

这张照片很好地捕捉了组件,除了接线。

第 4 步:电子产品

构建使用以下组件:

  • Arduino Nano (1)
  • DFPlayer 迷你 MP3 播放器(或 MP3-TF-16P)(1)
  • VL53L0X 飞行时间测距传感器 (1)
  • 通用 SG90 微型舵机 (3)
  • 5 毫米红色 LED (5)
  • 用于 LED 的 220 欧姆电阻器 (5)
  • 1kOhm 电阻 (1)
  • 4 厘米扬声器,4 欧姆,3 瓦 (1)
  • 2.1mm 电源连接器 (1)
  • 3" 长框钉 (4)
  • M2 x 6 螺丝 (8)
  • M2.5 x 8 螺钉 (2)
  • M3 x 8 螺钉 (4)
  • M3 x 12 螺钉 (4)
  • M3 x 16 螺钉 (2)
  • 收缩包装
  • 小领带

所有组件均可从 Arduino、亚马逊或 Banggood 和其他来源轻松获得。

螺钉来自分类套件。否则让他们很痛苦......

第五步:机械组装

大多数机械装配是合理的。打印出来的零件会在必要时用较大的孔进行打印,因此在最终组装之前用螺丝快速追逐会很有帮助,并且可以使螺纹组件的组装变得非常容易。

Arduino 和 MP3 芯片无需硬件即可卡入底座。 VL53LOX 无需紧固件即可滑入前壳。先试戴,连线后拆装。

滑块组件使用 4 个框架钉作为滑块导轨。它们的直径约为 1/8",头部被剪掉。这些是从一条 DeWalt 框架钉上取下来的,与他们的电动框架钉枪一起使用。不用说,光滑的钉子是必须的。

舵机安装如图所示。方向很重要。当安装到它们的部件中时,俯仰和枢轴伺服系统是“居中”的。曲柄的安装方式是,当处于打开位置时,从正面看时,它会通过逆时针方向旋转而关闭。打开位置是杆和曲柄在一条直线上,再旋转10度直到锁定。

腿部组装是最简单的部分。 2-2.5 毫米螺钉,腿帽卡在每条腿的肘部上。使用的紧固件不要突出到腿板顶部。这样,如果您调整旋转范围,旋转体就不会绑定。

与打印部件的所有伺服连接均使用伺服系统附带的白色短曲柄进行。这些曲柄只是压入打印部件中。我尝试在连接到每个伺服器的零件中打印花键孔,但成功率有限,可重复。使用伺服系统附带的曲柄更容易。

曲柄组件使用较长的 2.5mm 螺钉。曲柄杆不应被挤压在两半曲柄之间。事实上,您可以尝试在没有 Crank2 部件的情况下使用较短的螺钉。这也应该有效(如果机翼自由滑动,希望这里没有明显的扭矩)。

扬声器由捕获扬声器的伺服支架(2 个)捕获。这些“腿”之间的扬声器,并通过将它们固定到音高伺服器来保持位置。这个伺服然后连接到俯仰(滑块)组件,然后是带有杆的曲柄组件。所有这些都是在用 4 个小螺丝安装到 LHS 机身之前组装的。

一旦安装了主要的内脏,Arduino 和 MP3 播放器临时放置,那么乐趣就开始了 - 接线!

第 6 步:接线

V5 - 无线电选项(红色炮塔照片)。这包括一个 nRF24L01 无线电芯片。完全改变 Arduino 引脚接线以适应所有连接。详情来...

最终的包装很紧凑,所以花一些时间在这里弄清楚电线长度是非常值得的。我最终得到的大多数互连线都在 3" - 4" 之间。

LED 直接与 220 欧姆电阻器连接,然后进行一些收缩包装和一些接线扭曲,然后在经过测试后放在一边。我在这里使用了轻型布线,因为我周围有一些(CAT5 类型的通信布线)并且不希望可见的布线显得突兀。

机械钻头模拟安装在外壳中,然后确定布线,然后切割和准备电线。

我建造了伺服连接器,这样我就可以插入并更换伺服系统,如果我搞砸了一些东西并剥离了齿轮。在我的第一个原型中搞砸之后,这绝对有帮助。

一旦对大量布线感到满意,LED 就会在最后焊接起来。然后是时候小心地将接线组件塞进外壳的一半了。最后一步是将电源连接器全部放入电源线后将其焊接到电源线上。

-- 重要提示:确保塞在 Nano 后面的接线没有按下重置按钮!!这显然会导致问题并阻止设备正常运行。 --

此时,所有接线都已完成,但在最终组装之前,重要的是将代码上传到 Nano 并为其通电,以确保 LED、伺服器和 MP3 播放器都按设计工作。之后,是时候把剩下的机械钻头放在一起了。

第 7 步:Arduino 代码

更新代码!清理它并进行了一些调整。

附件是我想出的驱动该装置的文件,如视频所示。我将继续调整以改变炮塔的特性及其行为方式。这里有很多选择。

我使用我根据需要调用的子程序来构建代码。它保持主体清洁,当我玩弄不同的特性时非常有帮助。它帮助我针对不同的行为操纵代码。

例如,我还预先使用了许多变量,这有助于我调整和调整停车位置以及最小和最大范围。

我在我的代码中使用了 DFMiniMP3 库。我尝试了其他库,例如 DFRobot 库,但遇到了问题,所以又回到了这个库。这意味着我必须保留“静态无效”部分以保持其功能。这些不是操作所必需的,但是嘿,我不是编码大师。我很想听到另一个与 VL53LOX 库一样简单和整洁的库。如果您找到更好的方法,请告诉我!

至于声音,实现的方法很简单,在SD卡上有一个名为“mp3”的文件夹,文件名为0001.mp3、0002.mp3等。前四位数字必须是这种格式,但是您可以在此之后添加任何后缀来帮助识别特定的声音。有关示例,请参见 https://www.dfrobot.com/blog-277.html。我已经包含了我在文件夹中使用的文件名的图片。数字对应于代码中的呼出。

我从 Portal Turret 声音的维基百科页面中提取的声音文件。该代码会随机生成一个声音文件(2 个或 3 个声音中的 1 个)以防止内容过时。

第 8 步:最终车身组装

由于黑色填充条,这部分有点棘手。最终组装的规模足够小,使得条带和接收槽很小。这需要用指针或其他小型刮削工具追逐通道,以确保条带在尝试将另一侧放在上面之前几乎没有阻力。

将电线整齐地绑在一起并根据需要绑扎起来会使这件事变得容易得多。

我现在已经把其中的几个放在一起,发现先把两半放在一起,然后插入填充条更容易。将一侧插入带有防止填充条掉入的“架子”的一半,然后轻轻撬开并轻轻压入。现在还不错。

这是比较棘手的部分之一。也许有一天,我会重新考虑这个程序集,但我确实喜欢它完成后的样子,而且它非常坚固。

第 9 步:机翼组件

现在身体已经在一起了,机翼 LED 灯伸出来,是时候准备机翼并组装起来了。

必须用 1/8" 钻头钻出滑块孔,然后将其清理干净。使用断线钳、虎钳、钢锯或最喜欢的剪钉工具将头部从钉子上剪下来。滑块销(剪下的钉子) ) 通过将它们压装到每个翼片上而安装到翼中。笔直、去毛刺和平滑的钉子是完成这项工作的关键。翼滑块和孔在连接曲柄杆和运行之前应进行润滑和测试。干燥推荐使用石墨或其他 PLA 合适的润滑剂。我发现一小管个人润滑剂效果很好,而且便宜。它真的很光滑。当你的伴侣或父母进来并询问究竟是什么时,它还需要一些“splainin”你在工作台上需要它!!

首先弄清楚机翼的哪个部分去哪里,然后先尝试滑动那个部分。安装好销钉后,然后将上半部和下半部安装在一起,涂抹一些润滑剂(q-tip 对此很有效)并确保机翼滑动良好。这可能很棘手,但如果不确保机翼轻松滑动,没有绑定,您将陷入沮丧的境地。相信我...

一旦机翼准备好,只需将它们滑入到位,将连杆定位在机翼上的孔上并用单个螺钉组装。然后,将 LED 插入枪孔中,将电线塞在机翼上,您就可以开始了!测试完所有内容后,您还可以使用一些热胶将它们锁定到位。

第 10 步:吓唬你的朋友!

这种设计的最后一点需要注意的是,有角度的插头是一个好主意,因为它在旋转时不会干扰后腿。修改后的后腿 (v3) 已被拉伸以提供更多空间。

一旦构建并插入(5V 或适用于 Nano),它会安静地坐着,直到在编程的距离内检测到有人,然后复活并杀死任何进入其领域的人!!

如果您构建了一个(或多个),并且提出了新的功能或概念,请告诉我!

代码

  • Portal turret w Radio (RED)
Portal turret w Radio (RED)C/C++
用于炮塔的代码。这包括将启用主炮塔控制的代码,在另一页上有特色。
不同的口味需要调整。
///* 传送门炮塔 - 带有收音机的选项!! * Chris Nowak - 2019 年 2 月 * https://www.instructables.com/member/ChrisN219/ * https://create.arduino.cc/projecthub/Novachris/talking-portal-2-turret-gun-637bf3 * * 这代码包括执行 Cara Mia Opera 所需的所有功能,*聊天时间和手动模式,由 Maseter Turret Control (MTC) 控制。 * MTC 是另一个版本的独立控制器。炮塔 * 将使用此代码自主运行,无需 MTC。 * * 代码可与三个炮塔配合使用,但每个炮塔都将独立运行。 * 保留了大量调试代码。根据需要使用或清理。它主要经过调试,* 但并不完美。鉴于您支付的价格,我认为没关系!;) * ================红色 ====================*/#include  #include #include "Arduino.h"#include #include #include #include #include # include class Mp3Notify{public:static void OnError(uint8_t errorCode) { // 参见 DfMp3_Error 代码含义 Serial.println(); Serial.print("通讯错误"); Serial.println(errorCode); } static void OnPlayFinished(uint8_t globalTrack) { Serial.println(); Serial.print("播放完毕#"); Serial.println(globalTrack); } static void OnCardOnline(uint8_t code) { Serial.println(); Serial.print("卡片在线"); Serial.println(代码); } static void OnCardInserted(uint8_t code) { Serial.println(); Serial.print("卡插入"); Serial.println(代码); } static void OnCardRemoved(uint8_t code) { Serial.println(); Serial.print("卡片已移除"); Serial.println(代码); }}; Servoservo_pivot;Servoservo_wings;Servoservo_pitch;VL53L0X sensor;//设置声卡SoftwareSerial secondarySerial(4, 2); // RX, TXDFMiniMp3 mp3(secondarySerial);// radioRF24 radio(10, 9)的设置; // nRF24L01 (CE,CSN)RF24Network network(radio); // 在 networkconst 中包含 radioconst uint64_t this_node =01; // 这个炮塔 - 红色 - 八进制格式(04,031 等)const uint64_t WHT =02; // 炮塔 02 - Whiteconst uint64_t BLU =03; // 炮塔 03 - Blueconst uint64_t MTC =00; // 主炮塔控制unsigned long previousMillis1 =0;unsigned long previousMillis2 =0;unsigned long previousMillis3 =0;byte LED_LH_up =A1;byte LED_LH_down =A2;byte LED_CENTRE =A3;byte LED_RH_up =7;byte LED_RH_down =8;byte PIVOT =6; //whitebyte WINGS =3; //yellowbyte PITCH =5; //bluebyte parkPIVOT =96; //从topbyte posPIVOT =96;byte maxPIVOT =116;byte minPIVOT =76;byte WINGclose =165;byte WINGopen =10;byte WINGpos =160;byte parkPITCH =86;byte posPITCH =86;字节 maxPITCH =96;字节 minPITCH =75;字节位置 =90;字节脉冲 =20;字节pitchCW =1;字节pivotCW =1;字节随机唤醒;字节随机打开;字节随机假;字节随机开始;字节随机脱离;int triggerDistance =300;字节按钮状态;字节busyRed =1;字节restModeWhite;字节goState;int x;int y;字节pb1State; // Firebyte pb2State; // 说随机 commentbyte pb3State;byte randomPic;// 来自主炮塔控制 (MTC) 的有效载荷// int payload [] ={0, 1, 2 , 3 , 4 , 5 };// int payload [] ={x , y, pb1State, pb2State, pb3State, goState};int payload [6];/* 这是“聊天时间”的“对话”映射。 * 0-99 =红色炮台语 * 100-199 =白色炮台语 * 200-299 =蓝色炮台语 * 所有 SD 卡上的文件都保存为 0-100。 * 在此处的文件编号中为白色添加 100,为蓝色添加 200。 * 文件 204 将是蓝色炮塔,文件编号 0004。 */ int chatSayings [] ={ 0, // 在 i =0 时开始暂停,然后是 "rounds"... 204, 164, 25, // 1 205, 127, 76, // 2 208, 162, 65, // 3 143, 230, 23, // 4 130, 41, 225, // 5 153, 31, 133, // 6 234, 49, 155, / / 7 229, 175, 74, // 8 231, 58, 226, // 9 161, 223, 59, // 10 227, 68, 236, // 11 136, 50, 224, // 12 34, 1 , 78, // 13 222, 42 // End};/* 这是红白炮塔时序图。他们分享谚语。 * 这些时间对应于 * 播放单个语句所需的时间,以毫秒为单位。 * 根据需要更改上面的说法,但不要更改这些时间。 * 例如, i =2 将需要 0.8 秒 (NormalTimings[2]) * 播放 chatSayings[2] 文件。 */int NormalTimings [] ={1000, // 在 i =0 时开始暂停,然后是 "rounds"...2600, 800, 2800, 900, 1700, 1600, 1300, 2500, 1400, 1900, // 1 - 101600, 2300, 800, 3000, 300, 100, 200, 0, 0, 300, // 11 - 20298000, 1300, 2600, 1300, 1400, 2100, 0, 10, 10, 11, 0, 10 , 1000, 1000, 2100, 1500, 1300, 1100, 800, 1200, 1000, // 31 - 402200, 1700, 1300, 1400, 1500, 10,0,0,0,0,10,0,0,10009 , 900, 2400, 1200, 1100, 2100, 2000, 2500, 1700, // 51 - 601100, 1000, 1100, 500, 1900, 0, 1300, 10, 10, 10, 0, 10, 10, 0, 10, 010, 010 , 1700, 1100, 1100, 1500, 1500, 500, 900, // 71 - 802100 // 81};/* 这是蓝色炮塔时序图。 * 这些时间对应于 * 播放个别谚语所需的时间,以秒为单位。 * 例如, i =2 将需要 0.9 秒 (DefectiveTimings[2]) * 播放 chatSayings [2] 文件。 */int DefectiveTimings [] ={1000, // 在 i =0 时开始暂停,然后是 "rounds"...1700, 900, 2000, 600, 1100, 1800, 1900, 3000, 1500, 800, // 1 - 102100, 800, 1900, 900, 3200, 2700, 0, 0, 0, 2000, // 11 - 204400, 800, 3200, 900, 1400, 2000, 10, 10, 10, 10, 10, 0, 2000, // , 1400, 2100, 1000, 1600, 1000, 1200 // 31 - 40};//////////////////////////// //////////////////////////////////////======================设置==================================//// ////////////////////////////////////////////////// ////////////void setup(){ secondarySerial.begin(9600);// Serial.begin(9600);// mp3.begin(); mp3.setVolume(22); Wire.begin(); SPI.begin(); // 无线电设置 radio.begin(); radio.setPALevel(RF24_PA_LOW); // 将无线电设置为低功率。彼此靠近 radio.setDataRate(RF24_2MBPS); // 我发现这对多个无线电最有效 network.begin(70, this_node); //(通道,节点地址)sensor_read(); pinMode(LED_LH_up,输出); pinMode(LED_LH_down,输出); pinMode(LED_CENTRE,输出); pinMode(LED_RH_up,输出); pinMode(LED_RH_down,输出);数字写入(LED_CENTRE,高); activate_servos();伺服翼。写(WINGopen); // 打开翅膀servo_pivot.write(parkPIVOT); // 停放枢轴servo_pitch.write(parkPITCH); // 停放球场 randomWake =random(1, 3); mp3.playMp3FolderTrack(1); // 播放唤醒评论延迟(2000);伺服翼。写(翼关闭); // 关闭翅膀延迟(1500);数字写入(LED_CENTRE,低); turn_off_servos(); busyRed =0;}/////////////////////////////////////////// //////////////////////========================主循环 =============================////////////////////// ///////////////////////////////////////////////无效循环( ){ while (sensor.readRangeSingleMillimeters()>triggerDistance) { //传感器前面什么都不做,什么都不做 ReadNet();写网络();输出传感器(); if (payload[5] ==1) { // 与 MTC 一起使用的条件。炮塔自动工作,无MTC延迟(500);写网络(); Cara_Mia(); // 歌剧时间!! } else if (payload[5] ==2) { delay(500);写网络(); Chatty_time(); // 闲聊时间!!} ReadNet(); } else if (payload[5] ==3) { delay(500);写网络();手动 (); // 手动控制 } } if (sensor.readRangeSingleMillimeters()triggerDistance){ // 打开后人走了 falseActivate(); //说“你去哪儿了?”评论和关闭延迟(2000);扫描区域(); // 执行区域扫描 } else { // 肯定有人在那里 - 开火!!从事();延迟(2400); for (int j=0; j <=2; j++){ if (sensor.readRangeSingleMillimeters()=maxPIVOT)pivotCW =0;如果(posPIVOT <=minPIVOT)pivotCW =1;如果(posPITCH>=maxPITCH)pitchCW =0; if (posPITCH <=minPITCH) pitchCW =1;}//////////////////////////////////// ///////////////////////////////========================激活 ==============================////////////// ////////////////////////////////////////////////// ////void activate(){ // 张开翅膀说些话busyRed =1;读取网络();写网络();输出传感器();数字写入(LED_CENTRE,高); // LED 眼睛 on randomOpen =random(3, 6);// 选择随机开场评论 mp3.playMp3FolderTrack(randomOpen); // 随机播放“我看见你”评论servo_wings.write(WINGopen); // 打开翅膀 output_sensor();延迟 (3400);}////////////////////////////////////////// /////////////////////////====================假激活 =============================//////////////////////// //////////////////////////////////////////void falseActivate(){ / /busyRed =1;读取网络();写网络();输出传感器(); randomFalse =random(6, 9);// 随机选取开头评论 mp3.playMp3FolderTrack(randomFalse); // 随机播放“你去哪儿了?”评论延迟(1800);}///////////////////////////////////////// ////////////////////////==========================扫描区域 ==============================////////////////// /////////////////////////////////////////////////空白scanArea(){ // continue scanning for a bit after falseActivate busyRed =1; ReadNet(); WriteNet(); output_sensor(); mp3.playMp3FolderTrack(2); // "searching..." servo_pitch.write(parkPITCH); delay(1600); servo_pitch.detach(); servo_wings.detach(); mp3.playMp3FolderTrack(21); for (int i=0; i <=220; i++){ //scan for a little bit... output_sensor(); if (pivotCW ==0) posPIVOT =posPIVOT - 1; // increment one step CW if CW =0 if (pivotCW ==1) posPIVOT =posPIVOT + 1; // otherwise go one step other direction if (posPIVOT>=maxPIVOT) pivotCW =0; // if max rotation clockwise, switch to counterclockwise if (posPIVOT <=minPIVOT) pivotCW =1; // if min rotation counterclockwise,switch to clockwise servo_pivot.write(posPIVOT); if (sensor.readRangeSingleMillimeters()=(850 + (i * 100))) { // 1050 randomWingPos =random(10 + (i*20), (60 + (i*20))); servo_wings.write(randomWingPos); previousMillis1 =millis(); } } } disengage(); busyRed =0; goState =0; mp3.stop(); ReadNet(); delay(1000);}/////////////////////////////////////////////////////////////////// //=======================CHATTY TIME ===========================/////////////////////////////////////////////////////////////////////void Chatty_time(){ busyRed =1; WriteNet(); int i =0; int talk; int saying; int timeadder =750; int talkTime =NormalTimings[i]; int randomPivotPos; activate_servos(); servo_wings.write(WINGopen); digitalWrite(LED_CENTRE, HIGH); do { ReadNet(); WriteNet(); //output_sensor(); // used for debugging... if (i>=43) { // end of sequence busyRed =0; WriteNet(); disengage();返回; } unsigned long currentMillis =millis(); // grab current time if ((unsigned long)(currentMillis - previousMillis3)>=talkTime) { if (chatSayings[i] <100) { // RED Turret talking talk =chatSayings[i]; saying =chatSayings[i]; talkTime =(NormalTimings[saying] + timeadder); } else if ((chatSayings[i]> 99) &&(chatSayings[i] <200)) { // WHITE turret talking talk =0; saying =chatSayings[i] - 100; talkTime =(NormalTimings[saying] + timeadder); } else { // BLUE turret talking talk =0; saying =chatSayings[i] - 200; // sound file # of BLUE talkTime =(DefectiveTimings[saying] + timeadder); // Time for that saying } if (talk ==0) { digitalWrite(LED_CENTRE, LOW); } else { digitalWrite(LED_CENTRE, HIGH); mp3.playMp3FolderTrack(talk); } randomPivotPos =random(minPIVOT, maxPIVOT); servo_pivot.write(randomPivotPos); Serial.println(); Serial.print(F("i:")); Serial.print (i); Serial.print ("\t"); Serial.print(F("chatSayings[i] ")); Serial.print (chatSayings[i]); Serial.print ("\t"); Serial.print(F("Saying ")); Serial.print (saying); Serial.print ("\t"); Serial.print(F("talk ")); Serial.print (talk); Serial.print ("\t"); Serial.print(F("chat time ")); Serial.print (talkTime); Serial.print ("\t"); Serial.print(F("busyRed:"));Serial.print (busyRed); Serial.print(""); previousMillis3 =millis();我++; } } while (payload[4] ==1); busyRed =0; WriteNet(); digitalWrite(LED_CENTRE, LOW); disengage();}/////////////////////////////////////////////////////////////////// //=======================MANUAL CONTROL =======================/////////////////////////////////////////////////////////////////////void ManualControl(){ int servoWings; int servoPitch; int servoPivot; activate_servos(); servo_wings.write(WINGopen); digitalWrite(LED_CENTRE, HIGH); ReadNet(); do { output_sensor(); ReadNet(); servoPivot =map(payload[0], 1023, 0, minPIVOT, maxPIVOT); servoPitch =map(payload[1], 1023, 0, minPITCH, maxPITCH); servo_pivot.write(servoPivot); servo_pitch.write(servoPitch); unsigned long currentMillis =millis(); // grab current time if (payload[3] ==0) { if ((unsigned long)(currentMillis - previousMillis1)>=2500) { randomPic =random(1, 20); mp3.playMp3FolderTrack(randomPic); previousMillis1 =millis(); } } if (payload[2] ==0){ fire(); } } while (payload[5] ==3); disengage(); busyRed =0; WriteNet(); digitalWrite(LED_CENTRE, LOW); }/////////////////////////////////////////////////////////////////////=========================RECEIVING ===========================/////////////////////////////////////////////////////////////////////void ReadNet(){ network.update(); if ( network.available() ) { RF24NetworkHeader header; network.peek(header); network.read(header, &payload, sizeof(payload));} // Read the package }/////////////////////////////////////////////////////////////////////=========================SENDING =============================/////////////////////////////////////////////////////////////////////void WriteNet(){ network.update(); RF24NetworkHeader header4(MTC); bool ok4 =network.write(header4, &busyRed, sizeof(busyRed));/* if (ok4) { // used for debugging... Serial.print("MTC ok4 ");} else { Serial.print("------- ");} */}

定制零件和外壳

Lens%2Bv3b.stl Body-RHS%2Bv4.stl Body-LHS%2Bw%2Bcomponents%2Bv4.stl Wing%2BRH%2Bbottom%2Bv4.stl Wing%2BRH%2Btop%2Bv4.stl Wing%2BLH%2Bbottom%2Bv4.stl Wing%2BLH%2Btop%2Bv4.stl Pitch%2BFrame%2Bv4.stl Leg%2B-%2BREAR%2Bv4.stl Infill%2Bstrips%2Bv3.stl Leg%2B-%2BREAR%2Btest.stl Pitch%2BFrame%2B-%2Bmodified%2B1.stl Arduino%2BBase%2Bw%2BRadio.stl

示意图

Schematic that I made for building the turret.

制造工艺

  1. 琥珀色
  2. 断头台
  3. 墓碑
  4. 泳装
  5. 滑板
  6. 汤普森冲锋枪
  7. 伏特加
  8. 轮播
  9. 沙发
  10. 末端加工转塔缩短循环时间