Arduino 比4X4矩阵按键更好的按键组设计

用最少的引脚连接最大的按键

  • 多按键的作用
  • 基本原理
    • 电阻的连接
    • 测试代码
  • 多按键开关电路图
    • 注意事项
    • 和4X4按键矩阵相比的优缺点
  • 密码锁
  • 附件

个人原创,未经允许请问转载!
该设计是由本人在2016年构想并经过多次改进设计出来的,未经允许勿用于商业等,未参考如何资料,如有雷同或侵权请联系博主

多按键的作用

可以用来制作密码锁,特别方便,因为连的线比较少,还可以制作钢琴,具体制作后期更新

基本原理

灵感来源于光明传感器(原理图如下),光明传感器接在模拟输入口会读取光敏电阻和定值电阻连接点的先对点位,也可理解成连接点与GND之间的电压,这也是模拟输入读取原理,由此可推导用按键开关控制电阻的串联、并联即可判断是哪个按键被按下。
Arduino 比4X4矩阵按键更好的按键组设计_第1张图片

电阻的连接

电路图如下
但S1按键本按下时,5V和A0之间的68k电阻与47k电阻并联,总电阻变小,A0读取的点位就会增大
但S2按键本按下时,GND和A0之间的68k电阻与47k电阻并联,总电阻变小,A0读取的点位就会增减小
Arduino 比4X4矩阵按键更好的按键组设计_第2张图片

测试代码

arduino IDE测试代码如下,打开串口监视器按下不同按键即可看到效果

// 测试代码
void setup()
{
  Serial.begin(9600);
}
void loop()
{
  Serial.println(analogRead(A0));
  delay(200);
}

图形化编程如下

Arduino 比4X4矩阵按键更好的按键组设计_第3张图片

多按键开关电路图

电路图如下
Arduino 比4X4矩阵按键更好的按键组设计_第4张图片
图中的电阻阻值仅供参考,也就是一个Excel表加几个公式计算一下数据(末尾有参考数据),尽量让按键按下时的读取数值比较均匀且差值大一点,使按键开关控制更稳定。
电路图看不懂的欢迎留言讨论

注意事项

连接两个以上的模拟口时一定要选择大电阻串联、并联,且按下按键后的总电阻阻值不要低于10k。(不要问我为什么,这是一个说来话长的物理知识)

和4X4按键矩阵相比的优缺点

需要自己焊接或连接电路,如果都不卖的换焊接和连接电路图的难度也并不难多少
优点就是按键判断的代码逻辑简单,不需要加载类库

密码锁

实际的密码锁
当时没学过编程,代码编写的不忍直视,现在硬件调试太麻烦,就不修改了,意思到了就行,程序逻辑还是很清晰的

代码如下,想了解更多的请看下一篇

// 测试代码
int key[]={0,0,0,0,0,0};           // 用来保存6位按序输入的数字

int password[]={2,4,5,6,8,1};      // 6位密码,改密码改括号里的6位数字
int n=0,m=0;                       // n用来记录输入密码次数,超过一定次数时暂时不能输入密码
                                   // m用来记录输入密码数量,当输入6位密码之后不能在输入密码

#include <Servo.h>
Servo servo_2;                    // 设置控制舵机的是2号数字引脚

void setup()
{
  for(int i=4;i < 16 ;i++){        // 把4到16号引脚依次设置为按键开关就收引脚
  pinMode(i, INPUT);              // 把4到16号引脚依次设置为按键开关就收引脚
  pinMode(i, OUTPUT);            // 把4到16号引脚依次设置为按键开关就收引脚
  digitalWrite(i, HIGH);}       // 把4到16号引脚依次设置为按键开关就收引脚

  pinMode(2, OUTPUT);
  servo_2.attach(2);
  servo_2.write(0);
  Serial.begin(9600);
}

void loop()
{
  //for(int y=0;y<6;y++)          //显示密码
   // Serial.println(password[y]);
     Serial.println("Please enter the password");
    
  while (1) {                   //读取密码

    while ( digitalRead(4)&& digitalRead(5)&& digitalRead(6)&& digitalRead(7)&& digitalRead(8)&& digitalRead(9)&& digitalRead(10)&& digitalRead(11)&& digitalRead(12)&& digitalRead(13)&&digitalRead(14) && digitalRead(15)) {}                           //等待按键按下
    
    if (digitalRead(15)==0 || (m>1&&m<5))     //  接A1口  按下“确定”按键跳出while大循环
      {
        m=0;
        break;        
      }

  for(int i=0;i<6;i++)                             //读取6位密码 
  {                    
    while (digitalRead(4)&& digitalRead(5)&& digitalRead(6)&& digitalRead(7)&& digitalRead(8)&& digitalRead(9)&& digitalRead(10)&& digitalRead(11)&& digitalRead(12)&& digitalRead(13)&&digitalRead(14) && digitalRead(15)) {}                           //等待按键按下
    
    if ( digitalRead(4) || digitalRead(5) || digitalRead(6) || digitalRead(7) || digitalRead(8) || digitalRead(9) || digitalRead(10) || digitalRead(11) || digitalRead(12)||digitalRead(14) || digitalRead(15) ) 
    {
      if (digitalRead(14)==0 || m>5)    //  取消按键接A0引脚, 按下“取消”按键重新输入密码
      {
        while( digitalRead(14) && digitalRead(15))  {}    //等待按下取消或确定
        
         if(digitalRead(15)==0)                          //如果按下的是确认按键
         {
          i=6;                                          //直接跳至密码输入是否正确处
          break;
         }
         
         if(digitalRead(14)==0)                          //如果按下的是取消按键
         {
          Serial.println("  ");                          //清楚所有输入密码,可以重新输入
          Serial.println("Please re-enter the password");
          delay(300);
          m=i=0; 
          analogWrite(3, 0);
          break;
         }
      }
    /*for(int e=4;e<16;e++)              //监视器打印窗口
     {
      Serial.println(digitalRead(e));  //监视器打印窗口
     Serial.println(e);  
      }*/
      for(int j=0;j<11;j++)               //判断哪个按键按下 接在4号引脚的按键表示0,即D4=0,同理D5=1....D12=8,D13=9
      {                     
        if((digitalRead(j+4) == 0) && i<6 )          //判断哪个按键按下
        {                     
        if(i==0)
          {                                //输入第1位密码,输入数字保存在key这个数组的第1位,此时i=0     
          key[i]=j;
          //Serial.print("key[0]=");
          analogWrite(3, 2);
          Serial.print("*");
          }
        if(i==1)
          {                                //输入第2位密码,输入数字保存在key这个数组的第2位,此时i=1   
          key[i]=j;
          //Serial.print("key[1]=");
          analogWrite(3, 7);
          Serial.print("*");
          }
        if(i==2)
          {                                //输入第3位密码,输入数字保存在key这个数组的第3位,此时i=2    
          key[i]=j;
          //Serial.print("key[2]=");
          analogWrite(3, 11);
          Serial.print("*");
          }
        if(i==3)
          {                                 //输入第4位密码,输入数字保存在key这个数组的第4位,此时i=3    
          key[i]=j;
          //Serial.print("key[3]=");
          analogWrite(3, 15);
          Serial.print("*");
          }
        if(i==4)
          {                                //输入第5位密码,输入数字保存在key这个数组的第5位,此时i=4   
          key[i]=j;
          //Serial.print("key[4]=");
          analogWrite(3, 30);
          Serial.print("*");
          }
        if(i==5)
          {                                //输入第6位密码,输入数字保存在key这个数组的第6位,此时i=5      
          key[i]=j;
          //Serial.print("key[5]=");
          analogWrite(3, 40);
          Serial.println("*");
          for(int i=0;i<2;i++)
          {
            analogWrite(3, 0);
            delay(150);
            analogWrite(3, 40);
            delay(150);
          }

          }
       delay(300);                     //延时避免按下一次按键时记录多位密码
       }
      }
      m++;
    }
    if (digitalRead(15)==0 || m>5 )     //等待确认按键按下
        break;                          //跳至密码输入是否正确处
   }
    
  }

    Serial.println("key=");
  for(int y=0;y<6;y++)
    Serial.print(key[y]);
    Serial.println( );
    
if( key[0]==password[0] && key[1]==password[1] && key[2]==password[2] && key[3]==password[3] && key[4]==password[4] && key[5]==password[5] )     //比较密码是否正确
  {                         //密码正确执行内容 
    servo_2.write(50);                        //舵机转动50°让锁打开 
    Serial.println("The door is open, please enter");
    for(int i=0;i<9;i++)                     //3号上的LED灯亮灭4秒 
    {
      analogWrite(3, 125);
      delay(250);
      analogWrite(3, 0);                                                                                                                         //密码正确执行内容 
      delay(250);
    }
    servo_2.write(0);                        //舵机转动0°让锁关闭
    m=0,n=0;                                //重置m、n,既把m、n重新设置为0
    delay(300);
  }
  else
  {                                          //密码错误执行内容 
    if((2-n)>0)                             //密码错误小于3次时执行内容 
    {
      Serial.print("You still have");
      Serial.print(2-n);                  //显示剩下输入次数 
      Serial.println("  chances");
      analogWrite(3, 0);
      
      for(int i=0;i<6;i++)
       Serial.println(sr[i]); 
      
     }
    n++;
    
  }
//  Serial.println("p");
 // Serial.println(n);
   delay(300);
  for(int y=0;y<6;y++)
    key[y]=0;
  if( n > 2)
  {
    for(int y=60;y>=0;y=y-1)            //密码错误等于3次需要在此等待60秒
    {
      Serial.print("Please try again in ");
      Serial.print( y );
      Serial.println(" seconds");
      analogWrite(3, 0);
      delay(500);
      analogWrite(3, 255);
      delay(500);
    }
  }
analogWrite(3, 0);
}

附件

电阻数据参考
Arduino 比4X4矩阵按键更好的按键组设计_第5张图片

你可能感兴趣的:(教学研发)