Arduino I/O 之模拟输出
模拟输出,即用于输出的 pin (管脚,也叫 GPIO)能输出“连续”的电压值,不像数字输出只能输出 0V 和 5V
模拟输出对应的函数是:
analogWrite(pin,value)
value 取值 0 ~ 255,值越小输出电压越低。可以看作把 5V 电压“均分”成 256 份,value 值看作取多少份
用于模拟输出的 pin,在大多数 Arduino 板子上(用 ATMEGA168 和 ATMEGA328)只能是 pin 3, 5, 6, 9, 10, 11。在 Arduino Mega 上为 2 ~ 13
把一个普通 LED 发光二极管,正极接在 pin 3 上,负极接地,如下程序可以实现 LED 由暗变亮的过程(LED 的亮度对电压敏感):
uint8_t brightness = 0;
uint8_t led_pin = 3;
void setup()
{
pinMode(led_pin, OUTPUT);
}
void loop()
{
analogWrite(led_pin, brightness++);
delay(1000);
analogWrite(led_pin, 0);
if(brightness >= 12) brightness = 0;
}
深入模拟输出
对于只有 '0' 和 '1' 的数字电路,要产生类似模拟信号的连续输出,用的是 PWM (Pulse Width Modulation) 技术。
PWM (Pulse Width Modulation),即:脉冲宽度调制,是一种使用数字方法获得模拟结果(连续)的技术。数字电路产生方波(一种在开/关之间跳变的信号),比较容易
如下一段程序使用 Arduino 的数字输出 pin 4,产生一段方波(其周期为 1ms):
uint8_t pin = 4;
uint16_t cycle = 1000; // 周期是 1000 微秒
uint16_t duty = 500; // 高电平持续时间是 500 微秒
void setup()
{
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
}
void loop()
{
digitalWrite(pin, HIGH);
delayMicroseconds(duty);
digitalWrite(pin, LOW);
delayMicroseconds(cycle - duty);
}
示波器的波形是这样的:
下面这个程序:
uint8_t pin = 4;
uint16_t cycle = 1000; // 周期是 1000 微秒
uint16_t duty = 800; // 高电平持续时间是 800 微秒
void setup()
{
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
}
void loop()
{
digitalWrite(pin, HIGH);
delayMicroseconds(duty);
digitalWrite(pin, LOW);
delayMicroseconds(cycle - duty);
}
也生成方波,周期也是 1ms,不同的是,一个周期内高电平的持续时间占整个周期的80%,更方便地,常把这个 80% 称为占空比
示波器的波形:
PWM 是使用数字输出,通过控制高电平和低电平所占的时间,就能模拟出介于高电平(5V)和低电平(0V)之间的电压。高电平的持续时间称为脉冲宽度。要获得不同的模拟值,你只需要改变(调制)脉冲的宽度。如果这个高-低组合的变化速度足够快,在LED示例中的结果看起来就象是一个稳定在0-5V之间的电压在控制LED的亮度
对于下面的程序:
void setup()
{
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
}
void loop()
{
analogWrite(3, 127);
analogWrite(5, 204);
}
在 Arduino Leonardo 上,pin 3 的输出波形为:
在 Arduino Leonardo 上,pin 5 的输出波形为:
可以看出,在 Arduino Leonardo 上,analogWrite() 使用的方波周期为 1ms;127 时,占空比为 50%;204 时,占空比为 80
使用万用表的直流电压挡,测得 pin 3 的电压为 2.5V (5V x 50%),pin 5 的电压为 4V (5V x 80%)



