无用箱项目:
在这次的Digi-DIY中,我将介绍如何利用无用箱进行创作。由于之前的箱子已经无法工作了,因此我决定将它的ATMEGA328P-PU芯片更新为Arduino Nano,以增加编程功能并提高易用性。
我从研究无用箱着手,尝试寻找任何其他DIY或操作教程。最终,我从Vagelis Chantzis获得了灵感,它帮助我掌握了有关此项目的基本知识。
在这一DIY指南中,我介绍了无用箱的制作过程,所以你也可以来试试这个有趣的项目。这个项目对我而言也是个很好的学习项目,正如你将看到的那样,在整个过程中会需要进行各种调整。和许多项目一样,我也遇到了一些问题。
比如说……
安装伺服电机: 我没有找到安装伺服电机的好方法。由于手臂会不停地压在物体上,因此我决定不切断热溶胶。随着时间的推移,它会因扭矩而自行从平坦的表面上撕开。随后我使用OnShape为两个伺服电机设计独特的支架。你可以看看下面的计划。
电源问题: 我的6伏电源有些问题。Arduino Nano至少需要7-12伏才能内部整流为5伏,以用于5伏引脚。由于馈电电压为6伏,它无法正确输出5伏电压。因此伺服电机的动力不足,无法工作。为解决这一问题,我制作了一根自定义电源电线馈入微型USB端口,因为它不会整流该电源。或者,你也可以只用一个6 AA电池组,以提供高达9伏的电压。
与一般的构建过程一样,我先将电路板焊接在一起。在能够通过示例代码工作的电路板做好之后,我开始制作箱子。准备好能够正常工作的伺服电机和箱子后,我留出了一个手臂长的行程距离。然后我在OnShape上画出手臂的形状,并用3D打印机打印出来。如果你没有3D打印机,也可以用木头做出类似的形状。总装完毕后,我需要解决电源问题。
Arduino Nano : (1050-1001-ND)
选择Arduino Nano是因为它体积小且易于编程。我打算使用小型电路板封装,而全尺寸的Arduino Uno对我而言有些偏大。
电路板选择: (1528-1195-ND)
在规划电路板布局(零件清单见下)时,我刚开始使用的是全尺寸的面包板,但后来我发现还剩余了过多的空间。为了保持小型封装的初衷,我用小型琢美(Dremel)工具和切割轮将全尺寸板切成两半,得到两块尺寸较小的板。我们也提供适合此类应用的一半长度的面包板(零件编号见上)。该板适合小尺寸的Arduino Nano,且仍然有足够的空间来放置所有其他组件。如果你想要更小的也可以。
布线: (BKWK-3-ND)
你可以在面包板上使用多种类型的电线。我选择的是‘布线用线’,因为它们的尺寸专为面包板设计,此外还采用了彩色和预先剥线设计。
伺服电机: (1528-1084-ND)
我决定使用5伏高转矩伺服电机,因为它适合Arduino Nano功率输出并且可以举起沉重的橡木箱子。如果你使用的是轻质材料(如塑料或轻木料),那么使用常规伺服电机即可。但需确保使用的是位置旋转电机,而不是连续旋转电机。
伺服电机引脚排列:
电源输入:红色
接地:棕色
控件:黄色
电容: (399-6602-ND)
最初的计划是使用两个100uF电容,以帮助抵消伺服电机的电流消耗。
插件头引脚: (S9258-ND)
由于伺服电机上具有3引脚母头连接器,因此可以轻松地在电路板上放置一些插件头引脚进行连接。
USB A 型(公)至 Micro B (公)型电线: (WM14083-ND)
我从此电线中切断了USB A型(公)部分,并将正负极引线连接到9伏卡扣电池连接器中,这样就做好了一个自定义电源电线。这条电线连接到电池组和Arduino Nano的Micro B型(公)部分。这样做是为了绕过Nano上的内部整流器,因为它未能将电池组的6伏电压正确转换为适用于5伏电源引脚的5伏电压。你需要7到12伏之间的电压,以便内部整流为5伏。
如果你使用的是6 AA电池组,则无需这样做。只需将电池组连接到Vin并接地即可。
9 伏卡扣电池连接器: (36-232-ND)
之所以选择此连接器是因为,它能够快速连接AA电源组,也可以快速断开其连接。
适用于 AA 的四槽电池座: (BH24AASF-ND)
之所以选择此零件是因为,它能够容纳为Arduino Nano供电(高达6伏)所需的四节AA电池。如使用6槽AA电池座(BH24AASF-ND),可输出9伏电压,而该电压需适当整流至5伏,以便用于Vin输入引脚。
单刀双掷开关: (EG2350-ND)
我沿用了上一个箱子中的开关,但如果必须重选一个的话,我会选择(EG2350-ND)。
开 / 关摇臂开关: (EG5619-ND)
如果你希望添加一个开/关电源开关以节省电池电量,可以将其设置在电池组和Vin引脚之间。
10kΩ 电阻: (CF14JT10K0CT-ND)
此电阻用于偏置来自SPDT开关的信号,从而告知电路板何时移动开关和闭门臂。
烙铁: (243-1267-ND)
焊料: (473-1128-ND)
剥线器: (K598-ND)
钳子: (K633-ND)
箱子尺寸:
箱子尺寸完全由你自己决定。我把自己所做的事情记录下来是为了让你有个总体的概念。你只需要记住从开关到箱盖边缘的行程距离。如果开关太远,则需要加长的开关臂才能碰得到。这可能会在箱子内造成行程问题。
(2个)7" x 5 ½"(尾端件)
(3个)12" x 5 ½"(箱壁+底部)
(1个)5 ½" x 5"(顶部1,箱盖)
(1个)5 ½" x 6 ¾"(顶部2,固定)
箱子信息:
木材:我用的是橡木,但轻质木材更易用于伺服电机。
结构:我做的箱子比较大,里面装了一些小组件。你在制作箱子时,可以缩小其尺寸。
其他零件:
2个小铰链(先拧入箱体端壁,然后拧入盖子。)
4个1/2"小螺丝(长度取决于所用材料的厚度。)
12个2"螺丝(用与螺丝芯尺寸相等的钻头预钻木材,以防木材裂开。)
钻
钻头(商店购买的标准组件即可。木头和塑料都很软,易于钻孔。)
砂纸(刚开始使用粗砂纸:40-50,然后使用中等砂纸:100,最后使用细砂纸:220-240)
铅笔
木凿(可选,因为我必须在木头中凿出一个区域来放置开关。)
闭门臂:
我用OnShape为项目制作了一个3D可打印的闭门臂。你可以“在此”查看具体设计。
自定义闭门臂支架:
我用OnShape为项目制作了一个3D可打印的闭门臂支架。你可以“在此”查看具体设计。
开关臂:
我用OnShape为项目制作了一个3D可打印的开关臂。你可以“在此”查看具体设计。
自定义开关臂支架:
我用OnShape为项目制作了一个3D可打印的开关臂支架。你可以“在此”查看具体设计。
电路图:
代码:
#include <Servo.h>
Servo doorServo;
Servo fingerServo;
int swPin = 2; // Switch on pin 2
int pos = 0; // Sets initial arm positions.
int selectedMove = 0; // Move selector
void setup() {
pinMode(swPin, INPUT); // Sets pin 2 as input.
doorServo.attach(9); // Sets door servo on Pin 9
fingerServo.attach(10); // Sets finger servo on Pin 10
doorServo.write(0); // Sets door to position
fingerServo.write(80); // Sets finger to position
}
void loop() { // If the switch is on, move door and finger to switch it off
if (digitalRead(swPin) == HIGH) {
if (selectedMove > 9) { // If greater than 9 count, reset to 0.
selectedMove = 0; // ^
}
if (selectedMove == 0) { // If count = 0 then perform this function / Same logic for the following.
simpleClose();
}
else if (selectedMove == 1) {
simpleClose();
}
else if (selectedMove == 2) {
simpleClose2();
}
else if (selectedMove == 3) {
crazydoor();
}
else if (selectedMove == 4) {
slow();
}
else if (selectedMove == 5) {
serious();
}
else if (selectedMove == 6) {
trollClose();
}
else if (selectedMove == 7) {
simpleClose();
}
else if (selectedMove == 8) {
matrix();
}
else if (selectedMove == 9) {
sneak();
}
selectedMove += 1; // Add's 1 to "selectMove" count.
}
}
void simpleClose() {
for (pos = 0; pos < 140; pos += 3) { // Defines starting postition for door
doorServo.write(pos); // Executes starting position for door
delay(20); // Delay before next action
}
for (pos = 0; pos < 200; pos += 4) { // Defines starting position for finger
fingerServo.write(pos); // Executes position position for finger
delay(10); // Delay before next action
}
for (pos = 200; pos >= 0; pos -= 4) { // Defines next position for finger
fingerServo.write(pos); // Executes next position for finger
delay(20); // Delay before next action
}
for (pos = 140; pos >= 0; pos -= 3) { // Defines next position for door
doorServo.write(pos); // Executes next position for door
delay(10); // Delay before next action
}
}
// The following code follows the same schema. Play around with the code to get the correct travel distance. Watch out for doorServo vs. fingerServo, to know which one you are using.
// The following code has extra delays (200+) to make the arms more expresive. Mess with these also to get different timings for movement.
void simpleClose2() {
for (pos = 0; pos < 140; pos += 3) {
doorServo.write(pos);
delay(15);
}
delay(800);
for (pos = 0; pos < 140; pos += 4) {
fingerServo.write(pos);
delay(15);
}
delay(1000);
for (pos = 140; pos < 180; pos += 4) {
fingerServo.write(pos);
delay(15);
}
for (pos = 180; pos >= 0; pos -= 5) {
fingerServo.write(pos);
delay(15);
}
for (pos = 140; pos >= 0; pos -= 3) {
doorServo.write(pos);
delay(15);
}
}
void crazydoor(){
for (pos = 0; pos < 120; pos += 3){
doorServo.write(pos);
delay(15);
}
for (pos = 120; pos >= 0; pos -= 5){
doorServo.write(pos);
delay(15);
}
for (pos = 0; pos < 120; pos += 3){
doorServo.write(pos);
delay(15);
}
for (pos = 120; pos >= 0; pos -= 15){
doorServo.write(pos);
delay(15);
}
delay(700);
for (pos = 0; pos < 120; pos += 3){
doorServo.write(pos);
delay(15);
}
delay(700);
for (pos = 120; pos >= 0; pos -= 5){
doorServo.write(pos);
delay(15);
}
for (pos = 0; pos < 140; pos += 8){
doorServo.write(pos);
delay(15);
}
for (pos = 0; pos < 180; pos += 3){
fingerServo.write(pos);
delay(15);
}
for (pos = 180; pos >= 0; pos -= 3){
fingerServo.write(pos);
delay(15);
}
for (pos = 140; pos >= 0; pos -= 15){
doorServo.write(pos);
delay(15);
}
}
void slow(){
for (pos = 0; pos < 130; pos += 1){
doorServo.write(pos);
delay(100);
}
for (pos = 80; pos < 160; pos += 1){
fingerServo.write(pos);
delay(100);
}
for (pos = 160; pos >= 80; pos -= 1){
fingerServo.write(pos);
delay(100);
}
for (pos = 130; pos >= 0; pos -= 1){
doorServo.write(pos);
delay(100);
}
}
void serious() {
for (pos = 0; pos < 130; pos += 3){
doorServo.write(pos);
delay(15);
}
for (pos = 80; pos < 120; pos += 1){
fingerServo.write(pos);
delay(15);
}
delay(800);
for (pos = 120; pos >= 100; pos -= 3){
doorServo.write(pos);
delay(15);
}
for (pos = 100; pos < 130; pos += 3){
doorServo.write(pos);
delay(15);
}
for (pos = 130; pos >= 90; pos -= 3){
doorServo.write(pos);
delay(15);
}
for (pos = 90; pos < 150; pos += 3){
doorServo.write(pos);
delay(15);
}
fingerServo.write(80);
delay(1000);
for (pos = 80; pos < 160; pos += 4){
fingerServo.write(pos);
delay(15);
}
for (pos = 160; pos >= 80; pos -= 4){
fingerServo.write(pos);
delay(15);
}
for (pos = 150; pos >= 0; pos -= 1){
doorServo.write(pos);
delay(15);
}
}
void trollClose() {
for (pos = 0; pos < 155; pos += 3){
doorServo.write(pos);
delay(15);
}
for (pos = 0; pos < 160; pos += 4){
fingerServo.write(pos);
delay(15);
}
for (pos = 155; pos >= 100; pos -= 3){
doorServo.write(pos);
delay(15);
}
delay(10000);
for (pos = 160; pos >= 0; pos -= 4){
fingerServo.write(pos);
delay(15);
}
for (pos = 100; pos >= 0; pos -= 3){
doorServo.write(pos);
delay(15);
}
}
void matrix(){
for (pos = 0; pos < 120; pos += 3){
doorServo.write(pos);
delay(15);
}
for (pos = 80; pos < 100; pos += 4){
fingerServo.write(pos);
delay(15);
}
for (pos = 100; pos < 160; pos += 1){
fingerServo.write(pos);
delay(30);
}
delay(300);
for (pos = 160; pos >= 0; pos -= 4){
fingerServo.write(pos);
delay(10);
}
for (pos = 120; pos >= 0; pos -= 3){
doorServo.write(pos);
delay(15);
}
}
void sneak(){
for (pos = 0; pos < 100; pos += 1) {
doorServo.write(pos);
delay(30);
}
delay(2000);
for (pos = 80; pos < 100; pos += 1) {
fingerServo.write(pos);
delay(30);
}
delay(500);
for (pos = 100; pos < 120; pos += 4) {
doorServo.write(pos);
delay(15);
}
delay(100);
for (pos = 100; pos < 130; pos += 4) {
fingerServo.write(pos);
delay(15);
}
delay(500);
for (pos = 130; pos >= 100; pos -= 4) {
fingerServo.write(pos);
delay(15);
}
delay(100);
for (pos = 100; pos < 130; pos += 4) {
fingerServo.write(pos);
delay(15);
}
delay(100);
for (pos = 130; pos >= 100; pos -= 4) {
fingerServo.write(pos);
delay(15);
}
delay(100);
for (pos = 100; pos < 160; pos += 4) {
fingerServo.write(pos);
delay(15);
}
for (pos = 160; pos >= 80; pos -= 4) {
fingerServo.write(pos);
delay(15);
}
for (pos = 120; pos >= 0; pos -= 3) {
doorServo.write(pos);
delay(15);
}
}