複数の電子部品を、delay
関数を使用せずにタイミング制御する方法の解説動画です。
【考え方】1個のLEDをdelay関数を使用せずにタイミング制御
基本的な考え方を確認するために、delay関数を使用せずに、1秒ごとにON/OFF制御するスケッチを確認します。
次の動作をする点がこの制御方法のポイントです!
- 前回制御した時刻からからどれぐらい時間が経過しているか調べる
- その結果、1秒経過していなければ何もせず、1秒経過していたらLEDのON/OFF制御をする
これをスケッチにすると次のようになります。
/*
1個のLEDをmillis関数で1秒ごとにON/OFF制御するスケッチ
*/
// LEDの接続ピン
#define RED_LED 12
// 前回制御時刻を保存しておく変数
unsigned long zenkai = 0;
void setup() {
// LED接続ピンの出力設定
pinMode(RED_LED, OUTPUT);
}
void loop() {
// 今回の制御時刻
unsigned long konkai = millis();
// LEDの制御
if( konkai - zenkai >= 1000 ) {
digitalWrite(RED_LED, !digitalRead(RED_LED));
zenkai = konkai;
}
}
【基本形】2個のLEDをdelay関数を使用せずにタイミング制御
1個のLEDを制御するスケッチをベースにすると、簡単に電子部品を追加制御することができます。
次のスケッチは,1個のLEDの制御と同じようにもう1個のLED制御を追加したものです。
複数の電子部品を制御する場合、「前回制御した時刻」はそれぞれの電子部品ごとに覚えておく必要があります。
「前回制御した時刻」はそれぞれの電子部品ごとに変数を用意する点がポイントになります。
/*
2個のLEDをmillis関数で1秒ごとにON/OFF制御するスケッチ
*/
// LEDの接続ピン
#define RED_LED 12
#define GREEN_LED 4
// 前回制御時刻を保存しておく変数
unsigned long zenkai_aka = 0;
unsigned long zenkai_midori = 0;
void setup() {
// LED接続ピンの出力設定
pinMode(RED_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
}
void loop() {
// 今回の制御時刻
unsigned long konkai = millis();
// 赤色LEDの制御
if( konkai - zenkai_aka >= 2000 ) {
digitalWrite(RED_LED, !digitalRead(RED_LED));
zenkai_aka = konkai;
}
// 緑色LEDの制御
if( konkai - zenkai_midori >= 700 ) {
digitalWrite(GREEN_LED, !digitalRead(GREEN_LED));
zenkai_midori = konkai;
}
}
【注意点】サーボモーター制御を追加
上のスケッチに、サーボモーター制御を追加します。
次のようなスケッチで、「0度から60度まで1度30msで回転」➡︎ 「60度から0度まで1度30msで回転」という制御をします。
for( int angle=0; angle<=60; angle++ ) {
servo.write(angle);
delay(30);
}
for( int angle=60; angle>=0; angle-- ) {
servo.write(angle);
delay(30);
}
この制御コードを2個のLEDを制御するスケッチに追加します。
/*
2個のLEDとサーボモーターを
millis関数で1秒ごとにON/OFF制御するスケッチ
*/
// サーボモーターのライブラリインクルードとオブジェクト生成
#include <Servo.h>
Servo servo;
// LEDの接続ピン
#define RED_LED 12
#define GREEN_LED 4
// サーボモーター信号線接続ピン
#define SERVO_PIN 6
// 前回制御時刻を保存しておく変数
unsigned long zenkai_aka = 0;
unsigned long zenkai_midori = 0;
unsigned long zenkai_servo = 0;
void setup() {
// LED接続ピンの出力設定
pinMode(RED_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
// サーボモーター制御ピン設定
servo.attach(SERVO_PIN);
// サーボモーターを0度位置に回転
servo.write(0);
}
void loop() {
// 今回の制御時刻
unsigned long konkai = millis();
// 赤色LEDの制御
if( konkai - zenkai_aka >= 1000 ) {
digitalWrite(RED_LED, !digitalRead(RED_LED));
zenkai_aka = konkai;
}
// 緑色LEDの制御
if( konkai - zenkai_midori >= 500 ) {
digitalWrite(GREEN_LED, !digitalRead(GREEN_LED));
zenkai_midori = konkai;
}
// サーボモーターの制御
if( konkai - zenkai_servo >= 5000 ) {
for( int angle=0; angle<=60; angle++ ) {
servo.write(angle);
delay(30);
}
for( int angle=60; angle>=0; angle-- ) {
servo.write(angle);
delay(30);
}
zenkai_servo = konkai;
}
}
このスケッチを実行すると残念ながらうまく制御できません。(動作の様子は動画をご確認ください)
サーボモーター制御中はLED制御が止まってしまいます。
理由は、if
文内のサーボモーター制御が合計3.6秒間かかってしまい、この間、LEDの制御ができなくなるためです。
スケッチを工夫すればこの問題を回避できますが、かなり複雑になってしまいます。
そのようなときは「リアルタイムOS」を利用するとうまく制御できます。
リアルタイムOSは別の記事で詳しく解説予定です。
テンプレートスケッチ
複数の電子部品を異なるタイミングで制御する場合、millis
関数を使うと見やすく変更しやすいスケッチが作成できます。
次のスケッチは、3個の電子部品を制御するテンプレートです。
/*
3個の電子部品を異なるタイミングで制御するテンプレート
*/
// 電子部品制御に必要なライブラリがあればここでインクルードします
// 例
// #include <Servo.h> // サーボモーターのライブラリ
// 電子部品のオブジェクト生成が必要な場合、ここで生成します
// 例
// Servo servo;
// その他必要な定義があればここに書きます
// 例
// #define RED_LED 12 // LEDの接続ピン
// const int servo_pin = 6; // サーボモーターの接続ピン
// それぞれの電子部品制御の時間間隔 (単位:ms)
#define kankaku_1 1000 // 1つ目の電子部品
#define kankaku_2 700 // 2つ目の電子部品
#define kankaku_3 3500 // 3つ目の電子部品
// 前回制御時刻を保存しておく変数
unsigned long zenkai_1 = 0;
unsigned long zenkai_2 = 0;
unsigned long zenkai_3 = 0;
void setup() {
// ピンの設定などが必要であればここに書きます
// 例
// pinMode(RED_LED, OUTPUT);
}
void loop() {
// 今回の制御時刻
unsigned long konkai = millis();
// 電子部品1の制御
if( konkai - zenkai_1 >= kankaku_1 ) {
// ここに1つ目の電子部品の制御コードを書きます
// 例
// digitalWrite(RED_LED, !digitalRead(RED_LED));
zenkai_1 = konkai;
}
// 電子部品2の制御
if( konkai - zenkai_2 >= kankaku_2 ) {
// ここに1つ目の電子部品の制御コードを書きます
zenkai_2 = konkai;
}
// 電子部品3の制御
if( konkai - zenkai_3 >= kankaku_3 ) {
// ここに3つ目の電子部品の制御コードを書きます
zenkai_3 = konkai;
}
}
更新履歴
日付 | 内容 |
---|---|
2025.8.28 | 新規投稿 |