twitter icon   twitter icon   rss icon

Linux.com Japan

Home Linux Jp チュートリアル Arduino をしゃべるリマインダー マシンにする - 第 2 部

Arduino をしゃべるリマインダー マシンにする - 第 2 部

原文は、こちらです。

Arduino reminder tutorial

第 1 部では、ブレッドボードと DS1307 リアルタイム クロックを使った Arduino デバイスの時刻保持について学びました。ここでは、動きを検知してリマインダーを再生するスケッチの完全版をロードしてテストします。


全部をまとめる

メッセージを格納した SD カードをロードします。メッセージは、支払い、犬の散歩、好きな詩、印象に残ったフレーズ、好きな歌など、何でも良いです。オーディオ ファイルは 22,050Hz WAV 形式で格納してください。それでは、リマインダー マシン スケッチに挑戦しましょう。下記のスケッチのファイル名は、実際のファイル名に変更してください。時刻は、現在のちょっと先の時刻を指定してください。
MaxBotix から何が出るか、そして、何が起こるかを待ちます。

 

/* Arduino Reminder Machine
*  Play audio reminders, inspirational
*  quotations, poetry, or anything
*  you like. Playback is triggered by
*  motion sensor and schedule
*/
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"
#include <Wire.h>
#include "RTClib.h"
/* Variables for reading SD card
*  and printing filenames
*/
SdReader card;  
FatVolume vol;
FatReader root;  
FatReader f;  
WaveHC wave;  
uint8_t dirLevel;
dir_t dirBuf;    
#define error(msg) error_P(PSTR(msg))
RTC_DS1307 RTC;
void setup () {
    Serial.begin(9600);
    Wire.begin();
    RTC.begin();  
/* Begin initializing and checking SD card for errors
*/
  putstring_nl("\nLet's start by testing the SD card and files.");
/* Test if card will play with the default 8 MHz SPI
*  (Serial Peripheral Interface) bus speed. If it doesn't, comment out
*   "if (!card.init()) " and uncomment "if (!card.init(true))"
*/
  //  if (!card.init(true)) {   
  if (!card.init()) {    
    error("Card init. failed!");
  } 
/* enable optimized reads - 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) {                      
    error("Sorry, I could not find a valid FAT partition!");  
  }
/* Print partition information
*/
  putstring("I'm using partition ");
  Serial.print(part, DEC);
  putstring(", and the filesystem type is FAT");
  Serial.println(vol.fatType(), DEC);
/* Can the root directory be opened? Print an error
*  message if it can't.
*/  
  if (!root.openRoot(vol)) {
    error("Can't open root dir!");
  }
/* All right, everything looks good. Print
* the filenames found on the SD card.
*/
  putstring_nl("\nI found these files on your SD card: (* = fragmented):");
  root.ls(LS_R | LS_FLAG_FRAGMENTED);
  putstring_nl("\nEverything checks out, so let's get started!\n");
}
/*** End Initialize and check SD card for errors ***/
/* Begin Reminder Machine sketch
* First display time, date, and 
* MaxBotix sensor value
*/
 
void loop() 
{    
    DateTime now = RTC.now();
    int a0value = analogRead(0);
    Serial.print("The reading from the sensor, taken from analog pin 0, is ");
    Serial.print(analogRead(0));
    Serial.println();
    Serial.print("The day of the week is ");
    Serial.print(now.dayOfWeek(), DEC);
    Serial.println();
    Serial.println("The date and time are:");    
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.println(now.second(), DEC);   
/*** End date, time, and sensor value display ***/  
/* Now we schedule audio playback. Audio will play
* when two conditions are met: the sensor detects
* movement, and it is the scheduled time
*/
    if  ((a0value <= 45) && (now.hour() == 14)) {            
       Serial.println("\nNow playing: Walk the dogs!\n");
       playcomplete("WALKDOGS.WAV");
       delay(600000); //do not replay for 10 minutes
       }    
    else if ((a0value <=45) && (now.day() == 5)) {
       Serial.println("\nNow playing: Mow the lawn!\n");
       playcomplete("MOWLAWN.WAV");
       delay(600000);
       }
       
    else if ((a0value <=45) && (now.dayOfWeek() == 7) && (now.hour() == 18)) {
      Serial.println("\nNow playing: Relax and read a book!\n");
      playcomplete("READBOOK.WAV");
       delay(600000);
       }
    else {
      Serial.print("\nSorry, your numbers don't match. No music for you.\n\n");
       delay(30000);
      }       
}
/*** End playback schedule ***/
/* Audio playback and error functions
*/
void error_P(const char *str) {
  PgmPrint("Error: ");
  SerialPrint_P(str);
  sdErrorCheck();
  while(1);
}
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);
}
/* Play a WAV file from beginning to end with no pause.
* Play only one file at a time
*/
void playcomplete(char *name) {
  playfile(name);
  while (wave.isplaying) {
     }
}
void playfile(char *name) {
  if (wave.isplaying) {
    wave.stop();
  }
  if (!f.open(root, name)) {
    Serial.print("\nCouldn't open file ");
    Serial.println(name);
    return;
  }
  if (!wave.create(f)) {
    Serial.print("\nNot a valid WAV"); return;
  }  
  wave.play();
}
/*** end Audio playback and error functions ***/
/*** end sketch ***/

良いスタートです

問題なかったときには、次のように表示されます。

Let's start by testing the SD card and files.
I'm using partition 1, and the filesystem type is FAT32
I found these files on your SD card: (* = fragmented):
MOWLAWN.WAV  
WALKDOGS.WAV  
READBOOK.WAV  
Everything checks out, so let's get started!
The reading from the sensor, taken from analog pin 0, is 11
The day of the week is 3
The date and time are:
2014/5/21 15:59:35
Sorry, your numbers don't match. No music for you.

条件が成立したら、次のように表示されるでしょう。

The reading from the sensor, taken from analog pin 0, is 39
The day of the week is 3
The date and time are:
2014/5/21 16:0:11
Now playing: Walk the dogs!

コードは、SD カードを読み込み、オーディオの再生を制御します。このコードは、WaveHC のスケッチの例から取りました。日付と時刻のコードは、RTClib のスケッチの例を元にしました。真ん中付近の処理、オーディオファイルの再生を制御するループは、連続する簡単な if-else-if 文です。loop 関数を編集することで、自分の必要とするものに変更できます。

最初に散歩のトリガーをかけられたら、散歩している間はもう必要ない、ということもあるでしょう。Arduino の delay() 関数を使うことです。delay() 関数の引数は、遅延時間を mS (ミリ秒: 1000が 1 秒となります) で表した値 delay() 関数で、600,000 を指定すると、10 分間はリマインダーが再生されません。遅延時間は、WAVE ファイルの再生が終わったときからカウントされます。

A0value の設定は最大距離になっているので、反対側の壁やその他のリマインダーの再生が不要なときには、センサーは働きません。

スケッチの例は、ある 1 時間の間にリマインダーを再生するようになっています。時間の間隔を変えたいときは、次のようにします。

((a0value >= 30) && (now.hour() == 16)  && ((now.minute() >= 0) && (now.minute() < = 30)))

この設定で、リマインダーは、4:00 から 4:30 の間になります。括弧の位置を間違えると大変なことになります。スケッチを編集して、センサーを無視してスケジュールに沿ったリマインダーを出したり、センサーの結果だけに従ってリマインダーを出すこともできます。

これで、説明を終わります。さらに勉強したい人は、リファレンスを見て下さい。

リファレンス

How to Build a Custom Arduino Talking Reminder Machine, Part 1
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では広く皆様の提案、要望、投稿を受け付ける予定です。

乞うご期待!