是的,你是正確的,這是不可能創造真正的線性褪色與微控制器。輸出將始終有一些最小步長或分辨率。對於你來說,問題是「PWM是否有足夠的分辨率,以至於不會察覺到這些步驟?」
的PWN可以輸出0〜255級的步驟100%。這與顯示器上每個像素的8位分辨率相同。看看任何監視器校準頁面,你可能會說服自己,8位分辨率提供了基本上平滑的規模。 Example monitor gradient
因此,這裏是你的樣品變淡並每4秒關機的LED。這向您顯示了一些如何在後臺執行任務的方法。
開到關的4秒改變使用無延遲的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();
}