乞丐版ATmega8L的实践——敲击开关(arduino自动开关茶桌)

关键字:敲击开关 自动茶台 蛐蛐叫声 ATmega8L


cricket.jpg





早就想改下我办公室的自动茶台了。早年用数字电路4017搭的控制器一直不稳定,后来索性改成遥控工作了,可这不符合我追求完美的习惯。



说说初衷:经过声控、磁控、触摸、遥控、金属按钮等多种方案理性评估后,还是感性的认为,敲击控制的开关在这种场合比较有感觉。于是我又胡乱的搜了一圈,证明大脑短路的还是自己——没有发现有人设计过这种开关,可能是大家觉得这个设计不够炫,很白痴吧。。。但是,我喜欢





一接触Arduino,我就罗列了一堆想做的东西,敲击开关的应用是首当其冲的。不过Arduino成品板做这么简单的应用,有些大材小用了。自从上一次我的乞丐版ATmega8L烧制成功,觉得这个价位和功能特别适合这种应用。不是简单的成本问题,只是觉得用这个价位实现这个功能更有乐趣。



电路部分也无需多说,在上次的ATmega8L最小系统板子上直接焊接了两路三极管结构驱动的继电器输出,用来驱动茶台的开合;常规供电是12V的,加了个7805的电源电路用来对MCU供电;传感器是几年前从电子市场上买的报警器用的震动传感器,拆开后发现实质是压电陶瓷片配合运放电路的模块,灵敏度可调。


p1070187.jpg



传感器,买了很久了。当时价格好像是¥15



另外需要说明的是,以前有一路扩展功能(茶台隔板的水平移动,使用储物空间)因为机械部分材料不可靠被拆掉了,程序中已经预留了接口,以后再改结构恢复。

p1070191.jpg



在上期做的乞丐版8L洞洞板上直接焊接的三极管,继电器,稳压IC。裁掉周边多余的,刚好装入以前的遥控接收外壳。

p1070192.jpg



背面看惨不忍睹...



控制部分总共花费< ¥25



完整的功能实现:



1.系统接电启动,蜂鸣器发出三声蛐蛐低音叫声,然后停顿后发出两声高音叫声,表示系统已经启动。

关于声音部分,有个花絮:我一直接受不了有源蜂鸣器产生的单一”嘀“的噪声,本来打算用音符体现,结果调用一个音符库就要6k左右空间,对于8k的容量来说,是不可能完成的任务。如果没有音符,我能接受的就是高级轿车安全带提示的咚咚声,但我一直不知是怎么实现的,据说用了和弦芯片。希望有了解的同学给扫下盲。经过无意间的实践,居然歪打正着的把铃音调成了蛐蛐叫声。

而且音色还算正点。但最理想的状态是不接有源蜂鸣器的保护贴纸,就会产生蛐蛐叫的效果,揭了以后像是另一种虫子,本地叫“油葫芦”,不过声音太大,不实用。细节决定成败,在提示音的问题上,用最简单的几行代码做了个蛐蛐效果,而且重要的是在这个场合比较合适,超过了我最喜欢的“咚咚”声(用在仪器上会更好)。

言归正传,此时系统已经启动成功开始待命了。





2.茶台展开:用手有节奏的拍击桌面三次,表示茶台展开指令,蜂鸣器发出两声高音蛐蛐叫声,继电器工作,驱动推杆电机将茶台展开。如果敲击一次,或者二次,四次、五次。。。茶台会认为是干扰信号,发出三声低音蛐蛐叫声,重新等待指令。



3.茶台隔板平移,展开储物空间。(这个功能目前因为机械原因暂时没有加入,但程序中已经体现)这是下一个逻辑,茶台展开时才会启用。用手有节奏的拍击桌面两次,蜂鸣器发出两声高音蛐蛐叫声,继电器工作,驱动电机工作,将茶台隔板平移,展开储物空间,这时,可以把藏在储物空间里的好茶拿出来了。!-_-这里的电机,以前是上学时花3块钱买的处理110v步进电机,以后准备换成同步电机。舵机其实可以直接用,但速度太快,不优雅。。。(从没用过舵机,不知能不能加入pwm调速功能)



然后,再拍两次,隔板平移归位,此时就可以泡茶了。



如果在隔板移开的情况下,拍了三次,或者别的次数,茶台都会忽略,发出三声低音叫声,表示抗议。



4.茶台恢复。茶喝完了,在隔板归位的前提下,或者你只是无聊试试,根本没有拍出隔板,再拍三次,继电器工作,推杆电机换相,茶台关闭,得瑟结束。中间设计了一个友善的停顿,防止夹手。



照片在相机里没导出,回头补上。



当年的视频,比较完整,后来把隔板功能去掉了,换成了能储水的小茶台,最近准备恢复。

视频需要头部左倾90度观赏。





代码是在深夜在神志不清前,写了两个多小时。很乱,逻辑更乱,期待达人给优化一下。
输出后hex是5103字节,还算满意。我把编译后的hex附上,有8L的可以直接用USBISP线烧进去。
//Knocking switch by Thomas 2012.04.28

int sensorPin = A0; // 指定震动传感器输入端口
int BeepPin = 8; // 指定有源蜂鸣器输出端口
int b3Pin1 = 3; // 指定b3功能输出继电器端口,给推杆电机换向用。
int b3Pin2 = 4; // 指定b3功能输出继电器端口,给推杆电机换向用。
int b2Pin = 2; // 指定b2功能输出继电器端口,此功能以后启用。
int iv = 0; // input value 输入数值置零
int si=0; // 输入编码号置零
unsigned long time=0; //计时器清零
unsigned long t0=0; //
unsigned long t1=0; //敲击时间
unsigned long t11=0;//空闲时间
int taMax=837; //时间常数初始化
int taMin=400; //时间常数初始化
int ba=2500; //敲击失效等待时间
int tcMax=190; //敲击时间上限
int tcMin=90; //敲击时间下线
int b2status=0; //功能模块互锁逻辑参数
int b3status=0; //功能模块互锁逻辑参数
boolean tw=false; //敲击逻辑开关
boolean bw=false; //等待逻辑开关
boolean b2lock=true;//功能模块互锁逻辑开关
boolean b3lock=false; //功能模块互锁逻辑开关

void setup() {
pinMode(BeepPin, OUTPUT); //初始化端口
pinMode(b2Pin, OUTPUT);
pinMode(b3Pin1, OUTPUT);
pinMode(b3Pin2, OUTPUT);
beep_long(); //蛐蛐开叫,证明系统运行。
delay(1000);
beep_short();
}

void loop() {
iv = analogRead(sensorPin);//监测传感器
time = millis(); //计时器基准
if(iv<tcMin){ //是否触发判断
if(tw==false){ //各种逻辑顺序...
tw=true;
bw=false;
t0=time;
}
}
else if(iv>tcMax){ //如果触发

if(tw==true){//如果触发并启动等待判断
t1=time-t0;
tw=false;

if(t1>taMin&&t1<taMax){//有效触发时间窗口
si++;
bw=true;
t11=time+ba;
}
else{
si=0;
t1=0;
}
}

if(bw==true){//如果敲击后,判断空闲时间
if(time>t11){
bw=false;
btSwitch(); //空闲时间过后,根据敲击次数调用相应代码
si=0;
}
}
else{
t11=time+ba;
}
}
}


void btSwitch(void){
switch (si) {
case 1:
beep_long(); //敲击1次,蛐蛐长叫表示抗议。
break;
case 2:
if(b2lock==false){
beep_short();//敲击2次,蛐蛐短叫表示成功触发,隔板动作。前提是,已经执行过敲击3次指令。
doSlide();
}
break;
case 3:
if(b3lock==false){
beep_short();
doOpen(); //敲击3次,蛐蛐短叫,为你开门,如果开门后,被敲击2次,激活隔板平移功能,开门功能被锁定,只接受2次敲击指令,直到隔板恢复。
}
break;
default:
beep_long();
//多敲无益,蛐蛐长叫表示抗议。
break;
}
}

void doOpen(){ //茶台展开功能
if(b3status==0){
b3status=1;
b2lock=false;
digitalWrite(b3Pin1, HIGH); // 1号继电器工作,推杆电机伸出
delay(10000); //10秒工作延迟
digitalWrite(b3Pin1, LOW); // 1号继电器停止工作
}
else{
b3status=0;
b2lock=true;
digitalWrite(b3Pin2, HIGH); // 2号继电器工作,换相,推杆电机缩回
delay(5000); // 5秒的工作延迟
digitalWrite(b3Pin2, LOW); // 友善的停顿1秒,防止夹手
delay(1000);
digitalWrite(b3Pin2, HIGH); // 恢复供电3秒,让推杆电机继续缩回归零
delay(3000);
digitalWrite(b3Pin2, LOW); // 2号继电器停止工作
}
}

void doSlide(){ //隔板滑动功能,没写完,硬件完善后再做
if(b2status==0){
b2status=1;
b3lock=true;
}
else{
b2status=0;
b3lock=false;
}
}

void beep_long(){ //蛐蛐叫声,表示错误。
for(int j=0;j<3;j++){
for(int i=0;i<5;i++){
digitalWrite(BeepPin, HIGH);
delay(20);
digitalWrite(BeepPin, LOW);
delay(20);
}
delay(800);
}
}

void beep_short(){ //蛐蛐叫声,表示成功。
for(int j=0;j<2;j++){
for(int i=0;i<2;i++){
digitalWrite(BeepPin, HIGH);
delay(20);
digitalWrite(BeepPin, LOW);
delay(20);
}
delay(500);
}
}



via - 极客工坊

标签: Arduino教程