
ArduinoのLEDの点滅。これはよりシンプルで使いものにならない場合があります。 実際、この単純な機能の実用的な利点を見つけることができます。
デバイスのプログラミング時に、マイクロコントローラーの入力/出力ポートが十分にないことがあります。 または、経済的な理由、または場合によってはスペースが不足しているため、ディスプレイを設置したくありませんが、デバイスの動作モードを何らかの方法で知らせたいと思います。 多くの場合、これらのモードを通知するには、LEDを焼き付けまたは点滅させます。 そして、多くのモードがある場合はどうなりますか?
どういうわけか自動起動モードをプログラムした車のアラームは、私をそのアイデアに導きました。 そこで、たとえば、特定のレジスタの14番目のビットを設定するには、このレジスタのプログラミングモードに入った後、特定のキーフォブボタンを14回押してから、14の短い信号(または方向指示器のウインカー)を待つ必要がありました。 次に確認ボタンを押して、長いビープ音を聞きます。 独創的! ディスプレイや画面上のメニューはありません。 確かに、同時に、ひどく不便です。
ただし、内部モードが少ない場合は、LEDの点滅回数を使用することは非常に機能的です。
簡単なものから始めましょう。
ArduinoのLED点滅の例
これは、Arduinoの研究で習得された最初のプログラムです。 最近出会った多くのコントローラーでは、このプログラムは工場で配線されており、明らかにこれをマスターしていない人向けです。
点滅するLEDの最も単純な例
void setup() { pinMode(13, OUTPUT); digitalWrite(13, LOW); } void loop() { digitalWrite(13,HIGH); delay(500); digitalWrite(13,LOW); delay(500); }

ポートの高レベルと低レベルの間で異なる間隔を要求するように思われ、必要になります。 しかし同時に、コントローラーは他に何もしません(まあ、ほとんど何もせず、まだ割り込みを処理します)。 もちろん、彼は何か他のことをすることができますが、メインループ()ループではできません。
したがって、遅延を放棄し()、ミリスを使用してイベントに進みます()
millis()を使用したイベントの使用
ミリを使用したLED点滅コード()
void setup() { pinMode(13, OUTPUT); digitalWrite(13, LOW); } uint32_t ms, ms1 = 0; bool led_stat = true; void loop() { ms = millis(); // 500 if( ( ms - ms1 ) > 500 || ms < ms1 ){ ms1 = ms; // digitalWrite(13, led_stat); led_stat = !led_stat; } }
よくここに。 目標が達成されました。 LEDが点滅し、ループ()サイクル内のプロセッサー時間は、他の機能でほぼ完全に使用可能になります。 確かに、そのようなコードでは、必要な点滅モードの使用は非常に困難です-間隔が異なるいくつかのイベント、必要なモードと以前の状態の多くの条件。 複雑すぎます。
LEDビットマトリックス処理
イベントの応答時間を1/8秒に短縮し、1バイトで、8ビットの状態を順番にエンコードします。
ステータスコードLED点滅コード
// byte modes[] = { 0B00000000, // 0B11111111, // 0B00001111, // 0.5 0B00000001, // 0B00000101, // 0B00010101, // 0B01010101 // (4 ) }; uint32_t ms, ms1 = 0, ms2 = 0; uint8_t blink_loop = 0; uint8_t blink_mode = 0; uint8_t modes_count = 0; void setup() { pinMode(13, OUTPUT); digitalWrite(13, LOW); modes_count = 1; blink_mode = modes[modes_count]; } void loop() { ms = millis(); // 125 if( ( ms - ms1 ) > 125|| ms < ms1 ){ ms1 = ms; // if( blink_mode & 1<<(blink_loop&0x07) ) digitalWrite(13, HIGH); else digitalWrite(13, LOW); blink_loop++; } // // 5 if( ( ms - ms2 ) > 5000|| ms < ms2 ){ ms2 = ms; blink_mode = modes[modes_count++]; if( modes_count >= 7 )modes_count = 1; } }
LED操作の最初の3つのモードは簡単です。 ただし、残りはすでにマイクロコントローラーモードのデモに使用できます。
1秒に1回の短い点滅

1秒間に2回点滅

3回点滅

毎秒4回の一定の点滅

ほとんどのプロジェクトではこれで十分だったので、原則として、これは停止できました。 しかし、これが十分ではなく、車のアラームプログラミングを開発する必要がある場合)))
8ビットのLED状態が少ない場合はどうなりますか?
4バイトを使用してLEDのステータスを判断する
SOS信号コードモールス信号
byte bytes[] = {0B00010101,0B00110011,0B10100011,0B00000010}; uint32_t ms, ms1 = 0; uint8_t blink_loop = 0; void setup() { pinMode(13, OUTPUT); digitalWrite(13, LOW); } void loop() { ms = millis(); // 125 if( ( ms - ms1 ) > 125|| ms < ms1 ){ ms1 = ms; // (3 ) uint8_t n_shift = blink_loop&0x07; // (2 3 ) uint8_t b_count = (blink_loop>>3)&0x3; if( bytes[b_count] & 1<< n_shift )digitalWrite(13, HIGH); else digitalWrite(13, LOW); blink_loop++; } }
周期的なSOS信号を取得します-LEDで3つの短い信号、3つの長い信号、3つの短い信号を4秒ごとに繰り返します

多くの人々が、割り込みを使用せずにマイクロコントローラをプログラミングするひどいスタイルについてArduinoを批判しました
ハードコアのみ。 中断のみ!
16ビットタイマー1を使用します。125msの間、割り込みをオーバーフローに設定します。
タイマー割り込みを使用したLEDマルチモード点滅コード
uint8_t blink_loop = 0; uint8_t blink_mode = 0; uint8_t modes_count = 0; // uint16_t n = 63583; // ISR( TIMER1_OVF_vect ) { if( blink_mode & 1<<(blink_loop&0x07) ) digitalWrite(13, HIGH); else digitalWrite(13, LOW); blink_loop++; TCNT1 = n; // TCNT1 } void setup() { pinMode(13,OUTPUT); blink_mode = 0B00000000; // - TCCR1A = 0; // 1024 16 TCCR1B = 1<<CS22 | 0<<CS21 | 1<<CS20; // Timer1 TIMSK1 = 1<<TOIE1; // TCNT1 = n; sei(); // } } void loop() { blink_mode = 0B00001111; // 0.5 delay(5000); blink_mode = 0B00000001; // delay(5000); blink_mode = 0B00000101; // delay(5000); blink_mode = 0B00010101; // delay(5000); blink_mode = 0B01010101; // (4 ) delay(5000); }
タイマーのプログラミングの詳細については、こちらをご覧ください 。 同時に、ループ()の5秒間の遅延()は、LEDの制御に干渉しません。
この方法の欠点は、タイマー1を使用する一部の関数とライブラリが機能しないことです(たとえば、PWM)。
タイマーレジスタのプログラミングが難しく、タイマー割り込みの使用が興味深い場合は、
「人間の顔」によるタイマー割り込み
親切な人がTimerOneライブラリの形式でタイマーへのプログラムインターフェイスを作成しました
TimerOneを使用したLEDマルチモード点滅コード
#include "TimerOne.h" uint8_t blink_loop = 0; uint8_t blink_mode = 0; uint8_t modes_count = 0; // Callback void timerIsr() { if( blink_mode & 1<<(blink_loop&0x07) ) digitalWrite(13, HIGH); else digitalWrite(13, LOW); blink_loop++; } void setup() { pinMode(13,OUTPUT); blink_mode = 0B00000000; Timer1.initialize(125000); Timer1.attachInterrupt( timerIsr ); } void loop() { blink_mode = 0B00001111; // 0.5 delay(5000); blink_mode = 0B00000001; // delay(5000); blink_mode = 0B00000101; // delay(5000); blink_mode = 0B00010101; // delay(5000); blink_mode = 0B01010101; // (4 ) delay(5000); }
TimerOneのライブラリはここからダウンロードできます。
そして最後に、私が好きな人のためのコードは、Arduino IDEの環境でWiFiモジュールESP8266のプログラミングを「ニブル」します。
ESP8266のタイマー割り込み
Arduinoで構築されたTickerライブラリのESPコアには、他にも良い人がいます。
ESP8266のタイマーLEDマルチモード点滅コード
#include <Ticker.h> uint8_t blink_loop = 0; uint8_t blink_mode = 0; uint8_t modes_count = 0; Ticker blinker; void timerIsr() { if( blink_mode & 1<<(blink_loop&0x07) ) digitalWrite(13, HIGH); else digitalWrite(13, LOW); blink_loop++; } void setup() { pinMode(13,OUTPUT); blink_mode = 0B00000000; blinker.attach(0.125, timerIsr); } void loop() { blink_mode = 0B00001111; // 0.5 delay(5000); blink_mode = 0B00000001; // delay(5000); blink_mode = 0B00000101; // delay(5000); blink_mode = 0B00010101; // delay(5000); blink_mode = 0B01010101; // (4 ) delay(5000); }
ESPで割り込みを使用すると、組み込みのWiFi機能の処理に割り当てられる時間が少なすぎると見なされる、邪悪なWDTウォッチドッグタイマーがトリガーされることが非常に多いため、注意が必要です。
この記事が、Arduinoだけでなく、Arduinoで点滅するLEDのすべてのファンに少し役立つことを願っています。
私のブログでマイクロコントローラーとスマートホームを使った私の実験について読んでください。