マカロニペンギンの健忘録

特にテーマを決めているわけじゃないが、私が気になったことを書いていく予定です。

Arduinoの音の出力機能について

2012年12月27日 | 電子工作
前回のブログに掲載した私が電子工作で作ったSIMONですが、実は音が出ません。

Arduinoで音を出すことが一つのハードルだと思ったので、まずはSIMONとしてゲームを作ることを最優先したからです。

いざ完成し「ほっ」としたので、次のハードルを越えようとArduinoの音を出そうと思ったのですが、意外にも意外、このハードルはものすごく低かったです。

Arduino IDEに最初から入っているサンプルスケッチを使ってみました。

ファイル>スケッチの例>02.DIGITAL>toneMelody

接続の説明は
http://arduino.cc/en/Tutorial/Tone

実際、100Ωの抵抗はあってもなくても構いません。
なくても音が大きくなるだけですし、私は100Ωの抵抗を持っていなかったので150Ωを使いましたが、少し音が小さくなったぐらいでした。

ArduinoのサンプルスケッチtoneMelody

電子工作でSIMONを作ってみた。 回路図編

2012年12月24日 | Weblog
SIMONというゲームをArduinoを使って電子工作してみました。
同じように作りたいという人のために説明編と回路図編とプログラム編に分けて、今回の電子工作を公開しています。
このブログは回路図編です。

今回はじめてFritzingを使ってみました。
フリーで使える回路図作成ソフトの一つです。
そのうち、DesignSparkとの比較をブログを書いてみたいと思います。

ブレットボードビューです。

実際とはかなり違います。
電池部分は単3を1本使い、5Vに昇圧する電池ボックスを使用しています。

5Vの照光スイッチを使用しているので、スイッチとLEDは一体です。
あと、トランジスタはSC1815を使用していますが、ベースとコレクタの位置が逆です。

上記のブレットボードを回路図にしたもの


今回のSIMONを作るにあたって、どうしても入れたかった機能がAUTO POWER OFFです。
電気設備の電磁開閉器の保持回路を参考にしています。

回路図の左上の部分がそれです。
電源スイッチを入れるとリレーが働き、それによってArduinoの電源が入ります。このままだと、スイッチから手を話すと電源が切れてしまいます。そのため、すぐに4番の出力ポートをHIGHし、リレーに電源を供給し続ければArduinoは動き続けます。そして、4番の出力ポートをLOWにすると自分自身の電源を落とすることになるのです。

ただ、4番ポートの出力を直接リレーにつないでしまうと負荷が大きすぎるので、トランジスタを使っています。

電子工作でSIMONゲームを作ってみた。説明編

2012年12月23日 | 電子工作
SIMONっていうゲームを御存知ですか?

赤ボタン・緑ボタン・青ボタン・黄色ボタンがランダムに点灯し、点灯した色のボタンを押します。次はそれから一つ色が増えたものが点灯し、その通りにボタンを押していきます。それがだんだん増えていきある一定の回数まで正しくボタンを押すことが出来れば、ゲームに勝つことができます。

詳しくはWikipediaに譲ります。おもちゃ屋さんに発売されていた頃の写真も掲載されています。
私はUbuntuの教育版Edubuntuをインストールした時にプリインストールされていて知りました。

このSIMONというゲームをArduinoを使って電子工作してみました。
同じように作りたいという人のために説明編と回路図編プログラム編に分けて、今回の電子工作を公開しています。
このブログは説明編です。

プログラムはSparkfunSimonのキット用のソフトが公開されていたので参考にしましたが、公開されていたのはC言語で、Arduinoの機能を使用しないものだったので、Arduino言語にのっとって作り直しました。参考にはしましたが、一から作ったと言っていいと思います。

出来上がったのが

です。
お菓子の箱に穴を開けて、照明付きボタンを配置しています。

フタの裏側は


箱の中身は

です。

Arduinoコンパチのスイッチサイエンス製のCielduinoを使用しています。理由はほんの少しだけユニバーサル基板が必要だったのですが、ユニバーサル基板タイプのシールドを使うほどではなかったので、Cielduinoで代用しました。

電池を1つ使っていますが、これはSparkfunの5V DC to DC Step Up - 1xAAという電池ボックスで1.5Vを5Vに昇圧しています。

電子工作でSIMONゲームを作ってみた。プログラム編

2012年12月23日 | 電子工作
このSIMONというゲームをArduinoを使って電子工作してみました。
同じように作りたいという人のために説明編回路図編とプログラム編に分けて、今回の電子工作を公開しています。
このブログはプログラム編です。


#define LED_RED 0
#define LED_GREEN 1
#define LED_BLUE 2
#define LED_YELLOW 3
#define FAILURE 9
#define LED_RED_PIN 10
#define LED_GREEN_PIN 11
#define LED_BLUE_PIN 12
#define LED_YELLOW_PIN 13
#define RELAY 4
#define BUTTON_RED_PIN 6
#define BUTTON_GREEN_PIN 7
#define BUTTON_BLUE_PIN 8
#define BUTTON_YELLOW_PIN 9
#define TIME_LIMIT 300
#define MOVE_TO_WIN 8
#define MARK_OF_LOST false
#define MARK_OF_WIN true

int moves[32];
int nmoves = 0;
int leave_counter;

void setup() {
pinMode(LED_RED_PIN, OUTPUT);
pinMode(LED_GREEN_PIN, OUTPUT);
pinMode(LED_BLUE_PIN, OUTPUT);
pinMode(LED_YELLOW_PIN, OUTPUT);
pinMode(BUTTON_RED_PIN, INPUT);
pinMode(BUTTON_GREEN_PIN, INPUT);
pinMode(BUTTON_BLUE_PIN, INPUT);
pinMode(BUTTON_YELLOW_PIN, INPUT);
pinMode(RELAY,OUTPUT);
digitalWrite(RELAY,HIGH);
play_winner(3);
randomSeed(analogRead(0));
}

void loop() {
delay(1000);
if (game_mode() == MARK_OF_WIN){
play_winner(10);
}else{
play_loser();
}
}

void led_all_switch_on(){
for ( int i = 0 ; i <= 25 ; ++i){
for ( int j = 0 ; j<= 3 ; ++j){
set_leds(j);
delay(1);
}
}
}

void play_loser(){
for (int i = 0; i <=5 ;++ i){
led_all_switch_on();
set_leds(4);
delay(100);
}
}

void play_winner(int count){
for ( int i = 0 ; i <= count ; ++i){
set_leds(0);
delay(80);
set_leds(1);
delay(80);
set_leds(3);
delay(80);
set_leds(2);
delay(80);
set_leds(4);
}
}

//問題を表示する
void play_moves(){
for (int c_move = 0 ; c_move < nmoves ; ++c_move){
set_leds(moves[c_move]);
delay(200);
set_leds(4);
delay(200);
}
}

//新しい色を加える
void add_to_moves(){
int new_button;
moves[nmoves] = random(4);
++nmoves;
}

// ボタンが押されるか、タイムアウトまで待つ。返り値は0から3までの色かFAILURE=9のどれか。
int wait_for_button(){
int old_button = FAILURE;
int time_limit = TIME_LIMIT;
while( time_limit > 0){
int button;
button = check_button();
if (((old_button == 0)||(old_button == 1)||(old_button == 2)||(old_button == 3))&&(button == FAILURE)){
return old_button;
}
old_button = button;
delay(10);
--time_limit;
}
return FAILURE;
}

//ゲームのメインサブルーチン
boolean game_mode(){
nmoves= 0;
while ( nmoves < MOVE_TO_WIN){
add_to_moves();
play_moves();
for ( int c_move = 0 ; c_move < nmoves ; ++c_move){
int choice = wait_for_button();
if (choice == FAILURE) {
//リレーを操作 auto power off
if (nmoves == 1) {
++leave_counter ;
if (leave_counter >= 5) digitalWrite(RELAY,LOW);
}else leave_counter =0;
//
return MARK_OF_LOST;
}

set_leds(choice);
delay(200);
if (choice != moves[c_move]) return MARK_OF_LOST;
set_leds(4);
}
delay(1000);
}
return MARK_OF_WIN;
}

//ボタンをチェック。0~3の色かFAILURE=9の返り値
int check_button(){
int i = FAILURE;
if (digitalRead(BUTTON_RED_PIN) == HIGH){
delay(10);
i = LED_RED;
}
if (digitalRead(BUTTON_GREEN_PIN) == HIGH){
delay(10);
i = LED_GREEN;
}
if (digitalRead(BUTTON_BLUE_PIN) == HIGH){
delay(10);
i = LED_BLUE;
}
if (digitalRead(BUTTON_YELLOW_PIN) == HIGH){
delay(10);
i = LED_YELLOW;
}
return i;
}

//LEDの表示。返り値なし
void set_leds(int leds){
digitalWrite(LED_RED_PIN,LOW);
digitalWrite(LED_GREEN_PIN,LOW);
digitalWrite(LED_BLUE_PIN,LOW);
digitalWrite(LED_YELLOW_PIN,LOW);
switch (leds){
case 0:
digitalWrite(LED_RED_PIN,HIGH);
break;
case 1:
digitalWrite(LED_GREEN_PIN,HIGH);
break;
case 2:
digitalWrite(LED_BLUE_PIN,HIGH);
break;
case 3:
digitalWrite(LED_YELLOW_PIN,HIGH);
break;
}
}