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%)