热门资讯
选择困难症福音: DIY“囚徒困境”抢答器
来源:3XMaker 发布时间:2019年03月26日选择困难症福音: DIY“囚徒困境”抢答器
0.序言
本作品是和几名工业设计专业的同学在十一月一起做的一个 workshop 产物,有相关的 Arduino 课程。
主要的分工,我来写代码,调试程序,排布器件。工业设计的同学做了模型和实体。
这篇文章是我稍带演绎的一篇纪录~
成品做出来好漂亮,大家都是心灵手巧的人啊~
1.理念和需求
workshop 的主题是做一个儿童向的互动玩具,用于抢答情景。我觉得这个情景不局限于自身,在以下场景中:
“谁去拿快递?”
“谁叫外卖?”
“谁来埋单?”
需求如下:
抢答场景:定然有两个按键输入。用于比谁更快速
输出的指示: 有一个输出的灯光指示,用于给予开始抢答的信号。
输出的指示: 有若干计分灯光,用于计分。这部分和工设联动,设计成了一个灯光爬山的效果。
胜利条件: 谁抢到山顶的“灯”谁就胜利!
输入: 用于resetstart
2.作品设计
2.1 外观设计
外观是一座山,模拟两个人攀比登峰,谁先到山顶,谁便胜利。手工制作实体,和输入按键。可以看到我排的led灯在山的两侧
2.2 硬件设计
主控当然选用 Arduino,因为 workshop要求就是用它来当主控。
输入我选用了3端入口,为了节省不太富裕的io口。一个用于 startreset,另外两个是抢答端。
输出的话依赖灯光。选用了4+4+1的设计,正好用足了所有的io口。因为没必要加外部元件用于专门的灯光管理。索性直接用 Arduino 驱动。
另外说一句,pullup 功能可以自带拉高点评。因此输入端不需要人工布线拉高电平。
2.3 逻辑设计:
红灯用于指示抢答。
状态1:所有 led 跑马灯,等待红色按钮输入开始信号。
状态2:开始抢答,红灯亮起。若干秒后熄灭,开始按钮抢答输入
状态3:成功抢答的一端判断为胜利。计数加1,蓝灯或绿灯亮起。亮满4个最终胜利
状态4:重新循环状态1
2.4 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | /* 趴会儿Project项目集 http://steinslab.xyz/archives/752 No.002 详见http://steinslab.xyz/archives/1008 囚徒困境抢答器-《命运女神的抉择》 SPtuan@steinslab.xyz */
int A[4]={10,11,12,13}; int B[4]={6,7,8,9}; int info = 5; int Ain = 4; int Bin = 3; int Cin = 2; volatile int flag=0; int Aflag=0,Bflag=0,ix=0,jx=0; int Atemp=Aflag; int Btemp=Bflag;
void setup() { Serial.begin(9600); for(ix=0;ix<4;ix++) { pinMode(A[ix],OUTPUT); digitalWrite(A[ix],LOW); pinMode(B[ix],OUTPUT); digitalWrite(B[ix],LOW); } pinMode(Ain,INPUT_PULLUP); pinMode(Bin,INPUT_PULLUP); pinMode(Cin,INPUT_PULLUP); pinMode(info,OUTPUT); digitalWrite(info,LOW); attachInterrupt(0,signal0,RISING); }
void signal0() { if(flag==0) flag = 1; }
void wait() { digitalWrite(info,HIGH); delay(3000); digitalWrite(info,LOW); }
void display0() { digitalWrite(B[Bflag-1],HIGH); digitalWrite(A[Aflag-1],HIGH); }
void display1() { if(Aflag==4) { for(ix=0;ix<3;ix++) { for(jx=0;jx<4;jx++) { digitalWrite(A[jx],HIGH); digitalWrite(B[jx],LOW); } delay(500); for(jx=0;jx<4;jx++) { digitalWrite(A[jx],LOW); } delay(500); } }
else if(Bflag==4) { for(ix=0;ix<3;ix++) { for(jx=0;jx<4;jx++) { digitalWrite(B[jx],HIGH); digitalWrite(A[jx],LOW); } delay(500); for(jx=0;jx<4;jx++) { digitalWrite(B[jx],LOW); } delay(500); } } } void loop() { Atemp=Aflag=Btemp=Bflag=0; do { for(ix=0;ix<4;ix++) { digitalWrite(A[ix],HIGH); digitalWrite(B[ix],HIGH); delay(300); if(flag==1) break; } for(ix=0;ix<4;ix++) { digitalWrite(A[ix],LOW); digitalWrite(B[ix],LOW); delay(300); if(flag==1) break;
} }while(flag==0); for(ix=0;ix<4;ix++) { digitalWrite(A[ix],LOW); digitalWrite(B[ix],LOW);
} delay(1000); do { do{ wait(); Atemp=Aflag; Btemp=Bflag; do{ if(digitalRead(Ain)==LOW) { delay(20); if(digitalRead(Ain)==LOW) Aflag++; Serial.print("Aflag"); while(digitalRead(Ain)==LOW); } else if(digitalRead(Bin)==LOW) { delay(20); if(digitalRead(Bin)==LOW) Bflag++; Serial.print("Bflag"); while(digitalRead(Bin)==LOW); } }while((Atemp==Aflag)&&(Btemp==Bflag)); display0(); if(Bflag<4) digitalWrite(B[3],LOW); if(Aflag<4) digitalWrite(A[3],LOW);
}while((Aflag!=4)&&(Bflag!=4)); display1(); flag = 0; }while(flag==1); } |
注:后来我也思考了一下。这个代码还是有相当的改进余地的。
对于抢答按钮的输入,使用了循环扫描的方法,势必会有一个优先级的问题,一旦一个持续按下,就会触发 bug 必赢。
可以改用中断,套用几个 flag 变量,综合判断真正在抢答器结束后按击的人。或者提前按下的人直接判负。
3 展示
3.1 成果
我和小崔在原形上就玩得不亦乐乎……生生玩了一晚上……
作品最后外观是相当漂亮的~
工设同学做的项目记录总是非常漂亮的,下面是制作过程若干图片。
固定 LED。
在面包板上调试LED。
制作抢答按钮。
连接导线。
在纸板上布线,固定。
将LED迁移到了做好的纸板上。
纯手工剪纸技艺,做最后的装饰。
大功告成!