Arduinoアイデアレゴ電子工作|ビジュアルプログラミング使った信号機制御プログラムの作り方
Arduinoを使った信号機電子工作「信GO機」の設計手法について紹介します。
本記事は、小学生やプログラミング初心者でも理解できるようやさしく、ていねいに解説しています。
小学生やプログラミングが苦手な方には、ブロックプログラミングの活用がおすすめです
- 信号機の点灯回路設計の考え方
- Arduino IDEのプログラミング設計方法
- Scrattino3(スクラッチーノ3)でのプログラミング設計方法
せでぃあはこんな人物です
✅プライム企業に勤める電気・機械設計エンジニア
✅親子の絆を深めるため、夏休みに子供と一緒に電子工作を製作
✅Arduinoプログラミングを用いて作ったプログラミング電子工作「信GO機」が市の発明くふう展で「優秀賞」を受賞
✅本ブログにてArduinoスクラッチプログラミングLESSON記事投稿中
✅YouTubeチャンネル「せでぃあブログちゃんねる」運営中
この工作はArduinoスターターキットを使って作成しています。
この工作で使っているプログラミング要素は、以下のLESSON記事でも学習することができます。
子供の成長を育む!小学生にぴったりなプログラミング教室を見つけるために厳選しました!
電子工作「信GO機」とは
私が当時小6の息子と一緒に、夏休みの課題研究テーマとして作った工作です。
親子の絆を深めたいと思い、チャレンジしてみました!
動作解説
- 身近な制御機器である信号機を題材にしたLEGO工作です
- 交差点の信号機で、車用が2つ・歩行者用が1つ設置されています
- 歩行者用押しボタンを押すと、早く緑信号に変わります
機器構成
この工作は大きく分けて4つの機器で構成されています。
- 自動車用信号機1
- 歩行者用信号機1
- 歩行者用押しボタン
- 自動車用信号機2
誰もが動作を知っている信号機がテーマであり、ONかOFFのデジタル信号しか使わないのでプログラミング初心者におすすめの工作テーマです。
設計方法
信号機の点灯モード(パターン)を考える
今回扱う信号機の点灯モード(パターン)は、全部で8通り存在します。
モード8まで動作が行われた後は、再びモード1に戻ってモード8までの動作が繰り返されます。
何度も繰り返し処理されることを「ループ処理」といいます
歩行者用押しボタンの機能を考える
歩行者用押しボタンの機能
歩行者用信号機1が赤信号のときにボタンを押すことで、早く緑信号に変わるように催促できるボタン。
押しボタンが機能するのはモード6のときだけ
押しボタンが機能するのは「歩行者用信号機1が赤信号で、自動車用信号機2が緑信号のとき」つまり、「モード6のときのみ」です。
この「条件」という考え方が、プログラム設計するときに生きてきます
入出力情報を整理する
入力情報(1点)
- 歩行者用押しボタン
出力情報(8点)
- 自動車用信号機1【緑信号】
- 自動車用信号機1【黄信号】
- 自動車用信号機1【赤信号】
- 歩行者用信号機1【赤信号】
- 歩行者用信号機1【緑信号】
- 自動車用信号機2【緑信号】
- 自動車用信号機2【黄信号】
- 自動車用信号機2【赤信号】
Arduinoの入出力ピン割り当てを考える
本工作では「電源関係」と「0~13番ピンのデジタル入出力」ソケットのみ使用します。
- 電源:「GND」と「5V」
- 入力:2番
- 出力:6~13番
今回配線やプログラムを分かりやすくするために、入力と出力の使用ソケット番号を離しています。
次に、各ソケットと電子パーツの割り当てを行います。
- 歩行者用押しボタン:2番
- 自動車用信号機1【緑信号】:6番
- 自動車用信号機1【黄信号】:7番
- 自動車用信号機1【赤信号】:8番
- 歩行者用信号機1【赤信号】:9番
- 歩行者用信号機1【緑信号】:10番
- 自動車用信号機2【緑信号】:11番
- 自動車用信号機2【黄信号】:12番
- 自動車用信号機2【赤信号】:13番
プログラムと使用ソケット番号が一致させれば、ソケット番号の割り当ては自由です。
プログラミング方法(Arduino IDE)
統合開発ソフトウェア「Arduino IDE」を使って、プログラミングします。
ソフトウェアのインストールがまだできていない方は、こちらの記事を参照してセットアップしてください。
Arduino IDEでのプログラミング方法
プログラムの構成は、基本的に3つに分けられます。
- 宣言やコメントエリア
- プログラム実行後、1度だけ実行される関数
- 繰り返し実行される関数
プログラムのソースコード
/* 作品名:「信GO機」 */
/* 作成者:せでぃあ https://cediablog.com */
/* プログラムによる信号機制御 */
int walker_btn = 2 ; //歩行者用押しボタンのIO割り当て
int led_G1A = 6 ; //自動車信号機1の緑IO割り当て
int led_Y1A = 7 ; //自動車信号機1の黄IO割り当て
int led_R1A = 8 ; //自動車信号機1の赤IO割り当て
int led_R1B = 9 ; //歩行者信号機1の赤IO割り当て
int led_G1B = 10; //歩行者信号機1の緑IO割り当て
int led_G2A = 11; //自動車信号機2の緑IO割り当て
int led_Y2A = 12; //自動車信号機2の黄IO割り当て
int led_R2A = 13; //自動車信号機2の赤IO割り当て
int i = 0; //歩行者用緑信号の点滅用、繰り返し変数
int j = 0; //歩行者用押しボタンの受付待ち用、繰り返し変数
void setup() {
// put your setup code here, to run once: プログラム起動時1回だけ処理される回路
// 入出力の割り当て
pinMode(walker_btn, INPUT); //2番ピンは入力として使用
pinMode(led_G1A, OUTPUT); //6番ピンは出力として使用
pinMode(led_Y1A, OUTPUT); //7番ピンは出力として使用
pinMode(led_R1A, OUTPUT); //8番ピンは出力として使用
pinMode(led_R1B, OUTPUT); //9番ピンは出力として使用
pinMode(led_G1B, OUTPUT); //10番ピンは出力として使用
pinMode(led_G2A, OUTPUT); //11番ピンは出力として使用
pinMode(led_Y2A, OUTPUT); //12番ピンは出力として使用
pinMode(led_R2A, OUTPUT); //13番ピンは出力として使用
//出力の初期化処理
digitalWrite(led_G1A, LOW);
digitalWrite(led_Y1A, LOW);
digitalWrite(led_R1A, LOW);
digitalWrite(led_R1B, LOW);
digitalWrite(led_G1B, LOW);
digitalWrite(led_G2A, LOW);
digitalWrite(led_Y2A, LOW);
digitalWrite(led_R2A, LOW);
}
void loop() {
// put your main code here, to run repeatedly: プログラム起動後ループ処理される回路
//信号点灯モードの切り替わりシーケンス
/* モード1・・・信号機1が緑点灯 */
digitalWrite(led_G1A, HIGH); //信号機1:緑点灯
digitalWrite(led_R1A, LOW);
digitalWrite(led_R1B, LOW);
digitalWrite(led_G1B, HIGH); //歩行者:緑点灯
digitalWrite(led_R2A, HIGH); //信号機2:赤点灯
delay(10000); //10秒ウェイト
/* モード2・・・信号機1の歩行者信号が緑点滅 */
//歩行者信号の緑点滅回路(0.25秒間隔)
for (i = 0 ; i <= 10 ; i++) {
digitalWrite(led_G1B, LOW);
delay(250);
digitalWrite(led_G1B, HIGH);
delay(250);
}
/* モード3・・・信号機1の歩行者信号が赤点灯 */
digitalWrite(led_R1B, HIGH); //歩行者:赤点灯
digitalWrite(led_G1B, LOW);
delay(1500); //1.5秒ウェイト
/* モード4・・・信号機1が黄点灯 */
digitalWrite(led_G1A, LOW);
digitalWrite(led_Y1A, HIGH); //信号機1:黄点灯
delay(2500); //2.5秒ウェイト
/* モード5・・・信号機1が赤点灯 */
digitalWrite(led_Y1A, LOW);
digitalWrite(led_R1A, HIGH); //信号機1:赤点灯
delay(2500); //2.5秒ウェイト
/* モード6・・・信号機2が緑点灯 */
digitalWrite(led_G2A, HIGH); //信号機2:緑点灯
digitalWrite(led_R2A, LOW);
//割り込み受付ウェイト回路(0.1秒間隔で9秒ウェイト)
for (j = 0 ; j <= 90 ; j++) {
if (digitalRead(walker_btn) != HIGH){
delay(100);
} else {
break;
}
}
delay(1000); //1秒ウェイト
/* モード7・・・信号機2が黄点灯 */
digitalWrite(led_G2A, LOW);
digitalWrite(led_Y2A, HIGH); //信号機2:黄点灯
delay(2500); //2.5秒ウェイト
/* モード8・・信号機2が赤点灯 */
digitalWrite(led_Y2A, LOW);
digitalWrite(led_R2A, HIGH); //信号機2:赤点灯
delay(2500); //2.5秒ウェイト
}
ソースコードのコピペが可能です
プログラム内容の説明
①宣言文
変数へのピン番号代入は絶対に必要というわけではありませんが、後の命令で使うときに「どのランプに対しての命令なのか」が分かりやすくなります。
- 初めにプログラム作成者などの「覚書」をコメントとして記入する
- 使用するソケット番号を変数に代入する
- ループ回路用の変数を宣言し0を代入する
プログラムの世界では、「データにはどんな数値が入っているかわからない」前提で考えます。
初期データが0であるとは限らないため、確実に0という数値が入っていてほしい場合は0を代入する初期化処理を行います。
②一度だけ実行する回路「setup()」関数
- デジタル入出力ソケット番号に対して、「入力」「出力」どちらの機能で使うのか宣言する
- 出力として使用するソケットは、初期の状態「ONかOFF」を代入する
③繰り返し実行する回路「loop()」関数
- モード1は全ランプの点灯条件を指示する
- その他のモードについては、ひとつ前のモードから点灯状態が変化するランプに対してのみ点灯消灯指示をする
- 現在のモードを維持する時間はdelay()関数で指定する
- 定期的に繰り返し処理を行う場合はfor文を使う
- 状態監視を行う場合はif文を使う
今回使用した命令文
- 変数のデータ型指定
- pinMode(入出力番号,INPUTまたはOUTPUT)
- digitalWrite(入出力番号,LOWまたはHIGH)
- digitalRead(入出力番号)
- delay(時間)
- for文
- if else文
- break文
- 比較演算子
変数のデータ型指定
変数のデータ型を指定するものです。
データ型 | 説明 | 扱える範囲 |
---|---|---|
int | 2バイトの整数を代入可能。 | -32768~32767 |
long | 4バイトの整数を代入可能 | -2,147,483,648~2,147,483,647 |
float | 4バイトの小数を代入可能。 | 3.4028235×1038~-3.4028235×1038 |
char | 1バイトの値を代入可能。文字列の代入に利用されます。 | -128~127 |
boolean | 0または1のみ代入可能。フラグのON-OFFなどに利用されます。 | 0,1 |
データ型の前に「unsigned」を付けると、正の値のみ扱うことができます。
負の数を扱う場合と比較して倍の数を扱えます。(boolean型は指定不可)
pinMode(入出力番号,INPUTまたはOUTPUT)
指定したデジタル入出力ソケット番号の機能を指示します。
入力として使用する場合は「INPUT」、出力の場合は「OUTPUT」を指定します。
digitalWrite(入出力番号,HIGHまたはLOW)
指定したデジタル入出力ソケット番号の電圧をON、またはOFFします。
ONさせたいときは「HIGH」、OFFさせたいときは「LOW」を指定します。
digitalRead(入出力番号)
指定したデジタル入出力ソケット番号の状態がON、またはOFFであるか確認します。
ONのときは「HIGH」、OFFのときは「LOW」の値が返ってきます。
delay(時間)
()内で指定した時間(単位はmsec)だけ、プログラム実行を待たせます。
今回のプログラムではモード切り替わりまでの時間(信号ランプ点灯時間)をこの命令文で制御しています。
マイクロ秒単位で指定したい場合は、delayMcroseconds(時間)を使います。
for文
初期値から加算値を加算しながら実行分を繰り返します。
条件式が成立すると繰り返し動作が終了します。
for(初期化 ; 条件式 ; 加算){
実行される文 ;
}
if else文
条件式が成立しているか否かで、どちらの命令文を実行するか振り分けます。
if( 条件 ){
条件成立時に実行する文 ;
} else {
条件不成立時に実行する文 ;
}
break文
for,while,doなどのループ回路から抜けます。
比較演算子
比較演算子 | 説明 |
---|---|
A == B | AとBが等しい場合に成立 |
A != B | AとBが等しくない場合に成立 |
A < B | AがBより小さい場合に成立 |
A <= B | AがB以下の場合に成立 |
A > B | AがBより大きい場合に成立 |
A >= B | AがB以上の場合に成立 |
プログラミング方法(Scrattino3)
Scrattino3(スクラッチーノ3)とは
Scrattino3(スクラッチーノ3) は、PC(パソコン)にインストールをしてプログラミングを行う無償ソフトウェアです。
Scratch(スクラッチ)とよばれるプログラミング言語を用いて、Arduino(アルディーノ)を動作をさせるアプリケーションです。
「入力」「出力」制御等、Arduinoを動作させるために必要なブロックが用意されています。
- 「ビジュアルプログラミング言語」を採用している
- 直感的なプログラミング操作が可能
- 小学生から使うことが可能なやさしい言語
プログラム設計する
- 「旗マークが押されたとき」はプログラム開始後1度だけ演算される
- 「ずっと」で指定された範囲は、繰り返し演算される
- ブロックの組み合わせだけで、ArduinoIDEプログラミングでの動作を再現できる
- for文、if文の代わりに「繰り返し」「もし~でなければ」のブロックが存在する
ブロックを選んでくっつけるだけでプログラミングできるよ
まとめ
- Scrattino3でのプログラミングはパソコンとArduino本体がUSBケーブルで接続されていないと動作できない
- 小学生やプログラミングが苦手な人はスクラッチでのプログラミングがおすすめ
- C言語などのプログラミングに慣れている人は、Arduino IDEプログラミングがおすすめ
おすすめ参考書
私もこの本を読んで、勉強しています!
オールカラーで図や写真も多く、とても丁寧でわかりやすいためおすすめです。
スクラッチプログラミングを学習するのにおすすめな勉強本をレビューしています。
子供の成長を育む!小学生にぴったりなプログラミング教室を見つけるために厳選しました!
レゴブロックを用いた電子工作の作り方はこちら
Arduinoスターターキットの紹介はこちら
コメント
コメント一覧 (2件)
( ゚д゚ )ホゲー
いやーやっぱりケタが違いますね知識の量、、
毎度勉強させて頂いております、、
コメントありがとうございます✨
いえいえ💦
わたしも勉強中です!
お役に立てましたら、幸いです😊