ESP8266 Arduino开发之路(5)— 使用PWM实现LED呼吸灯

ESP8266 Arduino开发之路(5)— 使用PWM实现LED呼吸灯

一、前言

ESP8266的PWM(Pulse Width Modulation)由FRC1在软件上实现,可实现同频率、不同占空比的最多8路的PWM波形输出。需要注意如下:

PWM驱动接口不能跟硬件定时器接口函数同时使用,因为二者共用同一个硬件定时器;
PWM驱动使用NMI中断,为最高优先级中断,可以保证PWM输出波形的准确度;
不能将自动睡眠模式设置为Light Sleep,Light Sleep模式下停用CPU不能响应NMI中断;
PWM周期需要设置在1000us(1kHz)~10000(100Hz)。

二、PWM输出

我们可以将如下所示NodeMCU的全部10个IO口设置为PWM输出,
在这里插入图片描述

但是因为GPIO1和GPIO3作为调试串口的TX和RX,一般不做使用,所以NodeMCU一般可支持同时输出8路PWM输出。编写程序如下所示:

void setup() {
  analogWrite(5, 15);   // D1 
  analogWrite(4, 31);   // D2
  analogWrite(0, 63);   // D3
  analogWrite(2, 127);  // D4
  analogWrite(14, 191); // D5
  analogWrite(12, 15);  // D6
  analogWrite(13, 31);  // D7
  analogWrite(15, 63);  // D8
  analogWrite(3, 127);  // RX
  analogWrite(1, 191);  // TX
}

void loop() {
  delay(300);
}

使用示波器抓取波形可以看到,当前输出我PWM波形周期为1ms(频率1kHz),如下为GPIO0的输出波形,可以看到占空比为25%,因为analogWrite()函数第二个参数为0~255,当填入63时即为25%。
在这里插入图片描述

三、修改PWM精度

在上面我们知道analogWrite()函数的第二个参数为0~255,这就决定了PWM波形的精度,当我们把这个范围扩大后,就可以提高PWM的精度,我们可以通过analogWriteRange()函数来修改,如下所示,将其修改为1023,

void setup() {
  analogWriteRange(1023);
  analogWrite(2, 255);  // D4 LED
}

void loop() {
  delay(300);
}

从示波器获取的波形如下所示,可见,其精度提高到了0~1023
在这里插入图片描述
通过查看源文件core_esp8266_wiring_pwm.cpp,可以知道最大范围可设置到65535,
在这里插入图片描述
但是这个可能存在一个bug,即当范围设置为65535时,analogWrite()函数填入大于53804的数不能实现想要得到的波形。另外当范围超过53687时无法实现100%占空比,所以建议最大范围为53687。

四、修改PWM频率

使用analogWriteFreq()函数可以修改PWM的频率,通过查看源文件core_esp8266_wiring_pwm.cpp,可以知道其频率范围为100Hz~1kHz
在这里插入图片描述
但实际上,我们可以将其范围设置为10hz~90kHz,编写程序如下所示

void setup() {
  analogWriteFreq(90000);
  analogWriteRange(65535);
  analogWrite(2, 32863);  // D4 LED
}

void loop() {
  delay(300);
}

抓取的示波器波形如下所示
在这里插入图片描述

五、LED呼吸灯

编写如下程序,实现LED呼吸灯:

/*
  ESP8266 使用PWM实现LED呼吸灯
*/

void setup() {
  analogWriteFreq(1000);            // 频率设置为1kHz,即周期为1ms
  analogWriteRange(1000);           // 范围设置为1000,即占空比步长为1us
  analogWrite(2, 750);              // GPIO2 - D4 - LED
}

void loop() {
  uint8_t dir = 0;
  uint32_t pwmval = 750;
  while(1)
  {
    if(dir) pwmval++;                 // dir==1  pwmval递增
    else pwmval--;                    // dir==0  pwmval递减
    if( pwmval <= 500 ) dir=1;        // pwmval降低至500后,方向为递增
    if( pwmval == 1000) dir=0;        // pwmval递增到1000后,方向改为递减
    analogWrite(2, pwmval);           // 修改占空比
    if( pwmval==1000 ) delay(300);    // 在LED熄灭时等待300ms
    delay(3);
  }
}

然后可得到呼吸灯的效果为
在这里插入图片描述

六、附录

上一篇:ESP8266 Arduino开发之路(4)— 通过HTTP进行网络通信
下一篇:ESP8266 Arduino开发之路(6)— 使用Ticker库的软件定时器

  • 13
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值