是的,你是对的,用微控制器不可能创建真正的线性淡入淡出。输出将始终具有一些最小步长或分辨率。对您来说,问题是“PWM 是否具有足够的分辨率以致无法感知这些步骤?”
PWN 可以分 255 步输出 0 到 100%。这与显示器上每个像素的 8 位分辨率相同。查看任何显示器校准页面,您可能会说服自己 8 位分辨率提供了基本上看起来平滑的刻度。示例监视器梯度
所以这是您的示例,它每 4 秒使 LED 亮起和熄灭一次。这向您展示了如何在后台执行任务的几种方法。
4 秒切换到关闭使用 Blink without Delay Arduino 文档中描述的方法。每次通过 loop() 检查自上次更改以来经过的时间是否超过指定的时间间隔 - 如果是,则更改状态并标记当前时间。
淡入淡出的完成方式略有不同。你留下了下一次改变发生的时间。每次循环循环(),您都会检查是否是下一个动作的时间。如果是,您进行更改,并存储何时进行下一次更改。
/* unfortunately standard LED on pin 13 does not have PWM
You will need to connect an LED and resistor */
const int pin = 3;
/* this is your step time between changes in light
output in milliseconds */
const unsigned int tstep = 8;
/* this is the time then next change can be made.
The change will happen at or after this value. */
unsigned int tnext = 0;
/* this is the current and target light level
The output will slowly ramp until the current value
meets the target. So to request that the change start,
the code just sets a new target. */
unsigned int target = 0;
unsigned int current = 0;
/* These are from Blink without Delay
Shows another way to execute delays. */
unsigned long previousMillis = 0;
unsigned long interval = 4000;
void setup() {
pinMode(pin,OUTPUT);
tnext = millis() + tstep;
analogWrite(pin, current);
}
/* something in the code calls this
to request a change in the LED state
Pass what you want to be the new value
and the LED will slowly change to that value. */
void newTarget(int value) {
tnext = millis() + tstep;
target = value;
}
/* call this frequently to update the LED
If the time of the next action has been reached,
execute the change and setup when the following
change will occur. */
void driveLed() {
unsigned int tnow = millis();
if(target != current) {
if(tnow >= tnext) {
if(target > current) {
current += 1;
}
else {
current -= 1;
}
analogWrite(pin, current);
tnext += tstep;
}
}
}
/* Note that the main loop has no delays.
Execution will spin rapidly through this, most times
checking and finding nothing to to.
You would add your other functionality here, and this
LED would continue to happen. As long as you don't pack
anything that takes on the order of 8 ms, you won't notice
a change in the LED fade behavior.
void loop() {
unsigned int tnow = millis();
// some other logic here would decide when to change the LED state
// For this sample, just toggle every 4 seconds
if((tnow - previousMillis) >= interval) {
if(0 == target) {
newTarget(255);
}
else {
newTarget(0);
}
previousMillis = tnow;
}
driveLed();
}