2015年08月12日

Arduino(10) aitendoの激安キャラクタ液晶をArduino Pro Mini(3.3V)に接続

Arduino Pro MiniへSPI TFT LCDが割とあっさり接続できたので、ついでに買い置きしてあったaitendoのキャラクタ液晶「SPLC792-I2C-M」も接続してみました。

この液晶モジュールは8x8ドットのキャラクタを16字×2行で表示できるものです。
インタフェースはI2Cで、バックライトはLEDです。
価格が50% OFFとなっており、375円(税別)と激安です。
3.3V専用なので、Arduino UNOからはちょっと使いにくいですが、3.3V動作のPro Miniなら問題ありません。

というわけでさっそくピンヘッダを取り付けます。
ジャンパピンが2つ(写真の青い部品)ありますが、これで表示の向きを指定できます。
arduino10-01.jpg


接続は以下のようになります。
電源ラインを除けば、Arduinoの信号線で使うのはI2CのためのA4、A5だけです。
なお電源は、Arduinoに接続したUSBシリアルアダプタが供給する想定です。
また、バックライト(BL+端子)は、100Ωの抵抗を入れて3.3Vに接続しました。
明るさ的にはこれで室内なら十分だと思います。

Arduino Pro MiniのA4、A5端子にはピンヘッダを付けてしまいましたので、接続にブレッドボード用のオス-オス型のジャンパケーブルは使えません。
ブレッドボード側にもピンヘッダを挿して、ピンヘッダ間を接続するメス型コネクタ(デュポンコネクタとかQIコネクタといいます)が両端に付いたワイヤを使います。

arduino10-04.png


(参考→aitendoのI2C低電圧キャラクタ液晶モジュールをArduino Pro Mini(3.3V)で駆動(配線編) - M.C.P.C. (Mamesibori Creation Plus Communication)

ライブラリは先人が作られたものをありがたく使わせていただきました。

I2C液晶のArduinoライブラリ – ST7032 | オレ工房

他のライブラリ同様、ZIPファイルをIDEに取り込めば、スケッチ例も自動的に追加されます。


無事動作確認ができたところで、一応何か作ってみようということで、ありがちですが手元にあったDHT11センサモジュールを使って、温度湿度計を作ってみました。
arduino10-02.jpg

aitendoの商品ページからリンクされているLCDコントローラ(SPLC792A)の仕様書を見ていたら、キャラクタROMにはカタカナも含まれていることが分かったので、カタカナ表示させてみました。
文字コード表を下に引用しておきます。
splc792a.png


使った温度湿度センサモジュールは、よく見かけるDHT11というセンサを使用した、中国Keyes社のKY-015という型番のものです。
arduino10-07.jpg

DHT11をArduinoから使用するためのソフトウェアは、例によってAdafruit製のライブラリがあります。

adafruit/DHT-sensor-library ・ GitHub

配線は以下の通りです。
(KY-015用の配線です。DHT11を直接接続する場合は配線が異なりますのでご注意ください。)

arduino10-05.png

スケッチファイルも一応アップロードしておきます。


#include <Wire.h>
#include <ST7032.h>
#include <DHT.h>

#define DHTTYPE DHT11
#define DHTPIN 2

ST7032 lcd;
DHT dht(DHTPIN, DHTTYPE);
char str1[14] = {' ',' ',' ',' ',' ',0xdf,'C',' ','/',' ',' ',' ','%',0};
char str2[10] = {' ',' ',0xcc,0xb6,0xb2,0xbc,0xbd,0xb3,0x3a,0};

void setup() {
 lcd.begin(16, 2);
 lcd.setContrast(40);
 lcd.setCursor(0, 0);
 lcd.print(str1);
 lcd.setCursor(0, 1);
 lcd.print(str2);
 
 dht.begin();
}

void loop() {
 delay(2000);
 float h = dht.readHumidity();
 float t = dht.readTemperature();
 if (isnan(h) || isnan(t)) {
   Serial.println("Failed to read from DHT sensor!");
   return;
 }
 float discomfort = 0.81 * t + 0.01 * h * (0.99 * t - 14.3) +46.3;

 lcd.setCursor(3, 0);
 lcd.print(t,0);
 lcd.setCursor(10, 0);
 lcd.print(h,0);
 lcd.setCursor(10, 1);
 lcd.print(discomfort,1);
}



余談ですが、今回使用したセンサモジュールは、中国の通販サイトaliexpressから、Keyes社のモジュール全部入りセットで入手しました。
購入価格は$17(送料無料)でしたので、1モジュール当たり50円強ということになります。

Keyes社のモジュールの一覧は以下のサイトなどで見ることができます。

Arduino 37 sensors - TkkrLab
Advanced Sensors Kit for Arduino - LinkSprite Playgound

届いたものはこんな感じで、全てのモジュールがジップロックの袋に無造作に袋詰めされていました。

arduino10-06.jpg


ホール素子モジュールなどは重複気味ですし、ただのLEDとか、磁気に反応するリードスイッチや傾くと接続する水銀スイッチなどの懐かしいデバイスが多く、ジャイロやI2Cデバイスのような最近のものは入っていませんので、お買い得かといえば迷うところではあります。
しかしロータリーエンコーダやリレー、レーザー、ジョイスティックなど、それなりに使えそうなものもあり、自分で情報を調べて使うことができる人には便利かもしれません。
posted by boochow at 19:55| Comment(0) | Arduino | このブログの読者になる | 更新情報をチェックする

2015年08月11日

Arduino(9) Adafruit_ST7735ライブラリの修正(aitendoの1.8型LCD用)

arduino08-03.jpg
Adafruit_ST7735ライブラリ+aitendo M-Z18SPI-2Pでgraphicstest。
画面右端と下端にゴミが出ています。Hの字の左端が切れています。

Adafruit_ST7735ライブラリでaitendo M-Z18SPI-2Pを制御すると、画面右端と下端にゴミが残り、画面左端が欠けてしまいます。
初期化時、initRのパラメータにINITR_GREENTABを指定するとこの現象は無くなりますが、その代わり色の配列がRGBではなくBGRになってしまいます。

ST7735ではMADCTLというコマンドが色表現のRGB/BGR指定を担っており、これをINITR_BLACKTABのときだけ違う値に設定しているのが関数initRの中の最後の部分です。

void Adafruit_ST7735::initR(uint8_t options) {
commonInit(Rcmd1);
if(options == INITR_GREENTAB) {
commandList(Rcmd2green);
colstart = 2;
rowstart = 1;
} else if(options == INITR_144GREENTAB) {
_height = ST7735_TFTHEIGHT_144;
commandList(Rcmd2green144);
colstart = 2;
rowstart = 3;
} else {
// colstart, rowstart left at default '0' values
commandList(Rcmd2red);
}
commandList(Rcmd3);

// if black, change MADCTL color filter
if (options == INITR_BLACKTAB) {
writecommand(ST7735_MADCTL);
writedata(0xC0);
}


tabcolor = options;
}

これをINITR_GREENTABでも実行するように変更すれば、色がRGBの並びになります。

ただし、本家のINITR_GREENTABが違う動作になるのも困るので、新しくINITR_BLUETABを定義しました。

まずAdafruit_ST7735.hに以下の定義を追加します。(赤字部分)

// some flags for initR() :(
#define INITR_GREENTAB 0x0
#define INITR_REDTAB 0x1
#define INITR_BLACKTAB 0x2
#define INITR_BLUETAB 0x3

#define INITR_18GREENTAB INITR_GREENTAB
#define INITR_18REDTAB INITR_REDTAB
#define INITR_18BLACKTAB INITR_BLACKTAB
#define INITR_144GREENTAB 0x1


そして、Adafruit_ST7735.cppのinitR関数を修正し、BLUETABではGREENTABの初期化+BLACKTAB用追加コードを実行するようにします。
void Adafruit_ST7735::initR(uint8_t options) {
commonInit(Rcmd1);
if((options == INITR_GREENTAB) || (options == INITR_BLUETAB)) {
commandList(Rcmd2green);
colstart = 2;
rowstart = 1;
} else if(options == INITR_144GREENTAB) {
_height = ST7735_TFTHEIGHT_144;
commandList(Rcmd2green144);
colstart = 2;
rowstart = 3;
} else {
// colstart, rowstart left at default '0' values
commandList(Rcmd2red);
}
commandList(Rcmd3);

// if black, change MADCTL color filter
if ((options == INITR_BLACKTAB)|| (options == INITR_BLUETAB)) {
writecommand(ST7735_MADCTL);
writedata(0xC0);
}

tabcolor = options;
}


これで、ノイズなし、かつ正しい色での表示ができるようになります。
(もちろん、setup()の中でinitRの引数をINITR_BLUETABにする必要があります。)

なお、以下のページにST7735の仕様の解説があり、参考になります。

表示器 (ST7735B 1.8" TFT SPI)

・修正後のライブラリ+aitendo M-Z18SPI-2Pでgraphicstest
arduino08-04.jpg
ゴミが消え、画面の左端が見えるようになりました。

posted by boochow at 13:07| Comment(0) | Arduino | このブログの読者になる | 更新情報をチェックする

Arduino(8) Arduino Pro Mini+aitendoの1.8型LCDでブロック崩し

aitendoの1.8インチSPI LCDがPro mini(3.3V/8MHz)で動作するようになったので、先日UNOで作成したブロック崩しを動かしてみました。

基本的には、画面解像度の違いへの対応と、LCD初期化の処理を若干変更するだけて対応できました。


解像度の違いへの対応は、拡大率の変更で行います。
以前使っていた液晶の解像度は240×320ピクセルでしたが、この液晶は解像度が128×160ピクセルです。
ブロック崩しは、論理的な解像度を30×40として作成していますので、座標値を4倍にすればこの液晶にフルスクリーンで表示できます。
(横方向は120ピクセルになるので、8ピクセル余ってしまいますが。)


LCD初期化処理は、Adafruit-TFTLibraryと今回使うAdafruit_ST7735でスケッチ例を見比べて、以下のように修正しました。

・includeするライブラリおよび信号線の定義
(当然ですね。)
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>

#define TFT_CS 10
#define TFT_RST 9
#define TFT_DC 8
#define TFT_SCLK 13 // set these to be whatever pins you like!
#define TFT_MOSI 11 // set these to be whatever pins you like!


・初期化シーケンス
void setup(void) {
tft.initR(INITR_GREENTAB); // initialize a ST7735S chip, green tab
tft.fillScreen(BLACK);

gameStatus = GAME_RESTART;
BallInit(ball);
}

1行目のinitRの引数になっている「INITR_GREENTAB」は、液晶モジュールのバージョンによって、異なる値を与えなければならないようです。

Adafruit_ST7735の現状のヘッダファイルでは、この引数に使える値は「INITR_BLACKTAB」「INITR_GREENTAB」「INITR_REDTAB」の3種類が定義されています。
この値によって、液晶コントローラに送られる初期化コマンド列が変わります。

液晶モジュールの種類をどう見分けるかですが、この「BLACK」「GREEN」「RED」は液晶パネルの保護シールの引き剥がし用の耳(tab)の色なのだそうです。
少し昔のバージョンのAdafruit_ST7735を使ったスケッチ例を見ると、コメントでそのように記載されていました。
以下引用です。
  // Our supplier changed the 1.8" display slightly after Jan 10, 2012
// so that the alignment of the TFT had to be shifted by a few pixels
// this just means the init code is slightly different. Check the
// color of the tab to see which init code to try. If the display is
// cut off or has extra 'random' pixels on the top & left, try the
// other option!
// If you are seeing red and green color inversion, use Black Tab

// If your TFT's plastic wrap has a Black Tab, use the following:
tft.initR(INITR_BLACKTAB); // initialize a ST7735S chip, black tab
// If your TFT's plastic wrap has a Red Tab, use the following:
//tft.initR(INITR_REDTAB); // initialize a ST7735R chip, red tab
// If your TFT's plastic wrap has a Green Tab, use the following:
//tft.initR(INITR_GREENTAB); // initialize a ST7735R chip, green tab


今回使用した液晶はAdafruitの製品ではありませんが、青緑色のプルタブが付いていました。
arduino08-02.jpg

Adafruit製品のLCDモジュールと今回のaitendoのLCDモジュールが同一サプライヤの製品であるかどうかは定かではありません。
ネットの情報では、緑のタブの製品でもINITR_BLACKTABを指定すると正しく動いた、という例もあるようで、結局3種類を試して一番正常なものを選ぶのが良さそうです。

ちなみに私が試したところ、今回のaitendoの液晶モジュールは

・INITR_BLACKTAB・・・画面の下端と右端にランダムな色のノイズピクセルが出る。
上端と左端が2ピクセルほど切れる。
(aitendoの商品ページでもそうなっています)

・INITR_REDTAB・・・画面の下半分が表示されない。

・INITR_GREENTAB・・・ピクセルは表示されるが、色指定がRGBではなくBGRとなる。

となりました。

ピクセルが正常に表示されるのは、INITR_GREENTABですが、赤と青が入れ替わるので、まったく違う色調になってしまいます。

今回のブロック崩しは、もともとカラーを8色しか使っていないので、この問題へはスケッチファイル側で色の定義を変更することで対応しました。
スケッチファイル側を変更したくない場合は、ライブラリのソースコード(Adafruit_ST7735.cpp)を編集することで対応することもできます。
ライブラリの修正部分は別記事で載せておきます。

配線は、下図のようにしました。
コントローラ用の可変抵抗器はA1、圧電ブザーは3番の信号線を使用しています。
液晶への配線は前回と変わっていません。

arduino08-01.png


以上の変更を反映したスケッチファイルと、動作の様子は以下の通りです。
breakout5.ino



posted by boochow at 02:39| Comment(0) | Arduino | このブログの読者になる | 更新情報をチェックする

2015年08月09日

Arduino(7) Arduino Pro MiniにSPI接続のカラーLCDをつないでみる

前回まで使ったArduino UNOと2.4インチTFT液晶は、簡単に動かすことができて良かったのですが、不満点もあります。

一つは、前回触れたように、このLCDを使うとArduino UNOのI/Oポートをほとんど使ってしまうので、センサなど他のデバイスを接続する余地が非常に小さいことです。

もう一つは、Arduino UNOは5V動作なので、3.3V動作のセンサ類を直接つなげられないことです。
3.3Vのデバイスをつなぐには、ブレッドボードなどにArduino UNOの線を引き出し、レベルコンバータを通してから接続する必要があります。

そこで、Arduino UNOの代わりに3.3V動作のArduino Pro Miniを使い、LCDもSPI接続のものにしてはどうかと考えました。

Arduino Pro Miniは、UNOをそのまま小さくして、動作時に不要なUSBシリアル変換やAVRプログラマなどの機能を削除したような製品です。
ただし、PCとの接続では、USB-シリアル変換器が必要になります。
また、3.3V動作製品があり、これをつかえば3.3V動作のセンサ等と直結できます。

SPIとは4つの信号線でシリアル通信を行う規格で、8本のデータバスに加えて制御信号線も必要になるパラレルインタフェースよりも、使用するI/Oポートを大幅に減らせます。
arduino07-02.jpg

というような目論見で、以下の製品を購入しました。

Arduino Pro Mini(3.3V)
arduino07-04.jpg

FTDI USBシリアル変換アダプター(5V/3.3V切り替え機能付き)
arduino07-05.jpg

aitendo TFT液晶with基板 [M-Z18SPI-2P]
arduino07-09.jpg


なお、Pro Miniはピンヘッダを自分でハンダ付けする必要があります。
ピンヘッダを持っていない場合は別途購入が必要です。
(普通のタイプのほかに、L字型も買っておくと良いと思います。)

また、aitendoの上記液晶は、フレキシブル基板をプリント基板にハンダ付けする必要があります。
ただし、このハンダ付けはピン間隔が狭いので、初心者には難しいと思います。


というわけで、今回は実質的にソフトウェアではなくハードウェアの話のみです。
ともかくニッパでベキベキとピンヘッダを切り離していきます。
切ったものが飛ばないように、切るときは指で抑えておきます。
arduino07-06.jpg


Pro Miniは14本×2列の信号線と、PCに接続するための6本×1列の信号線、さらにアナログポートのための2本×1列の信号線が2つ、合計5箇所にピンヘッダを取り付けます。

どのようなピンヘッダ(またはピンソケット)を付けるかは用途次第です。
前回使ったような、足の長いピンソケットを使えば、ブレッドボードに挿すことも、UNOのようにボードにジャンパピンを挿すことも可能になります。

私はブレッドボードを使う想定で、14本×2列のピンを下向きに付けました。
アナログポートの信号線は位置がずらされていますので、ピンヘッダを上向きに取り付けます。
また、PC接続用のピンは裏表を間違えにくいようにL字型ピンで横へ引き出しました。
arduino07-07.jpg

ちなみに、私は上のように2枚重ねのユニバーサル基板を用意して、そこにハンダ付けしたいピンヘッダを挿し、その上に基板を乗せてハンダ付けしています。
こうするとピンヘッダがグラついたり抜けたりしません。

USBシリアル変換アダプターは、特にハンダ付けは必要ありません。
今回のPro Miniは3.3V用ですので、ジャンパピンを3.3Vのほうへ付け直しておきます。

液晶基板は、フレキシブル基板と本体側のパターンを慎重に合わせて、まずカプトンテープでフレキ基板を仮止めします。
カプトンテープは耐熱性があるので、多少ハンダ付けの熱が伝わっても大丈夫です。
カプトンテープ(あるいはポリイミドテープ)もaitendoやamazonなどで入手できます。
arduino07-08.jpg

カプトンテープは褐色の透明なテープです。
分かりにくいですが、上の写真だと、基板の上にフレキをカプトンテープで貼り付けていますので、緑のレジストが一部だけオレンジ色っぽく見えています。その部分がカプトンテープです。

このフレキ基板のハンダ付けですが、ベース基板には予備ハンダをし、フレキ基板は予備ハンダなしで、ハンダ付けの際は追いハンダをそれなりの量を流し込む感じで行いました。
ベース基板のパターンと重なるあたりのフレキ基板のパターンにごく小さな穴が開いていますが、ハンダが十分な量であればそこからハンダが少し出てきます。
最初はハンダが少なすぎて、接触不良になっていました。

液晶モジュールの外部接続端子は、今回はピンソケットを取り付けて、ジャンパピンを挿せるようにしてみました。
また、この基板はバックライトのLEDに流す電流を決める抵抗を自分で取り付ける必要があります。
5V電源のときは150Ωが標準ということですが、今回はバックライトも3.3Vを使いたいので、100Ωを取り付けました。(昼間使うには若干暗いかもしれません。)


完成したら、早速接続です。

その前に、PCにUSBシリアル変換モジュールのドライバを、下記からダウンロードしてインストールする必要があります。

Virtual COM Port Drivers

無事認識されたら、まずはLチカで動作確認です。

Arduino IDEで、

ボード:"Arduino Pro or Pro Mini"
プロセッサ:"ATMega328(3.3V, 8MHz)"

を選択します。
arduino07-01.jpg

あとはUNOのときと同じようにBlinkのスケッチを開いて、コンパイルして転送すればPro Miniボード上のLEDが点滅するはずです。


次に、今回使うSPI接続LCDをArduinoから制御するためのソフトウェアですが、Adafruitから公開されている以下のライブラリを使います。

adafruit/Adafruit-ST7735-Library ・ GitHub

Arduino IDEにこのライブラリを追加する方法は、以前書いたのと同じです
なお、今回使った液晶モジュールはSDカードのインタフェースやタッチパネルは付いていませんので、利用できるのは描画関係の機能だけです。

ArduinoとLCD基板との接続方法はaitendoのページに書かれている通りです。
実際の配線図は以下のようになります。
arduino07-03.png

ライブラリを追加すると、スケッチの例も追加されます。
これも、今回のLCDで動作するのはgraphicstestとrotationtestだけです。
特に変更は行わなくても、上記の接続であれば動作するはずです。

posted by boochow at 01:23| Comment(0) | Arduino | このブログの読者になる | 更新情報をチェックする

2015年08月03日

Arduino(6) ブロック崩しを作ってみる(3)

前回までで、ブロック崩しのグラフィックスは大体出来上がりました。
今回はこのブロック崩しを、実際に遊べる状態にしていきます。

遊べるゲームにするには「入力装置」が必要です。
ラケットを動かすためには、回転型の「ノブ」がいいですね。
そのような入力装置には可変抵抗器(ポテンショメータ)か、ロータリーエンコーダが使えます。

また、ゲームにはやはり「サウンド」も欲しいところです。
Arduinoなどのマイコンで一番お手軽に使えるサウンド出力は圧電ブザーです。
消費電力が非常に小さいので、どんなマイコンでも利用できます。


Arduinoでは、LCDと同じく、これらのデバイスを拡張ポートに「外付け」にします。
入力装置は可変抵抗器、サウンド出力は圧電ブザーをつなぐとして、それぞれアナログ入力、デジタル出力が1つずつ必要になります。

しかし、今回使ったaitendoのLCD「UL024TF」は、下の画像にあるように、Arduino UNOの拡張ポートをほとんど使ってしまっています。
未使用のポートは、アナログ入力のできるA5、デジタル入出力のD0とD1だけです。
ただしD0とD1はシリアルポートと兼用で、PCからプログラムを書き込む時にも使われますので、デバイスを接続するとプログラムが書き込めなくなってしまいます。

UL024TF-468-pinout.png


どうするかですが、SDカードからの出力を読み取るD12をサウンド用に使います。
ブロック崩しではSDカードは使用しませんので、問題は出ません。
ただし、SDカードをカードホルダに挿したままでプログラムを動かさないほうが良いでしょう。


というわけでA5に可変抵抗、D12に圧電ブザーをつなげば入力とサウンドが実現できそうです。

接続イメージは下図のようになります。
これはとりあえずの回路ですが、このままだとアナログ入力のA5を間違ってデジタル出力モードに設定して、可変抵抗を介してGNDへつながっている状態でHigh状態にすると壊れてしまいますので、A5と可変抵抗の間(図の緑のラインの途中)に保護用に1KΩの抵抗を追加するとより安心です。
arduino06-00.png


ちなみにこのような図は、Fritzingというツールで描くのが定番になっているようです。

Fritzing Download

今回初めて使ってみましたが、部品ライブラリがArduino向けに充実していますし、使いやすいソフトでした。
メニューもある程度は日本語化されています。


さて、上図のようにArduinoに可変抵抗器や圧電ブザーを直接配線できればいいのですが、実際には液晶シールドがArduino UNOにかぶさって、拡張ポートを完全にふさいでしまっています。
そのため、他のパーツを接続することができません。

対処の常套手段としては、2階建てになっている基板の間に、もう1枚基板を入れて3階建てにします。
間に挟む基板は、試作用基板「プロトタイプシールド」や、ピンの信号を横方向に引き出せる「ウイングシールド」ないし「スクリューシールド」を使います。
これはTFT LCDのオリジナルを開発したAdafruitでも推奨されている方法です。


しかし、今回は使うピンが少なく、ちょっと試してみるには大げさですので、手元にあったパーツを使ってもう少し簡易な方法を考えてみました。

用意するものは、Arduinoのピン配列に合わせた「ピンソケット」と、ICの足にひっかけて信号を取り出す「ICクリップ」です。

ピンソケットは、Arduinoの基板の拡張ポートに使われているものと同じで、ピンを差し込むことができるソケットです。
6ピンが1つ、8ピンが2つ、10ピンが1つ必要です。
ピンの部分が10mm以上のものでなければなりません。
私が使ったのは、aitendoでArduinoシールド自作用に販売されている「ピンソケットセット」です。
arduino06-01.jpg


ICクリップは、クリップのお尻を押すとカギ状の端子が出てきて、ICのピンに引っ掛けることができます。
バネが入っていて、手を離すとカギが引っ込み、ICのピンに固定されます。
arduino06-02.jpg

arduino06-03.jpg


購入する場合は、コード付きのICクリップが手間がなくて良いです。
「ICテストリード」「プローブ付きジャンパワイヤ」などの名称で販売されています。
両端ともICクリップになっているものが使いやすいでしょう。


では使用方法です。
ショートによる故障を避けるため、USBケーブルはArduinoから外してください。

まず、ピンソケットをArduinoの拡張ポートに取り付けます。
このとき、ピンはソケットに完全には入らず、少し余ります。
この余った部分にICクリップを引っ掛けて信号を取り出そうというわけです。
arduino06-04.jpg

LCDは、取り付けたピンソケットにそのまま取り付けることができます。
arduino06-05.jpg


可変抵抗器は、手元にあった1KΩのものを使いました。
1KΩ〜100KΩくらいであれば、どんな値のものでも構いませんが、「Bカーブ」のものを使いましょう。
記載がない場合は、型番に「1KB」とか「B1K」とか、「B」の文字が含まれているものを選びます。

余談ですが「Bカーブ」は角度と抵抗値が比例しますが、「Aカーブ」は角度に対して抵抗値が「等比級数的に」変化します。
例えば20度回転して抵抗値が半分になったら、次の20度では抵抗値がさらに半分になります。
音量調節や明るさ調節などではAカーブを使うほうが人間の感覚にマッチします。

可変抵抗器は、Arduino UNOのA5、5V、GNDの各ピンに以下の写真のように接続します。
arduino06-06.jpg
arduino06-07.jpg


圧電ブザーは、ビニールコードのあるタイプと、基板実装用に硬い裸のリード線が出ているタイプがありますが、この手の実験用にはビニールコードつきのほうが扱いやすいです。
基板実装用タイプはブレッドボードで使うには便利です。

圧電ブザーは極性があります。
プラスのほうを12番ピン、マイナスのほうをGNDに接続します。
arduino06-08.jpg


以上で回路が組みあがりました。
プログラムのほうは、アナログポートからの入力はanalogRead命令、サウンド出力はtone命令が使えますので、ごく簡単な追加・修正で済みます。

まず使用するポートを定義しておきます。
#define GAMEPORT A5
#define SOUNDPORT 12


ラケットの移動の部分は以下のようになります。

  RacketDraw(racket,tft,BLACK);
racket=map(analogRead(GAMEPORT), 0, 1023, -5, SCRNWIDTH-RACKETSIZE+5);
racket=constrain(racket, 0, SCRNWIDTH-RACKETSIZE);

RacketDraw(racket,tft,WHITE);

赤い部分が修正箇所です。
前回は自前で定義したMAX・MINというマクロを使っていましたが、Arduinoの標準のconstrain関数を使うように変更しました。
なお、難易度調整のため、loopの中のdelayの引数は前回の倍の32にしています。

次にサウンドですが、音の高さの定義はIDEのスケッチの例題「toneMelody」(「02.Digital」に含まれています)の中の"pitches.h"で定義されている数値を引用しました。
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262

実際に使ったのはC3(ラケットに当たったとき)とC4(ブロックに当たったとき)だけです。

ラケットに当たったときの音は、loop関数内の以下の部分で出しています。
  if (ball.y == RACKETLINE) {
if (ball.x >= racket && ball.x < racket+RACKETSIZE) {
ball.vy = -ball.vy;
tone(SOUNDPORT,NOTE_C3,80);
}
}


ブロックに当たったときの音も、loop関数内で出しています。
まず、ブロックに当たったかどうかをbooleanで返すように、game_ongoing関数を修正しました。
boolean game_ongoing()
{
int8_t block;
boolean blockErased;

blockErased = false;
do {
block=BlocksHit(ball.x,ball.y,&ball.vx,&ball.vy);
if (block >= 0) {
exist[block] = false;
BlocksEraseOne(block);
blockErased = true;
}
} while (block > 0);
return blockErased;
}

その上で、この戻り値がtrueだったら音を出すようにしています。
  switch (gameStatus) {
case GAME_RESTART:
if (game_restart()) {
gameStatus = GAME_ONGOING;
}
break;
case GAME_ONGOING:
if (game_ongoing())
tone(SOUNDPORT,NOTE_C4,40);

if (BlocksLeft() == 0) {
gameStatus=GAME_RESTART;
}
break;
}


これでブロック崩しは完成です。
ゲームとしては、いろいろな拡張が考えられると思います。

たとえば

・ミスする回数に制限をつける
・ブロックを消した数に応じてだんだんスピードを早くする
・ブロックの並び方をステージによって変化させる
・ボールの跳ね返る方向を、ラケットのどの位置に当たったかで変化させる
・ボールやラケットを1ピクセル単位で動かす

などができそうです。

最後に、スケッチファイルと動作の様子のビデオを載せておきます。

ino-icon.pngbreakout3.ino



Breakout Game on Arduino Uno
posted by boochow at 02:14| Comment(0) | Arduino | このブログの読者になる | 更新情報をチェックする
人気記事