1. 普通5mm直径LED参数测定实验
以上为普通5mm直径LED,手册建议持续工作电流为20mA以内。以下,采用学生电源(带控压限流功能)通过限流电阻170欧给各色LED供电,通过缓慢加压测流和观察LED亮度的方法,确定电流、压降与亮度关系,实测该批次LED颜色与压降大致如下:
颜色 1mA状态与压降 5mA状态与压降 10mA状态与压降 15mA状态与压降 20mA状态与压降
红 1mA起亮 明亮,1.98V 明亮,2.04V 刺眼,2.08V 刺眼,2.13V
绿 1mA起亮 较亮,1.96V 亮,2.00V 亮,2.03V 亮,2.04V
黄 1mA起亮 明亮,1.96V 明亮,2.01V 刺眼,2.04V 刺眼,2.07V
蓝 1mA起亮 明亮,2.72V 明亮,2.77V 刺眼,2.85V 刺眼,2.91V
白 1mA起亮 刺眼,2.82V 明亮,2.92V 刺眼,3.01V 刺眼,3.07V
注:以上LED亮度肉眼区分为星亮、较亮、亮、明亮、刺眼5种状态,亮度依次增强。不同批次及规格LED不尽相同,供参考。
从以上实验结论可知,普通5mm直径LED在1-2mA就能观察到起亮(有些已经达到亮和明亮的程度),10mA就已经很明亮了。所以完成可以按10mA来设计LED工作电流。
ESP32可以提供3.3V的40mA输出能力,足以烧坏LED。而实测红色LED烧坏为短路状态,这可能进一步导致ESP32故障。为保证电路安全运行,请务必给LED串联限流电阻。电阻计算参考以上实验数据,约取100到200欧即可。
2. 普通数字输出功能
去掉影响闪存和仅建议用作输入的GPIO引脚,ESP32推荐用于普通IO输出功能的引脚标示如下图:
实测该ESP32控制板载LED灯的为编号为2的引脚,高有效,程序如下:
define LED 2
void setup()
{
pinMode(LED,OUTPUT);
}
void loop()
{
digitalWrite(LED,HIGH);
delay(100);
digitalWrite(LED,0);
delay(1000); //亮灭时间不同以示区别
}
继续用多路流水灯模块(共阴极、高有效)测定各引脚GPIO编号与程序中引脚编号的关系。如编写GPIO 0控制LED1、GPIO 13控制LED2、GPIO 23控制LED3,亮灭交替不同时间以示区别,程序如下:
define LED1 0
define LED2 13
define LED3 23
void setup()
{
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
}
void loop()
{
digitalWrite(LED1,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED3,HIGH);
delay(2000); // 3只LED全亮2秒
digitalWrite(LED1,HIGH);
digitalWrite(LED2,LOW);
digitalWrite(LED3,LOW);
delay(2000); // LED1亮、LED2灭、LED3灭,持续2秒
digitalWrite(LED1,LOW);
digitalWrite(LED2,HIGH);
digitalWrite(LED3,LOW);
delay(1000); // LED2亮、LED1灭、LED3灭,持续1秒
digitalWrite(LED1,LOW);
digitalWrite(LED2,LOW);
digitalWrite(LED3,HIGH);
delay(200); // LED2亮、LED1灭、LED3灭,持续1秒
}
对照引脚图连接电路,上传后观察可知,系统运行与程序设定及预想相符。通过以上实验可知,与Arduino UNO等单片机数字引脚全部支持普通数字输出不同,ESP32只有部分GPIO引脚适用于作普通数字输出。此外,编程方式式,GPIO号就是程序中的对应引脚编号。
3. 普通数字输入功能
与可以作为普通数字输出的引脚数量相比,ESP32可作为普通数字输入的引脚多了G34、G35、G36和G39,这些引脚的位置及编号如下图所示:
接下来,分别测试这些引脚的普通输入、上拉输入、下拉输入以及触摸感应功能。注意,G34、G35、G36、G39四路引脚内部无上下拉电阻设计,理论上仅支持普通数字输入模式。即使声明为上拉或下拉输入功能,也不能实现预期抗干扰效果。
(1)普通输入模式
采用一组8只数字IO作为输出,另一组8路IO作为普通数字输入,通过杜邦线接高(3.3V)、低(GND)和悬空3种输入状态,控制对应LED亮灭。
byte LED[8]={23,22,1,3,21,19,18,5}; // 注意:8位流水灯模块为共阳极,低有效(控制信号输出为低电平时灯亮)
byte KEY[8]={36,39,34,35,32,33,25,26};
void setup()
{
for(int i=0;i<8;i++)
{
pinMode(KEY[i],INPUT); //控制引脚均声明为普通输入模式
pinMode(LED[i],OUTPUT);
digitalWrite(LED[i],LOW);
}
delay(3000); //全亮持续3秒,表示程序正常完成初始化
for(int i=0;i<8;i++) //熄灭8只LED
digitalWrite(LED[i],HIGH);
}
void loop()
{
for(int i=0;i<8;i++)
digitalWrite(LED[i],digitalRead(KEY[i]));
}
通过观察执行效果可知,LED灯在输入控制引脚确定地接高/低电平时,呈现对应稳定的受控效果。但当输入引线悬空时,LED灯存在闪烁未定状态。说明普通输入功能可能给程序引入输入状态量不确定的BUG,除非输入能够确定在高/低2种电平之间,不存在不确定性。
(2)上拉输入模式
在Arduino单片机开发中,输入上拉模块通过编程实现内部上拉电阻电路的激活。这种输入上拉模式使得输入信号默认为高电平,输入为GND时才读到低电平。如此,输入量被确定在高/低2种电平之间,抗干扰能力强。
byte LED[8]={23,22,1,3,21,19,18,5}; // 注意:8位流水灯模块为共阳极,低有效(控制信号输出为低电平时灯亮)
byte KEY[8]={36,39,34,35,32,33,25,26};
void setup()
{
for(int i=0;i<8;i++)
{
pinMode(KEY[i],INPUT_PULLUP); //控制引脚均声明为输入上拉模式
pinMode(LED[i],OUTPUT);
digitalWrite(LED[i],LOW);
}
delay(3000); //全亮持续3秒,表示程序正常完成初始化
for(int i=0;i<8;i++) //熄灭8只LED
digitalWrite(LED[i],HIGH);
}
void loop()
{
for(int i=0;i<8;i++)
digitalWrite(LED[i],digitalRead(KEY[i]));
}
程序执行后,G34、G35、G36、G39四路输入控制下的四只LED仍存在闪烁。查找原因可知,即使声明为上拉输入的语句不报错,这四路输入由于内部没有上拉或下拉电阻,仅支持作为普通数字输入使用。其余内部带输入上拉设计的不会闪烁、功能符合程序及电路预设。当然,在一般电路中,干扰通常是较小的,普通输入功能也足够使用。
(3)下拉输入模式
下拉输入与上拉输入的电路及功能设计恰好相反,由于输入为下拉设计,引脚悬空或接低电平时,CPU总读到低电平输入。仅当输入确定地接高电平(3.3V)时,CPU才读到高电平。
byte LED[8]={23,22,1,3,21,19,18,5}; // 注意:8位流水灯模块为共阳极,低有效(控制信号输出为低电平时灯亮)
byte KEY[8]={36,39,34,35,32,33,25,26};
void setup()
{
for(int i=0;i<8;i++)
{
pinMode(KEY[i],INPUT_PULLDOWN); //控制引脚均声明为输入下拉模式
pinMode(LED[i],OUTPUT);
digitalWrite(LED[i],LOW);
}
delay(3000); //全亮持续3秒,表示程序正常完成初始化
for(int i=0;i<8;i++) //熄灭8只LED
digitalWrite(LED[i],HIGH);
}
void loop()
{
for(int i=0;i<8;i++)
digitalWrite(LED[i],digitalRead(KEY[i]));
}
没有悬念,仅支持普通数字输入功能(内部未设计上下拉电路)的引脚控制下的LED有闪烁现象。其余4路支持内部下拉功能的引脚,默认灯亮(共阳极、低有效),说明默认读入为低电平。仅当输入引脚接高电平时,对应受控LED才熄灭。
(4)触摸感应功能
ESP32具备普通Arduino数字输入引脚不具备的感应输入功能,这种输入功能原理是引脚支持感应皮肤触摸引脚后引起的电荷变化,从而判定触摸动作。支持触摸功能的引脚共有10路,如图所示:
启用这些引脚的触摸输入功能的语法类似中断功能,详见以下示例程序:
define TOUCH_PIN 4 // T0触摸传感器连接到GPIO4
define LED_PIN 23 // LED连接到GPIO23
void setup()
{
pinMode(LED_PIN, OUTPUT);
Serial.begin(115200);
touchAttachInterrupt(TOUCH_PIN, touchHandler, 40); // 第3个参数为触摸传感器的阈值,该值可根据需要调整
}
void loop()
{
// 主循环中不需要做任何操作,触摸检测在后台进行
}
void touchHandler() // 触摸事件处理函数
{
static bool ledState = false; // 切换LED的状态
ledState = !ledState;
digitalWrite(LED_PIN, ledState);
Serial.println("T0 touched!"); // 打印触摸事件
}
上述例程中,采用T0电容触摸传感器控制G23点灯。每触摸一次,电平翻转一次,且串口输出触摸检测情况。其中,阈值设置较为关键,这通常需要根据具体的硬件来确定合适的阈值,以调整触摸灵敏度。阈值越低,传感器越容易被触发,这可能会增加误触发风险,但可以更快地响应触摸。相反,较高的阈值需要更强的触摸信号才能触发,这可能 会降低误触发,但响应速度可慢一点。上述示例中设置的数值不高,单次触摸可能存在多次频繁动作。除了调整灵敏度阈值外,还可以设置程序上的抗干扰措施,比如检测到触摸后增加延时,以避免一次触摸导致多次电平翻转。