0

私は次のコードを試しています。LEDをゆっくりとフェードアップさせたい、たとえば2秒/2000ms。このコードは、書かれているように、ループdigitalWrite(2,HIGH)や。と見分けがつかないものdigitalWrite(2,LOW)です。プロセッサが255ステップを非常に速く圧縮するため、フェード期間が認識できないと思われます。

void setup () {                        # set pin 2 as output
    pinMode = (2,OUTPUT);
}

void loop () {
    (for int fi=0;fi<255;fi++) {   # fade IN pin2 from 0-254
    analogWrite(2,fi)
    }
    (for int fo=0;fo<255;fo--) {   # fade OUT pin2 from 0-254
    analogWrite(2,fo)
    }
}

フェードアップとフェードダウンを遅くする方法について、1つか2つの提案があります。私の最初の考えはdelay(8)、各forステップを追加することでした...しかし、それは滑らかで直線的なフェードよりも段階的なパワーの増加として表示されますか?それは必ずしもベストプラクティスですか、それとももっと受け入れられる方法がありますか?

他のアイデアはありますか?

4

2 に答える 2

2

micros関数を使用して、書き込みを発行するタイミングをより細かく制御します。

http://arduino.cc/en/Reference/Micros

これは遅延ではありませんが、ボードがオンラインになってから経過したマイクロ秒数を返すだけです。これを使用すると、次のようなロジックを実行できます。

setup()
{
     t0 = micros()
}


loop()
{
    t1 = micros();
    dt = t1 - t0;
    if (dt > SOME_SMALL_TIME_DELTA)
    {
         increment_or_decrement_led_value_by_one();
         t0 = t1
    }
}
于 2013-01-11T17:29:22.577 に答える
2

はい、マイクロコントローラーで真の線形フェードを作成することは不可能です。出力には、常に最小のステップサイズまたは解像度があります。あなたにとっての質問は、「PWMは、ステップが認識されないほど十分な分解能を持っているか」ということです。

PWNは、255ステップで0〜100%を出力できます。これは、モニターの各ピクセルの8ビット解像度と同じです。モニターのキャリブレーションページを見ると、8ビットの解像度が本質的に滑らかなスケールに見えるものを提供することをおそらく確信できます。モニターグラデーションの例

これが、4秒ごとにLEDをフェードオンおよびフェードオフするサンプルです。これは、バックグラウンドでタスクを実行する方法をいくつか示しています。

オンからオフへの4秒間の変更は、Arduinoのドキュメントを遅らせることなく点滅するで説明されている方法を使用します。loop()を通過するたびに、最後の変更からの経過時間が指定された間隔を超えているかどうかを確認します。超えている場合は、状態を変更して現在の時刻をマークします。

フェードはわずかに異なる方法で実行されます。次の変更が発生する時間を残します。次のアクションの時間かどうかを確認する各スピンスルー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();
}
于 2013-01-12T07:53:47.807 に答える