1、模拟输出函数analogWrite
(1)analogWrite函数借助PWM调制,可以用于输出模拟信号,它有两个参数,第一个参数是模拟引脚号,第二个参数是0到255之间的PWM频率值,0对应“off”,255对应“on”。
(2)在Arduino UNO控制器中,5号引脚和6号引脚的PWM频率为980Hz。在一些基于ATmega168和ATmega328的Arduino控制器中,analogWrite函数支持引脚 3、5、6、9、10、11(在开发板上的引脚处有“~”标记)。
(3)PWM(Pulse Width Modulation)即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速、开关电源等领域。
(4)PWM频率值0-255对应占空比0%-100%,呈正比关系,如下图所示。如果有规律地改变PWM频率值,就能产生等效的模拟波形(如上图紫色虚线描绘的波形),当然,PWM频率值固定,也能产生一个等效的模拟电压,其值不局限于高电平或低电平标定的电压,电压值取决于PWM频率值。
2、例1——按键控制LED亮度
(1)根据下图所示将电路连接好,其中电阻可选220Ω(总之在确保不宜过小的前提下不要太大即可)。
(2)将下面的程序下载到开发板中,首先LED会获得一个适中的亮度,持续按下按键1,LED的亮度会持续下降直至熄灭,持续按下按键2,LED的亮度会持续上升直至程序设定的最大值。
bool pushButton1; // 创建布尔型变量用来存储按键开关1的电平状态
bool pushButton2; // 创建布尔型变量用来存储按键开关2的电平状态
int ledPin = 9; //LED引脚号
int brightness = 128; //LED亮度参数(255/2=127.5,一个适中的亮度参数)
void setup()
{
pinMode(2, INPUT_PULLUP); //将引脚2设置为输入上拉模式
pinMode(8, INPUT_PULLUP); //将引脚8设置为输入上拉模式
pinMode(ledPin, OUTPUT); //将LED引脚设置为输出模式
Serial.begin(9600); //启动串口通讯,波特率为9600
}
void loop()
{
pushButton1 = digitalRead(2); //读取引脚2电平状态并将其赋值给布尔变量pushButton1
pushButton2 = digitalRead(8); //读取引脚8电平状态并将其赋值给布尔变量pushButton2
if (!pushButton1 && brightness > 0) //当(持续)按下按键开关1并且LED亮度参数大于0
{
brightness--; //减低LED亮度参数
}
else if (!pushButton2 && brightness < 255) //当(持续)按下按键开关2并且LED亮度参数小于255
{
brightness++; //增加LED亮度参数
}
analogWrite(ledPin, brightness); //模拟输出控制LED亮度
Serial.println(brightness); //将LED亮度参数显示在串口监视器上
delay(10);
}
①持续按下按键1,引脚2将持续处于低电平,每执行一次loop函数,brightness都进行一次自减,直至按键1被松开或者亮度参数减小至0,同时loop函数会将当前的亮度参数作为模拟量输出到引脚9上,并通过串口将当前的亮度参数输出到监视器上。
②持续按下按键2,引脚8将持续处于低电平,每执行一次loop函数,brightness都进行一次自减,直至按键2被松开或者亮度参数增加至255,同时loop函数会将当前的亮度参数作为模拟量输出到引脚9上,并通过串口将当前的亮度参数输出到监视器上。
③程序没有做异常情况的处理,比如两个按键同时按下,这种情况理论上是不允许的。
④亮度参数的取值范围为0-255,若不将其限定在此范围,那么它作为analogWrite函数的参数,会发生强制类型转换,最终的结果也会在0-255之间,至于强制类型转换会发生什么,这里不再赘述。
3、例2——LED呼吸灯
(1)根据下图所示将电路连接好,其中电阻可选220Ω(总之在确保不宜过小的前提下不要太大即可)。
(2)将下面的程序下载到开发板中,可以发现LED灯的亮度从暗变亮,再从亮变暗,以此往复,做一个周期性的“呼吸”。
void setup()
{
pinMode(9, OUTPUT); //设置9号引脚为输出模式
Serial.begin(9600); //启动串口通讯
}
void loop()
{
// LED由暗到明
for (int brightness = 0; brightness <= 255; brightness+=5)
{
analogWrite(9, brightness);
Serial.println(brightness);
delay(10);
}
// LED由明到暗
for (int brightness = 255; brightness >=0 ; brightness-=5)
{
analogWrite(9, brightness);
Serial.println(brightness);
delay(10);
}
}
①LED由暗到明的过程由一个for循环控制,首先亮度参数的初始值为0,它会随着时间的流逝而逐渐增加,直至到达最大值255,for循环结束。
②LED由明到暗的过程也由一个for循环控制,首先亮度参数的初始值为255,它会随着时间的流逝而逐渐减小,直至到达最小值0,for循环结束。
③loop函数重复执行上述两个for循环,以此达到呼吸灯的效果。