N.Yamazaki's blog

主に音声合成について思ったことを書いてみようと思います。
<< [Arduino] AquesTalk pico LSI を I2C で制御する | main | [AquesTalk pico LSI] ATP3011F4とATP3010F4の違い >>
[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.  <http://www.a-quest.com>
#include <SPI.h>
// pin10をSPIのスレーブセレクト端子(SS)とする 配線に応じて変更可
const int slaveSelectPin = 10;
// ローマ字音声記号列
//	 コマンドの最後のCR('¥r')を忘れずに
const char *TblKoe[] = {
"konnnichiwa¥r",
"yukkurisiteittene¥r",
"akuesuto-ku/pi'ko ba-jyonn <ALPHA =01a>.¥r",
"dennwaba'nngo-wa <NUM VAL=01-2345-6789>desu.¥r",
"<NUMK VAL=16 COUNTER=di>;<NUMK VAL=5 COUNTER=funn>/<NUMK VAL=35 COUNTER=byo->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
Follow
CATEGORIES
LATEST ENTRIES
SEARCH THIS SITE
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND
SONY MDR-CD900ST
SONY MDR-CD900ST (JUGEMレビュー »)

普段これで開発しています。
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND