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人のカーネル開発者

人気コンテンツ

  1. Today's Linux 2018/10/09 2018年 10月 08日
  2. Today's Linux 2018/10/10 2018年 10月 09日
  3. Today's Linux 2018/10/12 2018年 10月 11日
  4. Today's Linux 2018/10/17 2018年 10月 16日
  5. Today's Linux 2018/10/18 2018年 10月 17日

Linux Foundationについて

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

 

The Linux Foundation Japan

サイトマップ

問い合わせ先

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

Linux Foundation Japan

Linux Foundation

Linux Training

提案、要望

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

乞うご期待!