2018年02月03日

OpenTheremin@ピッチに段が付く問題が再発する

今日から本格的にプログラムの修正を開始しているが、ハードウエアの改装後に何故かピッチの段付きが発生していて、これがどうやっても解消できない。

段付きが発生するポイントには周期性が観測されているのだが、原因はWavetableを読出すオフセット値が特定のポイントで増加する方向に揺らぐことと想定している。

Wabetableを読みだすタイミングは強制的に外部からのクロックに同期されているので、この揺らぎがサンプリングレートの変動によって生じているとは考え難い。

当初は、データの不連続面が関係している可能性を疑っていたが、どうもこの辺がハッキリしない。 音量を決定するVolumeのパラメーターはフルスケール12bitで、これをスイープする間に数回の周期が観測されることがヒントかもしれない。

現象が目立つのは低音時に限られていて、高音時には殆ど気にならない。つまりこれは、オフセットに影響する揺らぎの値が一定している事を意味する。 

試しに、過去のヴァージョンのプログラムに戻してみたが、こちらも妙な段付きが再現されてしまう。

VCOのチューニングに問題があるのだろうか?

とりあえずの方策として、発音を1音減らして5音にダイエットしたものを用意しているが、別の問題はアンプの電池が死にかけていること。 もしかすると諸問題の原因はコレかもしれないので、明日は別に用意した電源で実験を行う予定。

以前、動作が不安定で168MHzに落としていたTeensy3.6のSystemClockを180MHzに設定し直して実験したところ、とりあえず稼働させることが出来ている。
posted by Yasuski at 01:10| open.Theremin

2018年02月01日

OpenTheremin@極低温下でオシレーターが不調になる

Pitch側のオシレーターの周波数が高い方にドリフトした結果、システムに不調が生じてしまった。

症状は、和音機構が全く働かずにオンチになることで、原因はPitch側のオシレーターが設定限界値の500kHzを超えたため。 この閾値を超えてしまうと、何故か基音以外の音程が滅茶苦茶になってしまう。 カウンタ入力の差分検知回路の出力が逆相になってしまうために生じるエラーと思われるが、対処法はオシレーターの発振周波数を下げるしかない。

今回は、更に4pFのマイカコンデンサーを投入して、なんとか発振周波数をIn-Rangeに設定できた。 5pF程度の温度保証されたコンデンサーは最後にチューニングを追い込むには絶対に必要なアイテム。

途中、IDEがTeensyを見失って焦るが、FIrewire系のオーディオインターフェイスとの併用時に発生するトラブルと思われる。

現在走らせているSketchのVersionは1.24。
posted by Yasuski at 21:02| open.Theremin

2018年01月31日

OpenTheremin@OverloadModeの波形を観測する

先に録画したTransitionにOffsetを掛ける音声の波形を表示してみた。



複雑な倍音構成がシームレスに変化していくのが判る。
posted by Yasuski at 22:36| AudioElectronics

OpenTheremin@Shield上のオシレーターのチューニングを行う

取り敢えず通電してはみたものの、オシレーターのドリフトが半端無く修正が必要。

27336681_1745658995464551_6693773792431257881_n.jpg

Vari-Capを駆動するVolume側のDAC2Bの修正値は4095でフルレンジ。こちらは、オシレーターの周波数が低過ぎるということで、現状330pFの設定を小さくする必要が。一方Pitch側のDAC2Aはどのレンジも対応できず、周波数を下げる方向で調整が必要。 現状は150+10pFなので、これを180pF程まで調整しなければならない。

結局、オシレーターの周波数チェックに一日を費やしてしまったが、夕刻になってようやく適正値にチューニングを追い込めた感触があった。 LCタンクのコンデンサの設定値は、Pitch側は150pF+17pF、Volume側は220pF+100pFで手打ちとしたが、理想値は180pF/310pF辺りになるだろう。

ただし、温度変化や電圧変動によって周波数がドリフトする環境に於いて、最後は電池切れによって作業を中断した情況なので、最適値が確定したと判断するのは早計か。 温度や電圧の変動の影響を考えると、やはり相対誤差の減少を目指す方向でシステムを構築したほうが良いと改めて結論している。

充電池を使っていたのは、アンプの電源投入時にシステムが怪しい挙動を示したためで、案の定交換した電源ICのジャンクパーツに不調が見つかった。 一度何かの拍子に不具合が発生するとそのまま破壊が進行していくことが判ったので、トラブル対策として電源ラインに保護用のツェナーダイオードを絶対に入れるべきだろう。 

怪しい部品は別の動作が保証されたジャンク品と交換した。 これでアンプの電源電圧に対応出来る筈だが、そのアンプ自体も極低温環境によって早々に電池切れとなって仕舞ったため、今日の作業はここで終了。

posted by Yasuski at 18:20| open.Theremin

2018年01月30日

OpenTheremin@緑基板が復活するもShield側の不調が続く

修理したテルミンに通電を試みたが、ガサゴソいうだけでオシレーターの差分をセンシング出来ない。 そのうちに、ガサゴソが沈黙してレベル変換ICの発熱が始まった。

IMG_7857.JPG

緑基板単体に関しては、MCUの健全性が確定していないもののデジタル通信の出力・レベル変換は正常に動作している模様。 問題は周波数カウンタの入力が生きているかどうかだが、これの検証を行うにはオシレーター側の正常な動作が前提となってしまう。

一方、Shieldの方は唯一交換していなかったオシレーター周りのチップが仇になったのか、発振を確認できなかった。 これを交換した後に再チェックを行う予定だが、現状は故障のドミノ倒しを連想させられる情況であまり良い雰囲気ではない。

これ以上の延焼を防ぐためにはShield単体のチェックを行うべきなので、午後は専用の電源を用意して故障判定システムの立ち上げを行うことにしよう。

追記:

OpenThereminShieldの修理を完了した。 

死亡していたオシレーターのチップMC4069を、ピン配置が同等のHC14に交換。インバーターの反応スピードが異なるために発振周波数にも若干のズレが生じているようだ。

ついでに配線関連のリファービッシュを行った後に緑基板を繋いでオシロスコープで回路を検査したところ、DAC→VariCapの制御系の正常な動作を確認できた。 VolumeAntのアウトレンジ状態を表示する出力(目玉LED)も反応しているので、MCU上の周波数カウンタ入力はダメージを受けていない模様。

IMG_7858.JPG

あとはチューニングを行って動作を確認することになるが、これがセオリー通りには動かず、結構面倒な作業だったりする。
posted by Yasuski at 11:35| open.Theremin

2018年01月29日

OpenTheremin@白基板系の試作機も再起不能に

白基板に実装したTeensy3.5がSerialPortから認識されなくなる案件が発生。 試しにストックの3.5(未使用)を試したが、こちらも何故かポートが認識されない。 ArduinoのVersionは1.8.5、Teensyduinoは1.41とどちらも最新版をインストールしている。 パソコンの再起動後も症状は変化なし。

ちなみに、Teensy3.6は使用中のものもストックも問題なく認識されている、、、。

事故発生前の前兆現象として、RGBロータリーエンコーダーの赤LEDが反応せず、端子のラッチアップが疑われた。 静電気が悪さをしているのだろうか?

実装を試みているハモンド製のキャスト筐体は、クリアランスが厳しくMCUをソケットを介して実装できない。ID-292系列の基板も実装は厳しく、特別にオシレーターのみを分離した回路を組むことになりそうだ。ピギーバック系の基板を2階建てにして、片方をオシレーター専用のプラットフォームとする手もある。

部品調達のタイムラグが懸念されるので早急に追加発注を行うつもりだが、Teensyは3.6だけに絞ったほうが良さそう。


追記:


追試の結果、白基板の死亡を確認。 動作していたロータリーエンコーダが反応しなくなった。Teensyはどうも段階的に死亡に至るようで、経験則ではあるが、ラッチアップ → 通信の途絶 → 完全に死亡 というステップを踏むようだ。

仕方がないので白基板はドナーとして再利用することになるが、まずは緑基板にレベルシフトICを移植しておいた。 この緑基板にはTeensy3.6が搭載されているが、先のトラブルでカウンタ端子に過電圧が掛かっていた場合は、こちらも徐々に動作不能に陥っていくことになる。

posted by Yasuski at 15:59| open.Theremin

2018年01月28日

OpenTheremin@試作機の再組み立てを失敗/回路が死亡する

試作中の短絡事故で電源ICをぶっ飛ばしてしまったが、在庫がない(郵政の無能な職員が発注した部品を送り返した)ので作業がストップしている。

WS001227.JPG

他の基板から該当する部品を引剥して起動させたものの、今度はOpenThereminのShield基板がご逝去された様子。チップの半分位はリプレイス用の部品と交換すればなんとかなりそうだが、焦って部品を交換する前に、オシレーターの発振を確認したほうが良い。

起動音のピポパが出ていて、ロータリーエンコーダーのプッシュスイッチも動作していることから、MCUは飛んでいない模様。

発振器の動作やロジックラインの信号をオシロで測定した結果、運良くSheld側の破壊を免れていた模様。一方、MCUからの信号をShield側のDACが受信しておらず、オシレーターのチューニングが出来ない。 青基板の前例からレベル変換ICのご逝去が疑わしくなった。 

WS001226.JPG

幸いこのパーツは一個だけ在庫が存在したので、虎の子のそれを使うか、もしくはジャンク基板からサルベージを行って急場をしのぐことにする。 

ちなみに、注文した行方不明なパーツの発送は遅れてるというか、社内でもこれまた行方不明っぽい情況なので予断は許されず、必要なパーツは別途調達しておいたほうが賢いとの判断に傾きつつある。

事故は二回目なので、MCUの書き換え時にpinの接続を失敗してしまう試作機の仕様がオカシイのだが、次期モデルでは其辺の構造を改良しなければならない。

追記:

組み直した緑基板にアンプを接続して再通電を行ったところ、今度は緑基板上に設置していたシングルチップのドライバICがご逝去されたことから、

WS001228.JPG

Shield側のチップにも死亡・短絡が発生していることが確認された。

WS001225.JPG

アンプに接続する前にバッテリーで通電していた時にはShield側のオシレーターの作動と差分出力を確認していたことから、レベル変換ICの動作不良が疑わしいと結論し、レベル変換ICのみを交換して再トライしたのだが、交換した中古のレベル交換ICにも不良が発生していたようで(そういえば、ジャンクの供給元になった筐体も原因不明で沈黙していた)死亡したシングルチップICを交換した後に、Shieldを接続しない状態でレベル変換が行われていないことを確認している。

WS001229.JPG

これはつまり、短絡によって"H"レベルに固定された出力に過電流が生じた結果、レベル変換ICが破壊されたと想定されるが、同時に接続先のMCP4922も死亡していると結論せざるを得ない。 ひいてはOpenThereminShieldは全半導体パーツを交換することにした。 音声出力の死亡も事前に確認しているが、このICだけは手持ちが無く欠番として処理する他はない。

つまりは、さっさとシングルボード機を完成させろということになるのであろう。

追記2:

先程OpenThereminShieldを調査した結果、12bitDAC/MCP4922のパッケージ上にスポットを発見し死亡を確認した。 

IMG_7862.JPG

基板上の4069が動作していたのは、耐圧が15Vと旧CMOS系の仕様だった為と思われる。

電源レギュレータICの破壊が入出力のショートモードに進行したと仮定すると、過去に発生した事故による部品の損壊パターンの説明が付く。よって、過電圧を供給されたHCMOS系とDACは全滅したものと思って間違いないだろう。

同時に緑基板上の5V系も全滅した筈だが、MCUはTeensy上のレギュレーターによって破壊を免れたと判断している。
posted by Yasuski at 06:54| open.Theremin

2018年01月27日

OpenTheremin@試作機の再組み立てを失敗/回路が死亡する

試作中の事故で電源ICをぶっ飛ばしてしまったが、在庫がない(郵政の無能な職員が発注した部品を送り返した)ので作業がストップしている。

他の基板から該当する部品を引剥して起動させたものの、今度はOpenThereminのShield基板がご逝去された様子。チップの半分位はリプレイス用の部品と交換すればなんとかなりそうだが、焦って部品を交換する前に、オシレーターの発振を確認したほうが良い。

起動音のピポパが出ていて、ロータリーエンコーダーのプッシュスイッチも動作していることから、MCUは飛んでいない模様。

発振器の動作やロジックラインの信号をオシロで測定した結果、運良くSheld側の破壊を免れていた模様。一方、MCUからの信号をShield側のDACが受信しておらず、オシレーターのチューニングが出来ない。 青基板の前例からレベル変換ICのご逝去が疑わしくなった。 幸いこのパーツは一個だけ在庫が存在したので、虎の子のそれを使うか、もしくはジャンク基板からサルベージを行って急場をしのぐことにする。 

ちなみに、注文した行方不明なパーツの発送は遅れてるというか、社内でもこれまた行方不明っぽい情況なので予断は許されず、必要なパーツは別途調達しておいたほうが賢いとの判断に傾きつつある。

その後、国内に資材が無い事を確認して必要なパーツのみを海外に発注した。モノは消耗品っぽい汎用性が高い代物なので、発注が重複する分には問題ないが、価格が倍以上するのは頂けない。

しかし、電源の短絡でぶっ壊れるデバイスというのは、パワーエレクトロニクス系以外では(コレは当たり前)あまり見掛けないような気がする。レベル変換ICは、電源電圧の変動に対してデリケートなのだろうが、片方の電源が瞬断した場合に道連れとなる仕様は危なっかしい。

事故は二回目なので、MCUの書き換え時にpinの接続を失敗してしまう試作機の仕様がオカシイのだが、次期モデルでは其辺の構造を改良しなければならない。

posted by Yasuski at 18:45| open.Theremin

2018年01月26日

OpenTheremin@TransitionControlにOffset設定機能を実装する

TransitionControllerの参照波形に関する考察。

やはりピークのQを可変にしないと動作が破綻しそうなのだが、これを計算式で行うのと予め用意したWavetableを切り替えて行うという2つの方法を思い付く。

パラメーターの変化に即応性が要求されない一方で、発音時にDoubleで計算するとレイテンシーが発生する問題があり、RAMの専有領域が増えるものの速度面からするとWavetableを切り替える方式の方が良さ気な雰囲気だ。 既に、制御波形の後半に糊代分の無音地帯を1024アドレスくっつけた"Q"のピークが異なる8種類のWavetableを製作している。

で、既に実装済の単純に読み出しポイントをズラす方式を試してみた。



結果は必要十分だったので、暫くはこの方式で運用試験を継続することになる。

次は試行錯誤の過程で思いついた、音源の波形にオフセットを掛ける実験を行う予定。
posted by Yasuski at 16:10| open.Theremin

2018年01月25日

OpenTheremin@Transitionにオフセットを掛ける

今日は、OverLoadモードと通常モードのレベル差をチェックしていたが、気になったのはTransitionModeのリエゾンの扱いで、選択するモードによって動作の違いがとても大きくなることが判明している。

問題を解決するには、和音のピッチ制御と同じような仕掛けでオフセット値を変化させるのが正解なのだが、これを大まかな設定値の切り替えで行うのか、ユーザーが微調整を行うのが良いのか、判断が難しいところだ。

現状は折衷案としてVolumeノブを使ってTransitionの感度を調整しているが、記録するパラメーターを増やした方がより便利に運用できそうだ。

現行のシステムではTransitionControllerの波形にサイン波のプラス側の山を半波使用している。

controlSignals.png

この波形の開始位置をズラしたWavetableを6波用意して各音源毎のヴォリュームコントロールに宛てているが、Transitionの間隔を変更する場合には基本とする1波にオフセットを掛ける形に変更する手法が正解だろう。 つまり、ヴォリューム・コントロール用のWavetableを読みだすアドレス用の関数、vol_mod にオフセットを掛ければよい。

で、実際のコードはこんな感じになった。

if ((vol_16> 0)&&(vol_16<4096))
{vol_mod = (((vol_16 + 2047 ) % 2047));
vol_mod_2 = (((vol_16 + 2047 + (vol_offset + 340)) % 2047));
vol_mod_3 = (((vol_16 + 2047 + (vol_offset + 680)) % 2047));
vol_mod_4 = (((vol_16 + 2047 + (vol_offset + 1020)) % 2047));
vol_mod_5 = (((vol_16 + 2047 + (vol_offset + 1360)) % 2047));
vol_mod_6 = (((vol_16 + 2047 + (vol_offset + 1700)) % 2047));
} // volume value as the controller if value in range

vol_mod = constrain(vol_mod, 1, 2047);
vol_mod_2 = constrain(vol_mod_2, 1, 2047);
vol_mod_3 = constrain(vol_mod_3, 1, 2047);
vol_mod_4 = constrain(vol_mod_4, 1, 2047);
vol_mod_5 = constrain(vol_mod_5, 1, 2047);
vol_mod_6 = constrain(vol_mod_6, 1, 2047);

temp_Volume_a = (((uint16_t)pgm_read_word_near (volumeCurb[0] + vol_mod)));
temp_Volume_a = ((temp_Volume_a * vol_16)>>11) + 1;

temp_Volume_b = (((uint16_t)pgm_read_word_near (volumeCurb[0] + vol_mod_2)));
temp_Volume_b = ((temp_Volume_b * vol_16)>>11) + 1;

temp_Volume_c = (((uint16_t)pgm_read_word_near (volumeCurb[0] + vol_mod_3)));
temp_Volume_c = ((temp_Volume_c * vol_16)>>11) + 1;

temp_Volume_d = (((uint16_t)pgm_read_word_near (volumeCurb[0] + vol_mod_4)));
temp_Volume_d = ((temp_Volume_d * vol_16)>>11) + 1;

temp_Volume_e = (((uint16_t)pgm_read_word_near (volumeCurb[0] + vol_mod_5)));
temp_Volume_e = ((temp_Volume_e * vol_16)>>11) + 1;

temp_Volume_f = (((uint16_t)pgm_read_word_near (volumeCurb[0] + vol_mod_6)));
temp_Volume_f = ((temp_Volume_f * vol_16)>>11) + 1;


posted by Yasuski at 14:50| open.Theremin