ESP32 for Arduino 模拟信号学习笔记

一、模拟信号输入

1. 读取函数 analogRead()

  • 功能:从指定引脚读取模拟信号,并获取其返回值。
  • 返回值:ESP32 的 ADC 模块分辨率默认为 12 位,这意味着 analogRead() 函数返回值的范围是 0 ~ 4095 ,对应输入电压 0 ~ 3.3v 。比如返回值为 4095 时,输入电压就是 3.3v ;返回值为 0 ,输入电压为 0v 。不过,ESP32 的 ADC 模块返回值线性度不是很好。
  • 可用引脚:一共有 15 个可用引脚 ,当打开 WiFi 功能时,其中 9 个引脚不能使用,建议优先使用 A0、A3、A4、A5、A6、A7 引脚。

2. 设置取样精度函数 analogSetWidth(bits)

  • 功能:用于设置 analogRead() 函数的取样精度。
  • 参数bits 取值范围在 9 ~ 12 之间。当设为 9 时,analogRead() 函数返回值为 0 ~ 511 ;设为 12 时返回 0 - 4095 。

3. 示例代码

const int potPin = A0; // 定义模拟输入引脚为A0,一般可接电位器等模拟信号源
void setup() {
  pinMode(potPin,INPUT); // 将A0引脚设置为输入模式
  Serial.begin(115200); // 初始化串口通信,波特率为115200,方便查看读取的数据
  analogSetWidth(10); // 设置模拟输入精度为10位,此时返回值范围是0 - 1023
}
int val; // 定义变量用于存储读取到的模拟值
void loop() {
  val = analogRead(potPin); // 从A0引脚读取模拟值
  Serial.println(val); // 通过串口打印读取到的模拟值
  delay(10); // 延迟10毫秒,避免读取过于频繁
}

二、模拟信号输出

1. 输出方式概述

Arduino 模拟输出通过 PWM 实现,对应的函数是 analogWrite() ,但在 ESP32 中没有这个函数。ESP32 提供了 3 种模拟输出方式:

  • LEDC:基于 PWM 调制的 16 通道模拟输出,是我们常用的方式。
  • SigmaDelta:基于 SigmaDelta 调制的 8 通道模拟输出。
  • DAC:硬件(DAC)实现的 2 个通道的模拟输出 。

2. LEDC 输出相关函数

(1)ledcSetup(channel,freq,bit_num)

  • 功能:设置指定 LEDC 通道的参数。
  • 参数
    • channel :PWM 通道,总共有 16 个通道,编号为 0 ~ 15 。
    • freq :设置 PWM 的频率。
    • bit_num :占空比的分辨率,范围是 1 ~ 16 。比如设置为 8 ,则控制 LED 的亮度可以在 0 ~ 255 之间变化。

(2)ledcAttachPin(pin,channel)

  • 功能:将指定通道上产生的 PWM 信号输出到指定引脚。
  • 参数
    • pin :开发板上除 34 、 35 、 36 、 39 以外的 19 个引脚。
    • channel :PWM 通道,编号 0 ~ 15 。

(3)ledcWrite(channel,Value)

  • 功能:设置指定通道的占空比数值,进而控制输出信号。
  • 参数
    • channel :PWM 通道,0 ~ 15 。
    • Value :指定占空比数值,具体范围取决于 ledcSetup 中设置的占空比分辨率。

3. 示例代码

(1)简单 LED 亮灭示例

const int ledPin =  27; // 定义LED连接引脚为27
void setup() {
  pinMode(ledPin,OUTPUT); // 将引脚27设置为输出模式
  ledcSetup(0,5000,10); // 设置通道0,频率为5000Hz,占空比分辨率为10位(0 - 1023)
  ledcAttachPin(ledPin,0); // 将引脚27与通道0关联
}
void loop() {
  ledcWrite(0,1023); // 设置通道0的占空比为最大值,LED最亮
  delay(1000); // 延迟1秒
  ledcWrite(0,0); // 设置通道0的占空比为0,LED熄灭
  delay(1000); // 延迟1秒
}

(2)模拟输入控制模拟输出示例

const int ledPin =  27; // 定义LED连接引脚为27
const int potPin =  A0; // 定义模拟输入引脚为A0
void setup() {
  pinMode(ledPin,OUTPUT); // 将引脚27设置为输出模式
  pinMode(potPin,INPUT); // 将A0引脚设置为输入模式
  ledcSetup(0,5000,10); // 设置通道0,频率为5000Hz,占空比分辨率为10位(0 - 1023)
  ledcAttachPin(ledPin,0); // 将引脚27与通道0关联
  Serial.begin(115200); // 初始化串口通信,

2 条评论

  • @ 2025-8-2 19:36:54

    ESP32 for Arduino 模拟信号开发学习笔记

    一、基础概念与核心函数

    (一)模拟输入

    ESP32 可通过 analogRead(pin) 读取模拟信号,默认 ADC 分辨率 12 位,返回值范围 0~4095,对应电压 0~3.3V 。若需调整精度,用 analogSetWidth(bits)bits 取 9~12 ,如设为 10 ,返回值范围变为 0~1023 。

    (二)模拟输出

    ESP32 无 Arduino 传统 analogWrite() ,改用 LEDC、SigmaDelta、DAC 三种方式。常用 LEDC(基于 PWM ,16 通道),需三步配置:

    1. ledcSetup(channel, freq, bit_num) :设通道参数(通道 0~15 、频率、占空比分辨率 1~16 )。
    2. ledcAttachPin(pin, channel) :关联引脚与通道。
    3. ledcWrite(channel, value) :输出占空比,控制设备(如 LED 亮度)。

    二、代码实践与解析

    (一)基础模拟输入(读取电位器值)

    const int potPin = A0; // 定义模拟输入引脚(接电位器)
    void setup() {
      pinMode(potPin, INPUT); // 设为输入模式
      Serial.begin(115200); // 初始化串口,波特率115200
      analogSetWidth(10); // 设ADC精度为10位,返回值0~1023
    }
    int val;
    void loop() {
      val = analogRead(potPin); // 读模拟值
      Serial.println(val); // 串口打印
      delay(10); // 延时防抖
    }
    

    说明:通过电位器改变电压,analogRead 读取后串口输出,analogSetWidth 灵活调整精度适配场景。

    (二)基础模拟输出(LED 亮灭控制)

    const int ledPin = 27; // 定义LED引脚
    void setup() {
      pinMode(ledPin, OUTPUT); // 设为输出
      ledcSetup(0, 5000, 10); // 通道0,频率5000Hz,占空比分辨率10位(0~1023)
      ledcAttachPin(ledPin, 0); // 引脚27关联通道0
    }
    void loop() {
      ledcWrite(0, 1023); // 占空比最大,LED最亮
      delay(1000); 
      ledcWrite(0, 0); // 占空比0,LED灭
      delay(1000); 
    }
    

    说明ledcSetup 配置通道,ledcAttachPin 绑定引脚,ledcWrite 控制占空比实现亮灭循环。

    (三)模拟输入控制输出(电位器调 LED 亮度)

    const int ledPin = 27; 
    const int potPin = A0; 
    void setup() {
      pinMode(ledPin, OUTPUT);
      pinMode(potPin, INPUT);
      ledcSetup(0, 5000, 10); // 通道0,频率5000Hz,分辨率10位
      ledcAttachPin(ledPin, 0); 
      Serial.begin(115200);
      analogSetWidth(10); // ADC精度10位
    }
    int val;
    void loop() {
      val = analogRead(potPin); // 读电位器值
      Serial.println(val); 
      ledcWrite(0, val); // 直接用读取值控制占空比
      delay(10); 
    }
    

    说明:电位器值实时改变 ledcWrite 占空比,实现 LED 亮度随电位器转动渐变,体现“输入 - 处理 - 输出”闭环。

    (四)进阶:映射函数适配范围(精准调亮度)

    const int ledPin = 27; 
    const int potPin = A0; 
    void setup() {
      pinMode(ledPin, OUTPUT);
      pinMode(potPin, INPUT);
      ledcSetup(0, 5000, 8); // 通道0,分辨率8位(0~255)
      ledcAttachPin(ledPin, 0); 
      Serial.begin(115200);
      analogSetWidth(12); // ADC精度12位(0~4095)
    }
    int val;
    void loop() {
      val = analogRead(potPin); // 读12位值(0~4095)
      Serial.println(val); 
      val = map(val, 0, 4095, 0, 255); // 映射到8位范围(0~255)
      ledcWrite(0, val); // 控制LED
      delay(10); 
    }
    

    说明map 函数将 12 位输入(0~4095)映射到 8 位占空比范围(0~255),解决输入输出分辨率不匹配问题,让亮度调节更线性、精准。

    (五)双 LED 渐变控制(循环亮暗)

    const int ledPin1 = 27; 
    const int ledPin2 = 26; 
    void setup() {
      pinMode(ledPin1, OUTPUT);
      pinMode(ledPin2, OUTPUT);
      ledcSetup(0, 5000, 8); // 通道0,分辨率8位(0~255)
      ledcSetup(1, 5000, 8); // 通道1,参数同通道0
      ledcAttachPin(ledPin1, 0); // 引脚27-通道0
      ledcAttachPin(ledPin2, 1); // 引脚26-通道1
    }
    void loop() {
      // 从暗到亮
      for (int light = 0; light <= 255; light++) { 
        ledcWrite(0, light); // 通道0占空比递增
        ledcWrite(1, light); // 通道1占空比递增
        delay(10); // 延时控制渐变速度
      }
      // 从亮到暗
      for (int light = 255; light >= 0; light--) { 
        ledcWrite(0, light); // 通道0占空比递减
        ledcWrite(1, light); // 通道1占空比递减
        delay(10); 
      }
    }
    

    说明:用 for 循环实现双 LED 同步渐变,ledcWrite 按循环变量调整占空比,delay 控制渐变节奏,打造灯光呼吸效果。

    三、总结与扩展

    通过上述代码,可掌握 ESP32 模拟信号 输入读取、输出控制、分辨率适配 核心逻辑。实际开发中,可结合传感器(如光敏、温度)拓展应用:

    • 光敏电阻接模拟输入,实时调节 LED 亮度模拟“环境光感应”;
    • 温度传感器(模拟型)读取值映射为 PWM 占空比,驱动风扇调速。

    多尝试不同函数组合、引脚配置,就能用 ESP32 玩转模拟信号,搭建创意硬件项目啦!

    • @ 2025-8-2 19:36:22

      ESP32 for Arduino 模拟信号入门教程

      一、模拟信号基础概念

      在电子设备中,信号分为数字信号模拟信号

      • 数字信号:只有0和1两种状态(高低电平)
      • 模拟信号:可以是连续变化的数值(如声音、光线、温度等)

      ESP32作为一款功能强大的单片机,支持模拟信号的输入和输出,这为我们制作调光、调速、传感器数据采集等项目提供了可能。

      二、ESP32模拟信号输入

      1. 核心函数:analogRead()

      用于从指定引脚读取模拟信号,基本语法:

      int value = analogRead(pin); // pin为指定的模拟输入引脚
      

      2. 输入特性

      • 默认精度为12位,返回值范围:0~4095
      • 对应电压范围:0~3.3V(4095对应3.3V,0对应0V)
      • 可用引脚:共15个,推荐使用A0、A3、A4、A5、A6、A7(尤其开启WiFi时)

      3. 精度设置:analogSetWidth()

      可以通过该函数修改模拟输入的精度,语法:

      analogSetWidth(bits); // bits取值范围9~12
      

      不同精度对应的返回值范围:

      • 9位:0~511
      • 10位:0~1023
      • 11位:0~2047
      • 12位:0~4095(默认)

      4. 基础示例:读取电位器值

      const int potPin = A0; // 定义电位器连接的引脚
      int val; // 存储读取到的数值
      
      void setup() {
        pinMode(potPin, INPUT); // 设置引脚为输入模式
        Serial.begin(115200); // 初始化串口通信
        // 可选:设置精度
        // analogSetWidth(10); // 设置为10位精度,返回值0-1023
      }
      
      void loop() {
        val = analogRead(potPin); // 读取模拟值
        Serial.print("电位器值:");
        Serial.println(val); // 串口打印数值
        delay(100); // 延时100ms
      }
      

      三、ESP32模拟信号输出

      ESP32没有Arduino UNO的analogWrite()函数,而是提供了三种模拟输出方式:

      • LEDC:基于PWM的16通道输出(最常用)
      • SigmaDelta:8通道输出
      • DAC:硬件2通道输出

      我们主要学习最常用的LEDC方式。

      1. LEDC输出三步骤

      步骤1:设置通道参数 ledcSetup()

      ledcSetup(channel, freq, bit_num);
      
      • channel:通道编号(0~15)
      • freq:PWM频率(如5000Hz)
      • bit_num:占空比分辨率(1~16),决定输出值范围
        • 8位:0~255
        • 10位:0~1023

      步骤2:绑定引脚 ledcAttachPin()

      ledcAttachPin(pin, channel);
      
      • pin:输出引脚(除34、35、36、39外的大多数引脚)
      • channel:要绑定的通道(与步骤1设置的通道一致)

      步骤3:输出PWM信号 ledcWrite()

      ledcWrite(channel, value);
      
      • channel:通道编号
      • value:输出值(范围由步骤1的bit_num决定)

      2. 基础示例:LED闪烁

      const int ledPin = 27; // LED连接的引脚
      
      void setup() {
        pinMode(ledPin, OUTPUT);
        // 步骤1:设置通道0,频率5000Hz,8位分辨率(0-255)
        ledcSetup(0, 5000, 8);
        // 步骤2:将引脚27绑定到通道0
        ledcAttachPin(ledPin, 0);
      }
      
      void loop() {
        ledcWrite(0, 255); // 最大亮度(8位分辨率的最大值)
        delay(1000);       // 亮1秒
        ledcWrite(0, 0);   // 熄灭
        delay(1000);       // 灭1秒
      }
      

      四、综合应用:模拟输入控制模拟输出

      1. 电位器控制LED亮度(同范围)

      const int ledPin = 27;   // LED引脚
      const int potPin = A0;   // 电位器引脚
      int val;                 // 存储读取值
      
      void setup() {
        pinMode(ledPin, OUTPUT);
        pinMode(potPin, INPUT);
        
        // 设置LED输出通道:通道0,5000Hz,10位分辨率(0-1023)
        ledcSetup(0, 5000, 10);
        ledcAttachPin(ledPin, 0);
        
        Serial.begin(115200);
        analogSetWidth(10); // 输入也设为10位(0-1023),与输出范围匹配
      }
      
      void loop() {
        val = analogRead(potPin);  // 读取电位器值(0-1023)
        Serial.println(val);       // 打印数值
        ledcWrite(0, val);         // 直接用于控制LED亮度
        delay(10);
      }
      

      2. 范围映射:map()函数的使用

      当输入和输出范围不同时,使用map()函数进行转换:

      val = map(原数值, 原最小值, 原最大值, 目标最小值, 目标最大值);
      

      示例:12位输入控制8位输出

      const int ledPin = 27;
      const int potPin = A0;
      int val;
      
      void setup() {
        pinMode(ledPin, OUTPUT);
        pinMode(potPin, INPUT);
        
        // 输出:8位分辨率(0-255)
        ledcSetup(0, 5000, 8);
        ledcAttachPin(ledPin, 0);
        
        Serial.begin(115200);
        analogSetWidth(12); // 输入:12位(0-4095)
      }
      
      void loop() {
        val = analogRead(potPin); // 读取0-4095
        Serial.print("原始值:");
        Serial.print(val);
        
        // 将0-4095映射到0-255
        val = map(val, 0, 4095, 0, 255);
        Serial.print(",映射后:");
        Serial.println(val);
        
        ledcWrite(0, val); // 控制LED
        delay(10);
      }
      

      3. 高级应用:LED渐变效果

      使用循环实现LED从暗到亮再到暗的渐变:

      const int ledPin1 = 27;
      const int ledPin2 = 26;
      
      void setup() {
        pinMode(ledPin1, OUTPUT);
        pinMode(ledPin2, OUTPUT);
        
        // 设置两个通道,都用8位分辨率(0-255)
        ledcSetup(0, 5000, 8);
        ledcSetup(1, 5000, 8);
        
        // 绑定引脚到通道
        ledcAttachPin(ledPin1, 0);
        ledcAttachPin(ledPin2, 1);
      }
      
      void loop() {
        // 从暗到亮(for循环版)
        for(int i = 0; i <= 255; i++){
          ledcWrite(0, i); // 控制第一个LED
          ledcWrite(1, i); // 控制第二个LED
          delay(15);       // 控制渐变速度
        }
        
        // 从亮到暗(while循环版)
        int light = 255;
        while(light >= 0){
          ledcWrite(0, light);
          ledcWrite(1, light);
          delay(15);
          light--; // 递减
        }
      }
      

      五、ESP32与Arduino UNO的区别

      特性 ESP32 Arduino UNO
      模拟输入范围 0~4095(12位) 0~1023(10位)
      模拟输出函数 analogWrite(),用LEDC系列函数 analogWrite()
      输出通道数 16个(LEDC) 6个PWM引脚
      工作电压 3.3V 5V

      六、常见问题解决

      1. 读取值不稳定

        • 确保接线牢固
        • 增加delay()时间
        • 尝试软件滤波(如取多次平均值)
      2. 引脚冲突

        • 开启WiFi时,避免使用特定引脚
        • 推荐使用A0、A3-A7作为模拟输入
      3. 范围不匹配

        • 始终注意输入输出的范围是否一致
        • 不同范围时务必使用map()函数转换

      通过本教程,你已经掌握了ESP32模拟信号的基本用法。尝试将这些知识应用到实际项目中,比如制作一个光线感应灯、温度控制器或音乐可视化装置吧!

      • 1