• ESP8266--Arduino开发(PWM)


    一、前言

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

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

    二、设置PWM输出

    在arduino中使用如下函数设置PWM输出:

    analogWrite(gpioID, pwmValue);
    
    • 1

    我们可以将如下所示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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    三、修改PWM精度

    使用analogWrite(gpioID, pwmValue);函数可以设置PWM输出,pwmValue的默认范围为0~255,这就决定了PWM波形的精度,当我们把这个范围扩大后,就可以提高PWM的精度,使用如下函数修改:

    analogWriteRange(uint32_t range);	//调整后的范围为0~range
    
    • 1

    通过查看源文件core_esp8266_wiring_pwm.cpp,可以知道最大范围可设置到65535:

    在这里插入图片描述
    但是这个可能存在一个bug,即当范围设置为65535时,analogWrite()函数填入大于53804的数不能实现想要得到的波形。另外当范围超过53687时无法实现100%占空比,所以建议最大范围为53687。


    四、修改PWM频率

    频率(F) = 1/周期(T),所以修改频率就等同于修改周期,使用如下函数可以修改PWM的频率:

    analogWriteFreq(uint32_t freq)
    
    • 1

    通过查看源文件core_esp8266_wiring_pwm.cpp,可以知道其频率范围为100Hz~1kHz:

    在这里插入图片描述
    但实际上,我们可以将其范围设置为10hz~90kHz,使用示例如下:

    void setup() {
      analogWriteFreq(90000);
      analogWriteRange(65535);
      analogWrite(2, 32863);  // D4 LED
    }
    
    void loop() {
      delay(300);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    五、呼吸灯实战

    /*
      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) {		// dir==1  pwmval递增
        	pwmval++;                 
       	}else {			// dir==0  pwmval递减
       		pwmval--;                    
       	}
       	
        if( pwmval == 0 ) {	// pwmval降低至0后,方向为递增
        	dir=1;        
        }
        if( pwmval == 1000) {	// pwmval递增到1000后,方向改为递减
        	dir=0;        
        }
        analogWrite(2, pwmval);           // 修改占空比
        if( pwmval==1000 ) 
        	delay(300);    // 在LED熄灭时等待300ms
        delay(3);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    程序烧录到开发板之后,可以看到板载小灯慢慢亮,慢慢灭,就行呼吸一样。

  • 相关阅读:
    颜色遍历法非递归遍历二叉树
    安装配置Kafka
    洛谷 P2350 [HAOI2012]外星人(素因子分解,欧拉函数)
    软件工程导论——第四章——形式化说明技术
    爬虫学习(16):selenium自动化测试:人为模拟滑块移动
    LeetCode - 611.有效三角形个数
    2.10 Go语言中的注释、关键字、内置函数和操作符
    数据库面试题+sql语句解析
    基于JAVA砂石矿山管理系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署
    Hazelcast系列(一):初识hazelcast
  • 原文地址:https://blog.csdn.net/Mr_robot_strange/article/details/127860569