N.Yamazaki's blog

主に音声合成について思ったことを書いてみようと思います。
音声テスターを作ってみた(その2 ソフト編)
音声テスターを作ってみた(その1 ハード編)のつづきです。
制御用マイコン(ATmega328P)にファームウェアを書き込んで動作させるまでの内容です。


Arduino UnoとAVRISP mkII

開発環境

必要なもの
統合開発環境は、ArduinoIDEでも作れますが、消費電力を下げるために動作クロックを1MHzにしたかったので、AVR Studio5.0で開発しました(Arduino環境ではフューズ設定を変えられない)。
ATmega328Pへのファーム書き込みは、上記写真にあるようなAVRISP mkIIとArduino Unoの組み合わせを使いました。この組み合わせはUSBで電源もとれるので便利です。
あと、何か動作に問題があった時用にオシロスコープはあったほうが良いです。というか無いとトラブルの解決は厳しいかと...

プログラム
TalkingTester.c  ←ダウンロードできます。

main()
起動音の出力後、約1秒間隔でテスターから値を取得して(72行)、AquesTalk Pico LSIに転送します(83行)。なお、前回と同じ値の場合は読み上げしません(82行)。また、テスターの応答がないなど何らかのエラーの場合は、パワーダウンします(89行)。

my_delay()
約1秒のディレイルーチンです。省電力化のためにウォッチドッグタイマーを利用してスリープ状態で待機します。

Init()
初期化ルーチンでは、UART、I2Cの周辺回路のパラメータを設定しています。

GetData()
テスターから測定値を読み込みます。任意の1バイトとして'¥r'をテスターに向けて送信します(158行)。その後、'¥r'が来るまでのバイト列を読み込みます(161行)。

Str2Cmd()
テスターの応答を、AquesTalk pico 用の音声記号列に変換しています。数値部分はNUMKタグを利用して数値を桁読みさせます(217行)。その後、単位を付与します(227行)。
なお、計測値がマイナスの時は先頭に"mainasu/"をつけます(214行)。例えば、"DC  3.306   V"という応答の場合には、"<NUMK VAL=3.306>bo'ruto" という文字列を生成します。

Speak()
音声記号列をAquesTalk picoに送信します。制御用マイコンとAquesTalk pico との通信にはI2Cを用います。送信に先立ち、Ready状態を示す'>'が返るかチェックし(251行)、'>'が返るのを確認してから、音声記号列を送信します(256行)。


ファームの書き込み
  1. Arduino UnoのAVRマイコンを今回ファームを書き込むマイコン差し替えます。
  2. Arduino Unoに、USBを接続して電源を供給(USBは、データ転送には使いません)。
  3. Arduino Unoに、AVRISP mkII を接続。
  4. プログラムをビルドして生成したHEXファイルをAVR Studioの"AVR Programming"で書き込み。
  5. フューズバイトを、次のように書き込み(内蔵RCクロック8MHz、8分周)。EXTENDED = 0xFF、HIGH = 0xD7、LOW = 0x62
  6. ファームを書き込んだAVRマイコンを音声テスターの基板に差し替えれば、完成!
          AVR studioの使い方や、細かい書き込み方法については割愛。


動作チェック
  1. テスターに接続しない状態で、電源(3V)を供給します。
  2. 「ポン! テスターの応答なし」と聞こえればOK。
  3. その後、テスターと接続し、テスターの電源をONにして
  4. 音声テスター基板のリセットボタンを押せば、順次測定値が読み上げられます。

音声テスター基板

ファームのプログラムを変更すれば、読み上げ間隔や、読み上げ条件(今回は前回と同じ値の場合は読みあげないようにした)、メッセージの内容などを好きなようにカスタマイズできますね。


LINK

  音声テスターを作ってみた(その1 ハード編)
  テスターMAS-345の通信仕様
  紹介動画 音声テスター youtube   ニコ動
  AquesTalk pico LSI ATP3011F4-PU

| AquesTalk pico LSI | 16:20 | - | - |
テスターMAS-345の通信仕様
音声テスター作成のために、秋月電子で入手したデジタルマルチメータ(テスター)「MAS-345」のRS232C通信部分を調査。



テスター写真

ハード



テスターの基板に書いてあったRS232C端子端子の名称です。




RS232C近辺の回路です。
端子はフォトカプラで絶縁されています。
RS232Cといっても出力電圧はホストのDTRとRTSの電位差から取っているようです。


インターフェース

data format: 7n2 at 600 baud (7 bits, no parity, 2 stop bits).
Control lines:
   DTR and RTS lines are used to power the TX line: RTS is clear
   for -12 supply; DTR is set for +12 supply. Data transmission is
   solicited sending whatever character to the RX line.
Data string format:
   MAS-345 sends a 14 bytes string with:
         <mode>< ><sign><value>< ><units><return>

     BYTE 1-2     : MEASURING MODE (ex;DC,AC,OH,CA,TE...)
     BYTE 3        : one space
     BYTE 4        : SIGN(-) or space
     BYTE 5-9    : Decimal point and value
              Current measurement value(ex;10.00, OL.,3.999)
     BYTE 10-13 : Unit (ex; mV,A,kOhm,nF...)
     BYTE 14      : Carriage Return '¥r'

   <mode>:  two bytes with the oerating mode: DC, AC, OH, CA, TE ...
   <sign>:  one byte with - or space
   <value>: five bytes with four digits and one decimal dot.(ex;10.00,  OL ,3.999)
   <units>: four bytes with the units: V,mV, A, kOhm, nF ...
   <return>: '¥r'
   One space is inserted between <mode> and <sign>, one between   <value> and <units>.
上は、ネットでみつけた情報です。テスター付属のCDにも情報があったけど、若干内容が違うようです。
600bpsの7bitノンパリティ、2ストップビットのUART通信となります。ホスト側から任意の内容の1バイトを送信すると、CRをデリミタとした1行(14byte固定)のASCIIテキストで、モードや測定値などを返す仕様になっています。


0123456789012
OH   O.L MOhm
OH  000.4 Ohm
OH  098.6kOhm
OH  0.032kOhm
OH  09.43kOhm
DC  3.306   V
DC  0.001   V
DC  05.05   V
DI  1624   mV
DI    OL   mV
TE -  OL    C
TE  0022    C
CA   .OL   nF
CA  137.4  nF
CA   .OL   nF
CA   OL.   nF
CA  000.8  nF
DC  015.5  mA
DC  000.0  mA
DC  0.051  mA
DC  0.974  mA
DC  001.0  mA
DC -00.00   A

これは、実際にテスターから返ってきた情報の例です。

あくまでも手元のテスターの1つでの調査なので、個体差があるかもしれません。
| その他 | 12:35 | - | - |
音声テスターを作ってみた(その1 ハード編)
デジタルマルチメータ(テスター)の計測数値を音声で読み上げるようにしてみました。
電圧を測る時に視線をテスターに移した途端、手元がズレてショートなんてことが防げるでしょう。




音声合成には AquesTalk pico LSI(ATP3011F4-PU)を使います。
初期版のATP3010F4でもセラロックなど外部クロックをつければOKです。
その他に制御用のマイコンが必要です。テスターからUARTで取り込んだASCIIテキストを、フォーマット変換してI2C通信でAquesTalk pico LSI に送るだけなので、このマイコンの選択はかなり自由です。今回はAVRマイコンのATmega328Pを用いましたが、かなりオーバースペックです(回路図ではATmega168になってます)。

回路図


とてもシンプルな回路です。オーディオアンプも簡易的なもの。
回路図上に16MHzのセラロックが2つありますが、今回はATmega328Pは内蔵RCクロックで動かし、また、ATP3011F4-PUは外付けクロック不要なので、実際には2つとも部品は載せていません。LEDは、動作確認用です。

基板
実装はユニバーサル基板でとも思ったのですが、以前から目をつけていたFusionPCBにPCB基板を注文してみました。5x5cmくらいのPCB10枚、送料込みで$14の破格!旧正月が挟まれたため納期は1ヶ月かかりましたが…




テスターは、秋月電子で購入したMAS-345です。
このテスター、RS232CでPCと接続できるものです。RS232Cといってもフォトカプラで構成され、電気的には絶縁されています。というわけでRS232Cというのは無視してマイコンのUARTのTXD/RXDを直接接続しました。なお、UARTとRS232Cの論理は反転しているので、この点は注意が必要です。
このテスターの通信仕様は後ほど別途記事にまとめておきます。


テスターとの接続コネクタには、かなり長いピンヘッダが必要です。
今回は手元にあったラッピング用ICソケットを使用しました。ラッピング、若い人は知らないだろうけど昔は結構お世話になりました。今でもラッピング用ICソケットは手に入るのか?このソケットの不要なピンをカットし、ブレッドボード用のジャンパーワイヤーを差し込みました。





電源はとりあえず3Vで動かしますが、電池が消耗してくると通信ができなくなる現象が起こりました。
テスター側の受信フォトカプラに流す電流が3Vではギリギリのようで、テスターの個体差で3Vでは動かないものもあるかもしれません。その時は、電源を4.5Vなどに高めに変更するか、テスターを改造する必要が有りそうです。テスターの改造は、内部のR57 3.3KΩを 300Ωくらいに小さくすればよいかと思います。


制御用マイコンのファームウェアは、また次回。

LINK
 音声テスターを作ってみた(その2 ソフト編)
 テスターMAS-345の通信仕様
 ATP3011F4-PU


2012/03/01 本記事のプリント基板(PCB)をプレゼント!
ご希望の方で、AQUEST OnlineStoreにてATP3011F4-PUを新規購入された、先着10名様にプレゼントします。
ご希望の方は、オンライン注文時の備考に「音声テスター基板希望」とお書きください。
ご注意:
基板に部品はついていません。先着とはお支払い手続き完了時を基準とし、銀行振込はプレゼントの対象外とさせて頂きます。また10枚無くなり次第終了し、特に当落の連絡はいたしませんので予めご了承ください。基板はATP3011F4-PUに同梱して発送します。基板に保証はありませんので使用前にパタンの導通チェックをお勧めします。
| AquesTalk pico LSI | 11:31 | - | - |
[AquesTalk pico LSI] ATP3011F4とATP3010F4の違い


ATP3011F4-PUは、音声合成LSI AquesTalk picoの新バージョンです。
ATP3010F4からの主な変更点は次のとおりです。

  • 電源電圧
    2.5Vから動作するようになりました。(ATP3010F4は3.8Vから)

  • クロック
    外付発振子から内蔵クロックにし、外付け部品をなくしました。

  • スリープ機能
    SLEEP端子をLOWにすることで待機時消費電流を1μA程度まで下げることができます。

なお、内蔵クロックの精度が良くないため、UARTのボーレートは自動調整となりました。
ボーレート設定には、通信に先立ち、ホストから'?'を送信する必要があります。ATP3010F4から置換の場合は、ご注意ください。
| AquesTalk pico LSI | 19:04 | - | - |
[Arduino] AquesTalk pico LSI を SPI で制御する
 音声合成LSI 「AquesTalk pico LSI」 (ATP3010F4/ATP3011F4)は、UARTの他にI2CやSPIのインターフェースを持っています。
一方、Arduino側のUARTは、PCとの通信で既に使われているので、ArduinoとAquesTalk pico LSI間の通信には、I2CやSPIを利用するのが便利です。
ココまでは、前回(I2C)と同じ。

今回は、SPIを使ってAquesTalk pico LSIを動かす方法を示します。

配線



通信モードをSPI(Mode0)にするため SMOD0(4pin), SMOD1(5pin)をGNDに接続、
ATP3010F4とArduinoのSPI接続は次のとおり。
SCK(19pin)   <-> D13
MISO(18pin) <-> D12
MOSI(17pin) <-> D11
/SS(16pin)    <-> D10

サンプルスケッチ

このスケッチは、予めプログラムに用意した複数のメッセージを順番に読み上げるものです。

注意点が3つあります。
1. スレーブセレクト(/SS)は、独自に実装する必要があります。
今回のスケッチでは、Arduinoのpin10をこれに割り当てて、転送の開始時にLowに、終了後にHiにするようにしています。

2. SPIのバイト転送毎に10μsec以上間隔をあける必要があります。これはATP3010F4の制限によるものです。

3. 発声の終了はポーリングで確認する必要があります。
ダミーデータ0xFFを送って'>'が返るのを待ちます。
なお、ポーリングの間隔は10ms以上あけてください。

aqtkpico_spi.ino ダウンロード (コピペは"¥”にゴミが入ることがあるのでソースはダウンロードがおすすめ)

/////////////////////////////////
// aqtkpico_spi - SPI通信で AquesTalk Pico LSIを操作するArdionoスケッチ
//	 
// by N.Yamazaki AQUEST Corp.  

#include 

// pin10をSPIのスレーブセレクト端子(SS)とする 配線に応じて変更可
const int slaveSelectPin = 10;

// ローマ字音声記号列
//	 コマンドの最後のCR('¥r')を忘れずに
const char *TblKoe[] = {
"konnnichiwa¥r",
"yukkurisiteittene¥r",
"akuesuto-ku/pi'ko ba-jyonn .¥r",
"dennwaba'nngo-wa desu.¥r",
";/desu.¥r",
"#J¥r", // チャイム音J
"#K¥r", // チャイム音K
};

void setup()
{
	// pin10を出力に設定
	pinMode (slaveSelectPin, OUTPUT);

	// SPIの初期化
	SPI.begin(); 
	SPI.setClockDivider(SPI_CLOCK_DIV16); // 最大クロックは1MHz(16MHz/16)
	SPI.setBitOrder(MSBFIRST);	// MSBファースト
	SPI.setDataMode(SPI_MODE0);	// SPIモード0	SMOD1:0 SMOD0:0
//	SPI.setDataMode(SPI_MODE3); // SPIモード3	SMOD1:0 SMOD0:1

	Serial.begin(9600);
}

void loop()
{
	int iret;
	for(int iMsg=0; iMsg< sizeof(TblKoe) / sizeof(char*); iMsg++){
		// Ready待ち
		iret = Pico_WaitReady();
		if(iret==0){
			Serial.print("OK¥n");
		}
		else { // Error
			Serial.print('E');
			Serial.print(iret);
			Serial.print('¥n');
		}

		// コマンド送出
		Pico_Synthe(TblKoe[iMsg]); 
	}
}

/////////////////////////////
// Picoにコマンド送信
// 音声合成開始	引数に音声記号列を指定
// コマンド送出後、発声の終了を待たずに戻る
void Pico_Synthe(const char *koe)
{
	// SS端子をLOWに
	digitalWrite(slaveSelectPin,LOW);

	const char *p = koe;
	for(;*p!=0;){
		Pico_SPI_trans(*p++);
	}

	// SS端子をHIに
	digitalWrite(slaveSelectPin,HIGH);
}

/////////////////////////////
// PicoがRedyになるのを待つ
// コマンドが受信可能な状態(音声合成の終了)になるのを待つ
// return 0:正常終了 それ以外:エラー(エラーコード)
int Pico_WaitReady()
{
	int iret=0;

	// SS端子をLOWに
	digitalWrite(slaveSelectPin,LOW);

	for(;;){
		byte c = Pico_SPI_trans(0xff); // 0xffはダミーデータ

		 //!!  '¥r'後の最初の応答は常に'*'になるという制約有り
		if(c=='>')	break;
		else if(c=='*' || c==0xff){
			// スレーブが処理中なのでしばらく放っておく
			delay(10);		// ポーリング間隔は10ms以上
		}
		else if(c=='E'){ // 何らかのエラーを返した
			char sErr[4];
			sErr[0] = Pico_SPI_trans(0xff);
			sErr[1] = Pico_SPI_trans(0xff);
			sErr[2] = Pico_SPI_trans(0xff);
			sErr[3]=0;
			iret = atoi(sErr);
		}
	}
 
	// SS端子をHIに
	digitalWrite(slaveSelectPin,HIGH);
	return iret;
}

/////////////////////////////
// SPI で1バイトの転送(双方向)
byte Pico_SPI_trans(byte c)
{
	delayMicroseconds(20);// バイト毎の転送間隔は10usec以上必要
	return SPI.transfer(c);
}



応用

ここでは、Arduino側の/SS端子をpin10にしましたが、他の端子でもかまいません。変更した場合は、スケッチの slaveSelectPin の値もそれに合わせて変更してください。

SPIのクロックは1MHz以下であれば良いので、スケッチの SPI_CLOCK_DIV16 SPI_CLOCK_DIV32 SPI_CLOCK_DIV64 にしても構いません。

SPIMode0
の代わりにSPIモード3を使う場合は、スケッチのSPI_MODE0SPI_MODE3に変更し、SMOD0端子はオープンにします。

| AquesTalk pico LSI | 16:06 | - | - |
PROFILE
CATEGORIES
SELECTED ENTRIES
LATEST ENTRIES
SEARCH THIS SITE
RECOMMEND
RECOMMEND
RECOMMEND
iOS4プログラミングブック
iOS4プログラミングブック (JUGEMレビュー »)
畑 圭輔,加藤 寛人,坂本 一樹,藤川 宏之,高橋 啓治郎,沖田 知彦,柳澤 昇
RECOMMEND
RECOMMEND
SONY MDR-CD900ST
SONY MDR-CD900ST (JUGEMレビュー »)

普段これで開発しています。
RECOMMEND
音声符号化
音声符号化 (JUGEMレビュー »)
守谷 健弘
CODECの本ですが、音声合成でも実用的なテクニックが満載
RECOMMEND
日本語 発音アクセント辞典
日本語 発音アクセント辞典 (JUGEMレビュー »)
NHK
辞典としてだけでなく、巻末のアクセントに関する解説が知識として役に立ちます。