ブレッドボードを使ったtinyBasic流ものづくり(ESP8266版)
更新

ブレッドボードを使ったtinyBasic流 ものづくり(ESP8266版)
コンピュータの仕組み: ATtiny2313版
Arduino流: ATtiny4313版ATmega328P版NANO版ESP8266版
tinyBasic流: NANO版ProMicro版ESP8266版
WebIO: Arduino流IO制御(ProMicro版)

小山智史(弘前大学教育学部)


0. 準備
1. tinyBasicのコマンド操作
2. デジタル出力(1): LEDの点滅
3. デジタル入力: スイッチ操作でLEDのオンオフ
4. アナログ出力: LEDの明るさを変える
5. アナログ入力
6. デジタル出力(2): 液晶ディスプレイ
7. センサーの利用
8. ブザー音で演奏
9. 合成音声でおしゃべり
10. イルミネーション
11. 赤外線リモコン
12. 動くものを作る
13. 押しボタン信号機
14. シリアル通信教材(光通信)
15. WiFi経由で制御する
(付録1) tinyBasicのArduinoへの書き込み
(付録2) 入出力に利用できるピン
(付録3) tinyBasic リファレンス
(付録4) 入出力モジュールの例
(付録5) 使用する主な部品
(付録6) 文字と文字コード


 私達の身近にある電子機器の多くにコンピュータが内蔵されており、このようなコンピュータは「マイコン」と呼ばれます。マイクロコンピュータあるいはマイクロコントローラの略です。マイコンにはメーカーが開発したプログラムが書き込まれています。リモコンの中に入っているマイコンには、押したボタンに応じて決まったパターンで赤外線をオンオフするプログラムが書き込まれています。このプログラムはマイコン製造時に書き込まれ、後から書き換えることはできませんが、フラッシュメモリー(電気的に書き換え可能なプログラムメモリー)を搭載したマイコンを使えば、私達もさまざまな機器を作ることができます。実際に、11章ではリモコンの製作例を紹介しています。
 マイコンを使った機器を設計・製作するには、電子回路、論理回路、コンピュータの仕組み、プログラミングなど広範囲の知識が要求されます。これは大変なことではありますが、一方ではこれらのことを学ぶ格好の教材であるということを意味しています。
 このテキストでは、Arduino版tinyBasicを使った実習を行いながら、「マイコンを使ったものづくり」について学習します。

☆ ここでは複雑な電子回路は登場していませんが、電気回路の最低限の知識は前提としています。必要な場合はこちらの資料[4]を参考にしてください。
☆ 本テキストは実習時に適宜解説や補足を行うことを前提にしています。自学自習には適していないかもしれません。
☆ 14章まではArduinoNANO版やArduinoProMicro版とほとんど同じ内容です。15章のWiFiとtinyBasicの組み合わせが「いったいどういう可能性が開けるのか」試行錯誤中です。


0. 準備

0.1 ブレッドボードの使い方

 ここでは下図(a)のブレッドボード(EIC-301)を使います。ボードの内部は下図(b)のように接続されています。


(a) ブレッドボード(EIC-301)の外観

(b) ブレッドボードの内部の接続

 ESP8266をブレッドボードに下図(b)のように接続します。USBケーブルをパソコンに接続すると、電源(5V)がパソコンから供給されます。(a)が回路図、(b)が実体配線図です。


(a) 回路図(電源はUSBから供給される)

(b) 実体配線図

 ESP8266にはラベルを貼っておきます(テプラファイル)。

 ここで、初めてブレッドボードを使う場合は、練習としてLEDと抵抗を下図(a)のように接続してみます。電流の流れは(c)のようになります。ブレッドボードの内部の結線も含めて「電流が流れる経路」を意識することが重要です。


(a) 回路図

(b) 実体配線図

(c) 電流の流れ

0.2 tinyBasicの準備

 付録1を参考に、ESP8266にtinyBasicのプログラムを書き込みます。

 tinyBasicのプログラムはArduinoのマイコンで動作し、パソコンからの指示を受けて、ハードウェアを制御したり、命令の並び(プログラム)としてRAMに一時保存したり、そのプログラムを1行ずつ順に解釈しながら実行(RUN)したりします(下図左)。

 また、RAMのプログラムはマイコン上のEEPROM(不揮発メモリー)に保存(SAVE)することができます。電源を切るとRAM内のプログラムは消えてしまいますが、EEPROMに保存したプログラムをRAMに読み込むことができ(LOAD)、また電源投入時には自動的に読み込まれてプログラムが自動実行されます。

 プログラムが完成したら、100均などで入手できるUSB電源アダプタを使うとよいでしょう。

 入出力に利用できるピンを付録2にまとめてあります。

0.3 通信ソフトTeraTermの準備

 パソコンに通信ソフトTeraTermをインストールします。[設定][シリアルポート]で「ポート」をArduinoを接続して現れるポートにし、「ボー・レート」は「115200」にします。また、[設定][フォント]で「サイズ」を「20」ぐらいにすると見やすいかもしれません。設定が終わったら[設定][保存]で保存します。

 通信ソフトで接続すると「HalfByte...Hitany key!」の表示が現れるので、何かキーを押します。そして、「0.2 Arduino NanoにtinyBasicを準備」の後初めて使う場合に一度だけ「new」「save」の操作をしてください。


1. tinyBasicのコマンド操作

1.1 コマンドの実行

 パソコンからTeraTermなどの通信ソフトを用いてESP8266に接続すると、下の画面が表示されます。


パソコンの通信ソフト(TeraTerm)の表示画面
 はじめに、コマンドで直接指示を与える方法を試してみましょう。
print 100
これは、「100を表示しなさい」という「命令」を表していて、この1行が「命令文」になっています。「文」といっても、疑問文や感嘆文があるわけではありません。コンピュータ(tinyBasic)に対して指示を与える「命令文」があるだけです。
 では、次のようにするとどうでしょうか。
print 100*200/50+2 print 30000+2000 print 30000+8000
それぞれ計算結果が表示されますが、最後の命令文は計算結果が扱える数「-32767~32767」を越えてしまったため、正しく表示されません。

 文字列を表示することもできます(日本語も表示できます)。また、「,(カンマ)」で区切ると、文字列や数値(計算結果)を続けて表示することができます。

print "ABC" print "弘前大学" print "100+200" print "100+200=",100+200

(練習)大文字と小文字は区別されないので、キー操作は「print」でも「PRINT」でも構いません。また、「print」の代わりに「?」でも構いません。確かめなさい。

1.2 変数

 「変数」は値をしまっておく入れ物です。変数にはA~Zの名前がついていて(変数名)、26個あります。大文字小文字は区別されません。変数には-32767~32767の整数を格納できます。
X=1 Y=2
と操作すると、「X」「Y」という変数(入れ物)にそれぞれ「1」「2」という値が代入されます。XとYに値を入れたので、以下の操作で変数同士の計算結果が表示されます。
print X+Y


2. デジタル出力(1): LEDの点滅

2.1 LEDを点灯・消灯する

 以下の回路を組み立ててください。


回路図

実体配線図

 LEDはD13ピンに接続します。「dWrite」というコマンドでD13ピンに高い電圧を出力したり低い電圧を出力したりすることができます。
dWrite 13, 1 または dWrite 13,HIGH

と操作すると、D13ピンに高い電圧(3.3V)が出力され、接続したLEDが点灯します。
dWrite 13, 0 または dWrite 13,LOW

と操作すると、D13ピンに低い電圧(0V)が出力され、LEDは消灯します。

上記の「dWrite 13, 1(またはHIGH)」は「D13ピンに1(高い電圧)を出力しなさい」という意味です。

 LEDが点灯する時の電流の流れは下図のようになります。

(練習)「dWrite 13, 1」および「dWrite 13, 0」の時のD13ピンの電圧を、テスターで測りなさい。

(練習)LEDを他のピンにつなぎ替えて、点灯・消灯してみなさい。

2.2 プログラムでLEDを点滅させる

 はじめに、「NEW」の操作でプログラムを消去します。
new

 プログラムのはじめの一歩は「Lチカ」です。以下の「プログラム」を入力してください。プログラムは「命令の並び」で、並びの順に実行されます。各行先頭の10~50は「行番号」で、コンピュータの中では、行番号の小さい行から順に並んでいます。先に大きな行番号の行を入力して後から小さな行番号の行を入力しても結果は同じになります。また、同じ行番号で入力しなおせば、置き換えられます。行番号だけを入力するとその行は削除されます。

10 dWrite 13, 1 20 delay 1000 30 dWrite 13, 0 40 delay 1000 50 goto 10 ピン13に1(HIGH)を出力する 1000ms(1秒)待つ ピン13に0(LOW)を出力する 1000ms(1秒)待つ 行10に行く

 以下、プログラムの内容について簡単に説明します。10~50の各行は「命令文」になっていて、それぞれ次のような意味です。これにより、行10~50が繰り返されます。

 「LIST」と操作すると、入力したプログラムが表示されます。
list

 「RUN」と操作すると、最も小さい行番号から順にプログラムが実行され、LEDが点滅を繰り返します。
run

 プログラムの実行を中断するには「ESCキー」を押します。

 後から途中にプログラムを挿入したくなることもありますから、行番号は10刻みぐらいにしておきます。

 1行に「:」で区切って複数の命令文を書くことができます。以下のプログラムはこの方法で書き直したものです。動作は同じです。

10 dWrite 13, 1: delay 1000 20 dWrite 13, 0: delay 1000 30 goto 10

 このように入力したプログラムは、RAMに一時保存されていて、電源を切ると消えてしまいます。「SAVE」の操作でEEPROM(不揮発メモリー)に保存することができます。
save

 保存したプログラムは、「LOAD」の操作で読み込まれます。
load

保存できるプログラムはひとつで、名前をつけたりすることはできません。

(練習) (1)上のプログラムを入力し、LISTで確認後、SAVEで保存しなさい。(2)続いてNEWで消去し、LISTで確認後、LOADして再びLISTで確認しなさい。(3)一旦電源を切断し、その後電源を接続してプログラムが自動実行されることを確認しなさい。可能ならばパソコン以外のUSB電源に接続して動作を確認しなさい。

(練習) LEDを0.5秒点灯、0.5秒消灯を繰り返すようにプログラムを変更しなさい。また、0.2秒点灯、1.8秒消灯を繰り返すように変更しなさい。

2.3 LEDを高速に点滅させる

 LEDの点灯時間と消灯時間を変更してみます。

 「delay 1000」→「delay 100」→「delay 20」→「delay 10」→「delay 1」と変えて、点滅の様子を確認してください。「delay 10」の時は10ms点灯、10ms消灯を繰り返し、50Hzの点滅になります。「delay 20」(25Hz)の時は点滅しているのがわかりますが、「delay 10」(50Hz)では点滅を感じなくなります。人間の目が感じる「点滅のちらつき」はフリッカと呼ばれ、高速の点滅(50~60Hz)ではちらつきを感じなくなります。

 通常の蛍光灯は100Hz(50Hzの2倍)で点滅しますが、蛍光管の状態によっては発光にムラが生じ50Hzで点滅し、その場合はちらつきが気になることがあります。インバーター式の蛍光灯はちらつきを抑えるために超高速(数10kHz)で点滅させています。また、ブラウン管テレビが毎秒30フレーム(実際にはインターレースで60Hzのフリッカ)、映画のフィルムが毎秒24フレーム(実際には同じフレームを2度映すことで48Hzのフリッカ)になっているのは、このような目の特性を考慮してのことです。

(練習) LEDの点滅速度を30Hz, 40Hz, 50Hz, 60Hzと変化させ、ちらつきが感じられるかどうかを、ブレッドボードを静止した場合と、左右に振った場合の両方で調べなさい。

(練習) 緑色LEDと1kΩの抵抗をD12ピンに追加接続し、そのLEDを1秒毎に点滅させなさい。また、赤色LEDと緑色LEDが1秒毎に交互に点灯するようにしなさい。


3. デジタル入力: スイッチ操作でLEDのオンオフ

3.1 スイッチが押されているかどうか調べる

 下図左のようにD14ピンにスイッチを接続すると、D14ピンはスイッチをオンにすると低い電圧(0V)になり、スイッチをオフにすると高い電圧(5V)になります。これは、下図右のようにマイコンの中に抵抗が内蔵されているためです。この抵抗を「プルアップ抵抗」といいます。「高い電圧に引っ張り上げる抵抗」というような意味です。

回路図
スイッチを接続
回路図
プルアップ抵抗
D14ピンが高い電圧(1)か低い電圧(0)かをdRead(14)で読み取り、PRINTで表示することができます。

print dRead(14)
回路図

 以下はスイッチの状態を時々刻々調べて表示するプログラムです。

10 print dRead(14) 20 delay 200 30 goto 10 スイッチ(ピン14)の状態を表示する 200ms待つ 行10に行く
回路図

 以下はこれを「1行プログラム」として書いたものです。プログラムが思ったように動作せずに頭を抱えている時など、このような方法で調べるとすぐに原因がわかることもあります。

10 print dRead(14):delay 200:goto 10
回路図

(練習) スイッチを押した時と放した時のスイッチ両端の電圧を、テスターで測りなさい。

(練習) スイッチを押した場合と放した場合で、「print dRead(14)」が変化することを確かめなさい。

3.2 スイッチ操作でLEDを点灯・消灯する

 以下のプログラムは、行10でスイッチ(ピン14)の状態を読み取って(0または1)変数Aに代入し、この値をLED(ピン13)に出力し、これを繰り返します。スイッチを押すとAの値は0になりLEDは消灯し、放すとAの値は1になりLEDは点灯します。

10 A=dRead(14) 20 dWrite 13,A 30 goto 10 Aはスイッチ(ピン14)の状態 Aの値をLED(ピン13)に出力 繰り返す
回路図

 「!A」はAが0の時に1、Aが1の時に0となるので、以下のようにするとスイッチを押した時にLEDが点灯します。

10 A=dRead(14) 20 dWrite 13,!A 30 goto 10

3.3 スイッチ操作で交互に点灯・消灯する

 以下のプログラムは、スイッチを押すと交互にLEDが点灯・消灯します。考え方は、「スイッチが押された瞬間に(つまりさっき押されていなくて今押されたら)LED表示を反転する」というものです。変数Bには「今のスイッチの状態(0または1)」、変数Aには「さっきのスイッチの状態(0または1)」、変数Lには「今のLEDの点灯状態(1が点灯、0が消灯)」を保存します。

 行30で、現在のスイッチ(ピン14)の状態(1または0)を読み取り、Bに入れます。行40で、スイッチが「さっきまで押されていなくて今押されている」ならLの値を反転(0なら1、1なら0)します。その後、行50で「今のスイッチの状態を記憶」しなおし、行60でLの値をLEDに出力します。行70で、少し待ってから行30に行きます。

10 L=0 20 A=1 30 B=dRead(14) 40 if A=1 if B=0 L=!L 50 A=B 60 dWrite 13, L 70 delay 10 80 goto 30 LはLEDの点灯状態 Aはさっきのスイッチの状態 Bは現在のスイッチの状態 さっき押されていなくて今押されたらLを反転 スイッチの状態を覚え直す LをLED出力 少し待って 繰り返す
回路図

 「delay 10」がないと、誤動作することがあります。それは、スイッチを押した時に、ごく短い時間にその接点がオンになったりオフになったりするからです。スイッチを離した時も同様です。スイッチによって異なりますが、10ms程で落ち着きます。この現象は「チャタリング」と呼ばれます。

(練習) 「delay 10」を極端に長くし、例えば待ち時間が2秒になるようにして、どのような動作になるか調べなさい。

(練習) 緑色LEDを増設し、スイッチを押すと赤色LEDと緑色LEDが交互に点灯するようにしなさい。

3.4 スイッチを4回押すと点灯する

 以下のプログラムは、スイッチ操作4回に一度LEDが点灯します。

 上の例ではLEDの表示状態を記憶し、スイッチが押されるとその値を反転させていましたが、ここではCに「スイッチが押された回数」を記憶します。スイッチが「さっきまで押されていなくて今押されている」ならCの値に1を加えます(行40)。その後、「今のスイッチの状態」を記憶し(行50)、「C%4=0」つまり「Cを4で割った余りが0」であればLEDを点灯し(行60)、そうでなければLEDを消灯します(行70)。最後に、少し待ってから行30に行き、繰り返します。

10 C=0 20 A=1 30 B=dRead(14) 40 if A=1 if B=0 C=C+1 50 A=B 60 if C%4=0 dWrite 13,1: goto 80 70 dWrite 13,0 80 delay 10 90 goto 30 Cはスイッチが押された回数 Aはさっきのスイッチの状態 Bは現在のスイッチの状態 スイッチが押されたらCに1を加える スイッチの状態を覚え直す Cを4で割った余りが0ならLEDを点灯 LEDを消灯 少し待って 繰り返す
回路図

(練習) 行60の「C%4=0」の箇所を「C%7=0」や「C%4!=0」などに変えて、どのような動作になるか調べなさい。

(練習) 2個の押しボタンスイッチを使い、一方のスイッチを押すとLEDが点灯し、もう一方のスイッチを押すと消灯するようにしなさい。

3.5 スイッチが押されるとLEDを3秒点灯する

 以下のプログラムは、スイッチが押されるとLEDを3秒点灯します。

10 if dRead(14)=0 dWrite 13,1: delay 3000: goto 10 20 dWrite 13,0 30 goto 10
回路図

4. アナログ出力: LEDの明るさを変える

4.1 LEDの明るさを変える

 これまでは、LEDが点灯するか消灯するかでした。しかし、点灯時の明るさを変化させたいこともあります。 aWrite という命令を使い

とすると、指定したピンにアナログ値 0~255 を出力できます。

 LEDの接続はそのままで、以下の操作をしてみましょう。

aWrite 13, 10 aWrite 13, 255

LEDの明るさが変わるのが確認できます。

(練習)LEDの明るさを0~255の範囲で変えてみなさい。また、その時の波形をオシロスコープで観察して記録しなさい。

4.2 プログラムでLEDの明るさを変える

 2.3ではLEDの点灯時間と消灯時間を変えてどのように見えるかを確認しました。ここでは行20と行40を「delay 1」にしてみます(1ms)。

10 dWrite 13,1 20 delay 1 30 dWrite 13,0 40 delay 1 50 goto 10

 既に経験したように、点灯と消灯を高速に切り替えると、私達の目は点滅を認識できなくなります。代わりに、常時点灯している場合よりも少しだけ暗く感じます。「平均的に」半分の明るさになるからです。下図左は、この時のLEDの出力の波形を示したものです。行30の0を1にすれば常時点灯となりますから、LEDの明るさを比較してみてください。私達の目は、明るさが半分になっても、「ちょっと暗くなった」ぐらいにしか感じません。

PWM波形

 次に、行20はそのままにして行40を「delay 9」としてみてください。こうすることにより、1ms点灯、9ms消灯を繰り返すようになり、明るさはより暗く感じられます。この時の波形が上図中央です。

 HIGHとLOWの時間が等しい時「デューティ比50%」、常時HIGHの時「デューティ比100%」、HIGHが1msでLOWが9msなら「デューティ比10%」といいます。この技術は「パルス幅変調(PWM)」と呼ばれ、モータのスピードコントロールや、デジタルオーディオアンプなどに利用されています。

 4.1で使ったaWriteというコマンドを使うと、0/255~255/255のデューティ比で上記のようなPWM信号が出力される仕組みになっています。

(練習) スイッチを押す度に「消灯→暗い→明るい→消灯→...」の動作をするプログラムを作りなさい。

4.3 LEDの明るさを連続的に変える

 デューティ比を連続的に変化させれば、下図のように任意の波形を表すことができます。

PWM波形

 以下は、デューティ比を0%から100%まで少しずつ変化させるプログラムです。暗い状態から次第に明るくなり、その後次第に暗くなり、これを繰り返します。Bが明るさの値、Fが明るさの変化量です。行30でBの値をアナログ出力し、行40でBの値をFだけプラスします。

10 B=5 20 F=5 30 aWrite 13, B 40 B=B+F 50 if B=0 F=5 60 if B=255 F=-5 70 delay 30 80 goto 30 Bは明るさ Fは明るさの変化量 LED(ピン9)に明るさ(Bの値)を出力 BにFを加える Bが0ならFを5にする Bが255ならFを-5にする 少し待って 繰り返す

(練習) スイッチを押すとLEDがだんだん明るくなり、スイッチを離すだんだん暗くなるプログラムを作りなさい。


5. アナログ入力

5.1 アナログ値の入力

 以下のようにA0ピンにボリュームを接続し、ボリュームを中ほどの位置にして以下の操作をしてみてください。ボリュームの位置に応じて0~1023の値が表示されます。aReadは指定されたピンのアナログ値(0~1023)を返す「関数」です。aRead(0)は、A0ピンの電圧(0~1V)に応じて0~1023の値が返ってきます。PRINTコマンドを使い、ボリュームの位置を変えて、表示される値を確認してください。また、1行プログラムで値を時々刻々表示できます。

print aRead(0)
10 print aRead(0): delay 200: goto 10

(練習) A0の電圧をテスターで測り、ボリュームを回すとどのように変化するか調べなさい(ボリュームの位置が左・中央・右)。また、上記のプログラムを動作させた時に、電圧がいくらの時に表示される値がいくらになるかを調べなさい(ボリュームの位置が左・中央・右)。

5.2 アナログ値に応じてLEDの点灯時間を変える

 以下のプログラムは、ボリュームの値(0~1023)に応じてLEDの点滅時間が変化します。

10 dWrite 13,1 20 delay aRead(0) 30 dWrite 13,0 40 delay aRead(0) 50 goto 10
回路図

5.3 アナログ値に応じてLEDを点灯・消灯する

 以下のプログラムは、ボリュームのアナログ値(0~1023)が600未満の時にLEDを点灯します。

10 if aRead(0)<600 dWrite 13,1: goto 10 20 dWrite 13,0 30 goto 10
回路図

5.4 アナログ値に応じて明るさを変える(調光)

 照明の明るさを調整することを「調光」といいます。

 以下のプログラムは、ボリュームのアナログ値(0~1023)に応じてLEDの明るさ(0~255)を連続的に変えます。

10 A=aRead(0)/4 20 aWrite 13,A 30 goto 10 Aは0~255 LED(ピン13)にAの値を出力 繰り返す
回路図

6 デジタル出力(2): 液晶ディスプレイ

6.1 液晶ディスプレイに文字や数字を表示する

 I2C接続の液晶ディスプレイ(2行16文字)を以下のように接続します。

 CLS(画面クリア)、CURSOR(カーソル位置指定)、PRINT(表示)の3つのコマンドは、通信ソフト(teraTerm等)と液晶の両方の表示に適用されます。

cls print "COUNT: "; print 100

6.2 液晶ディスプレイにカウントアップ表示する

 以下のプログラムは、1秒毎にカウントアップ表示します(通信ソフトの画面にも表示されます)。

10 C=0 20 cls 30 print "COUNT: ",C 40 delay 1000 50 C=C+1 60 goto 20 Cはカウント値 画面クリア Cの値を表示 1秒待つ Cをカウントアップ 繰り返す
回路図

 以下のプログラムは、スイッチを押すとカウントアップするプログラムです(通信ソフトの画面にも表示されます)。

10 C=0 20 A=1 30 cls:print "COUNT: ",C 40 B=dRead(14) 50 if A=1 if B=0 C=C+1:cls:print "COUNT: ",C 60 A=B 70 delay 10 80 goto 40 Cはカウント値 Aはさっきのスイッチの状態 画面クリアしてCの値を表示 Bは現在のスイッチの状態 スイッチが押されたらCに1加えて表示 スイッチの状態を覚え直す 少し待って 繰り返す
回路図

6.3 アナログ値を液晶ディスプレイに表示する

 以下のプログラムは、ボリュームのアナログ値(0~1023)を液晶ディスプレイに表示させます(通信ソフトの画面にも表示されます)。

10 cls 20 print "VAL: ",aRead(0) 30 delay 200 40 goto 10 画面クリア アナログ値を表示 少し待って 繰り返す
回路図

7. センサーの利用

7.1 スイッチをセンサーとして使う

 押しボタンスイッチやスライドスイッチは、操作用のスイッチですが、センサーとしても活躍しています。例えば、CD/DVDデッキやコピー機やプリンタなど動きを伴う機器には、所定の位置に来たがどうかを検知するために、マイクロスイッチが必ずといっていいほど使われています。このような使われ方をするスイッチを「リミットスイッチ」と呼ぶこともあります。

 ふたつの金属片を接触させるだけでスイッチ(センサー)となるので、オリジナルのスイッチを作ることも難しくはありません。所定の水位になったかどうかを検知するピンポン球を使った浮力スイッチ、傾けると金属ボールが移動する傾斜スイッチなど、用途に応じて工夫するのも楽しいでしょう。

 スイッチの値はprintコマンドで表示できます。また、下の1行プログラムでスイッチの様子を時々刻々表示できます。

print dRead(14)
10 print dRead(14): delay 200: goto 10
回路図

7.2 明るさセンサー(CDS): 明るい時にLEDを点灯する

 5.1のボリュームの代わりに明るさセンサー(CDS)をつないでみましょう。CDSは明るくなるほど抵抗値が低くなり、A0ピンの電圧は高くなります。

 printコマンドでA0ピンの値を確認してください。また、下の1行プログラムでA0ピンの値を時々刻々表示できます。

print aRead(0)
10 print aRead(0): delay 200: goto 10

 以下のプログラムは一定以下に暗くなるとLEDが点灯します。プログラムは5.3と同様です。ただし、行10の「600」の値は適切な値に変更する必要があります。

10 if aRead(0)<600 dWrite 13,1: goto 10 20 dWrite 13,0 30 goto 10 アナログ値が600未満ならLEDを点灯し繰り返す LEDを消灯 繰り返す
回路図

 街路灯などでは、境界値付近で点灯したり消灯したり不安定になるのを避けるために、下図のような「ヒステリシス特性」を持たせます。

行20はledが消灯(Lが0)している時に600未満の明るさになったらledを点灯(Lを1)します。行30はledが点灯(Lが1)している時に700以上の明るさになったらledを消灯(Lを0)します。実際の点灯消灯は行40で行っています。

10 L=0 20 if L=0 if aRead(0)<600 L=1 30 if L=1 if aRead(0)>=700 L=0 40 dWrite 13,L 50 goto 20 LはLEDの点灯状態 消灯状態で明るさが600未満なら点灯(L=1)にする 点灯状態で明るさが700以上なら消灯(L=0)にする LをLEDに出力 繰り返す
回路図

(練習) 行20の600と行30の700の値を変えて、適切な値をみつけなさい。

7.3 温度センサー(サーミスタ): 温度が高い時にLEDを点灯する

 CDSの代わりに温度センサー(サーミスタ)をつないでみましょう。サーミスタは温度が高くなるほど抵抗値が低くなり、A0ピンの電圧は高くなります。

 printコマンドでA0ピンの値を確認してください。また、下の1行プログラムでA0ピンの値を時々刻々表示できます。

print aRead(0)
10 print aRead(0): delay 200: goto 10

 以下のプログラムは温度がある値以上になるとLEDが点灯します。プログラムは上と同様です。ただし、行10の「25」の値は適切な値に変更する必要があります。

10 if tRead(0)<25 dWrite 13,1: goto 10 20 dWrite 13,0 30 goto 10 温度が25未満ならLEDを点灯し繰り返す LEDを消灯 繰り返す
回路図

(練習) LEDをエアコンに置き換えて考えてみましょう。街路灯の場合と同様、境界値付近で点灯したり消灯したり不安定になるのを避けるために、下図のような「ヒステリシス特性」を持たせます。

ヒステリシス特性を持たせたプログラムでその動作を確かめなさい。

(練習) 温度が高ければ赤、温度が低ければ青のLEDが点灯するようにしてみなさい。

7.4 音量センサー: 音を検知するとLEDを点灯する

 音量センサーは、マイクが検知する音の大きさに応じてA0ピンの電圧は高くなります。

 printコマンドでA0ピンの値を確認してください。また、下の「1行プログラム」でA0ピンの値を時々刻々表示できます。

print aRead(0)
10 print aRead(0): delay 200: goto 10

 以下のプログラムは、音を検知したら(A0のレベルが300を超えたら)、LEDを3秒点灯します。

10 if aRead(0)>300 dWrite 13,1: delay 3000: goto 10 20 dWrite 13,0 30 goto 10
回路図

(練習) 5.2のスイッチの代わりに音センサを使い、手をたたくとカウントアップするようにしなさい。

7.5 赤外線反射センサー: 何かに接近するとLEDを点灯する

 赤外線反射センサーは、光を反射する物がない時は1000程度の値、数cmのところに光を反射する物がある時は20~30の値を返します。

 printコマンドでA0ピンの値を確認してください。また、下の1行プログラムでA0ピンの値を時々刻々表示できます。

print aRead(0)
10 print aRead(0): delay 200: goto 10

以下のプログラムは、何かに接近したら(A0のレベルが40より小さくなったら)、LEDを点灯します。

10 if aRead(0)>300 dWrite 11,1: delay 3000: goto 10 20 dWrite 11,0: goto 10
回路図

7.6 人感センサー: 人を検知してLEDを点灯する

 以下のプログラムは、人感センサー(焦電センサー)を使って人を検知するとLEDを点灯します。玄関などに使われています。センサーの出力は普段は0(低い電圧)で、人を検知すると一定時間1(高い電圧)になります。センサーについているボリュームで感度や検出後の不感時間を調整できます。

10 dWrite 13,dRead(14) 20 goto 10
回路図

7.7 温湿度センサー: 温湿度計を作る

 ここでは高精度のデジタル温湿度センサー(SHT31)を使います。tRead()で温湿度を直接読み取ることができます。温度が23度であればtRead()は「23」という値を返し、相対湿度が45%であればhRead()は「45」という値を返します。PRINTコマンドで確認してください。また、「1行プログラム」で温度を時々刻々表示できます。

print tRead() print hRead()
10 print tRead(): delay 1000: goto 10

 以下のプログラムは、温湿度センサー(SHT31)で測定した温度と湿度を液晶ディスプレイに表示します。なお、パソコンと接続している場合は、通信ソフト(teraTerm等)にも液晶ディスプレイと同じ表示が現れます。

10 cls 20 cursor 0,0 30 print tRead(),chr(&df),"C" 40 cursor 8,0 50 print hRead(),"%RH" 60 delay 1000 70 goto 10

 プログラムを保存(SAVE)しておくと、パソコンと接続しなくても、電源を入れるとプログラムが起動します。ケースに入れれば温湿度計の完成です。


8. ブザー音で演奏

 ここではブザー音で電子オルゴールを作ってみましょう。和音など音にこだわる方は「私だけの電子オルゴール」[8]を参考にしてください。

8.1 ブザー音を作る

 下図のように圧電ブザー(Bzz)を接続し、「1秒ごとに点滅させるプログラム」を実行してください。するとブザーからカチカチと音が聞こえます。ここで、点灯時間と消灯時間を以下のように1msにしてみましょう。

10 dWrite 13,1 20 delay 1 30 dWrite 13,0 40 delay 1 50 goto 10

 この時の波形は下図のように500Hzの矩形波となり、聞こえるのは500Hzの音です(といっても倍音成分が含まれていますが)。

トーン波形

(練習) オシロスコープでトーン信号の波形を観察しなさい。また、WaveGeneなどの信号発生ソフトを用い、パソコンで500Hzの矩形波を出し、音を比べてみなさい。

8.2 音程を変える

 指定したピンに、指定した周波数の音を、指定した時間出力する tone という命令を使います。以下は時報の音を出すプログラムです。ソが784Hz、ドが1046Hzです。初めにtoneコマンドで指示した音が出ることを確認し、それからプログラムにします。音の終了を待たずにプログラムは次に進むので、多くの場合は次行にdelayを置きます。

tone 13,784,200 tone 13,784,200 tone 13,784,200 tone 13,1046,2000
10 tone 13,784,200: delay 1000 20 tone 13,784,200: delay 1000 30 tone 13,784,200: delay 1000 40 tone 13,1046,2000

(練習) 440Hzのラの音(A4)に対し1オクターブ高いラ(A5)の音は880Hzで、その間は隣同士(半音)の周波数の比が一定(21/12)となるように音階が作られます。表計算ソフトを用い、A4~A6の各音の周波数を計算しなさい。上のプログラム中の784Hzが「ソ」、1046Hzが「ド」であることが確認できます。

(練習) 上のプログラムを参考に、簡単な曲を演奏させるプログラムを作りなさい。

(練習) 時計のアラーム音、信号機の音、風呂や電気ポットの湯沸かし音など、身近にある電子音を録音し、その音をプログラムで再現しなさい。

8.3 楽譜を演奏する

 以下は、文字列で記述した楽譜情報を参照しながら演奏するプログラムです。楽譜情報がプログラムと分離されているので、長い曲も表しやすくなっています。

10 P=top(0):POKE P,"RDDBAGDR RDDBAGER REEcBAFR RdddcABR RDDBAGDR RDDBAGER REEcBAdd ddedcAGR" 20 C=peek(P):P=P+1 30 if C=13 B=0:stop 40 if C=32 goto 20 50 if C=82 F=0 60 if C=67 F=262 70 if C=68 F=294 80 if C=69 F=330 90 if C=70 F=349 100 if C=71 F=392 110 if C=65 F=440 120 if C=66 F=494 130 if C=99 F=523 140 if C=100 F=587 150 if C=101 F=659 160 if C=102 F=698 170 if C=103 F=784 180 tone 13,F,300:delay 300:goto 20 楽譜データ 改行 スペース R(休符) C D E F G A B c d e f g

(練習) 行10の楽譜を変え、必要な場合は行60~170を拡張し、好きな曲の電子オルゴールを作りなさい。

8.4 楽器を作る

 以下のプログラムは、ボタンを押すと、ボリュームで決まる周波数のブザー音がでます。

10 if dRead(14)=1 goto 10 20 A=aRead(0) 30 tone 13,A,200 40 goto 10

 上のプログラムで一応楽器として使えるのですが、ドレミ...の音を丁度よく出すのは難しいと思います。そこで、ドレミ...の音しか出ないようにしたのが次のプログラムです。

10 if dRead(14)=1 goto 10 20 A=aRead(0) 30 if A>784 tone 13,784,200: goto 10 40 if A>698 tone 13,698,200: goto 10 50 if A>659 tone 13,659,200: goto 10 60 if A>587 tone 13,587,200: goto 10 70 if A>523 tone 13,523,200: goto 10 80 if A>494 tone 13,494,200: goto 10 90 if A>440 tone 13,440,200: goto 10 100 if A>392 tone 13,392,200: goto 10 110 if A>349 tone 13,349,200: goto 10 120 if A>330 tone 13,330,200: goto 10 130 if A>294 tone 13,294,200: goto 10 140 tone 13,262,200 150 goto 10

(練習) ボリュームの代わりに明るさセンサで音程が変わるようにしなさい。また、必要ならば音階を拡張しなさい。


9. 合成音声でおしゃべり

9.1 コマンド操作でおしゃべり

 I2C接続した音声合成LSI(ATP3011F4)を使ってスピーカから合成音声を出します。

 まず、コマンド操作で動かしてみてください。

talk "aiueo" talk 123 talk 4,"kakeru",5,"wa",4*5,"desu" talk "ju'nbi/o'-kei"

 日本語音声をしゃべってくれますが、文字列はローマ字で書く必要があります。また、上の最後の操作例のように、アクセントその他さまざまな約束事があります。

9.2 プログラムでおしゃべり

 以下の例は、「九九」を合成音声で読み上げるものです[音を聞く]。

10 FOR A=1 TO 9 20 FOR B=1 TO 9 30 TALK A,"kakeru",B,"wa",A*B 40 NEXT B 50 NEXT A

 以下は、外部スイッチが押されると「九九」をランダムに読み上げるプログラムです。

10 A=1 20 B=dRead(14) 30 if A=1 if B=0 gosub 100 40 A=B 50 goto 20 100 X=1+rnd(9): Y=1+rnd(9) 110 talk X,"kakeru",Y,"wa",X*Y 120 return

 利用者に適したスイッチを使い、合成音声の読み上げで支援するさまざまなツール(VOCA)を作ることができます。

(練習) 2個のスイッチを接続し、それぞれ「はい」「いいえ」の合成音声が出るようなVOCAを作りなさい。

9.3 センサーと組み合わせ

 以下は、人感センサーと組み合わせた例です。

10 if dRead(14)=0 delay 50: goto 10 20 talk "maido/ari'gato-gozaimasu" 30 delay 10000: goto 10

 また、以下は、2個の人感センサーを用いた例で、玄関などに置くといいかもしれません。先にセンサーAが反応し(X=1)その後センサーBが反応(Y=0,B=1)すると「行ってらっしゃい」に(行30)、逆に先にセンサーBが反応し(Y=1)その後センサーAが反応(X=0,A=1)すると「お帰りなさい」になります(行40)。この仕組みを念頭に、2つのセンサーの置き方を工夫します。

10 X=A: Y=B: delay 50 20 A=dread(14): B=dread(1) 30 if X=1 if Y=0 if B=1 talk "itterassyai":delay 10000 40 if X=0 if A=1 if Y=1 talk "okaerinasai":delay 10000 50 goto 10

(練習) 人感センサーの反応する時のメッセージを、いくつかの中からランダムに選ばれるようにしてみなさい。


10. イルミネーション

10.1 NeoPixelの利用

 NeoPixelはフルカラーLEDがシリアルに連結されていて(ここでは10連LEDを使用)、1本の信号線で任意のLEDの発光をコントロールできるのが特徴です。tinyBasicでは、A3(D17)ピンに接続した最大50連のNeoPixelをpixelコマンドで制御することができます。パラメータで、順にLEDの番号(0~49)、Redの明るさ(0~255)、Greenの明るさ(0~255)、Blueの明るさ(0~255)を指定します。

 LEDの番号(0~11)と色相(0~255)と明るさ(0~255)を指定することもできます。明るさの指定を省略すると255として扱われます。

 RGBの値と表示色の関係は下図のようになっています。


HUE04285128170212255
シアンマジェンタ

 まず、コマンド操作で試してみてください。

pixel 0,50,0,0 pixel 1,0,50,0 pixel 2,0,0,50 pixel 0,50,50,0 pixel 1,0,50,50 pixel 2,50,50,50 pixel 0,0,0,0 pixel 1,0,0,0 pixel 2,0,0,0 pixel 0,0 pixel 1,42 pixel 2,85 pixel 0,0,50 pixel 1,42,50 pixel 2,85,50 LED0のRGBを(50,0,0)にする LED1のRGBを(0,50,0)にする LED2のRGBを(0,0,50)にする LED0のRGBを(50,50,0)にする LED1のRGBを(0,50,50)にする LED2のRGBを(50,50,50)にする LED0を消す LED1を消す LED2を消す LED0のHUEを0(赤)にする LED1のHUEを42(黄)にする LED2のHUEを85(緑)にする LED0のHUEを0(赤)明るさ50にする LED1のHUEを42(黄)明るさ50にする LED2のHUEを85(緑)明るさ50にする

10.2 プログラムによる点滅とフラッシュ

 以下のプログラムは、ひとつ目のLEDを赤で点滅させます。1秒点灯・1秒消灯をくりかえします。下図右は点滅の時間的な変化をタイムチャートで示したものです。

10 pixel 0,50,0,0 20 delay 1000 30 pixel 0,0,0,0 40 delay 1000 50 goto 10

10行目を

10 pixel 0,0,50,0 とすると緑で点滅します。

 次のようにすると10個のLEDが点滅します。

10 for i=0 to 9 20 pixel i,0,50,0 30 next i 40 delay 1000 50 for i=0 to 9 60 pixel i,0,0,0 70 next i 80 delay 1000 90 goto 10

20行目を

20 pixel i,0,100,0

40行目を

40 delay 200 とすると明るく短時間点灯する「フラッシュ」になります。

(練習) 10個のLEDが1秒毎に「青→黄→赤」を繰り返すプログラムを作りなさい。

10.3 ワイプ

 以下のプログラムは、10個のLEDを順に点灯させます。このようなイルミネーション効果は「ワイプ」と呼ばれます。

10 for i=0 to 9 20 pixel i,50,0,0 30 delay 100 40 next i

20行目を

20 pixel i,0,0,0 とすると順に消灯します。

(練習) 「赤のワイプ→緑のワイプ→青のワイプ」を繰り返すプログラムを作りなさい。

10.4 スイープ

 以下のプログラムは、10個のLEDを順に点灯・消灯させます。

10 for i=0 to 9 20 pixel i,50,0,0 30 delay 100 40 pixel i,0,0,0 50 next i

(練習) 30行目のdelay を100msにし、また、繰り返しスイープするようにしなさい。

10.5 ウェーブ

 以下のプログラムは、2個おきの点灯パターンがスイープし、波(ウェーブ)のように(あるいは追いかけているように)見えます。100行目はサブルーチンになっていて、与えられた色Hでウェーブ表示します。10行目は赤、20行目は緑、30行目は青のそれぞれウェーブで、これを繰り返します。

10 H=0: gosub 100 20 H=85: gosub 100 30 H=170:gosub 100 40 goto 10 100 for j=20 to 0 step -1 110 for i=0 to 9 120 if (i+j)%3=0 pixel i,H,50:goto 140 130 pixel i,H,0 140 next i 150 delay 80 160 next j 170 return

(練習) 120行目を変更し、「1個おき」「3個おき」のウェーブにしてみなさい。

10.6 フェードイン・フェードアウト

 以下のプログラムは、ひとつ目のLEDをだんだん明るくし(赤を0→50)、だんだん暗くし(赤を50→0)、これを繰り返します。

10 for r=0 to 50 20 pixel 0,r,0,0 30 delay 10 40 next r 50 for r=50 to 0 step -1 60 pixel 0,r,0,0 70 delay 10 80 next r 90 goto 10

(練習) 色を変えてみなさい。また速さを変えてみなさい。

(練習) 10個のLEDを同時にフェードイン・フェードアウトさせなさい。

10.7 クロスフェード

 ひとつ目のLEDをフェードアウトしながら、ふたつ目のLEDをフェードインすると滑らかに変化させることができます。これを「クロスフェード」といいます。

 以下は、クロスフェードをスイープに応用した例で、LEDの点灯位置が滑らかに変化します。

10 for i=0 to 9 20 for r=0 to 50 30 pixel i,50-r,0,0 40 pixel (i+1)%10,r,0,0 50 delay 10 60 next r 70 next i 80 goto 10

 以下は、クロスフェードをスイープに応用した例で、LEDの点灯位置が滑らかに変化します。

10 for i=0 to 9 20 for r=0 to 50 30 pixel i,50-r,0,0 40 pixel (i+1)%10,r,0,0 50 delay 10 60 next r 70 next i 80 goto 10

10.8 フルカラー表示

 クロスフェードを用いると色を滑らかに変化させることができます。以下のプログラムは、ひとつ目のLEDの色が赤→緑に滑らかに変化します。

10 for r=50 to 0 step -1 20 pixel 0,r,50-r,0 30 delay 10 40 next r

 以下のプログラムは、すべてのLEDの色をフルカラーで連続的に変化させます。

10 for H=0 to 255 20 for i=0 to 9 30 pixel i,H,50 40 next i 50 delay 10 60 next H 70 goto 10

 以下のプログラムは、すべてのLEDの色を場所を変えながらフルカラーで連続的に変化させます。

10 for j=0 to 256 step 8 20 for i=0 to 9 30 pixel i,(i*256/10+j)%256,50 40 next i 50 delay 10 60 next j 70 goto 10

10.9 イルミネーションの例

(1) ドロップ

 以下は、「ドロップ」のイルミネーションの作例です。水滴が滴り落ちるイメージで、最後にキラッと光ります。

10 N=6+rnd(5) 20 for i=0 to N-2 30 u=(i+1)*10 40 for b=0 to u 50 pixel i, u-b,u-b,u-b 60 pixel (i+1)%10,b,b,b 70 delay 3 80 next b 90 delay (10-N)*2 100 next i 110 for b=u to 255 120 pixel N-1,b,b,b 130 delay 3 140 next b 150 for b=255 to 0 step -1 160 pixel N-1,b,b,b 170 delay 3 180 next b 190 delay rnd(2000) 200 goto 10
N:ドロップの長さ(ランダムに6~10) iをNまで繰り返す  uは最大の明るさ  明るさbを0~u   iのLEDをu-bの明るさで表示(だんだん暗く)   i+1のLEDをbの明るさで表示(だんだん明るく)   3ms待つ  速さ調整 明るさbを最大までだんだん明るくする(キラリ)  速さ調整 明るさbを0までだんだん暗くする  速さ調整 次のドロップまで0~2秒待つ

(2) イルミネーションオブジェ

 以下は、NeoPixelリング(12個)を使い、ランダムに点灯させるようにした例です。オブジェの作り方はngo-tecさんのページを参考にしました(カップはダイソーの「ザ・クリアロックカップ」を使用)。点灯位置と点灯色と点灯時間間隔をランダムにし、点灯後はだんだん暗くしています。

10 N=12: T=1 20 for i=0 to N-1 30 @(i)=0: pixel i,0,0,0 40 next i 50 for i=0 to N-1 60 if @(i)>0 @(i)=@(i)*95/100: pixel i, @(N+i), @(i) 70 next i 80 delay 50 90 T=T-1 100 if T>0 goto 50 110 p=rnd(N): @(p)=255: @(N+p)=rnd(256) 120 T=1+rnd(20)+rnd(20) 130 goto 50 N:LEDの数, T:50ms単位で次のfire すべて消す(明るさの配列も0に) 明るさを減衰 処理は50ms毎 T*50ms経過したらfire ランダムなLED pの明るさを255, 色はランダムに 0~2秒後にfireするようにTをランダムに

(3) イルミネーションオブジェ(オルゴール付き)

 以下は、8.3の電子オルゴールと組み合わせた例で、音楽を演奏しながらイルミネーションが変化します。プログラム中のFは周波数、HはA~Aの1オクターブをHUE 0~255に対応させた値になっています。小型のスピーカ UGSM23Aをブレッドボードに直接付けても、3cmφの圧電サウンダをイルミネーションカップの底に貼り付けてもいいでしょう。

1 P=top(0):POKE P,"DFBaB2FD EgcBagaF FAdcd2AF GBedcBcA dAGAF2R" 10 C=peek(P):P=P+1:L=200 11 if peek(P)=50 L=L*2:P=P+1 12 if C=13 stop 20 if C=32 goto 10 30 B=255 40 if C=82 F=0:B=0 50 if C=68 F=311:H=128 60 if C=69 F=330:H=149 70 if C=70 F=370:H=192 80 if C=71 F=392:H=213 90 if C=103 F=415:H=235 100 if C=65 F=440:H=0 110 if C=97 F=466:H=21 120 if C=66 F=494:H=43 130 if C=99 F=554:H=85 140 if C=100 F=587:H=107 150 if C=101 F=659:H=149 160 gosub 300 170 tone 13,F,L:delay L:goto 10 300 for i=0 to 11 310 pixel i,H,B 320 next i 330 return 楽譜データ 1音データ抽出・200ms 2なら長さ2倍 改行なら終了 スペースなら次へ 明るさ最大 R(休符) D(D#) E F(F#) G g(G#) A a(A#) B c(c#) d e 指定色でLED点灯 周波数F 0.3秒の音  (以下サブルーチン) 12個のLEDを 色H 明るさB で点灯

(4) イルミネーションオブジェ(オルゴール・人感センサ付き)

 以下は、更に人感センサ(焦電センサ)を組み合わせたもので、人を感知するとオルゴールを鳴らしながらイルミネーションが変化します。

1 P=top(0):POKE P,"DFBaB2FD EgcBagaF FAdcd2AF GBedcBcA dAGAF2" 2 if dRead(14)=0 delay50:goto2 10 C=peek(P):P=P+1:L=200 11 if peek(P)=50 L=L*2:P=P+1 12 if C!=13 goto20 13 if B=0 delay10000:goto1 14 B=B*96/100:gosub300 15 delay50:goto13 20 if C=32 goto10 30 B=255 50 if C=68 F=311:H=128 60 if C=69 F=330:H=149 70 if C=70 F=370:H=192 80 if C=71 F=392:H=213 90 if C=103 F=415:H=235 100 if C=65 F=440:H=0 110 if C=97 F=466:H=21 120 if C=66 F=494:H=43 130 if C=99 F=554:H=85 140 if C=100 F=587:H=107 150 if C=101 F=659:H=149 160 gosub 300 170 tone 13,F,L:delay L:goto10 300 for i=0 to 11 310 pixel i,H,B 320 next i 330 return 楽譜データ 人を検知するまで待つ 1音データ抽出・200ms 2なら長さ2倍 改行なら 消灯したら10秒後に再開 少し暗くして 50ms待って消灯チェック スペースなら次へ 明るさ最大 D(D#) E F(F#) G g(G#) A a(A#) B c(c#) d e 指定色でLED点灯 周波数F Lmsの音  (以下サブルーチン) 12個のLEDを 色H 明るさB で点灯

 以下は、更に人感センサ(焦電センサ)を2個使い、「おでかけ」と「おかえり」で違うメロディーを鳴らすようにしたものです。玄関などに置くといいかもしれません。

1 U=V: X=Y: V=dread(14): Y=dread(1) 2 if Y=1 if U=0 if V=1 P=top(0):POKE P, "DFBaB2FD EHCBaHaF FAdCd2AF GBedCBCA dAGAF2":goto10 3 if V=1 if X=0 if Y=1 P=top(0):POKE P, "B3AGB c3BAc dcBdgf edcBAG A6 G2RBGd g2":goto10 4 delay 50: goto1 10 C=peek(P):P=P+1:L=240 11 if peek(P)>49 if peek(P)<57 L=L*(peek(P)-48):P=P+1 12 if C!=13 goto17 13 if B=0 goto1 14 B=B*96/100:gosub40 15 delay50:goto13 17 B=255 18 if C=32 goto10 19 if C=82 F=0:B=0 20 if C=68 F=311:H=128 21 if C=69 F=330:H=149 22 if C=70 F=370:H=192 23 if C=71 F=392:H=213 24 if C=72 F=415:H=235 25 if C=65 F=440:H=0 26 if C=97 F=466:H=21 27 if C=66 F=494:H=43 28 if C=99 F=523:H=64 29 if C=67 F=554:H=85 30 if C=100 F=587:H=107 31 if C=101 F=659:H=149 32 if C=102 F=740:H=192 33 if C=103 F=784:H=213 34 gosub40 35 tone 13,F,L:delay L 36 goto10 40 for i=0 to 11 41 pixel i,H,B 42 next i 43 return 人感センサ読み取り・記憶 「おでかけ」の時 「おかえり」の時 検知するまで待つ 1音データ抽出 2~8なら長さ 改行なら 消灯したら最初から 少し暗くして 50ms待って消灯チェック 明るさ最大 スペースなら次へ R(休符) D(D#) E F(F#) G H(G#) A a(A#) B c C(c#) d e f(F#) g 指定色でLED点灯 周波数F Lmsの音 次の音へ  (以下サブルーチン) 12個のLEDを 色H 明るさB で点灯

(5) イルミネーションオブジェ(複数台連携動作: グループ学習向け)

 以下は人感センサの代わりに明るさセンサCDSを使い、「隣のLEDが消灯(担当フレーズの演奏終了)したら自分の担当フレーズを演奏(LEDも点灯)する」ようにしたものです。CDSは不要な光が入らないようにヒシチューブで覆っています。グループ学習で利用すると楽しいと思っているのですがいかがでしょうか。

(練習) オリジナルのイルミネーションパターンを考え、作ってみなさい。

(練習) 音量センサーを使い、音に反応するイルミネーションを作ってみなさい。


11. 赤外線リモコン

11.1 赤外線リモコンを作る

 テレビなどのリモコンは、ボタンを押すと赤外線LEDが「決められたタイミングで点滅」するように作られています。どのように点滅しているかは、リモコン受光器に向けてリモコンのボタンを押し、受光器の信号をオシロスコープで観測するとわかります。

 実際に観測してみると、各社テレビのリモコン信号は以下のようになっています。図の着色した部分が信号が「オン」の箇所で、「オン」とは「赤外線LEDを13μs点灯し、13μs消灯し、これを一定時間繰り返す」ことです。また、「オフ」とは「一定時間消灯する」ことです。これを参考に、赤外線LEDを点滅させるプログラムを作ればよいわけです。

電源 ON/OFF 40 bf 12 ed
チャンネルUP 40 bf 1b e4
チャンネルDOWN 40 bf 1f e0
ボリュームUP 40 bf 1a e5
ボリュームDOWN 40 bf 1e e1
東芝製テレビのリモコン信号
電源 ON/OFF 02 20 80 00 3d bd
チャンネルUP 02 20 80 00 34 b4
チャンネルDOWN 02 20 80 00 35 b5
ボリュームUP 02 20 80 00 20 a0
ボリュームDOWN 02 20 80 00 21 a1
パナソニック製テレビのリモコン信号
電源 ON/OFF 8f 12 16 d1
チャンネルUP 8f 12 11 a1
チャンネルDOWN 8f 12 12 91
ボリュームUP 8f 12 14 f1
ボリュームDOWN 8f 12 15 e1
シャープ製テレビのリモコン信号
電源 ON/OFF 95 0
チャンネルUP 90 0
チャンネルDOWN 91 0
ボリュームUP 92 0
ボリュームDOWN 93 0
SONY製テレビのリモコン信号
OCR-05 ON 78
OFF b4
OCR-05WON 3c
OFF d2
OHM製コンセントリモコンの信号

 以下の回路とプログラムは、CHupボタンを押すと各社リモコンの「チャンネルアップ」信号が次々出力され、CHdnボタンを押すと各社リモコンの「チャンネルダウン」信号が次々出力されます。実際には各社の信号を出す必要はありません。

10 L=13:U=14:D=12 20 if dRead(U)=HIGH goto 90 30 f38k L,9000/26:delayus 4500:rcbyte L,$40,$bf,$1b,$e4:delay 90 50 f38k L,3600/26:delayus 1600:rcbyte L,$02,$20,$80,$00,$34,$b4:delay 90 60 f38k L,3600/26:delayus 1600:rcbyte L,$02,$20,$b0,$00,$34,$84:delay 90 70 rcbyte L,$8f,$12,$42,$11,$a1:delay 90 80 scbyte L,$90:delay 90 90 if dRead(D)=HIGH goto 20 100 f38k L,9000/26:delayus 4500:rcbyte L,$40,$bf,$1f,$e0:delay 90 110 f38k L,3600/26:delayus 1600:rcbyte L,$02,$20,$80,$00,$35,$b5:delay 90 120 f38k L,3600/26:delayus 1600:rcbyte L,$02,$20,$b0,$00,$35,$85:delay 90 130 rcbyte L,$8f,$12,$42,$12,$91:delay 90 140 scbyte L,$91:delay 90 150 goto 20
回路図

11.2 なんでもリモコン

 以下の回路とプログラムは、1個のスイッチ操作で電源・CHup・CHdnをコントロールできる「なんでもリモコン」のtinyBasic版です(オリジナルはこちら)。ブザー音の「ドに電源」「レにCHup」「ミにCHdn」が割り当ててあります。スイッチを押すと「ドーレーミー」とブザー音が鳴るので、希望の箇所でもう一度スイッチを押します。このプログラムはパナソニックTV用です。他社の場合は、510~530の行を変更します。

10 B=13:L=15:S=14:@(0)=262,294,330,349,392,440,494,523 20 if dRead(S)=HIGH goto 20 30 if dRead(S)=LOW goto 30 40 for i=0 to 2 50 tone B,@(i),1000 60 for j=1 to 100 70 if dRead(S)=LOW gosub 500 80 delay 10 90 next j 100 next i 110 goto 20 500 tone B,1000,100: J=100 510 if i=0 f38k L,9000/26:delayus 4500:rcbyte L,$40,$bf,$12,$ed 520 if i=1 f38k L,9000/26:delayus 4500:rcbyte L,$40,$bf,$1b,$e4 530 if i=2 f38k L,9000/26:delayus 4500:rcbyte L,$40,$bf,$1f,$e0 540 i=2:delay 1000:return
回路図

 以下は各社対応のリモコン信号を続けて出すようにしたデモンストレーション用プログラムです。実際には各社の信号を出す必要はありませんので、必要箇所以外はコメントアウトします(511, 521, 531の各行は東芝TV、512, 522, 532の各行はパナソニックTV、513, 523, 533の各行はパナソニックBD、514, 524, 534の各行はシャープTV、515, 525, 535の各行はソニーTV)。

10 B=12:L=13:S=14:@(0)=262,294,330,349,392,440,494,523 20 if dRead(S)=HIGH goto 20 30 if dRead(S)=LOW goto 30 40 for i=0 to 2 50 tone B,@(i),1000 60 for j=1 to 100 70 if dRead(S)=LOW gosub 500 80 delay 10 90 next j 100 next i 110 goto 20 500 tone B,1000,100: J=100 #POWER 510 if i!=0 goto 520 511 f38k L,9000/26:delayus 4500:rcbyte L,$40,$bf,$12,$ed:delay 90 512 f38k L,3600/26:delayus 1600:rcbyte L,$02,$20,$80,$00,$3d,$bd:delay 90 513 f38k L,3600/26:delayus 1600:rcbyte L,$02,$20,$b0,$00,$3d,$8d:delay 90 #514 rcbyte L,$8f,$12,$16,$d1:delay 90 515 scbyte L,$95 #CHup 520 if i!=1 goto 530 521 f38k L,9000/26:delayus 4500:rcbyte L,$40,$bf,$1b,$e4:delay 90 522 f38k L,3600/26:delayus 1600:rcbyte L,$02,$20,$80,$00,$34,$b4:delay 90 523 f38k L,3600/26:delayus 1600:rcbyte L,$02,$20,$b0,$00,$34,$84:delay 90 #524 rcbyte L,$8f,$12,$11,$a1:daley 90 525 scbyte L,$90 #CHdn 530 if i!=2 goto 540 531 f38k L,9000/26:delayus 4500:rcbyte L,$40,$bf,$1f,$e0:delay 90 532 f38k L,3600/26:delayus 1600:rcbyte L,$02,$20,$80,$00,$35,$b5:delay 90 533 f38k L,3600/26:delayus 1600:rcbyte L,$02,$20,$b0,$00,$35,$85:delay 90 #534 rcbyte L,$8f,$12,$12,$91:delay 90 535 scbyte L,$91 540 i=2:delay 1000:return
回路図

12. 動くものを作る

 これまでの例では、マイコンの出力ピンにLEDや圧電ブザーを接続しました。ESP8266は最大12mAの電流を流すことができるので、この範囲であれば直接接続できます。この章では、モータなど大きな電流が流れる素子を駆動する例を紹介します。大きな電流が流れる回路を制御する場合は、「電流が流れる経路」を意識することが回路の誤動作を防ぐことにつながります。

12.1 サーボモーターを動かす

 以下のようにサーボモーターを接続します。サーボモーターの電源はVoutからとります。まず、コマンド操作で動かしてみてください。

servo 10,0 servo 10,90 servo 10,180

12.2 プログラムでサーボモーターを動かす

 以下の例は、サーボモーターが車のワイパーのように動きます。

10 P=0 20 D=1 30 servo 10,P 40 P=P+D 50 if P=180 D=-1 60 if P=0 D=1 70 delay 20 80 goto 30 Pは角度 Dは角度の変化量 サーボモータの位置をPに Pを更新 Pが180ならDを-1にする Pが0ならDを1にする 少し待って 繰り返す

 以下のように「for文」を使っても結果は同じです。

10 for P=0 to 179 20 servo 10,P 30 delay 20 40 next P 50 for P=180 to 1 step -1 60 servo 10,P 70 delay 20 80 next P 90 goto 10 角度Pを0から179まで サーボモータの位置をPに 少し待って 繰り返す 角度Pを180から1まで サーボモータの位置をPに 少し待って 繰り返す

 以下のプログラムは、ボリュームの値によってサーボモーターの位置(角度)が変わります。

10 servo 10,aRead(0)*9/5 20 delay 50 30 goto 10 サーボモータの位置を0~180に 少し待って 繰り返す

(練習) ボリュームの代わりに明るさセンサを使い、明るさで位置が変わるようにしなさい。

12.3 モーターを動かす

 下図のようにモーターを接続します。モーターの電源はVoutからとります。まず、「MOTOR」コマンドでモーターを動かしてみてください。左右のモーターの速度は0~255で指定します。

motor 255,100 motor 100,255 motor 255,255 motor 0,0

12.4 プログラムでモーターを動かす

 以下はボリュームの値によってモーターの回転速度が変わります。

10 A=aRead(4)/4 20 motor A,A 30 delay 100 40 goto 10 Aは0~255 左右のモーターをAの値で回転 少し待って 繰り返す

 以下は音センサモジュールと組み合わせた例で、手を叩く(A6に接続した音センサーが400以上)と1秒間前進します。

10 if aRead(6)<400 goto 10 20 motor 255,255 30 delay 1000 40 motor 0,0 50 goto 10 音が400未満なら待つ 400以上なら左右のモーターを255にし 1秒待つ 左右のモーターを停止 繰り返す

 以下の例は、車を前進させ、車の先端がテーブルから落ちそう(A7に接続した赤外線反射センサーが30以上)になると、少し後退し、左ターンして、再び前進します。

10 if aRead(0)<30 motor 255,255: delay 100: goto 10 20 motor -200,-200 30 delay 500 40 motor 0,200 50 delay 500 60 goto 10 赤外線反射センサーが30未満なら少しずつ前進 30以上なら一旦後退し 少し待って 左ターンし 少し待って 繰り返す

13. 押しボタン信号機

 NeoPixelを使った押しボタン信号機の制御プログラムです。NeoPixelのLED 0,1,2をそれぞれ車用信号の赤・黄・青、LED 8,9をそれぞれ歩行者用信号の赤・青とします。

 まず行10で「車用信号を青」、行20で「歩行者用信号を赤」にします。行30で歩行者のボタンが押されるまで待ち、ボタンが押されると、4秒後に行50で「車用信号を黄色」にし、4秒後に行70で「車用信号を赤」、行80で「歩行者用信号を青」にします。その後16秒待ち、行100~130で歩行者用信号を点滅させます。行140で「歩行者用信号を赤」にして4秒後に初めに戻ります。

10 R=0: Y=42: B=170 20 pixel 0,R,0: pixel 1,Y,0: pixel 2,B,100 30 pixel 8,R,100: pixel 9,B,0 40 if dRead(1)=1 delay(50): goto 40 50 delay 4000 60 pixel 0,R,0: pixel 1,Y,100: pixel 2,B,0 70 delay 4000 80 pixel 0,R,100: pixel 1,Y,0: pixel 2,B,0 90 pixel 8,R,0: pixel 9,B,100 100 delay 16000 110 for I=1 to 8 120 pixel 8,R,0: pixel 9,B,100: delay 500 130 pixel 8,R,0: pixel 9,B,0: delay 500 140 next I 150 pixel 8,R,100: pixel 9,B,0: delay 4000 160 goto 20

 以下は歩行者用の「カッコー」の音を付け加えた例です。

10 R=0: Y=42: B=170: e=659: c=523 20 pixel 0,R,0: pixel 1,Y,0: pixel 2,B,100 30 pixel 8,R,100: pixel 9,B,0 40 if dRead(1)=1 delay(50): goto 40 50 delay 4000 60 pixel 0,R,0: pixel 1,Y,100: pixel 2,B,0 70 delay 4000 80 pixel 0,R,100: pixel 1,Y,0: pixel 2,B,0 90 pixel 8,R,0: pixel 9,B,100 100 for I=1 to 5 110 tone 13,e,100: delay 400 120 tone 13,c,200: delay 900 130 tone 13,e,100: delay 200 140 tone 13,e,100: delay 200 150 tone 13,c,200: delay 1000 160 next I 170 for I=1 to 8 180 pixel 8,R,0: pixel 9,B,100: delay 500 190 pixel 8,R,0: pixel 9,B,0: delay 500 200 next I 210 pixel 8,R,100: pixel 9,B,0: delay 4000 220 goto 10

 また、以下はこれを発展させた「交通安全教室用信号機」です。


14. シリアル通信教材(光通信)

 シリアル通信の仕組みを理解するための教材を取り上げます。また、通信は光の点滅による「光通信」で行います。

14.1 シリアル通信の仕組み

 下図は、送り手が受け手にメッセージとして「G」という文字を送る時の様子を表しています。ここではJISコードを用いることで互いに了解が得られているものとします。「G」の文字コードは(01000111)2と表されます。図(a)はこれをパラレル通信で送る様子を、図(b)はシリアル通信で送る様子を表しています。パラレル通信の場合は8本の信号線が必要ですが、複数ビットのデータを同時に送ることができます。一方、シリアル通信の場合は信号線の数は1本で、データを「時系列信号」として順に送ります。

 ここではシリアル通信のひとつである非同期通信について具体的にみていきましょう。非同期通信は調歩同期とも呼ばれ、パソコンのCOMポート(RS-232C)などで広く用いられています。

 下図は8ビットのデータ(bit0~bit7)を1秒間に1ビットの速さ(1 bps)で送信する時の信号の様子を表したものです。8ビットデータを送るための手順は次のようになります。ビットデータが1の場合はLEDを点灯し、0の場合はLEDを消灯することにより、光通信の信号となります。

 今、送りたい文字が「G」であるとすると、「G」の文字コードは(01000111)2で、これを送信する時の信号は下図のようになります。1文字を表すのに約10秒かかります。

 以下のようにスイッチとLEDを接続すると、スイッチ操作で上記の信号(光信号)を発生させることができます。LEDを明るく点灯するために、抵抗は47Ωにしています。それでは「G」を表す上記の光信号をスイッチ操作で発生させてみましょう。

 今度は2人一組となり、送信者(送り手)と受信者(受け手)を決めます。送信者は上の方法で「G」の文字を送ります。受信者は1秒毎に受信した0または1を「11100...」のように書き取り、8ビット受信したら付録6の文字コード表を見て、「G」を受信したことを確認します。実際にやってみると、送信者が正確なタイミングで信号を変化させる必要があることや、受信者が決まったタイミングでビットを読み取ることが重要であることがわかります。

(練習) 送信者が「A~Z」の何か1文字を送信し、これを受信者が正しく復元できるか試しなさい。

14.2 プログラムによるシリアル信号の送信

 今度は、光信号をスイッチ操作ではなくプログラムで発生させてみます。以下は上と同様に「G」の文字コードの光信号を発生させるプログラムです。

 8ビットデータを下位ビットから順に出力する仕組みは次のとおりです。

10 T=1000 20 C='G' 30 dWrite 13,1: delay T*2 40 dWrite 13,0: delay T 50 for i=0 to 7 60 dWrite 13,C&1: delay T 70 C=C/2 80 next i 90 dWrite 13,1: delay T 1ビット1秒(1000ms) Cは送信文字(G) 通常は点灯状態(1) スタートビット(1秒間0) ビット0~ビット7まで ビット0を1秒間出力 Cを右シフト ストップビット(1秒間1)
回路図

(練習) 上記のプログラムで以下の信号が発生することを確認しなさい。また、行20を変更し、別の文字の信号を発生させ、付録6を参考に正しく信号が作られていることを確認しなさい。

14.3 プログラムによる複数文字の送信

 上のプログラムは「G」を送信するプログラムでしたが、以下は、複数の文字を次々に送信するプログラムです。行20で文字列「Hello」をメモリのフリーエリアにpokeで格納しておき、行30以降でそこからpeekで1文字ずつ取り出して送信します。

10 T=1000 20 P=top(0):poke P,"Hello" 30 dWrite 13,1: delay T*2 40 C=peek(P):P=P+1 50 if C=13 delay T*2: goto 20 60 dWrite 13,0: delay T 70 for i=0 to 7 80 dWrite 13,C&1: delay T 90 C=C/2 100 next i 110 dWrite 13,1: delay T 120 goto 30 1ビット1秒(1000ms) P番地に"Hello"を格納 2秒間点灯(1) Cは送信文字 Cが改行なら終了 スタートビット(1秒間0) ビット0~ビット7まで ビット0を1秒間出力 Cを右シフト ストップビット(1秒間1) 次の文字へ
回路図

14.4 通信ソフトで入力した文字の送信

 以下は、通信ソフトで入力した文字を送信するプログラムです。行20の「in()」は通信ソフトからの文字入力を待ち、文字が入力されるとその文字コードを返します。ESCキーを押されると「-1」が返ってくるので、プログラムを終了します。

10 T=1000 20 C=in(): if(C<0) stop 30 dWrite 13,1: delay T*2 40 dWrite 13,0: delay T 50 for i=0 to 7 60 dWrite 13,C&1: delay T 70 C=C/2 80 next i 90 dWrite 13,1: delay T 100 goto 20 1ビット1秒(1000ms) Cは通信ソフトからの入力文字(ESCで終了) 通常は点灯状態(1) スタートビット(1秒間0) ビット0~ビット7まで ビット0を1秒間出力 Cを右シフト ストップビット(1秒間1) 繰返す
回路図

14.5 プログラムによるシリアル信号の受信

 今度はシリアル信号を受信するプログラムを作ります。

 はじめに、送信者の光信号が点灯の時と消灯の時に、受信者のアナログ値(0~1023)がどのくらいになるか調べます。

 送信信号はプログラムで発生させても、スイッチ操作のオンオフで行ってもどちらでも構いません。

 受信者は明るさセンサー(CDS)で送信者の光信号を受信します。8.2で行ったように、CDSをつなぎ、1行プログラムでA0ピンの値を時々刻々表示してみると、LEDの点滅に応じて受信信号のアナログ値が変化する様子を確認できます。

10 print aRead(0): delay 200: goto 10

 点灯時と消灯時の受信信号の差が大きいほど安定した通信が可能となります。そのためには、LEDとCDSの向きを合わせる、距離を短くする、外からの光が入りにくくするなどの工夫が有効です。

 点灯時と消灯時の受信信号の値の中間に「境界値」を決め、その境界値よりも大きければ(明るければ)「1」が受信されたとみなし、小さければ(暗ければ)「0」が受信されたとみなします。例えば、点灯時に1000、消灯時に600であれば境界値を800にし、点灯時に200、消灯時に100であれば境界値を150にします。

 受信の仕組みは以下のとおりです。

 以下は明るさの境界値を「800」としたプログラムです。通信ソフト(teraTerm等)に受信文字が表示され、液晶ディスプレイを接続しておけば液晶ディスプレイにも同じく表示されます。

 行100では、それまでのCの値を1ビット右シフトし、ビット7を受信ビットBにします。上記の「G」の光信号を受信した場合、Cの値は「xxxxxxxx」→「1xxxxxxx」→「11xxxxxx」→「111xxxxx」→「0111xxxx」→「00111xxx」→「000111xx」→「1000111x」→「01000111」のように更新されます。

10 T=1000 20 A=800 30 if aRead(0)>=A goto 30 40 delay T/2 50 if aRead(0)>=A print "Error": goto 30 60 C=0: delay T 70 for i=0 to 7 80 B=0:if aRead(0)>=A B=1 90 print B; 100 C=C/2+B*128: delay T 110 next i 120 if aRead(0)<A print " Error": goto 30 130 print ' ',chr(C): goto 30 1ビット1秒(1000ms) 明るさの境界値は800 スタートビットを待つ 500ms待つ スタートビット(0)でなければエラー 受信文字Cを初期化し、1秒待つ ビット0~ビット7まで 明るさに応じてBを0または1 受信ビットBを表示 Cを右にシフトしビット7をBにし 1秒待って次のビットへ ストップビット(1)でなければエラー 受信文字Cを表示し、再び受信待機
回路図

 ディスプレイのブラウザ表示画面で、受信プログラムの動作を確認することができます。受信装置のCDSを下の↓で示された箇所に密着させ、入力欄に「Hello」などの文字を入力し、「送信」ボタンを押すと、その箇所が ■■■□■■□...のように1 bpsの速さで変化し、受信装置がこれを文字として受け取ることができます。ただし、ディスプレイはLEDほど明るくないので、境界値(行20のAの値)は小さくする必要があります(例えば80程度)。

(  ここに受信装置のCDSを当て、入力欄に文字を入力し、送信ボタンを押してください。 )

14.6 シリアル通信システム

 送信装置と受信装置を組み合わせると、通信システムが完成します。送信装置のLEDと受信装置のCDSの距離は数cmの距離であれば確実に動作しますし、部屋を暗くしたり、CDSに不要な光が入らないように覆うなどの工夫をした上で、プログラム中の「境界値」すなわち行20のAの値を小さくすると(例えば300程度)、50cm程度の距離で光通信が可能です。

 本章では 1 bps(1秒間に1ビット)の速さで通信を行ってきましたが、より速い 10 bps(1秒間に10ビット)や 100 bps(1秒間に100ビット)でも通信できます。100 bpsで正しく通信できない時は、Tの値を10±1の範囲で調整するとうまくいく場合があります。

 以下は、100 bpsで通信を行っている様子です。

(練習) 2人一組となり、送信者が15.3のプログラムでデータを送信し、受信者が正しく受信できることを確認しなさい。

(練習) 10 bps(1秒間に10ビット)や100 bps(1秒間に100ビット)でもうまく通信できるかを確かめなさい。


15. WiFi経由で制御する

 これまでは、「ESP8266+tinyBasicソフト」をパソコンの通信ソフト(teraTerm等)で操作してきました。

 上の図はコマンド操作で直接入出力などを指示する様子を、下の図はコマンドに行番号を付し、その並びをプログラムとして保存・実行した様子を表しています。

 本章では、「ESP8266+tinyBasicソフト」をWiFiに接続し、パソコン、タブレット、スマートホンなどから制御できるものを作ります。

15.1 コマンド操作でWiFiに接続しブラウザから制御する

 まず、コマンド操作で既設のWiFiアクセスポイントに接続し、ブラウザからLEDの点灯・消灯を行ってみます。パソコンの通信ソフトで、以下のように入力します。「SSID」と「PASSWORD」の箇所は接続するアクセスポイントに合わせます。また、「myESP」の箇所はWebサーバ名です。

(通信ソフト)
WiFi "SSID","PASSWORD","myESP"

 すると、同じネットワークに接続したパソコンのブラウザで「http://myESP.local」を表示することができます。ただし、Windowsパソコンの場合は、Appleから提供されている「Bonjour」をインストールしておく必要があります。

 ここで、ページ中の「コマンド」入力欄にtinyBasicのコマンドを入力すると、WiFi経由で直接操作することができます。

(ブラウザのコマンド入力欄)
dwrite 13,1(Enter) dwrite 13,0(Enter) awrite 13,50(Enter)

 これらの操作を行うと、LEDが点灯・消灯あるいは指定の明るさで点灯します。また、ブラウザの画面は以下のようになります。

 ブラウザのコマンド操作は、ESP8266のWebSocketサーバを経由して受け付けられ、パソコンの通信ソフトで操作した場合と同様に実行されます。

 引き続き、ブラウザの「tinyBasicコマンド」の入力欄またはパソコンの通信ソフトで以下の操作を行うと、順次ページ中にタイトルやボタンやスライダーが現れます。ボタンの番号は1~9で、番号順に3×3に配置されます。スライダーの番号は上から順に1~3で、「%%」はスライダーの値を表します。

(通信ソフトまたはブラウザのコマンド入力欄)
title "WiFi制御" button 1,"LED ON","dwrite 13,1" button 2,"LED OFF","dwrite 13,0" slider 1,"明るさ","awrite 13,%%"

 ブラウザのコマンド操作の時と同様に、ボタンを押すとボタンに登録されたコマンド操作の情報がESP8266のWebSocketサーバを経由して受け付けられ、実行されます。また、スライダの値が変わるとaWriteコマンドが送られ、実行されます。

 このように、ブラウザの表示画面は、動的に追加・差し替えが行われます。また、複数のパソコンやタブレットから接続した場合は、連動して動作し、同じ画面が表示されます。

15.2 プログラムでWiFiに接続する

 以下は、上で行った操作をプログラムで行うようにしたものです。プログラムは順に実行され、終了しますが、ブラウザのボタン操作でコントロールすることができます。プログラムを保存(SAVE)しておけば、電源投入時に自動的にプログラムが起動するので、ブラウザにははじめからボタンやスライダーが表示されます。

(通信ソフト)
1  WiFi "SSID","PASSWORD","myESP" 10 title "WiFi制御" 20 button 1,"LED ON","dwrite 13,1" 30 button 2,"LED OFF","dwrite 13,0" 40 slider 1,"明るさ","awrite 13,%%"

 ここまでは、パソコンの通信ソフト(teraTerm)でプログラムを入力してきましたが、WiFi接続したパソコンのブラウザからプログラムを入力することもできます。以下のように、ブラウザ画面のプログラム入力欄にプログラムを入力し、を押すと、プログラムがEPS8266に送られ、EEPROMに保存され、実行されます。

(ブラウザのプログラム入力欄)

 一方、を押すとESP8266上にあるプログラムがプログラム入力欄に表示されます。プログラムは1~5まで30日間ブラウザに保存されます。

 上の例では、プログラムは順次実行された後、終了(Ready状態)しますが、次項の例のようにプログラムが実行し続けるような場合は、を押すとプログラムは中断します。通信ソフトでESCキーを押すのと同じです。

 一旦このような状態にしておけば、ESP8266はUSB電源で動作させ、タブレット等のブラウザ画面でコントロールすることが可能となります。ただし、行番号1のWiFi接続コマンドを忘れたり正しく入力しなかったりすると、ブラウザ画面からは直すことができなくなりますので、注意が必要です。この場合は、通信ソフト(teraTerm等)で様子を確認し、接続操作をしなおします。

15.3 スイッチの状態を表示する

 以下は、「3.5 プルアップ抵抗」の時と回路は同じで、プログラムもWiFi接続の箇所を追加しただけです。ブラウザにはプログラムで利用している入出力(スイッチとLED)の状態が表示されます。

1 WiFi "SSID","PASSWORD","myESP" 10 if dRead(12)=0 dWrite 13,1: goto 20 20 dWrite 13,0 30 goto 10
回路図

 下の画面はこれをプログラム2として入力して実行した様子です。

(ブラウザのプログラム入力欄)

 行番号10のdRead(12)でスイッチの状態が読み取られますが、この時WebSocketサーバから値がbroadcastされ、ブラウザはこれを受け取り表示します。

15.4 センサーの利用

 以下は、CDSを用いて明るさをバーグラフ表示する例です。

1 WiFi "SSID","PASSWORD","myESP" 10 title "WiFi制御" 20 bar 2,"明るさ",aread(0)/10 30 delay 100 40 goto 20

 下の画面はこれをプログラム3として入力して実行した様子です。行番号20でブラウザのグラフ表示が更新されます。

(ブラウザのプログラム入力欄)

 行番号20のbarコマンドでバーグラフ表示に必要な情報がWebSocketサーバから値がbroadcastされ、ブラウザはこれを受け取り表示します。

15.5 モーターカーの制御

 以下は、ボタン操作でモーターカーを制御する例です。12.2と同様、プログラムは順に実行され、終了しますが、ボタン操作でコントロールすることができます。

1 WiFi "SSID","PASSWORD","myESP" 10 title "WiFi制御" 20 button 2,"前進","motor 200,200" 30 button 4,"左ターン","motor 0,100:delay 500:motor 0,0" 40 button 5,"停止","motor 0,0" 50 button 6,"右ターン","motor 100,0:delay 500:motor 0,0" 60 button 8,"後退","motor -50,-50"

 下の画面はこれをプログラム4として入力して実行した様子です。

(ブラウザのプログラム入力欄)

 以下は、スライダー操作でモーターカーのスピードを制御する例です。

1 WiFi "SSID","PASSWORD","myESP" 10 title "WiFi制御" 20 slider 1,"モーター","motor %%,%%"

 下の画面はこれをプログラム5として入力して実行した様子です。

(ブラウザのプログラム入力欄)

15.6 NTP時計を作る

 NTPというインターネット上で時刻を合わせる仕組みを使った時計で、液晶ディスプレイに年月日と時分秒が表示されます。WiFiがインターネットに接続されている必要があります。時刻合わせはWiFi接続時とその後24時間に1度行われます。なお、パソコンと接続している場合は、通信ソフト(teraTerm等)にも液晶ディスプレイと同じ表示が現れます。

1 WiFi "SSID","PASSWORD" 10 CLS 20 CURSOR 0,0 30 PRINT YEAR(),"/",MONTH(),"/",DAY() 40 CURSOR 0,1 50 PRINT HOUR(),":",MINUTE(),":",SECOND() 60 DELAY 1000 70 GOTO 10

 プログラムを保存(SAVE)しておくと、パソコンと接続しなくても、電源を入れるとプログラムが起動します。ケースに入れればNTP時計の完成です。

(練習) 月日や時分秒が0~9の時に10の位に「0」が表示されるようにしなさい。

(練習) 8.5の合成音声と組み合わせ、「10時になりました」などとしゃべる「音声時計」を作ってみなさい。


(参考資料)

[1] George Gray, Half-byte tinyBasic, https://halfbyteblog.wordpress.com/
[2] TinyBasic を動かしてみる, http://ht-deko.com/arduino/tinybasic.html
[3] DSbasic, http://desktopstation.net/wiki/doku.php/dsbasic
[4] Arduinoで超ミニBASICパソコンが作れる!, http://yumeiroandroid.blog.fc2.com/blog-entry-313.html
[5] グラフで考える直流回路, http://siva.cc.hirosaki-u.ac.jp/usr/koyama/lecture/it/elec.html


(付録1) tinyBasicのArduinoへの書き込み

  1. Arduino 1.8.5をダウンロードし、インストールします。
  2. Arduino IDEを起動し、[ファイル][環境設定]で、「追加のボードマネージャのURL」に「http://arduino.esp8266.com/stable/package_esp8266com_index.json」と入力し、OKを押します。[ツール][ボード][ボードマネージャ]で「esp8266」を探し、インストールします。
  3. [スケッチ][ライブラリをインクルード][ライブラリの管理]で、一覧の中から「ESP8266」「esp8266_mdns」「ESP8266HTTP Client」「ESP8266 WiFi」「Servo(esp8266)」をインストールします。
  4. Arduinoを起動し、[ファイル][環境設定]で、スケッチブックの保存場所を確認し、その下にlibrariesフォルダを作ります。
  5. 液晶モジュールを利用するために、ST7032のライブラリ(ZIPファイル)をダウンロードし、解凍して上記librariesフォルダに置きます。この中のST7032.cppの24行目を のようにコメントアウトします。
  6. NTP機能を利用するために、NTPClientライブラリ(ZIPファイル)Timeライブラリ(ZIPファイル)をダウンロードし、それぞれ解凍して上記librariesフォルダに置きます。
  7. WebSocket機能を利用するために、arduinoWebSocketsライブラリ(ZIPファイル)をダウンロードし、解凍して上記librariesフォルダに置きます。
  8. [ツール][ボード]で「Generic ESP8266 Module」を選択し、[ツール][Flash Mode]を「QIO」、[ツール][Flash Size]を「4M(3M SPIFFS)」、[ツール][Reset Method]を「nodemcu」にします。また、ESP8266を接続し、[ツール][シリアルポート]でポートを選択します。
  9. tinybasic20180712.zipを解凍し、ESP8266に書き込みます。WiFi機能利用時のブラウザ表示画面は別ファイル(index.h)にしてあるので、違うデザインにしたり別の機能を加える場合はこのファイルを変更します。

 プログラム(tinybasic.ino)は、「Tyny Basic を動かしてみる[2]」のページの中ほどにある「HalfByteTinyBasic_mod.zip」を拡張したものです。拡張した主な内容は以下のとおりです。

  1. プログラム実行の中断(ブレーク)をESCキーで行うようにしたこと
  2. 入力ミスの修正にBS(BackSpace)キーを使えるようにしたこと
  3. 起動時にEEPROMに保存されているプログラムをLOADし、3秒後に自動実行するようにしたこと(プログラムが完成したらパソコン無しで動作する)
  4. %(剰余) &(and) |(or) !=(<>と同じ)の演算子を使えるようにしたこと
  5. dRead()で内部プルアップ抵抗を有効にしたこと
  6. PRINTコマンドで液晶ディスプレイ(ST7032)にも表示させるようにしたこと
  7. 温湿度センサ(SHT31)用に「tRead」「hRead」関数を追加したこと
  8. サーボモーター制御用に「SERVO」コマンドを追加したこと
  9. モーター制御用に「MOTOR」コマンドを追加したこと
  10. 「TONE」コマンドを追加したこと
  11. 音声合成用に「TALK」コマンドを追加したこと
  12. NeoPixel LED制御用に「PIXEL」コマンドを追加したこと
  13. 赤外線リモコン信号用に「f38k」「RCBYTE」「SCBYTE」の各コマンドを追加したこと
  14. 「PRINT」コマンドで液晶ディスプレイにも表示されるようにしたこと。関連して、「CLS」コマンドや「CURSOR」コマンドもそれらの表示デバイスに適用されるようにしたこと。
  15. 既設のアクセスポイントに接続しWebサーバを起動する「WiFi」コマンドを追加し、関連する「TITLE」「BUTTON」「BAR」などのコマンドと「Year()」「Month()」「Day()」「Hour()」「Minute()」「Second()」などの関数を追加したこと

 通信ソフトで接続すると「HalfByte...Hitany key!」の表示が現れるので何かキーを押し、初めて使う場合に一度だけ「new」「save」の操作をしてください。


(付録2) 入出力に利用できるピン

種類ピン番号
デジタル出力ピン0, 2, 4, 5, 12, 13, 14, 15, 16
(ただし 4, 5 ピンはI2Cで使用)
デジタル入力ピン
アナログ出力ピン
アナログ入力ピンA0

(付録3) tinyBasic リファレンス...グリーンが拡張箇所

□ コマンド

NEW
プログラムを初期化する。変数は「0」に初期化されないので注意。

CLEAR
A~Zのすべての変数の値を0にする。

MEM
メモリーの残量を表示する。

命令文
命令文を入力すると直ちに実行される(行末はEnterキー)。「A=1: B=2: PRINT A+B」のように「:」で区切って1行に複数の文を書いてもよい。

行番号 命令文
行番号をつけて命令文を入力すると、プログラムとして格納される(格納されたプログラムはRUNで実行)。

RUN
格納されたプログラムを先頭の行番号から実行する。

SAVE
EEPROMにプログラムを保存する。最大1000バイトで、プログラムは1つしか保存できない。

LOAD
EEPROMに保存したプログラムをロードする。起動時には自動的にLOADが行われる。

LIST
プログラムすべてを表示する。
LIST 行番号
行番号以降のプログラムを表示する。
LIST 行番号.
行番号のプログラムだけを表示する。

□ 数と変数と演算

-32767~32767の整数。16進表記の場合は、$FF, &FF, #FF のようにする。

定数(組み込み定数)
HIGH(またはHI)は「1」、LOW(またはLO)は「0」と同じ。

文字列
文字列は「"」で囲む。日本語も表示できる。

変数
変数名はA~Zで、大文字小文字は区別されない。変数には-32767~32767の整数を格納できる。
配列
@(0~1023)で代入・参照する。変数には-32767~32767の整数を格納できる。PEEK/POKEで用いるメモリ領域と兼ねているので注意。
演算
+(加算) -(減算) *(乗算) /(除算) %(剰余) &(and) |(or) !(0なら1, 1なら0)
=(等しい) <>(等しくない) !=(等しくない) >(大きい) >=(以上) <(小さい) <=(以下)

□ 命令文

REM または #
以降行末までコメントとなる。メモリーを消費するので注意。

代入
変数に値を代入する。LETは省略してよい。
(例) LET A=100

POKE 番地, 値
@ 番地, 値
指定した番地(0~2047)に値を書き込む。
(例) POKE 1450,64...1450番地の値を64にする
(例) POKE 0,"ABCDE"...メモリー(0~2047)の先頭に文字列を"ABCDE"を格納する。文字列の末尾には改行コード(13)が付加される。
利用する時はPEEKを使い、何度も使う文字列で利用する。POKEとINKEYを組み合わせると、実行時に入力した文字列をしまっておくことができる。

FOR ループ
以下の例は1~20を表示する。 10 FOR X=1 TO 20 20 PRINT X 30 NEXT X 以下の例は10~100を表示する。 10 FOR X=0 TO 100 STEP 10 20 PRINT X 30 NEXT X ECHO 「FOR」と「NEXT」を同じ行に書くことはできない。

NEXT 変数
対応するFORループを終了する。

IF 式 文
式がtrueなら文を実行する。式に論理演算を使えないが、「IF A=1 IF B=2 PRINT A+B」のような方法で「AND」を表現できる。ELSEはない。

GOTO 行番号
指定した行番号にジャンプする。

GOSUB 行番号
指定した行番号のサブルーチンを呼び出す。サブルーチンは同じ処理を何度も実行する時に使う。

RETURN
サブルーチンを終了し、呼び出されたGOSUBの次の行に戻る。

STOP
プログラムを終了し、編集画面に戻る。

DELAY 時間
時間はms単位で指定する。

CLS
通信ソフト(teraTerm等)の画面とI2C液晶をクリヤーする。

PRINT 変数や文字列
? 変数や文字列
変数や文字列を通信ソフト(teraTerm等)の画面とI2C液晶に表示する。「,」で区切ると、複数の変数や文字列が連続して表示される。末尾に「;」を置くと改行されない。

INPUT 変数
変数に数値を入力する。 10 X=0 20 PRINT "X? ";: INPUT X 30 PRINT X

OUT 値
シリアルポートに値を出力する。「OUT 65」でシリアル端末に「A」が表示される。

CURSOR X, Y
カーソル位置を(X,Y)にする。XとYは文字単位で位置を指定。その後printで文字を表示する。

AWRITE ピン番号, 値
指定したピン(0)に値(0~255)を出力する。

DWRITE ピン番号, 値
指定したピン(D0~D16)に値(0または1)を出力する。

MOTOR 左速度, 右速度
I2C接続した左右のモーターの速度を指定する。左速度、右速度はそれぞれ-255~255。0で停止。

SERVO ピン番号, 角度
接続したピン(D0~D16)のサーボモーターを指定した角度(0~180)に動かす。

TONE ピン番号, 周波数, 時間
周波数はHz、時間はmsで指定する。

TALK 変数や文字列
数値や文字列を合成音声で読み上げる。「,」で区切ると、複数の変数や文字列を連続して読み上げる。文字列は半角ローマ字を基本とし、「'」アクセント、「/」アクセント区切り、「-」長音、「.」「?」文末ポーズなどで修飾できる。

f38k ピン番号, 繰り返し数
ピンに接続した赤外線LEDを指定回数点灯13μs消灯13μsする。

RCBYTE ピン番号, データ, ...
ピンに接続した赤外線LEDを指定したビットパターンで点滅する。データは複数指定できる。

SCBYTE ピン番号, データ, ...
ピンに接続した赤外線LEDを指定したビットパターンで点滅する(SONY方式)。データは複数指定できる。

PIXEL LED番号, R, G, B
PIXEL LED番号, HUE, BRIGHT
PIXEL LED番号, HUE
指定したLED(0~49)に指定した色で点灯する。R(赤),G(緑),B(青)の明るさをそれぞれ0~255、またはHUEとBRIGHTで指定する(BRIGHT省略時は255)。なお、NeoPixelの制御信号(Din)はA3(D17)に接続する。

WIFI SSID, PASSWORD
WIFI SSID, PASSWORD, ドメイン名
既設のアクセスポイントに接続し、「http://ドメイン名.local」のWebサーバを起動する(省略時のドメイン名は「esp8266」)。

TITLE タイトル
Webページのタイトルを指定する。

BUTTON 番号,名前,コマンド
Webページにボタンを表示する。ボタンの番号は1~9、名前はボタンに表示する文字列、コマンドはボタンを押した時に実行するtinyBasicコマンド。Webページ上でのボタンの配置は横3個×縦3個。

SLIDER 番号,名前,コマンド
Webページにスライダーを表示する。スライダーの番号は1~3、名前はスライダーの左に表示する文字列、コマンドはスライダーを操作した時に実行するtinyBasicコマンド。ただし、コマンド中に「%%」を書くとスライダーの値が代入される。

BAR 番号,名前,値
Webページに横棒グラフを表示する。グラフの番号は上から1~3、名前はバーグラフの左に表示する文字列、値は0~100。

□ 関数

 括弧内に引数を与えると、値が返される。

ABS, POW, SIN, COS
ABS(絶対値)、POW(べき乗)など。SIN, COSは「度」で角度を与え、1000倍した値が返される。
(例) COS(60)...値は500

RND(数)
0から指定した数までの乱数を返す。

PEEK(番地)
指定した番地(0~2047)の値を返す。PEEKを使って、ユーザが入力した文字列を調べることができる。配列@(0~1023)で用いるメモリ領域と兼ねているので注意。

TOP(0)
PEEK/POKEで用いるメモリ領域の先頭番地(ESP8266では常に0)を返す。

CHR(文字コード)
指定した文字コードの文字を返す。「PRINT CHR(65)」で「A」が表示される。

INKEY(初期値)
キー操作のASCIIコードを返す。キーが押されるのを待つわけではない。 10 M=N 20 A=INKEY(0) 30 IF A=-1 GOTO 20 40 IF A=13 @M,13: RETURN 50 PRINT CHR(A); @M,A 60 M=M+1 70 GOTO 20 文字列を入力してもらう。キーが押されなければ、AはINKEYから0を受け取る。一度キーが押されると、そのASCIIコードがAの値となる。ENTERが押されると、メモリーに改行が格納される。メモリーの番地は+1される。

IN
通信ソフトからの文字入力を待って文字コードを返す。ESCキーが押されると-1を返す。

AREAD(0)
指定したアナログピン(0)から値を読み取る。0~1023の値が返される。

DREAD(ピン番号)
指定したピン(D0~D16)から値を読み取る。0か1の値が返される。0はLOW、1はHIGHを表す。

TREAD()
I2C接続した温湿度センサー(SHT31)が計測した温度(℃)が返される。

HREAD()
I2C接続した温湿度センサー(SHT31)が計測した湿度(%)が返される。

YEAR()
MONTH()
DAY()
HOUR()
MINUTE()
SECOND()
WiFi接続し、インターネットに接続されている場合、現在の年・月・日・時・分・秒をそれぞれ返す。NTPサーバはntp.nict.jpで、接続時および24時間に一度時刻合わせが行われる。


(付録4) 入出力モジュールの例

 ブレッドボードで利用できる入出力モジュールの製作例です。

モジュール回路図製作例
可変抵抗モジュール
明るさセンサーモジュール
赤外線反射モジュール
音量センサーモジュール
10連LEDモジュール
NeoPixel(DinはD15に接続)
モーターモジュール
右モーターはA0とA1をGNDに接続
音声合成モジュール

(付録5) 使用する主な部品

部品表
名称 外観 備考
ESP-WROOM-02開発ボード スイッチサイエンス 2160円
ブレッドボード EIC-301 秋月 300円
ブレッドボード ジャンパーワイヤ 15cm   秋月 10本 300円
ブレッドボード ジャンパーワイヤ EIC-J-S   秋月 250円
LED 秋月 10個 120円
フルカラーシリアルLEDテープ SwitchScience 756円
フルカラーシリアルLEDテープ SwitchScience 756円
圧電スピーカー SPT08 秋月 2個 100円
圧電サウンダ FGT-31T-3.7A1 秋月 70円
スピーカ UGSM23A 秋月 100円
プッシュスイッチ DS-660R-C 千石 84円
抵抗 1/4W 4.7Ω, 100Ω, 220Ω, 470Ω, 1kΩ, 10kΩ
100kΩ, 220kΩ
秋月 100本 100円
CDS(光センサ)秋月 30円
温湿度センサ SHT31秋月 950円
赤外線反射センサ LBR-127HLD   秋月 50円
人感センサ(焦電センサ)
ブレッドボード ジャンパーワイヤ 15cm
  秋月 400円
秋月 10本 220円
サーボモーター SG-90   秋月 400円
液晶ディスプレイ AQM1602A   秋月 550円
モータードライバ DRV8830   秋月 170円
音声合成LSI ATP3011F4/M6   秋月 850円

(付録6) 文字と文字コード(抜粋)


koyama@hirosaki-u.ac.jp