■自作デジタルエフェクター

■RasPd3 ハードウェア編

03_220_1raspd3p.jpg
今まで製作したRaspberry Pi搭載エフェクター(RasPd1RasPd2RasPd4)は単一エフェクトのみしか使えませんでしたが、今回のRasPd3は複数のエフェクトを同時に使えてパッチ切替もできる、いわゆるマルチエフェクターを想定したものです。当初はオーディオインターフェースにCS4272を使うつもりでした(別記事参照)が、うまくいかずWM8731を使っています。しかしながらCS4272を使ったオーディオカードTeensy Super Audio Board(SAB)は全データが公開されているので、大いに参考にしました。

▽回路図
03_220_2raspd3s.png
ΔΣ型ADコンバータでは入力のフィルタは簡易なものでよいらしいので、RasPd4より簡略化しました。ギター入力はモノラルですが、WM8731のLR入力を逆位相にして内部プログラム(下図)で足し合わせるという差動入力っぽいことをしています。
03_220_3raspdpd.png

ノイズ対策として、絶縁型DC-DCコンバータやデジタルアイソレータ(Si8662BB、Si8602AB)を用いてRaspberry PiとGNDを分離しました。スイッチについてはチャタリング対策の抵抗とコンデンサを入れています。ロータリーエンコーダは高速回転させるかもしれないので、コンデンサの容量が少なめです。

2.2インチLCDディスプレイモジュールはAmazonで購入しました。SAINSMARTの商品ページのManualに回路図が入っています。回路図中に3.3Vと記載がありますが、実際は3.0Vのレギュレータが使われていました。LEDピンへ抵抗を挿入すると明るさが減り、消費電力を抑えられます。Raspberry Piでの使用方法についてはadafruitのILI9341 TFT display用ページの内容で問題ありませんでした。

▽レイアウト(KiCadのデータはこちらへ)
03_220_4raspd3l 03_220_5raspd3swl.png
WM8731のアナログGNDとデジタルGNDは分離せず、裏面のベタGNDができるだけ一面プレーンになるようにしています。スイッチ類の基板はユニバーサル基板で作成しており、細い線がジャンパーです。ディスプレイモジュールのSDカードソケットは配線の邪魔なので取り外しました。ケースはタカチTD10-15-4Bです。

ノイズについては、劇的ではないですが少しは減少したようです。入力が0.5Vrmsぐらいで歪率1%となりますが、ブースターとして使うことはないので大丈夫でしょう。内部プログラムについてはまだ全然できていません。今までにない規模のプログラミングとなるので、相当時間がかかると思われます。

■ロータリエンコーダ用Pythonプログラム

RasPd1でロータリーエンコーダを使っていましたが操作性がイマイチでしたので、もう少しエフェクター向けの動作となるようPythonプログラムを作り直しました。参考ページ→RaspberryPi + Python でロータリエンコーダを制御してみた

▽回路図
03_219_1res.png
2つのスイッチ(AとB)のタイミングの違いを利用して回転方向を判断します。今回使用したのは秋月電子で購入したEC12E2420801というクリックありのものです。あまりチャタリングは発生しないようですが、念のためチャタリング対策のコンデンサと抵抗を挿入しました。一般にロータリーエンコーダの出力波形は下図のようになります。
03_219_2rep.png

▽テストプログラム
#!/usr/bin/env python
# coding:utf-8

import RPi.GPIO as GPIO
from time import sleep

Ap = 6 # Rotary_encoder_A
Bp = 12 # Rotary_encoder_B
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(Ap,GPIO.IN)
GPIO.setup(Bp,GPIO.IN)
re_value = 0

def rot(channel):
global re_value
if GPIO.input(Ap) == 0 :
cw = 0 # Crockwise or countercrockwise
Ac = 0 # Ap switching counter
Last_Bp = GPIO.input(Bp) # Bp status
for m in range(0,100):
if GPIO.input(Ap) == 1:
break
sleep(0.0005)
if Last_Bp == 0 and GPIO.input(Bp) == 1 :
cw = -1
if Last_Bp == 1 and GPIO.input(Bp) == 0 :
cw = 1
for n in range (0,24):
Last_Ap = GPIO.input(Ap) # Ap status
sleep(0.002)
if Last_Ap == 1 and GPIO.input(Ap) == 0 :
Ac = Ac + 1
if Ac == 0:
re_value = re_value + cw * 1
elif Ac == 1:
re_value = re_value + cw * 4
elif Ac == 2:
re_value = re_value + cw * 8
elif Ac == 3:
re_value = re_value + cw * 16
else:
re_value = re_value + cw * 32
print re_value

GPIO.add_event_detect(Ap,GPIO.FALLING,callback=rot,bouncetime=50)

try:
while True:
sleep(60)
except KeyboardInterrupt:
pass
finally:
GPIO.cleanup()
AピンがH→L(=FALLING、1→0)となった時にrot関数が呼び出されます。「if GPIO.input(Ap) == 0 :」という当たり前のことが入れてありますが、以前バックグラウンドでPure Dataを起動していた際にGPIOの読み取りがおかしくなったため、念の為の処置です。

まずAピンがHに戻るまでループを続け、Hになった瞬間のBピンの状態をみます。BピンがL→Hと変化していた場合は反時計回りで、逆の場合は時計回りと判断されます。次のループでは、Aピンが約50msの間に何回H→Lになったかカウントします。カウント数によって変化量が変わり、ロータリーエンコーダを速く回すほど値が大きく変化するということになります。

ロータリーエンコーダの種類によってはうまく動作しないかもしれません。また、値の更新が50msごとなのでリアルタイム性が必要な用途には向いていないだろうと思います。

■タグ : RaspberryPi

■RasPd4 プログラミング編

各設定についてはRasPd2 ソフトウェア編と同じですが、今回はオーディオ設定の入出力音量を操作していないので、alsamixerのMasterとCaptureのdB gainは両方0となっています。内部プログラムは2チャンネルのディストーションエフェクトです(データダウンロードはこちらへ)。

▽コントロール割り当て
左側LED: エフェクトオン時点灯、チャンネル切替モード時点滅
中央LED: Aチャンネル選択時点灯
右側LED: Bチャンネル選択時点灯
左側スイッチ: バイパス音とエフェクト音を同じ音量に合わせる機能
中央スイッチ: チャンネル切替
右側スイッチ: 2秒長押しでシャットダウン
各ポット: エフェクトパラメータ(自動保存されている)
フットスイッチ: 2秒長押しで通常モードとチャンネル切替モードを変更、通常モード時はエフェクトオン・オフ切替、チャンネル切替モード時はチャンネル切替

なかなかプログラミングが面倒でしたが、完成すると大したことはしていない感じです。フットスイッチに長押し機能を持たせた関係で、スイッチを押した時ではなく離した時に切替が働く形になり、少し違和感は残っています。

一つ原因不明の問題があり、バックグラウンドでPure Data(Pd)が起動状態のとき、立ち下がりエッジ検出で定義したコールバック関数がたまに立ち上がりエッジでも呼び出されるという現象が起こりました。どう調べてもスイッチのチャタリングではないようです。とりあえず呼び出される関数に「対象GPIOピンがLOW(0)」という条件を追加して対策しています。

▽Pdパッチ
03_214_1raspd4pd.png
なぜか今回は[spigot~]でエフェクトオン・オフを切り替えるとプツっとノイズが出るため、Isaac(139)さんの[pd spigot~]に[line~]を入れたものを使っています。[pd effect_distortion]の中身の表示は省略しましたが、前々回の記事のオーバードライブのトーン部分を変更したものが入っています。2チャンネル程度ならエフェクトをまるごとコピーすれば簡単ですが、今後の応用を考えてPdのメッセージ機能を使うことにしました。終了時にこのパッチ自体を上書き保存するため、外部ファイル操作はしていません。参考ページ→PureDataで値のプリセットを外部ファイルで管理する方法

エフェクトパラメータの取得は、RasPd2と同じでMCP3008を使っています。0.2秒ごとに0.0から100.0までの値を取得しますが、ノブを触らなくてもたまに値がブレることがあるようです。勝手に値が変わるとPdパッチに記録しているデータも変化して困る場合があるので、1以上変化しないとPythonからPdへ値を送信しないようしています。すごくゆっくりとポットを動かしたときはパラメータが変化しないことになってしまいますが、実用上は問題ないでしょう。

▽Twitter動画(そのうち消えるかもしれません)



RasPd4 ハードウェア編

■RasPd4 ハードウェア編

03_213_1raspd4p.jpg
微妙に不安定な面があったRasPd2を作り直しました。「3」を飛ばして「4」になっていますが、奇数番号は多機能タイプで、偶数番号はコンパクトタイプということにしておきます。スイッチやポットの基板についてはRasPd2のものを流用しており、外観は変わりません。初めてPCBを基板製造業者に注文しましたが、まぁまぁ納得の出来栄えでした。Raspberry Piは「zero W」です。

▽回路図
03_213_2raspd4s.png
入力にローパスフィルターを追加し、出力はヘッドフォン出力ではなくライン出力を使っています。ステレオ入力や出力バッファー追加も考えていたのですが、チップ部品でないと入らなさそうだったので諦めました。ダンピング抵抗は22Ωから47Ωへ上げて様子を見てみます。電源は9Vではなく5Vにしたので、大きな降圧レギュレータが不要となりました。DCジャックには間違えて9Vのプラグを挿さないように、秋月電子で買った「電圧区分4」というものを使用しています。

▽レイアウト(KiCadのデータはこちらへ)
03_213_3raspd4l.png
あまり意味はないかと思いますが、一応レイアウトも載せておきます。GNDはアナログ(右側)とデジタル(左側)に分けていて、中央下のあたりの一点で接続するようにしました。GPIOの番号は「*」印で示しており、使わないGPIOについては左端に引き出してあります。Raspberry Piが重なる部分は高さ7mmの電解コンデンサを使いましたが、スペースがあるので横に倒してもなんとか入りそうです。注文した基板は1M(R1)と1K(R2)の印字位置を逆にするというミスがあり、危ないところでした…

ノイズについてはRasPd2とほぼ同じくらいです。ギターが拾うノイズの方が大きいので、まぁOKということにしておきます。最大入出力レベルは0.9Vrms程度で、これも問題ないと思います。以前あったエラー音のような音については、起動して数十秒の間に短くビッと鳴ることがありますが、それ以外では今のところ大丈夫なようです。

WM8731より性能がよいIC(CS4272が候補)を使うとさらに高品質になると思われます。自作するとなると情報が少ないのですが、今後取り組んでみたいところです。



RasPd4 プログラミング編

■RasPd2 プログラミング編

参考になるかわかりませんが、とりあえずRasPd2に入っているファイルをアップロードしておきます。(直リンクできないようなのでこちらの別ページにダウンロードリンクを載せています。)
※RasPd4のデータをアップロードしたためRasPd2のデータは削除しました。(2018年2月22日追記)

▽コントロール割り当て
左スイッチ: エフェクト切替、切替時に右LEDが点滅
中央スイッチ: 特殊機能(ブースト機能等)オン・オフ、オン時中央LED点灯
右スイッチ: 長押しでシャットダウン
各ポット: エフェクトパラメータ
フットスイッチ: エフェクトオン・オフ、オン時左LED点灯

今回の内部プログラムはRasPd1のプログラムを単に移植しただけのものです。エフェクトを3種類入れているものの、エフェクトを切り替えた後いちいち各ポットを設定しなおさなければいけない仕様なので、現実的な運用は面倒だと思います。もちろん中身は自由に変更できるので、今後いろいろと発展させていきたいです。変態的なエフェクトをプログラムするのもいいし、スマートフォンと連携してエフェクトを操作するなんてこともできるかもしれません。



<スイッチ・LED>
RasPd1と同様、GPIOピンによるスイッチやLEDの制御を行っています。
こちらで丁寧に解説されています。→RaspberryPi電子工作入門

<可変抵抗>
エフェクトパラメータ設定は、ポットで分圧した電圧値をADコンバータMCP3008で読み取るという方式です。
こちらのページのプログラムを改変して利用しました。→Raspberry PiのPythonからTMP36のアナログ温度センサとMCP3008のADコンバータを使う
値の取得は0.3秒ごとにしています。取得した値が前回の値から変化していたとき、RasPd1と同様pdsendでPdへデータ送信しています。ポットを回したとき反応が遅く雑音が発生しますが、ワウペダルではないので実用上問題ないでしょう。
※最新のRaspbianで値が取得できなくなりました。プログラムにspi.max_speed_hz = 1000000を追加すると問題ないようです。(2018年1月28日追記)

<データ保存>
RasPd1からの名残でパラメータ保存機能は一応残っています。しかしすぐにパラメータが上書きされてしまうため、意味がない状態です。工夫次第ではプリセット保存・呼び出しといった機能をつけることも可能だと思います。



ハードウェア編へ  ソフトウェア編

管理人

ブログ内検索

メールフォーム

当ブログに関するお問い合わせはこちらからお願いします。 ※FAQ(よくある質問)もお読みください。

お名前
メールアドレス
件名
本文

アクセスカウンター