twitter icon   twitter icon   rss icon

Linux.com Japan

Home Linux Jp チュートリアル Arduino を害虫よけ器にする - 第 2 部

Arduino を害虫よけ器にする - 第 2 部

原文は、こちらです。

2 回目は、動物を怖がらせる音を出す Arduino スケッチをロードし、テストして、動きを検知して音を出すようにします。まず、第 1 部を確認して、EZ1 センサーのテスト スケッチを見てみましょう。

fig-1 rinkydinkrig

Arduino スケッチは、2 つの関数: setup() とloop() を含んでいます。Setup() は、スケッチの最初に 1 回だけ実行されるコードで、ピンのモードやハードウェアの初期化を行います。ez1_measure.ino スケッチには、setup() 関数でデータ転送速度を設定しています。Arduino は USB 接続ですが、シリアル ポートの速度設定をしています。なぜなら、それは依然としてシリアル ポート UART (Universal Asynchrous Receiver/Transmitter) であり、標準的なシリアル ポートの速度である 300、1200、2400、4800、9600、14400、19200、28800、38400、57600、115200 ボーをサポートしているからです。つまり、Arduino がシリアル モニター機能を持ち、スケッチの出力を見ることができるようになっているのです。

Loop() は実際のプログラムで、プラグを抜くまで繰り返し実行されるため、loop() と名付けました。何者かが EZ1 の超音波ビームを遮ったときに音を 1 回だけ出すようにします。

Loop() の最初に、2 つの変数、a0value inches を宣言します。これは、このスケッチ用の名前で、特に予約語ではありません。a0value は、アナログピン #0 の値を保持します。inches は、物体の距離を計算した結果を保持します。float は予約語で、ビルトインのデータ型浮動小数点の数値を意味します。10 進数値です。

analogRead() は、アナログ ピンから値を読み出すビルトイン関数です。

Serial.print() は、シングル クォートもしくはダブル クォートで囲まれた文字列をシリアル ポートに出力するビルトイン関数です。

Serial.println() は、データ型の値を印刷するビルトイン関数です。

delay() は、ミリ秒で指定された時間停止するビルトイン関数です。ez1_measure.ino スケッチは、各センサーの読み込みの間、3 秒待っています。

すべてわかったでしょうか。Arduino の公式 Web サイト Arduino language reference on Aruino.cc を見てください。

動物退散スケッチ

このスケッチを利用するときの注意点として、// は、1 行がコメントですから、そこに何か書いても実行されません。

以下がスケッチの全体です。

// CritterScare.ino. Plays scary sound effects
// when a deer or other freeloader comes within 
// 24 inches of the sonar rangefinder
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"
SdReader card; 
FatVolume vol;
FatReader root;
FatReader f;
WaveHC wave;
// declare functions; function bodies are 
// below loop() function
int freeRam(void);
void sdErrorCheck(void);
void playfile(char *name);
void playfile(char *name);
// setup() is a required Arduino function
void setup() {
  Serial.begin(9600);  
  Serial.print("\nThe serial port is set to 9600 baud. \nWelcome to the CritterScare Sketch!");
  Serial.print("\nYou have ");
  Serial.println(freeRam());
  Serial.print("bytes of free RAM.");
  
// Set the output pins for the DAC control
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  
  if (!card.init()) {      
    Serial.print("\nCard init. failed!");
    sdErrorCheck();
    while(1); 
  }
  
// enable optimize read - some cards may timeout. 
// Disable if you're having problems
  card.partialBlockRead(true);
 
// Now we will look for a FAT partition!
  uint8_t part;
  for (part = 0; part < 5; part++) {
    if (vol.init(card, part)) 
      break;    
  }
  if (part == 5) {    
    putstring_nl("Sorry, there is no valid FAT partition!");
    sdErrorCheck();  
    while(1);   
  }
  
// Print partition and filesystem information
  Serial.print("\nI'm using partition ");
  Serial.print(part, DEC);
  Serial.print(" on the SD card, and the filesystem type is FAT");
  Serial.println(vol.fatType(),DEC);
  
// Try to open the root directory
  if (!root.openRoot(vol)) {
    Serial.print("\nCan't open root dir!");
    while(1); 
  }
  
// Whew! We got past the tough parts.
  Serial.print("\nEverything checks out, so let's get going!\n");
}
// loop() is a required Arduino function
// convert voltage from sensor to inches
void loop() {
    float a0value = analogRead(0); 
    float inches = 0.496 * a0value; 
    Serial.print("\nThe value captured from pin a0 is: "); 
    Serial.println(a0value);
    Serial.print("\nThe distance in inches is "); 
    Serial.println(inches);
    delay(3000);
    
    int playback = 0;
    if (inches < 24 && playback == 0){
    playback = 1;
    playcomplete("COYOTEHOWL.WAV");
  }
  else if (inches < 24 && playback == !0){
  }
  else { playback = 0;
    wave.stop();
  }
}
// And now the other function bodies
// this handy function will return the number
// of bytes currently free in RAM, great for debugging!   
int freeRam(void)
{
  extern int  __bss_end; 
  extern int  *__brkval; 
  int free_memory; 
  if((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end); 
  }
  else {
    free_memory = ((int)&free_memory) - ((int)__brkval); 
  }
  return free_memory; 
} 
void sdErrorCheck(void)
{
  if (!card.errorCode()) return;
  Serial.print("\n\rSD I/O error: ");
  Serial.println(card.errorCode(), HEX);
  Serial.print(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}
// Plays a WAV file from beginning to end with no pause.
void playcomplete(char *name) {
// call our helper to find and play this name
  playfile(name);
  while (wave.isplaying) {
    //do nothing else
     }
}
  
void playfile(char *name) {
// see if the wave object is currently doing something
  if (wave.isplaying) {
    wave.stop();
  }
// look in the root directory and open the file
  if (!f.open(root, name)) {
    Serial.print("\nCouldn't open file "); 
    Serial.println(name); 
    return;
  }
// OK read the file and turn it into a wave object
  if (!wave.create(f)) {
    Serial.print("\nNot a valid WAV"); return;
  }  
// ok time to play! start playback
  wave.play();
}

動作解説

スケッチのコードの大半は、セットアップとエラー チェックです。loop() 関数が大事なところですので、詳細に説明します。

最初の 7 行は、わかっていますね。ez1_measure.ino から再利用しました。

次は、オーディオ ファイルを 1 回だけ再生、停止したら、センサーによるトリガーが来るまで停止させるためのものです。2 つの条件、つまり、「動物が 24 inch 以内に近づき」「再生中でない」が満たされたとき、オーディオ ファイルを再生します。

最初に、playback の値を 0 に初期化します (予約語以外なら任意の名前でかまいません)。これは、停止中を意味します。

int playback = 0;

つぎに、再生のための条件を設定しています。24 inch 以内に近づくこと、playback の値が 0 であること、つまり停止中であることです。この 2 つの条件が揃ったときに、playback の値を 1 に設定します。これは、再生を意味し、再生するオーディオ ファイルを指定します。

if (inches < 24 && playback == 0){
    playback = 1;
    playcomplete("COYOTEHOWL.WAV");
  }

すでにファイルが再生中のときは、playback に 0 を設定し、再生終了後に停止するようにします。

  else if (inches < 24 && playback == !0){
  }
  else { playback = 0;
    wave.stop();
  }

状態がリセットされて、再生のための 2 つの条件が揃うのを待ちます。もちろん、他のやり方もあります。コメント欄に、アイデアを書いてください。図 2 が、表示された内容です。

fig-2-sketch-output

これで、うまく動作するようになりました。もし、質問があれば、リソースの項に挙げたサイトなどを参照してください。

リソース

Ladyada.net Arduino Tutorials

Arduino language reference

入門書として、Simon Monk 著 Programming Arduino: Getting Started with Sketches、電子回路や C プログラミングを既に知っているならば Michael Margolis著 Arduino Cookbook, 2nd Edition などが良いと思います。

Linux Foundationメンバーシップ

30人のカーネル開発者

人気コンテンツ


Linux Foundationについて

Linux Foundation はLinux の普及,保護,標準化を進めるためにオープンソース コミュニティに資源とサービスを提供しています

 

The Linux Foundation Japan

サイトマップ

問い合わせ先

サイトに関するお問い合わせはこちらまで

Linux Foundation Japan

Linux Foundation

Linux Training

提案、要望

Linux.com JAPANでは広く皆様の提案、要望、投稿を受け付ける予定です。

乞うご期待!