N.Yamazaki's blog

主に音声合成について思ったことを書いてみようと思います。
M5Stackの音量を抵抗1つで調節する

keywords: M5Stack, Volume, 音量、スピーカー


 

■概要



M5Stackは、内蔵のオーディオアンプへの入力信号のレベルが大きすぎるため音が割れます。
一方、内蔵DACは量子化精度が8bitしかないので、ソフト的に音量を下げることは厳しいです。
今回は、1つの抵抗でM5Stackの音量を調整してみます。

 

 

■しくみ


 

DACの出力をGPIO26から出力し、抵抗を経て、GPIO25につながっているアンプに送る。

 

ESP32には2つのDACがあり、GPIO25とGPIO26にそれぞれつながっています。
M5Stackでは、DAC1(GPIO25)がアンプに接続されています。


ここで、DAC1を止めて、DAC2の出力をGPIO26から出し、抵抗で減衰させてGPIO25に戻せば、音量が調整できます。このときESP32のGPIO25はフローティング状態(電気的に絶縁)しておく必要があります。

 

上の動画では、10kΩと22KΩで切り替えています。10KΩの場合は、そのまま出力した場合とほとんど音量が変わらず、22KΩの場合は、約16dB(1/6)小さくなりました。

 

■プログラム



ベースはM5Stackのspeakerサンプルプログラムです。関数playMusicVolume()は、M5StackのライブラリのSpeaker.cから起動音の再生ルーチンを抜き出し、以下を修正したものです。


・最初にGPIO25を入力に設定する関数を呼び出す
・DACへの出力はDAC1からDAC2(GPIO26)に変更

 

// M5_volume.ino - M5Stack volume control
#include <M5Stack.h>
void setup() {
// Initialize the M5Stack object
M5.begin();
M5.Lcd.printf("M5Stack Speaker test:¥r¥n");
M5.Speaker.setVolume(8);
M5.Speaker.playMusic(m5stack_startup_music, 25000);
}
void loop() {
if(M5.BtnA.wasPressed()) {
M5.Lcd.printf("wasPressed A ¥r¥n");
playMusicVolume(m5stack_startup_music, 25000); //play the M5Stack startup sound
}
if(M5.BtnB.wasPressed())
{
M5.Lcd.printf("wasPressed B ¥r¥n");
M5.Speaker.tone(3000, 200); //frequency 3000, with a duration of 200ms
}
if(M5.BtnC.wasPressed())
{
M5.Lcd.printf("wasPressed C ¥r¥n");
M5.Speaker.setVolume(10);	// max
M5.Speaker.playMusic(m5stack_startup_music, 25000); //play the M5Stack startup sound
}
M5.update();
}
void playMusicVolume(const uint8_t* music_data, uint16_t sample_rate) 
{
// disconnect PWM & input on GPIO25
ledcDetachPin(SPEAKER_PIN);
pinMode(SPEAKER_PIN, INPUT);
uint32_t length = strlen((char*)music_data);
uint16_t delay_interval = ((uint32_t)1000000/sample_rate);
for(int i=0; i<length; i++) {
dacWrite(GPIO_NUM_26, music_data[i]);
delayMicroseconds(delay_interval);
}
for(int t=music_data[length-1]; t>=0; t--) {
dacWrite(GPIO_NUM_26, t);
delay(2);
}
ledcAttachPin(SPEAKER_PIN, TONE_PIN_CHANNEL);
}

 

■GPIO25がOFFにならない!?



アンプの入力インピーダンスが28KΩ(typ)なので、ESP32側のGPIO25が完全に切り離されているなら、22KΩでも半分程度の減衰になるはずです。しかし、実際は1/6。


ESP32側のGPIO25のGND間の内部抵抗が、なぜか10KΩ程度とかなり低くなっていました。オープンドレイン出力なども試したのですが、フローティング状態にできませんでした。なにか方法をご存知でしたらコメントください。

 


M5Stackはアンプとスピーカーを内蔵していますが、今のままではあまりにもったいない。
音が歪まないように改良して欲しいところです。
 

| 電子工作 | 18:05 | comments(3) | - |
ESP32のPDMでサウンド出力+ノイズ対策

keywords: ESP32、PDM、オーディオ、音声

 

■概要


 

ESP32は、PDM(Pulse-density modulation)の変調器を内蔵しています。
前の記事では内蔵DACでしたが、今回はこのPDMで音を出してみます。

PDMは1bitのデジタル信号ですが、パルスの密度がアナログ信号の振幅に直接対応しているので、アナログアンプに直に与えても鳴ります(アンプ自体がLPFの役割を担っているため)。

今回の実験は、ESP32-DevCとM5Stackで行ないました。


 

 

■崩れたPDM波形!?


 

最初のPDM出力波形はこんなでした。

 

 

波形がひどく崩れています。
立ち上がりは急峻で良いのですが、立下りが指数的に下がっていて、これでは、まともな音は出ません。

ネットでも同様の現象が報告されていたので、そんなものなのかと一時は諦めましたが・・・

 

実は、なんてことはない、単純なミスでした。
内蔵DAC用のコードを改良して使っていたため、出力ピンの指定を忘れていました。
i2s_set_pin()でこれを指定すれば、下のきれいな矩形のPDM信号が得られるようになりました。

 

 

 

 

■無音の再生時のノイズ



ゼロの値を連続して出力すると、ピーという周期性のノイズが現れます。
このノイズ、常に同じ高さでなく毎回違った高さの音が出ます。
どうも、前に出力した波形データに影響しているようです。

 

ESP32のデータシートをみると、PDMの処理は次の図で示されています。

これだけでは、実際どんな処理が行われているのか把握できませんが、
このPDM処理の部分で周期性ノイズが発生していることには間違いありません。

 

(ESP32 Technical Reference Manualより)

 

 

このノイズ対策には、ディザを加えれば良いようです。
ゼロの値を連続する代わりに、例えば、0,1,0,1,...とすることで、この周期性ノイズはなくなります。
ホワイトノイズは残りますが、これは信号出力時の背景ノイズと同じ大きさなので、我慢するしかないでしょう。
後述のプログラムでは、再生する信号にもディザを加えています。合成音声や小さい音などで量子化誤差がランダムでなくなる信号に対しても周期的ノイズを削減する効果が得られます。

 

 

■クリックノイズ対策



PDMの停止中の出力は0Vの状態が続くため、PDMの開始と終了時にクリックノイズが発生します。
DAC出力のときに行ったように、開始時には0VからVDD/2まで、終了時はその逆のVDD/2から0Vまでのスロープ状に値を変化させることでクリックノイズを削減できます。

 

ただ、PDMではスロープ状の値をデータとして指定しても、その出力はスロープ状になりません。先に示したようにPDMの変調器にはHPFやLPF、アップサンプリングが使われているので、DACの場合と異なり、入力の値がそのままストレートに出力されません。

 

そこで、PDMでスロープを表現するのはあきらめ、この部分は内蔵DACを用いることにします。
同じピンにDACとPDMの出力を割り当て、開始時には、内蔵DACで0からVDD/2[V]でスロープを出力した後、PDMに切り替えます。終了時はその逆です。

 

 

■サンプルプログラム



上で検討したことを盛り込んだ、PDMでサウンド/オーディオ/音声出力するライブラリ(ソースプログラム)を公開します。サンプルプログラムは、上の動画で使ったものです。

 

ダウンロード    TestPDM.zip (TestPDM.ino, PDMout.c, PDMout.h, magic07.h)

 

関数は以下の通りです。

 

  • PDMOut_create(): DACにより出力を0VからVDD/2までスロープさせる。
  • PDMOut_release(): DACにより出力をVDD/2から0Vまでスロープさせる。
  • PDMOut_start(): PDMの初期化後、出力をDACからPDMに切り替える。
  • PDMOut_stop(): PDMを停止し、DACに切り替える(VDD/2を維持)。
  • PDMOut_write(): 引数に1サンプルのデータを指定し、I2Sに送る。PDM変調器にはI2SのDMAで送られる。
  • PDMOut_clear(): I2SのDMAバッファをすべてクリア

内蔵DACも使っているので、出力ピンはGPIO25かGPIO26のいずれかになります。

 

write()のPCMデータは符号付き16bitです。内蔵DACのときは符号無しなので注意してください。

 

PDM変調器のほかに内蔵DACも使用しているので、本プログラムを動かした後はこれらのペリフェラルの状態が使用前と異なる可能性があります。M5Stackでは、PDM出力の終了後にM5.Speaker.tone()関数で音が出なくなりました。M5.begin()での内部状態が変わるためです。これについては、次の関数を呼び出せば、再び出るようになります。

(M5.begin()でGPIO25にPWMを繋げた状態にしているのは、今後変更されるかもしれません)

   ledcAttachPin(SPEAKER_PIN, TONE_PIN_CHANNEL);

 

 

■PDMでステレオ



ここで扱っているのはモノラルの信号ですが、pin_configの指定でPDMのクロックを出力し、i2s_push_sample()でLR別々の値を指定すればステレオのPDMを出力できます。
ただ、PDMのフォーマットでは1つのデータラインで左右の信号が交互に入るので、今回のようにPDM出力を直にアナログ信号として利用する方法ではステレオ化できません。
PDMのデジタルデータに対応したアンプ(MAX98356やSSM2537など)を使う必要があります。

 

 

■PDMは内蔵の8bitDACより量子化精度が高い?



信号を1/2づつ小さくしながら、どこまで聞こえるか試してみました。その結果、PDMの量子化は10bit以上あるようです。
ただ、S/N比(ピーク信号対雑音比)を測定してみると(FS:24KHz, 1023Hzのsin波、最大振幅)、49dBとなり、8bitDACと同等となりました。

 


■M5Stackで使う場合



現在のM5Stackは、アンプに入力する信号レベルが大きすぎて音割れが酷いです。PDMの場合も同じように音が割れます。
PDMの出力にLPFを通した波形のpeak-to-peakの最大振幅は約3.3Vで、DACとほとんど変わりません。

M5Stackで使用しているアンプ(NS4148)にPDMのデジタル信号を直接与えた場合、アンプ自体のLPF特性を利用して鳴るのですが、振幅が3.3Vのパルス信号を与えるのはかなり無理があるようです。特に音量が小さくなると、ノイズが絶対的に大きくなるようです。


試しに、PDM出力を1次のLPFを通してアナログ値にし、抵抗の分圧でゲインを下げててからアンプに入れたら、ずいぶん良くなりましたが・・・

 

 

■さいごに



量子化ビット数は10bit程度ありますが、S/N比が8bitDACと同じのため、音質の差はほどんどありません。
外付けLPFが必要なことを考えると、DACの代わりにPDMを使用するメリットは無さそうです。とほほ・・・

 

 

■リンク



・  前の記事「ESP32でサウンド出力時のクリックノイズ対策(I2S+内蔵DAC)

・  ESP32のデータシート
・  M5Stackのオーディオアンプ「NS4148
 

 

| 電子工作 | 15:04 | - | - |
ESP32でサウンド出力時のクリックノイズ対策(I2S+内蔵DAC)

keywords: ESP32, サウンド, DAC, I2S

 

■概要



ESP32の内蔵DACから音を出すとき、前後のプチプチというノイズが気になってので、これを防ぐ方法を検討してみました。

 

 

■クリックノイズの原因


 

ESP-IDFのI2Sドライバは無音時の値を0としている。
内蔵DACにおける値0は負の最大値である。

 

通常I2Sの16bitデータは符号付き(無音時の値が0、最小が-32768、最大が32767)で表現します(図1-A)。ESP-IDFのI2Sドライバも、その前提で書かれています。
しかし、内蔵DACは0Vから3.3Vの範囲を16bitの符号無し整数(0から65535)で指定します。
そのため、音声信号では無音時の値を32768、負の最大値を0、正の最大値を65535になるように変換して与える必要があります。

 

ESP-IDFのI2Sドライバは無音時の値が0という前提で書かれていますので、初期状態や動作の開始・終了の状態の変化のときに、この値0を出力することがあります。これは内蔵DACからみれば負の最大値であり、これがクリックノイズの原因です(図1-B)。

 

Waves

図1

 


■対策


 

図1-Cのように、再生の前後の立ち上がりと立下りを滑らかにします。

 

 

■Tips <ここが本記事のメイン



・立ち上がり、立下りは値を256づつ直線的に変化させる

このとき、より滑らかにしようと傾きを緩やかにするのはNGです。
内蔵DACの分解能が8bitしかないので(下位8bitは切り捨てられる)、同じ値が繰り返されるとステップノイズの基本周波数が低くなり、余計にノイズが目立つようになります。

 

・i2s_start()直後は、DMAバッファ1つ分のダミーを出力する

タイミングによりますが、先頭のデータが抜けることがあるために必要です。

 

・i2s_stop()の前に、DMAバッファすべてを0で埋める

再びi2s_start()で再開したときに異音が出ないようにするためです。

 

・i2s_stop()は、DMAバッファすべてとFIFOの長さの値を書き込んでから呼び出す

出力されるタイミングは値を書き込んだ時ではなく、実際はDMAバッファとI2S内のFIFOバッファ分の遅延があります(I2S内には32bitx64のFIFOがあります)。完全に立ち下がってからi2s_stop()を呼び出す必要があります。

 

・i2s_start()の操作で値0が一瞬出力されてしまう

たとえDMAバッファをすべて中間値(32768)で埋めても、値0が瞬間的に出てしまいます。そのため、停止時に中間値で維持する方法は使えません。

 

・DMAバッファを32768で埋めてi2sを止めない方法

この方法はありですが、音を出さないときにもI2Sを動してると、M5Stackでノイズが気になりました。

 

 ※現時点(2018/03/27)のESP-IDFなので今後動作が変わるかもしれません。

 


■サンプルプログラム


 

クリックノイズの対策を行ったサンプルプログラムを公開します。
正弦波のデータを4回に分けて出力しています。

 

・「TestClickNoise.ino
 

・「TestClickNoiseBef.ino」(クリックノイズ対策無し。比較用)

 


■リンク


 

 次の記事「ESP32のPDMでサウンド出力+ノイズ対策」

    http://blog-yama.a-quest.com/?eid=970192

 

「EPS-IDF Programming Guide -I2S」
     http://esp-idf.readthedocs.io/en/latest/api-reference/peripherals/i2s.html

 

「ESP-IDFのI2Sドライバソース i2s.c]
    https://github.com/espressif/esp-idf/blob/master/components/driver/i2s.c

 

「ESP32 Technical Reference Manual」    https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf

 

「ESP32で音声合成(AquesTalk pico for ESP32)」
    http://blog-yama.a-quest.com/?eid=970188

 

| 電子工作 | 23:19 | - | - |
ミルエネのUSBドングルでスマートメーターからリアルタイムに消費電力を取得する

Keywords: Wi-SUN, HEMS, スマートメーター, ECHONET Lite

 

■概要
USBドングル「UDG-1-WSNE」を使って、スマートメーター(電力量計)から瞬時電力を習得・蓄積し、現在の消費電力などをグラフと共に表示する表示するシステムを作りました。このモニター端末をリビングに常設し、電気の「見える化」を実現。

 

表示画面

monotor-sample

スマートメーターとの接続には、920MHz帯のWi-SUN規格の無線通信で行いますので、Wi-SUN通信のハードウェアが必要です。
このWi-SUN通信デバイスとしては ROHM の BP35A1 を使った例はありますが、今回はUSBドングル「UDG-1-WSNE」を使用しましたので、はんだ付けなどの電子工作は一切ありません。
なお、この記事では、このUSBドングルを使うときの注意点のみ詳しく記述します。


■システム構成
ハードウェア

hardware
スマートメーターは、電力会社が無料で設置してくれます。スマートメータにアクセスするためのIDやパスワードの取得に、Bルートサービスの利用申し込みが必要です。

 

USBドングル「UDG-1-WSNE」は、NTT東日本の「フレッツ・ミルエネ」サービスを申し込んだときに購入しました(¥5,400)。

サーバーは何でも良いのですが、我が家では既にサーバーとして使っていたWindowsのPCを使いました。USBドングルのデバイスドライバが入れられれば、Raspberry Pi等のLinux環境でも構築できそうです。

 

表示部分は、任意のWebブラウザでOK。今回は常時表示したかったので格安の中華タブレットを購入。なお、VPNを使えば外出先から手持ちのスマホでも見れます。

 

ソフトウェア

software

毎分瞬時電力と積算電力量をファイルに書き込む「データ取得プログラム」と、そのファイル情報をグラフ等に整形してHTTP出力する「表示プログラム」の2つから構成されます。

 

データ取得プログラム

- 機能は、毎分0秒に瞬時電力と積算電力量をスマートメーターから取得し、日時と共にファイルに追加書き込む。
- プログラム側からはUSBドングルはシリアルCOMポートとして見える。
- 通信プロトコルはスカイリー・ネットワークス社のSK STACK。
- 瞬時電力等の各種情報取得にはECHONET_Liteのフォーマット。
- 今回はC++で書いたコンソールアプリ(.exe)を作って常時起動。

 

表示プログラム

- 規定のURLにアクセスすると、グラフや各種消費電力を表示し、毎分30秒になると表示を自動更新。
- WebサーバーにはIISを用い、ファイルの情報を表示用に変換する部分はPHPで記述。

 

現在、我が家では次のような項目を表示しています。

- 現在の消費電力
- 待機電力
- 今日これまでの電力量
- 分単位の消費電力グラフ
- 毎時の電力量と累積のグラフ
- 過去30日の積算電力量

 

■UDG-1-WSNEのデバイスドライバ
このUSBドングルをWindows PC(Windows7 64bit)に挿しただけでは、不明のデバイスとなりました。
「UDG-1-WSNE」のドライバーは探しても見つからなかったので、デバイス名称「USB-UART LP」からCypressのチップと想定し、CypressのUSB-SerialドライバーのPIDを以下の方法で偽装してインストールしました。

 

1.    http://www.cypress.com/sdc から USB-Serial Driver Installer - Windowsをダウンロード(アカウントが必要)
2.    ダウンロードした CypressDriverInstaller_1.exe  を実行すると以下のフォルダに展開される。
        C:¥Program Files (x86)¥Cypress¥Cypress USB-Serial Driver¥DriverBinary¥
3.    この中のCDC_Driver¥bin¥win7¥x64フォルダを任意の場所にコピー(使用するOSに応じたものを選択)
4.    CypressUsbAndBus.inf をエディタで開く。
5.    [Cypress.NTamd64]の項目に次の行を追加
        %USB¥VID_0409&PID_04C7&MI_00.Desc% = CypressUsb.NTamd64, USB¥VID_0409&PID_04C7&MI_00
6.    [Strings]の項目に次の行を追加
        USB¥VID_0409&PID_04C7&MI_00.Desc="UDG-1-WSNE CypressUsb"
7.    同様に CypressSerial.inf をエディタで開く。
8.    [Cypress.NTamd64]の項目に次の行を追加
        %CypressSerial% = CypressSerial.NTamd64,Ports¥VID_0409&PID_04C7&MI_00
9.    [Strings]の項目に次の行を追加
        CypressSerial = "UDG-1-WSNE USB Serial Port"
10.    CypressUsbAndBus.inf(USBのドライバ)、CypressSerial.inf(仮想COMポート)の順序でインストール。

 

ドライバーのインストール後、115200bps/8bit/none-parity/1stop-bit/none-flow-control のパラメータでシリアル通信が出来るようになりました。

 

■通信シーケンス
以下に、瞬時電力と積算電力量を取得したときのシリアル通信の送受信内容を示します。
コマンド体系はBP35A1と同じSK STACK IPですが、バージョンが異なるため、BP35A1と比べて使えるコマンドが少なく、フォーマットも微妙に異なっているので注意が必要です。[BINARY:XX XX...]の部分は、ASCIIでなく8bitバイナリ列として送信します。送信はバイナリで受信は16進ASCIIって仕様はちょっと違和感ありますね。なお、送信時の改行コードはCRLFです。

積算電力量は、正しくは補正係数や単位も都度取得して求めるべきですが、今回は固定としました。補正係数と単位を別途取得したところ、私の場合は積算電力量計測値(EPC:E0)の単位は0.1KWhでした。

 

SKSETPWD C  XXXXXXXXXXX ←Bルートのパスワード
OK
SKSETRBID XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ←BルートのID
OK
SKSCAN 2 FFFFFFFF 6 0 ←フォーマット注意
OK
EVENT 20 FE80:0000:0000:0000:YYYY:YYYY:YYYY:YYYY 0
EPANDESC
Channel:2F
Channel Page:09
Pan ID:XXXX
Addr:ZZZZZZZZZZZZZZZZ
LQI:7D
Side:0
PairID:XXXXXXXX
EVENT 22 FE80:0000:0000:0000:YYYY:YYYY:YYYY:YYYY 0
SKSREG S2 2F  ←上のChannelを指定
OK
SKSREG S3 XXXX  ←上のPan IDを指定
OK
SKLL64 ZZZZZZZZZZZZZZZZ    ←上のAddrを指定
FE80:0000:0000:0000:XXXX:XXXX:XXXX:XXXX ←スマートメーターのIPアドレス取得
SKJOIN FE80:0000:0000:0000:XXXX:XXXX:XXXX:XXXX ←スマートメーターのIPアドレス設定
OK
EVENT 21 FE80:0000:0000:0000:XXXX:XXXX:XXXX:XXXX 0 00
〜中略〜
EVENT 25 FE80:0000:0000:0000:XXXX:XXXX:XXXX:XXXX 0
ERXUDP FE80:0000:0000:0000:XXXX:XXXX:XXXX:XXXX FF02:0000:0000:0000:0000:0000:0000:0001 0E1A 0E1A ZZZZZZZZZZZZZZZZ 1 0 0012 108100000EF0010EF0017301D50401028801 ←node start時の基本シーケンス
SKSENDTO 1 FE80:0000:0000:0000:XXXX:XXXX:XXXX:XXXX 0E1A 1 0 000E [BINARY:10 81 00 01 05 FF 01 02 88 01 62 01 E7 00] ←E7:瞬時電力計測値 フォーマット注意
ERXUDP FE80:0000:0000:0000:XXXX:XXXX:XXXX:XXXX FE80:0000:0000:0000:YYYY:YYYY:YYYY:YYYY 0E1A 0E1A ZZZZZZZZZZZZZZZZ 1 0 0026 1081000102880105FF017302EA0B07R0031F0B000000000E7DEB0B07E0031F0B00000000001B
EVENT 21 FE80:0000:0000:0000:YYYY:YYYY:YYYY:YYYY 0 00
OK
ERXUDP FE80:0000:0000:0000:XXXX:XXXX:XXXX:XXXX FE80:0000:0000:0000:YYYY:YYYY:YYYY:YYYY 0E1A 0E1A ZZZZZZZZZZZZZZZZ 1 0 0012 1081000102880105FF017201E70400000195	←最後の195が16進の瞬時電力計測値(W)
SKSENDTO 1 FE80:0000:0000:0000:XXXX:XXXX:XXXX:XXXX 0E1A 1 0 000E [BINARY:10 81 00 01 05 FF 01 02 88 01 62 01 E0 00] ←E0:積算電力量計測値 フォーマット注意
EVENT 21 FE80:0000:0000:0000:XXXX:XXXX:XXXX:XXXX 0 00
OK
ERXUDP FE80:0000:0000:0000:XXXX:XXXX:XXXX:XXXX FE80:0000:0000:0000:YYYY:YYYY:YYYY:YYYY 0E1A 0E1A ZZZZZZZZZZZZZZZZ 1 0 0012 1081000102880105FF017201E00400000EB9 ←最後のEB9が16進の積算電力量計測値(100Wh)

 

■リトライは必須
無線を使ったシステムなので、通信プロトコルの途中でタイムアウトやエラーが生じます。データ取得プログラムでは、エラー時のリトライの回数や待ち時間、エラー時にプロトコルのどこから再開するかなど、多くの工夫が必要です。これまで数ヶ月運用して、週一程度の頻度で10分程度取得できなくないことがありますが、いまのところ連続運用しています。


■参考リンク

 

 

■あとがき
消費電力の「リアルタイムな見える化」は想像以上に面白いです。グラフから冷蔵庫の消費電力の時間パタンなどもわかるようになります。今はスマートメーターとの接続だけですが、今後HEMS家電を購入したら、これらもすぐに応用できそう。高価で融通のきかないHEMSモニター機器を購入しなくても、自由に好みに合わせた情報を表示・利用できるのが自作のよいところですね。


 

| 電子工作 | 13:50 | - | - |
UDG-1-WSNEを調査
WSR35A1-00や、BP35A1にUSB-Serialに類似のもの。



メーカー:NEC
電波の型式、周波数及び空中線電力: F1D 922.5〜927.9MHz(200kHz間隔28波) 0.02W
総務省HPより

ドライバー: 
Cypress USB-Serial Driver
CypressUsbAndBus.inf、CypressSerial.infの2つとも
VID/PIDは書き換え必須 VID_0409&PID_04C7&MI_00

COM:
115200bps、8bit, non-parity, 1stop-bit, no-flow

コマンド:
SK STACK IP Ver.1.0 
Ver.2と比べると、使えるコマンドが限られている。また一部のコマンドと応答が1項目(1カラム)増えてる。


Keywords:
Wi-SUN, HEMS, スマートメーター, ECHONET Lite
| 電子工作 | 14:11 | - | - |
Atmel純正コマンドライン型の書き込みツール atprogram.exe の紹介

AVRマイコンの書き込みツールとしては、Atmel Studioといった統合プログラムを使えばよいのすが、大量に書き込む場合は、GUIよりコマンドラインのほうが便利です。バッチプログラムでも使えますしね。

今まで、STK500.exe(これもAtmel純正)を使っていたのですが、昨今のAtmel Studioには含まれていないし、自分の環境で最近なぜか使えなくなった("could not connect to AVRISP mkII on USB"というエラーでAVRISP mkIIが認識されない)ため、他の方法を探すことになりました。
他にも有名どころでavrdudeもありますが、今回はAtmel Studioに付属している純正のツールatprogram.exeを紹介します。

■atprogram.exeとは
AVRマイコンなどのAtmel製マイコンに書き込むためのコマンドラインプログラムです。もちろん、実際に書き込むにはAVRISP mkIIなどの書き込み器(ハードウェア)も必要です。

以下の機能があります。必要十分な機能は揃ってます。

  • .bin .hex .elfファイルの書き込み
  • 内蔵flashの読みこみ, 書き込み, 消去
  • フューズ、ロックビット、セキュリティビット、ユーザーページ、ユーザーシグネチャの書き込み
  • 接続している書き込み器の一覧出力
  • 書き込み器とのインターフェースの選択やクロックの設定


■インストール
Atmel Studioをインストールすれば、含まれています。
AtmelStudio7.0の標準的なインストールでは、次のところにありました。

C:¥Program Files (x86)¥Atmel¥Studio¥7.0¥atbackend¥atprogram.exe


■使用方法
例えば、Arduino Unoでも使われているatmega328pに書き込む場合、次のようにします。

>atprogram -t avrispmk2 -i ISP -d atmega328p program -f hoge.hex


フューズやロックビットを書き込むときは

>atprogram -t avrispmk2 -i ISP -d atmega328p write -fs --values FFD7FF write -lb --values FC

ちなみに、フューズはLow,High,Exの順です(atmega328pの場合)。
次のように複数のコマンドを並べて一括処理することもできます。

>atprogram -t avrispmk2 -i ISP -d atmega328p program -f hoge.hex program -ee -f hoge_eeprom.hex write -fs --values FFD7FF write -lb --values FC


より詳しい使い方は、コマンドのヘルプを参照します。コマンドの一覧は次で表示されます。ちなみに、atprogramのマニュアルを探したのですが、見つかりませんでした。

>atprogram -?


これはすべてのコマンドではなく、より詳しく知るにはhelpコマンドを使います。
例えば、書き込みのコマンド詳細は次で表示されます。

>atprogram help write


以上、atprogram.exeを簡単に紹介しました。avrdudeなどに比べてまだ知名度の低いツールですが、純正のツールは安心感がありますね。
 

■ 追記 (2017/4)
昨年、AVRのプログラマ(書込み器) AVRISPmk2が販売終了になってしまいました。頑健で信頼でき、もちろん純正なのでAtmelStudioとも相性がよかったので残念です。

 

今後は、Atmel純正としてデバッガ機能も付いた Atmel-ICE というものが後継になるのでしょうが、価格は数倍になりました。
もし、書込みだけで良いという場合には、 Pololu USB AVR Programmer v2 がお勧めです。

 

これを atprogram.exe で使用する場合には、コマンドラインオプションの -t avrispmk2 の部分を

-t stk500 -c com5 のように変更するだけで使用できます("com5" の部分は、デバイスマネージャー等で該当のCOMポート番号を調べて適宜指定)。
ターゲットの電圧測定など、AVRISPmk2にあった機能も揃ってます。

| 電子工作 | 09:03 | - | - |
給湯器リモコンに音声合成メッセージをつけてみた
「家電を改造しオリジナル音声メッセージをつける」プロジェクト第2弾です。前回は電子レンジでしたが、今回のターゲットは給湯器のリモコンです。"しゃべる給湯器"は最近では珍しくないですが、ウチのは古くてしゃべりません。そこで改造です!
今回は、圧電サウンダの駆動信号を取り出しその鳴動パタンを認識して、パタンに応じて異なる音声メッセージを出力することに加え、給湯器の点火状態を示すLEDの駆動信号を取り出して、燃焼を告げるメッセージも出力します。



■改造
予めブザー音を録音して鳴動パタンを調査したところ、今回用いた機種では以下のパタンとなりました。

Beepパタン

ブザー音を出力する圧電サウンダの回路とLEDを駆動する回路はおよそ以下のようになっています。
今回もそれぞれ5V系で動作しているICの出力から信号を取り出しています。

BEEP回路図

今回も、音声合成部は、試作で作った小型音声合成モジュールにビープパタンを認識するファームを追加することで実現しています。

VoiceModule

これを、基板の空きスペースにスピーカーと共に実装しました。

基板実装1
基板実装2


■電源について
この給湯リモコンは親機からの15Vを78LR05というレギュレーターで5Vを作っています。
このデバイスは5V系の電流が設計以上流れて電源電圧が下がるとマイコンにリセット信号が送られる機能があります。 給湯器ならではのフェイルセーフの設計だと思います。
そのためココは音声合成モジュールの電源容量が足りないので、写真には写っていませんが、3端子レギュレーターを別途使って15V系から音声合成モジュールの電源を作ってます。

■あとがき
給湯器の電源って、ついつい入れっぱなしにしちゃいますよね。
で、ちょっと手を洗うときなど、お湯が出始めないうちに終わってしまう使い方って多いじゃないですか。
そんなちょっとした時間でも給湯器は燃焼するので、まずエコでないし、給湯器の寿命をどんどん縮めてると思うんです。
てなわけで、音声メッセージをつけたら、酷使されてる給湯器の気持ち少しは意識できるかな?ってのが、今回の改造のきっかけでありました。

次なるターゲットは、"ビルトインガスコンロ"。頻繁にピーピーなってるのを何とかしようかと。
でも、ちょっと見た限りでは分解するのが大変そうで、断念の予感も・・・。

なお、市販製品の改造はリスクを伴いますのですべて自己責任です。念のため・・・

■リンク
| 電子工作 | 10:26 | - | - |
電子レンジに音声合成メッセージをつけてみた
ブザー音だけの電子レンジを、音声合成でメッセージ出力するように改造してみました。
圧電サウンダの駆動信号を取り出し、その鳴動パタンを認識して、パタンに応じて異なる音声メッセージを出力しています。




■仕組み
予めレンジを動かしてそのBEEPパタンを調査したところ、今回用いた機種では以下のパタンとなりました。

beep_pattern

ブザー音を出力する圧電サウンダの回路は大体以下のようになっています。
今回はICの出力から信号を取り出すことにしました。

beep_logic

音声合成部は、試作で作った超小型音声合成モジュールにビープパタンを認識するファームを追加することで実現しています。 一般的には、AquesTalk pico 音声合成LSIとコントローラ用のCPUを組み合わせて作ることになるかな。

AquesTalk VoiceModule

このモジュールを電子レンジの基板の空きスペースに実装しました。配線は電源と信号線とスピーカーの計5本のみ。スピーカーを筐体側にしっかりと取り付けて完成!

ne-c236


■あとがき
少し前に「世界最小(?)2.5Wアンプ付音声合成モジュール」というのを試作しました。
しかし、もっと良いアイデアが出てきたため、この企画は中断。
そこで、この余った試作品を有効活用するため電子レンジに応用した次第です。
特に便利になるような実用的な改造ではないですが、遊びに来たお客さんへのちょっとしたネタになれば良いかな。

なお、市販製品の改造はリスクを伴いますのですべて自己責任です。念のため・・・
 
| 電子工作 | 20:12 | - | - |
音声合成LSIで「オリジナルの音声時計」を作ろう!- その4 カスタマイズ編
前回、基本スケッチでハードウェアとソフトウェアの動作確認を行いました。あとは、オリジナル音声時計にするためのカスタマイズ・改良を行って完成です。

■スケッチをカスタマイズしよう
ソフト的なカスタマイズは、前の記事で使用した基本スケッチ(YukkuriClock2.ino)をベースに、このファイルを編集して行います。

基本スケッチでのメモリ容量は、チップの容量のROM:19%、RAM:23%でしたので、まだまだカスタマイズ・機能拡張の余地がありますね。ただ、注意すべき点は、メッセージの音声記号列をRAMに配置してしまうとあっという間にRAMが足りなくなりますので、文字列はROMに配置されるようメッセージのPSTR指定は必須です(ヒントは PROGMEM/ハーバードアーキテクチャー)

スケッチをカスタマイズしたら、ATmega328PをArduino Unoに挿して、以下の操作でカスタマイズしたスケッチを書き込めばOKです。
  1.     メニュー:ツール > ボード > Arduino Uno
  2.     メニュー:ファイル > マイコンボードに書き込む

以下に、具体的なスケッチの変更方法を示します。

・記念日と、そのメッセージを変更するには
基本スケッチでは2月11日と3月14日にメッセージを発声するようにしていますので、月日とメッセージを任意に書き換えます。 記念日は、ソースコードを並べればいくつでも増やせます。

なお、dayLast変数に発声日を保存することで、その日の最初に一回だけ発声するようにしています。
// 記念日のメッセージ発声
void MessageKinenbi(const AQ_DATE_TIME &dt)
{
  static uint8_t dayLast = 0;   // 同日の発声は1回のみにするため、発声日を保存
  if (dt.d != dayLast) {
    // 誕生日
    if (dt.m == 2 && dt.d == 11) {      // 2月11日
      TalkP(PSTR("otannjo-'bi,omedetoo'")); //「お誕生日おめでとう」
    }
    // 結婚記念日
    else if (dt.m == 3 && dt.d == 14) { // 3月14日
      TalkP(PSTR("kyo'-wa kekkonnkinenn'bi")); //「今日は、結婚記念日」
    }
    // ... 必要に応じて追加
    dayLast = dt.d;
  }
}
yukkuriclock2.ino:MessageKinenbi()

メッセージは、音声記号列で指定します。ローマ字のようですが、少しでも間違っているとエラーになり発声しませんので、別途、アクエストのサイトのデモページで確認することをおすすめします。このサイトでは漢字テキストから音声記号列を生成できますし・・・。また、「AquesTalk pico LSI」ATP3011XXのデータシートにこの音声記号の仕様があるので、一度目を通しておくとよいでしょう。

・曜日毎のメッセージを変更するには
MessageWeek()関数で、曜日毎のメッセージを記述しています。ここでも、その日に一度だけ発声するようにしています。 先の記念日と違う部分は、発声時間を限定している点です。基本スケッチではゴミ収集のメッセージなので夜は発声させません。 このような条件もメッセージに合わせて自由にカスタマイズできます。
// 曜日ごとのメッセージ発声
// ゴミ収集日のメッセージ発声
#define STR_WEEK_FUTSU  "kyo'-wa moyasu/gominohi."
#define STR_WEEK_PURA   "kyo'-wa purasuchi'kkuto shige'nngominohi."
#define STR_WEEK_PET    "kyo'-wa pettobo'toruno/gominohi."
void MessageWeek(const AQ_DATE_TIME &dt)
{
  static uint8_t dayLastWeek = 0;   // 同日の発声は1回のみにするため、発声日を保存
  if (6 <= dt.hh && dt.hh <= 9) {   // 6時から9時に限り
    if (dayLastWeek != dt.d) {
      if (dt.w == 2 || dt.w == 6) { // TUE/SAT
        TalkP(PSTR(STR_WEEK_FUTSU));
      }
      else if (dt.w == 3) { // WED
        TalkP(PSTR(STR_WEEK_PURA));
      }
      else if (dt.w == 5) { // FRI
        TalkP(PSTR(STR_WEEK_PET));
      }
      dayLastWeek = dt.d;
    }
  }
}
yukkuriclock2.ino:MessageWeek()


・アラームを変更するには
RTCにあらかじめ時刻を設定しておくと、その指定時刻に割り込みが発生し、このMessageAlarm()関数が呼ばれます。 設定時刻は、スケッチ先頭部分にある「アラーム起動時刻」で指定しています。
基本スケッチでは、平日に限り「おはよう 朝です」と発声していますが、これも自由に条件とメッセージを書き換えてください。
// アラームのメッセージ発声
void MessageAlarm(const AQ_DATE_TIME &dt)
{
  if (1 <= dt.w && dt.w <= 5) { // 平日のみ
    TalkP(PSTR("ohayo-' a'sade_su."));  // 「おはよう 朝です」
  }
}
yukkuriclock2.ino:MessageAlarm()

RTCのアラームは一度に1つしか設定できませんが、R8025_AlarmSet()関数で動的にアラーム時刻を設定できますので、アラーム割り込み発生ごとに次のアラーム時刻を設定すれば、曜日ごとにアラーム時刻を変えたり、毎時時報を発声するなんてこともできるでしょう。ちなみに、R8025のアラームは、繰り返えさないので毎回セットする必要があります。

・オリジナルの機能を実装するには
メインループ(loop()関数)内に、オリジナルの関数を追加して、たとえば、毎朝ラッキーカラーランダムに発声するなんてことも面白いと思います。

・発話速度を変えるには
AquesTalk.hのSetSpeed()関数を呼び出せば、発話速度を変更することができます。関数の使い方はArduino用音声合成LSIライブラリを参照ください。

・その他
今回は日時設定に2つのスイッチを使ってますが、1つ、あるいは3つでオリジナルのシーケンスで操作してもいいですね。
カスタマイズは、要は日時情報と振動のトリガでどんなメッセージを出力するかということにつきます。
色々なアイデアで、実際に面白いものをいろいろ試していただければ幸いです。

MySleep()関数は割り込みがあるまでスリープします。ここでATmega328Pや音声合成LSIをSleep状態にして待機時の消費電流を1uA以下にしています。割り込み要因は、振動スイッチ/SETボタン/UPボタンの状態変化(立ち上がり立下りの両方)とRTCのアラーム割り込みです。


■ハードウェアのカスタマイズ

音量の調整は
R4の抵抗を変えて音量を調整できます。音が大きいならR4を4.7KΩなどに変えれば小さくなります。ただし、逆に1KΩ以下にしても大きくはなりません。大音量で使うなら別途アンプ回路を実装します。

拡張用のGPIO
拡張用に3本のGPIO(IO9/IO10/IO11)を用意してますので、これを使ってハードウェアの改良ができます。
「LOTTORP」には3色LEDがついてますので、たとえば、割り込みがあったときにピカッと光らせてもよいですね。
また、今回は振動スイッチ(傾斜スイッチ)を使いましたが、圧力センサーをつなげて握ったときに発声させるなどの応用もできそうです。また、感熱センサーをつけて近くに寄ったら発声するのも良さそうですね。消費電流の課題がありますが・・・。

筐体
今回はIKEAの「LOTTORP」に組み込みましたが・・・
折角、通称「ゆっくりチップ」を使ってるので、やっぱりコレに入れたほうがいいのかな ラッキー


以上で「オリジナルの音声時計」の完成です。

■プレゼント
今回の試作で発注したプリント基板のあまりをプレゼントします。
ただし、実際に製作してそのブログ記事を書いてくれることを条件にしたいと思います。
特に内容や期限はありませんので、お気軽に。
ご希望の方は、こちらからどうぞ。先着順、1人1枚限り(ってほどニーズあるのか!?)


■LINK
AquesTalk デモページ
http://www.a-quest.com/demo/index.html

ATP3011XXのデータシート
http://www.a-quest.com/download/manual/atp3011_datasheet.pdf

Arduino用 音声合成LSIライブラリ
http://blog-yama.a-quest.com/?eid=970151

音声合成LSIで「オリジナルの音声時計」を作ろう!
| 電子工作 | 09:49 | - | - |
音声合成LSIで「オリジナルの音声時計」を作ろう!- その3 ソフト編

前回までに、部品や配線の半田付けで音声時計のハードウェアを組み立てました。今回は、コントローラであるATmega328Pにプログラムを入れ、実際に動作を確認してみます。



■スケッチの書き込み
まずは、ハードウェアの動作テストを兼ねて、下記からダウンロードした基本スケッチで動かしてみます。
Arduino Unoは、ブートローダ&Fuse設定を行ったATmega328Pに差し替えておいてください。
 


ダウンロードしたスケッチ一式を展開後、任意のフォルダに置き、次の手順で、Arduino IDE(Ver.1.6.1)でこれを開いてATmega328Pにスケッチを書き込みます。

  1. メニュー:ファイル > 開く > YukkuriClock2.ino
  2. メニュー:ツール > ボード > Arduino Uno
  3. メニュー:ファイル > マイコンボードに書き込む

書き込み時にエラーが出ないことを確認してください。

■動作確認します!
ATmega328Pを、音声時計の基板に差し替えます。
いよいよ、電池を挿入する、いつもの緊張する瞬間です。

ポン!日時を設定します」と聞こえたら、まずはオッケーです。

もし、なにも聞こえなかったら・・・。

電子工作してればそういうこともある、というか、最初から動く事の方が少なかったり・・・。
ただ、このことで回路のレビューを始めたり、いろいろ調べたりで、一発で動くより結果的にはるかにスキルアップします。 動かなくても、そのチャレンジを楽しみましょう!


■時刻を設定するには
基本スケッチで、日時・時刻を設定する手順は次のとおりです。

・年月日の設定
最初に電源をいれると、「ポン!日時を設定します。まずは何年?2015年」と発声しますので、よければSETボタンを、UPボタンで2016年、2017年と進み、SETボタンで確定します。その後、「次は何月?1月」で同様に月を、「最後に何日?1日」で同様に日にちを設定します。最後に「ポン、よろしければセットボタン、もう一度なら・・・・」と発声しますので、SETボタンを押して確定します。

・時刻の設定
UPボタンを押すと1時間づつ進みますのでこれで時(hour)を設定します。SETボタンを押すと30分を境に繰り下げ、繰上げされます。たとえば、8:55 にSETボタンを押すと9:00になります。分(min)の設定は、正時になった瞬間にSETボタンを押して設定します(笑)

・RTCバックアップについて
本時計は、待機時、電源ラインのコンデンサだけで数分間電源供給が可能です。したがってパネルが上を向く状態で電池交換をすればRTCは狂わず、日時の再設定は不要です。ちなみに、年月日の設定処理は、RTCへの電源供給が止まった後にのみ起動されます。


この後は、いよいよ最終段階。カスタマイズしてオリジナルの音声時計を完成させます。
その4 カスタマイズ編につづく

■LINK

YukkuriClock2 基本スケッチ
http://www.a-quest.com/download/blog/yukkuriclock2.zip

音声合成LSIで「オリジナルの音声時計」を作ろう!


 

| 電子工作 | 22:45 | - | - |
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