神圣的抉择!公平的对决!一种抢答器,可广泛用于“谁去拿快递”“谁叫外卖”“谁来埋单”等一系列令人深思的场景。
本项目隶属于趴会儿Project项目组,详见[企划]趴会儿Project–宿舍床上趴到底&解放双腿计划
项目编号002,分类为互动玩具/装置。
Table of Contents
0.序言
本作品是和几名工业设计专业的同学在十一月一起做的一个workshop产物,有相关的Arduino课程。
我则是纯去凑了热闹。
拖了这么久才攒文章,惭愧惭愧~
主要的分工,我来写代码,调试程序,排布器件。工业设计的同学做了模型和实体。
这篇文章是我稍带演绎的一篇纪录~
成品做出来好漂亮,工设的大触都是心灵手巧的人啊~
1.理念和需求
workshop的主题是做一个儿童向的互动玩具,用于抢答情景。我觉得这个情景不局限于自身,在以下场景中:
- “谁去拿快递?”
- “谁叫外卖?”
- “谁来埋单?”
都可以获得广泛的应用。所以我想了想,把它叫做
囚徒困境抢答器-《命运女神的抉择》(大雾)
——最棘手的问题,名字问题就算是解决了。
将需求分列出来,大概如下:
需求及对应的设计都写在这里 1 抢答场景:定然有两个按键输入。用于比谁更快速 2 输出的指示: 有一个输出的灯光指示,用于给予开始抢答的信号。 3 输出的指示: 有若干计分灯光,用于计分。这部分和工设联动,设计成了一个灯光爬山的效果。 4 胜利条件: 谁抢到山顶的“灯”谁就胜利! 5 输入: 用于reset\start
2 作品设计
2.1 外观设计
外观是一座山,模拟两个人攀比登峰,谁先到山顶,谁便胜利。手工制作实体,和输入按键。可以看到我排的led灯在山的两侧
2.2 硬件设计
主控当然选用Arduino,因为workshop要求就是用它来当主控。
输入我选用了3端入口,为了节省不太富裕的io口。一个用于start\reset,另外两个是抢答端。
输出的话依赖灯光。选用了4+4+1的设计,正好用足了所有的io口。因为没必要加外部元件用于专门的灯光管理。索性直接用Arduino驱动。
另外说一句,pullup功能可以自带拉高点评。因此输入端不需要人工布线拉高电平。
workshop产品就直接用杜邦线桥接的方式,一方面将led灯珠引脚直接穿透纸板,另一方面插入杜邦线,过短的地方用面包板线桥接,用胶带固定即可。
2.3 逻辑设计:
红灯用于指示抢答。
状态1:所有led跑马灯,等待红色按钮输入开始信号。
状态2:开始抢答,红灯亮起。若干秒后熄灭,开始按钮抢答输入
状态3:成功抢答的一端判断为胜利。计数加1,蓝灯或绿灯亮起。亮满4个最终胜利
状态4:重新循环状态1
2.4 代码段
/* 趴会儿Project项目集 https://steinslab.io/archives/752 No.002 详见https://steinslab.io/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 成果
我和小崔在原形上就玩得不亦乐乎……生生玩了一晚上……
视频大小2MB(原型时期录制)
作品最后外观是相当漂亮的~
工设同学做的项目记录总是非常漂亮的,下面是制作过程若干图片
成品图
[…] 2016-12-24 No.002 囚徒困境抢答器-《命运女神的抉择》 […]
卧槽,这么厉害,大触
@Cno 大佬说笑,一个作业
@SPtuan 我不是dalao。。。。
厉害word团长,考试周还能搞这个
@fandy 压仓底的存货儿,淡季拿出来发~
哈哈哈哈贼浮夸
@大树 原课题其实是抢答器玩具,被我演绎成了deepdark的东西了
@SPtuan 有意思