怎么使用Arduino+ESP32制作简易计时器

准备材料

1.一个可以正常使用且安装了Arduino及驱动的电脑

2.一块ESP32开发板

3.一个7.4V电池+两个接电池的导线

4.电池模块(有电)

5.74HC595模块

6.四位数码管

7.旋钮

8.按钮

事先准备

将电池延申出的先接入到“电池接口”中,将5V输出与开发板相连

绝对禁止7.4V电源直接接入开发板!!!否则接入数据线时会导致电脑停机!!!

将四位数码管插入74HC595中(别插错到点阵屏专用孔!)

旋钮电位器插入32(A4)

按钮插入到3

74HC595的V,G分别插入到5V,GND口

L,C,D分别插入到14,13,12口

连接数据线,编程开始!

编程

完整代码

先看完整代码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148const int dataPin = 12;const int clockPin = 13;const int latchPin = 14;const int keyPin = 3;const int rokeyPin = 32;int KeySta = 0;int de;const byte NUM[] = {0b11111100,0b01100000,0b11011010,0b11110010,0b01100110,0b10110110,0b10111110,0b11100000,0b11111110,0b11110110,0b00000010};void setup() { // put your setup code here, to run once:pinMode(dataPin,OUTPUT);pinMode(clockPin,OUTPUT);pinMode(latchPin,OUTPUT);pinMode(keyPin,INPUT);digitalWrite(clockPin,LOW);digitalWrite(latchPin,LOW);Serial.begin(115200);//delay(10);//siweiqidong(2,3,4,5);//delay(10);}int first,second,third,fourth,minute,second22;void loop() { // put your main code here, to run repeatedly: execute(); if(KeySta == 1){ if(map(analogRead(rokeyPin),0,4095,0,60) < 10){ first = 0; second = String(String(map(analogRead(rokeyPin),0,4095,0,60)).charAt(0)).toInt(); } else{ first = String(String(map(analogRead(rokeyPin),0,4095,0,60)).charAt(0)).toInt(); second = String(String(map(analogRead(rokeyPin),0,4095,0,60)).charAt(1)).toInt(); } minute = map(analogRead(rokeyPin),0,4095,0,60); siweiqidong(first,second,0,0); } else if(KeySta == 2){ if(map(analogRead(rokeyPin),0,4095,0,59) < 10){ third = 0; fourth = String(String(map(analogRead(rokeyPin),0,4095,0,59)).charAt(0)).toInt(); } else{ third = String(String(map(analogRead(rokeyPin),0,4095,0,59)).charAt(0)).toInt(); fourth = String(String(map(analogRead(rokeyPin),0,4095,0,59)).charAt(1)).toInt(); } second22 = map(analogRead(rokeyPin),0,4095,0,59); siweiqidong(first,second,third,fourth); } else if(KeySta == 3){ execute(); //Serial.println(de); if(millis() - de >= 1000){ TimeChan(); de = millis(); //Serial.println("R"); } //Serial.println("Running!"); } else if(KeySta == 0){ for(int i = 0;i < 4;i++){ specialDigitDisplay(i + 1,10); } } if(KeySta != 0){ siweiqidong(first,second,third,fourth); }}void TimeChan(){ if(second22 == 0){ if(minute == 0){ KeySta == 0; } else{ minute = minute - 1; second22 = 59; } } else{ second22 = second22 - 1; } if(minute < 10){ first = 0; second = String(String(minute).charAt(0)).toInt(); } else{ first = String(String(minute).charAt(0)).toInt(); second = String(String(minute).charAt(1)).toInt(); } if(second22 < 10){ third = 0; fourth = String(String(second22).charAt(0)).toInt(); } else{ third = String(String(second22).charAt(0)).toInt(); fourth = String(String(second22).charAt(1)).toInt(); } //Serial.println(String(minute)+":"+String(second22));}void execute(){ if(digitalRead(keyPin) == 0){ //Serial.println(digitalRead(keyPin)); //Serial.println(map(analogRead(rokeyPin),0,4095,0,60)); if(KeySta >= 3){ KeySta = 0; first = 0; second = 0; third = 0; fourth = 0; } else{ KeySta++; } delay(200); } }void siweiqidong(int number1,int number2,int number3,int number4){int results[4];int nym = String(String(number1)+String(number2)+String(number3)+String(number4)).toInt();results[0] = nym / 1000;nym = nym % 1000;results[1] = nym / 100;nym = nym % 100;results[2] = nym / 10;results[3] = nym % 10;/*results[0] = number1;results[1] = number2;results[2] = number3;results[3] = number4;*/for(int i = 0;i <= 3;i++){ specialDigitDisplay(i + 1,results[i]); delay(3); } //delay(10);}void specialDigitDisplay(int digit,int number){byte val = 0;val = bitSet(val,digit - 1);shiftOut(dataPin,clockPin,MSBFIRST,val);shiftOut(dataPin,clockPin,LSBFIRST,~NUM[number]);digitalWrite(latchPin,HIGH);digitalWrite(latchPin,LOW);//delay(10);}

下面我会给出解析

解析

首先的话

123456789const int dataPin = 12;const int clockPin = 13;const int latchPin = 14;const int keyPin = 3;const int rokeyPin = 32;int KeySta = 0;int de;const byte NUM[] = {0b11111100,0b01100000,0b11011010,0b11110010,0b01100110,0b10110110,0b10111110,0b11100000,0b11111110,0b11110110,0b00000010};

这段代码很明显是定义一堆管脚和状态的

接下来看setup中的

12345678910111213void setup() { // put your setup code here, to run once:pinMode(dataPin,OUTPUT);pinMode(clockPin,OUTPUT);pinMode(latchPin,OUTPUT);pinMode(keyPin,INPUT);digitalWrite(clockPin,LOW);digitalWrite(latchPin,LOW);Serial.begin(115200);//delay(10);//siweiqidong(2,3,4,5);//delay(10);}

这一堆pinMode都是调整接口状态的,包括下面的digitalWrite,都是初始化数码管的。

底部的Serial.begin是初始化串口的,无用。包括底部的被注释的,都是开发时为了方便找错而设立的。

接下来,我新建了一堆变量

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748int first,second,third,fourth,minute,second22;void loop() { // put your main code here, to run repeatedly: execute(); if(KeySta == 1){ if(map(analogRead(rokeyPin),0,4095,0,60) < 10){ first = 0; second = String(String(map(analogRead(rokeyPin),0,4095,0,60)).charAt(0)).toInt(); } else{ first = String(String(map(analogRead(rokeyPin),0,4095,0,60)).charAt(0)).toInt(); second = String(String(map(analogRead(rokeyPin),0,4095,0,60)).charAt(1)).toInt(); } minute = map(analogRead(rokeyPin),0,4095,0,60); siweiqidong(first,second,0,0); } else if(KeySta == 2){ if(map(analogRead(rokeyPin),0,4095,0,59) < 10){ third = 0; fourth = String(String(map(analogRead(rokeyPin),0,4095,0,59)).charAt(0)).toInt(); } else{ third = String(String(map(analogRead(rokeyPin),0,4095,0,59)).charAt(0)).toInt(); fourth = String(String(map(analogRead(rokeyPin),0,4095,0,59)).charAt(1)).toInt(); } second22 = map(analogRead(rokeyPin),0,4095,0,59); siweiqidong(first,second,third,fourth); } else if(KeySta == 3){ execute(); //Serial.println(de); if(millis() - de >= 1000){ TimeChan(); de = millis(); //Serial.println("R"); } //Serial.println("Running!"); } else if(KeySta == 0){ for(int i = 0;i < 4;i++){ specialDigitDisplay(i + 1,10); } } if(KeySta != 0){ siweiqidong(first,second,third,fourth); }}

先不说变量都是干啥的,直接讲loop中的

execute函数是检测的,再下面会有说明

之后检测按钮的按压次数,如果按了一次,就对分钟进行改动,加if是让“9”变成“09”

然后对小时约束,最大值为60,最小为1,通过转动旋钮更改

按第二次,更改秒,同小时

按第三次,正式开始计时,先进行检测,再看运行时间与之前记录时间是否大于等于1000ms(1秒)

这里不用delay是为了防止程序计算与数码管渲染导致的延时,

并且delay函数也影响四位数码管渲染效果,TimeChan是更改数码管的函数,再更新de的值,记录

如果按键计数的值为0,就清空成为"----"

不等于0就实时渲染数码管

12345678910111213141516171819202122232425262728293031void TimeChan(){ if(second22 == 0){ if(minute == 0){ KeySta == 0; } else{ minute = minute - 1; second22 = 59; } } else{ second22 = second22 - 1; } if(minute < 10){ first = 0; second = String(String(minute).charAt(0)).toInt(); } else{ first = String(String(minute).charAt(0)).toInt(); second = String(String(minute).charAt(1)).toInt(); } if(second22 < 10){ third = 0; fourth = String(String(second22).charAt(0)).toInt(); } else{ third = String(String(second22).charAt(0)).toInt(); fourth = String(String(second22).charAt(1)).toInt(); } //Serial.println(String(minute)+":"+String(second22));}

观察渲染四位数码管的函数,当秒为0时,检测分钟,分钟等于0就结束并改变按钮状态

否则分钟-1,秒变为59,这里也是方便按下按钮直接停止计时。

下面是当分钟小于10时,秒小于10时,在十位加个“0”

1234567891011121314151617void execute(){ if(digitalRead(keyPin) == 0){ //Serial.println(digitalRead(keyPin)); //Serial.println(map(analogRead(rokeyPin),0,4095,0,60)); if(KeySta >= 3){ KeySta = 0; first = 0; second = 0; third = 0; fourth = 0; } else{ KeySta++; } delay(200); } }

这段就是一个简单的按键计数程序,大于等于3时直接清空所有,不是的话就加一下按键计数

1234567891011121314151617181920212223242526272829void siweiqidong(int number1,int number2,int number3,int number4){int results[4];int nym = String(String(number1)+String(number2)+String(number3)+String(number4)).toInt();results[0] = nym / 1000;nym = nym % 1000;results[1] = nym / 100;nym = nym % 100;results[2] = nym / 10;results[3] = nym % 10;/*results[0] = number1;results[1] = number2;results[2] = number3;results[3] = number4;*/for(int i = 0;i <= 3;i++){ specialDigitDisplay(i + 1,results[i]); delay(3); } //delay(10);}void specialDigitDisplay(int digit,int number){byte val = 0;val = bitSet(val,digit - 1);shiftOut(dataPin,clockPin,MSBFIRST,val);shiftOut(dataPin,clockPin,LSBFIRST,~NUM[number]);digitalWrite(latchPin,HIGH);digitalWrite(latchPin,LOW);//delay(10);}

这段代码是专门负责渲染四位数码管的函数,没什么可解释的

好了,你学会了吗?