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

人気コンテンツ

  1. Today's Linux 2018/12/03 2018年 12月 02日
  2. Today's Linux 2018/12/04 2018年 12月 03日
  3. Today's Linux 2018/12/06 2018年 12月 05日
  4. Today's Linux 2018/12/07 2018年 12月 06日
  5. Today's Linux 2018/12/10 2018年 12月 09日

Linux Foundationについて

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

 

The Linux Foundation Japan

サイトマップ

問い合わせ先

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

Linux Foundation Japan

Linux Foundation

Linux Training

提案、要望

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

乞うご期待!