音声認識組込みモジュールを使ってみます(PIC編)

〔マイコンのトップに戻る〕


以前こちらで音声合成LSI(ATP3011F4-PU)を使って音声を発生させる実験の記事は書きました。

今回は、音声を認識するモジュール(SR-MOD100)を実験してみたいと思います。
音声認識組込みモジュールは、マイクロテクニカこちらから購入しました。 *3)
少し、値がお高いのですがぁ、USART通信(シリアル通信)で簡単に制御できます。

このモジュールは、登録(録音?)した音声を認識します、登録は32フレーズ可能でこれは登録した
本人の声のみ認識します、これを”特定話者認識フレーズ”と呼んでいます。
(パスワードフレーズと言う機能なら5人まで登録できる様です)
また、”特定話者認識フレーズ”機能であれば予め25フレーズ内蔵されています、これは誰の声でも
認識可能な様です。

※ 2017/01/12現在、"SR-MOD100C"と新しくなった様です、
  ユーザー定義SIフレーズ+20語(8語まで購入時に申請すれば無料)機能が新たに加わっている
  様です。 基板の接続は下記とは異なるでしょう! *3)

登録フレーズを認識した場合は、登録しているフレーズの該当するインデックス番号が送信されます。

尚、”音声認識組込みモジュールを使ってみます(Arduino編)”はこちらを見て下さい。

《SR-MOD100用のサポートソフトについて》

SR-MOD100用のマニュアルサポートソフトウエアは、マイクロテクニカのこちらからダウンロードして
下さい。("型式の先頭文字で検索"の項で""文字をクリック)

以下は、windows 7 Pro にインストールした場合での記述です。

@ ダウンロードしたファイル"EasyVR.zip"を解凍すると、「EasyVR」フォルダーが出来ます。
A この中に有る"EasyVR-Commander-3.4.10-QS-5.2.1.exe"を実行してインストールします。
インストール画面1
 B 途中で左図が表示されたら、[いいえ]を
   選択します。
   "QuickSynthesis 5.2.1"と言うツールは
   インストールをしなくてもOKです。
   インストールするとエラーもでるしぃ。

C "EasyVR Commander"ツールがインストールされます。
  ちなみに、ショートカットは作成されない

このツールで、モジュールのテストと特定話者認識フレーズの登録が出来ます、
詳しい使い方はマニュアルを見て下さい。

モジュールとパソコンの接続

PCと接続  左のモジュール写真は、マイクロテクニカからの拝借です、
 実際のモジュールと少し異なります。

 モジュールとパソコンの接続はシリアルインターフェイス
 行います。

 マイクロテクニカに、モジュールのUART信号をパソコンの
 USBポートに接続出来る様にする為のボードも販売して
 いますが少し値段が高いので、秋月電子の”USBシリアル
 変換モジュール
”を利用する方法をお勧めします。

 ”USBシリアル変換モジュール”の話はこちらの記事を
 参照下さい。


実験の準備

下記サンプルプログラムを利用する為に、”特定話者認識フレーズ”を登録します、登録方法は
マニュアルを見て下さい。
SDグループ(青色フォルダ)の最初の”1 Group”に下記フレーズを登録します。
・Index0: てんとう (点灯)
・Index1: しょうとう (消灯)
(点灯)で認識するとLEDを点けて、(消灯)で認識するとLEDを消します。

こんな感じに登録しますぅ。
ツールの画面

最初(LEDてんとう)(LEDしょうとう)と登録したのですがぁ、うまく認識せずだったので
(てんとう)(しょうとう)にしたら上手く行きました。

《配線図》

PICピン構成図  PIC12F1822のピン構成図です。

 1番ピン(VDD)に電源5Vを接続して
 8番ピンにGNDを接続します。
 2番と6番がRXの受信ピンです。
 3番と7番がTXの送信ピンです。
 今回は6・7番ピンを使用します。

配線図  2番(RA5)ピンにLEDを接続します、
 LEDの足が長い方をPIC側にします。

 3本のI/O端子が有り入出力が可能です。
 マイクは付属の物を取り付けます。
 (付属のメスーメス・リード線で配線)

 モジュールの詳しい端子の使い方は
 マニュアルを参照下さい。

 モジュール電源は3.3-5Vまで対応です。

 RA2端子から別途作成のLCDモニター
 出力し動作の状態を確認しています。

RA4端子にスイッチを配線していますが、下記プログラムでは未使用です、デバッグ用で使用しました。

《ダウンロードプログラムについて》

↓ここからサンプルプログラムソースファイルをダウンロードして下さい。
SR.lzh (2014/02/02) *1)
SR.zip ライブラリとMPLAB X用に変更 *2)

プログラムソースをダウンロードしたら、MPLAB Xにてプロジェクトを作成します。
以下のファイルをプロジェクトディレクトリにコピーしてプロジェクトに取込んで下さい。
次にコンパイルPIC書き込みを実行して下さい。 *2)
MPLAB(R) XC8 C Compiler Version 1.32コンパイラを使用しています。

ダウンロードファイルを解凍すると下記の様なファイル構成です。
SR.c・・・・・・・・・・・・・・ 本体のサンプルプログラムソースファイル *2)
skSRMOD100.c・・・・ 音声認識モジュールとUASRTで通信を行うライブラリ関数ソースファイル
skSRMOD100.h・・・・ 音声認識モジュールとUASRTで通信を行う関数のヘッダファイル
skUARTlib.c・・・・・・・ UASRT通信を行うライブラリ関数ソースファイル *2)
skUARTlib.h・・・・・・・ UASRT通信を行う関数のヘッダファイル *2)
millis.c・・・・・・・・・・・・ プログラム起動時からの時間をカウントするライブラリ関連ソースファイル
millis.h・・・・・・・・・・・・ プログラム起動時からの時間をカウントするライブラリ関連ヘッダファイル

このプログラムにはデバッグモニタープログラム「skMonitorLCD.c」「skMonitorLCD.h」が必要です。
デバッグLCDモニターについてはこちらを参照して下さい。
(無くても動作させる事は可能ですがぁ....、動き確認用に有った方が良いでしょう)
「skMonitorLCD.c」は送信データをTimer2のタイミングで送る様に変更しました、
その為にSR.cプログラムを変更しています。
 *1)

また、LCDモニターの出力はRA2から行っているので「skMonitorLCD.h」を下記の様に変更します。
#define _XTAL_FREQ 8000000  // 使用するPIC等により動作周波数値を設定する
#define BAUDRATE 51      // 9600bps(8MHz=51)(4MHz=25)(16MHz=103)(20MHz=129)
#define MONITOR_PIN RA2      // モニタ出力するピンの番号を設定する

SR.c

音声認識モジュール(SR-MOD100)と通信を行う為のメインのサンプルプログラムです。

起動させたら、(てんとう)(しょうとう)を発声すればLEDが点灯・消灯を行います。
LCDモニター画面にも”ON”/ ”OFF”を表示します。
これは電源を切るまでは繰り返し実行しているので、何時でも声を出せばLEDをON/OFF出来ます。

発声を認識できなかった場合は、LCDモニターに”Failed!!”と表示しエラー番号も表示します。
(エラー番号はマニュアルの22頁 "STS_ERROR"の項 を参照下さい)
また、今回の認識待ち時間は3秒です、この時間までに声を発生しないとタイムアウトになり、
LCDモニターに”Timeout!!”と表示されます。

skSRMOD100.h

音声認識モジュールとUASRTで通信を行うライブラリのヘッダファイルです。
"skSRMOD100.c"を利用する場合に
#include "skSRMOD100.h" をメインプログラムの先頭で記述して下さい。

又、下記の様に記述されています、クロック周波数を変更する場合は書換えて下さい。
#define _XTAL_FREQ 8000000    // 使用するPIC等により動作周波数値を設定する
skSRMOD100.c

音声認識モジュールとUASRTで通信を行う為のライブラリ関連ファイルです。
このライブラリ自体は他のPICでも動作可能です。

音声認識モジュールと通信を行う関数の使い方を説明します。

 ans = SR_Init(no)
  SR-MOD100を使用する為の初期化を行う処理です
  SR-MOD100は電源を入れた時はスリープ状態なのでウエイクアップをさせます。
   no  :使用言語を指定します(今回は日本語で初期化しています)
        0=英語 1=イタリア語 2=日本語 3=ドイツ語 4=スペイン語 5=フランス語
   ans  : 0=正常終了 -1=コマンドを受け入れ出来る状態で無い -2=言語設定エラー

 ans = SR_SendCMD(cmd,para1,para2)
  SR-MOD100にコマンドを発行する処理です
  コマンドの詳しい話はマニュアルを参照下さい。
  但し、CMD_BREAK/CMD_SLEEP/CMD_LANGUAGE/CMD_TIMEOUT/CMD_BAUDRATE/
  CMD_QUERY_IO/CMD_RECOG_SI/CMD_RECOG_SD のコマンドのみ対応です。
  これ以外のコマンドは、音声認識用の音声登録関連コマンド群ですが、
  音声の登録は"EasyVR Commander"ツールで行いましょう、その方が簡単に出来ます。
   cmd :発行するコマンドを指定します
   para1:コマンドに第1引数が有れば指定します(無ければ-1を必ず指定します)
   para2:コマンドに第2引数が有れば指定します(無ければ-1を必ず指定します)
   ans :0=正常終了 -1=コマンドを現在処理中です
  例1) 音声認識待ち時間を5秒に変更する場合(コマンド:CMD_TIMEOUT)
  SR_SendCMD('o',5,-1)   // 又は SR_SendCMD(0x6F,5,-1)

  例2) スイッチが押された時に3番I/OピンをONさせる場合(コマンド:CMD_QUERY_IO)
  if (RA4 == 0) {
       SR_SendCMD('q',3,1) ;
  }

  例3) スイッチが押された時に不特定話者認識フレーズを行う場合(コマンド:CMD_RECOG_SI)
  if (RA4 == 0) {
         // LCDモニター画面に表示を行う
         MonitorCls(0) ;
         MonitorPuts("Voice Come on   ") ;
         // 不特定話者認識プロセスの実行コマンドを発行する
         // 引数はワードセット2番のインデックスを渡す
         SR_SendCMD('i',2,-1) ;
  }
 SR_CMD_STS
  コマンドの実行状態をチェックします。
  0:コマンドは実行中でない  それ以外の値:実行中です
  コマンドを発行し、それが終了した後に何か処理を行いたい場合等に使用します。
  もちろん実行中なら、SR_SendCMD()は受けつけません。
  CMD_RECOG_SI/CMD_RECOG_SDコマンドは、音声認識処理が完了(74H)(65H)(72H)するまでは
  実行中の状態です。

 SR_CMD_CTL( )
  発行したコマンド(SR_SendCMD)の処理を制御する関数です

  SR-MOD100は、データを1バイト単位での送信受信となっています。
  その送信受信は20ms間隔で行わないとならない為にこの関数は存在します。
  例えば、音声認識待ち時間変更コマンドを送信する場合、
   UART_Write('o') ;    // コマンドの発行
   __delay_ms(20) ;
   UART_Write(5+0x41) ; // 引数の発行
   __delay_ms(20) ;
   UART_Read() ;        // ステータスを受信する
  こんな感じです、なので__delay_ms(20)を使えばこの待ち時間に他の処理をしないとダメな場合が
  有るでしょうそういう場合は__delay_ms(20)は使えません。

  なので、SR_CMD_CTL( )はループ内で常に下記の如く実行させないとダメです。
  main()
  {
       // SR-MOD100を使用する為に初期化を行う
       millisStart() ;        // 時間(Timer0)カウント開始(1ms毎にカウントさせる)
       InitUART(6,7,51) ;     // USARTの初期化を行う(SR-MOD100との通信用)
       SR_Init(2) ;           // 日本語で初期化

       while(1) ;
            if (RA4 == 0) {
                 // スイッチが押されたら
                   // 不特定話者認識プロセスの実行コマンドを発行する
                   // 引数はワードセット2番のインデックスを渡す
                   SR_SendCMD('i',2,-1) ;
            }

            //  SR-MOD100との通信を制御する処理
            SR_CMD_CTL() ;
        }
  }
 SR_USER_CALLBACKT_HANDLER(sts,para)
  発行したコマンドに対して、SR-MOD100から返答を受けた場合に処理されるコールバック関数
  です、なので、返答を受信した場合に何か処理を行うにはこの関数に全て記述します。
  また、この関数はメインプログラム(例"SR.c")の中に記述すると良いでしょう。
   sts :返答のステータス値が格納されます
   para:返されたステータス値に戻り引数が有ればここに格納されます
       STS_SIMILAR/STS_RESULT時なら音声を認識したインデックス番号がセットされます
       STS_ERRORならエラーコード番号がセットされます
       STS_PINなら入力設定した汎用I/Oピンの入力状態がセットされます
       このステータス以外は、STS_OUT_OF_MEM/STS_INTERR/STS_TIMEOUT/
       STS_INVALID のみ対応
  void SR_USER_CALLBACKT_HANDLER(unsigned char sts,unsigned char para)
  {
       switch (sts) {
            case SR_STS_SIMILAR :
                   // 不特定話者認識フレーズの該当するインデックス番号が返された場合の
                   // 処理をここに記述する
                   break ;
            case SR_STS_RESULT  :
                   // 特定話者認識フレーズの該当するインデックス番号が返された場合の
                   // 処理をここに記述する
                   // LEDをON/OFFするサンプルの記述です
                   if (para == 0) RA5 = 1 ;   // LED点灯
                   else           RA5 = 0 ;   // LED消灯
                   break ;
            case SR_STS_ERROR :
                   // エラーが返された(フレーズ認識失敗)場合の処理をここに記述する
                   break ;
            case SR_STS_PIN :
                   // 汎用I/Oピンの入力状態が返された場合の処理をここに記述する
                   break ;
            default :
                   // その他のステータスが返された場合の処理をここに記述する
                   break ;
       }
  }

skUARTlib.h

USART機能にアクセスする為のライブラリ用のヘッダファイルです。
"skUARTlib.c"を利用する場合に
#include "skUARTlib.h" をメインプログラムの先頭で記述して下さい。

受信バッファのサイズを変更する場合は下の行を変更して下さい。
(但し、UART_BUFFER_SIZE - 1 の個数だけ受信可能です、それ以上は読み捨てられます。)

#define UART_BUFFER_SIZE 32 // USARTの受信バッファサイズ

18F25K22/18F26K22等の様にUSARTモジュールが2個有るPICが有ります、通常はUSART1が
デフォルトです、USART2側のモジュールを使いたい場合は、"#define UART2_USE"を記述します。
"skUARTlib.h"にてコメントになっているので外せば良いでしょう。 *2)

skUARTlib.c

このライブラリはUSART通信を行う為の関数集です。
この関数集自体は現在 12F1822 16F1823/1826/1827 16F1938/19xx に対応しています。
その他に、16F1705 16F1825/1829 18F2xK22(USART1/2) 1814K50 18F8722でも動作するでしょう。*2)
送受信相手がUSARTに対応していればこの関数集は利用可能です。

USARTにアクセスを行う関数の使い方を説明します。

 InitUART(rx, tx, brg)
  USART通信の初期化を行う処理
  送受信を行うで初期化され、非同期モード 8ビット・ノンパリティ・9600bpsでの設定です。
  (今回は、6番RXピン/7番TXピンを使用しています)
   rx :受信(RX)するピンの番号を指定します(このピンはTRISレジスターで入力にして下さい)
   tx :送信(TX)するピンの番号を指定します
   brg :ボーレートジェネレータの設定値を指定します(通信速度になります)
      設定値とボーレートの関係は各PICのデータシートを参照して下さい。
      例えば、
      PIC12F1822のデータシートはこちらの299-300ページを見て下さい。
      SYNC=0、BRGH=1、BRG16=0で8MHzのクロック周波数で速度が9600ボーレートなら
      SPBRG=51だから設定値は51を指定します。

           (SYNC=0 BRGH=1 BRG16=0)で設定時の、ボーレート設定値一覧表
bps 4MHz 8MHZ 16MHz 32MHz 40MHz 48MHz 64MHz
9600 25 51 103 207 x x x
19200 12 25 51 103 129 155 207

  ※ ピン番号の指定は、12F1822,16F1823〜1829以外は指定しなくても良いです。
    例) InitUART(0,0,51)
  ※ SR-MOD100はデフォルトが9600ボーです、変更は"CMD_BAUDRATE"コマンドで行います。

 UART_Send(dt,num)
  相手に指定した個数のデータを送信する処理
   dt  :送信するデータを格納した配列を指定します
   num:送信するデータの個数を指定します。

 UART_Write(dt) *2)
  相手に1バイトのデータを送信する処理
   dt  :送信するデータを指定します

 ans = UART_Available( )
  受信したデータの個数を返す処理
   ans:受信したデータの個数を返します

 ans = UART_Read( )
  受信したデータを1バイト読み込む処理
   ans:受信したデータを返します、0xffffを返したら受信データは空です
  例)
     char dt ;

     if (UART_Available() != 0) {
          dt = UART_Read() ;    // 1バイトデータを受信する
          UART_Send(&dt,1) ;    // 1バイトデータを送信する
     }
 UART_Flush( )
  受信バッファをクリアする処理
  受信バッファにデータを受信していてもこの関数を実行させればデータはなくなります。

 InterUART( )
  USART関連の割り込み処理です。
  受信を行う場合は、メインプログラム(例"SR.c")の割込み処理で必ず呼びます。
  例)
     void interrupt InterFunction( void )
     {
          // USART関連の割り込み処理
          InterUART() ;
     }
millis.h

プログラム起動時からの時間をカウントするライブラリ関連ヘッダファイルです。
"millis.c"を利用する場合に
#include "millis.h" をメインプログラムの先頭で記述して下さい。

millis.c

プログラムの実行を開始した時から現在までの時間をミリ秒単位で返す関数です。
タイマー0を使って1ms毎にカウントを行うだけです。
少し詳しい話はこちらのページを参考にして下さい。

 millisStart( )
  Timer0を使用する為の初期化処理
  動作周波数は8MHzとして計算されています。

 millisInter( )
  millis関数用の割り込み処理です。
  メインプログラム(例"SR.c")の割込み処理で必ず呼びます。
  例)
     void interrupt InterFunction( void )
     {
          millisInter() ;     // Timer0割込み処理(millis関数用)
     }
 milliCount
  この変数にカウントされるので使用する場合は参照するだけです。
  "unsigned long"宣言です、4,294,967,295ms(2の32乗 - 1)までカウントしたら0に戻り再カウント


クロック周波数を変える場合は

PICの動作周波数は8MHzでの設定です変更した場合は、下記場所の変更も合わせて行います。
 ・「skMonitorLCD.h」「skSRMOD100.h」ファイルの #define _XTAL_FREQ 8000000 を変える
 ・「skMonitorLCD.h」ファイルの #define BAUDRATE 51 を変える
 ・ InitUART(6,7,51) 関数のボーレートジェネレータの設定値(51)を変える
 ・「millis.h」のタイマー0用カウントの初期値を変える

《その他》

下写真は実験風景です。
実験風景写真

感想などを....
不特定話者認識フレーズの場合はハッキリ発音しないと誤認識が多いかもって感じでしょうか。
実際にモジュールを組み込む場合として、取り付け穴が無い、ピンピッチも2mmなのでぇ、取り付けには
一工夫いるでしょう。
簡単に制御出来るのですがぁ、もう少し値段が安ければぁ、いろいろな物に組込もうって思えるの
ですがぁ....ねぇ...。



リンク切れ見直し(*3) 2017/01/12
ライブラリとMPLAB X用に変更(*2) 2015/10/27
"skMonitorLCD.c"変更により"SR.c"のプログラム変更(*1) 2014/02/01


【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.