トドお父さん通信

トドお父さん通信

北部九州在住 高BMI中高年のオタク趣味の活動記録


note記事からの転載です。
 

おもちゃ病院で、トランジスタ回路セミナーを開催したのは昨年の4月から10月です。

しばらくお休みして、2年目のセミナーを4月から第4土曜日に筑紫野市のカミーリヤで開催しています。


去年の5名はそのまま、2名新規に参加されたので、合計7名のメンバーになりました。
人数が増えるとサポートが大変なので、これぐらいの規模感がいいですね。

 

お題は、昨年のトランジスタ電子回路から、より実践的な「センサ・駆動系マスター (アナログ系) 」としています。

 

4月の第一回は新規参加者のために電子回路の基礎のおさらい、第二回はスイッチの動作、第三回は光センサについて勉強しました。


今回は、TTP223を使ったタッチセンサについて勉強します。

先月のセミナーの内容はこちらになります。
おもちゃドクター向けハンズオンセミナー第3回 光センサの基礎

前回の最後に、「障害児の遊び支援」活動をしているおもちゃドクターから、「Mさん、今回のトランジスタでスイッチを作る件ですが、教えて下さい。」とのこと。

「TTP223というタッチセンサを使って、おもちゃの犬のスイッチのON/OFFをしたい。」とのことだったので、今回のセミナーの題材にいれました。

静電容量タッチセンサの原理は、人間の体が電気を蓄える「導体(コンデンサ)」の性質を持っていることを利用して、指が近づいた際のわずかな静電容量の変化を検出し、スイッチのON/OFFを判定する仕組みです。

画像
 

1.静電容量の発生: タッチ電極には元々「寄生容量(回路自体の持つ静電容量)」が存在します。ここに指(人体)が近づくと、指と電極の間に新たな静電容量が並列に追加されるため、全体の静電容量が増加します。

2.静電容量-電流(電圧)変換: マイコンからタッチ電極に向けて「駆動パルス(矩形波)」を出力し、SW1・SW2を切り替えることで超高速な「充電」と「放電」を繰り返します

3.電圧をA/D変換: 静電容量が大きくなると、充放電にかかる時間(時定数)が変化します。これにより「TS端子の出力とA/Dタイミング」の波形にあるように、サンプリング時点での検出電圧に差(電圧の低下など)が生まれます。この電圧変化をマイコン内部のA/Dコンバータ(ADC)でデジタル値として読み取ります。

4.スイッチ状態のON/OFF判定: 読み取ったデジタル値が、あらかじめ設定した「しきい値(タッチTH)」を跨いだ場合に、指が触れた(ONになった)と判定し、システムへ通知します。

次は、今回使用するTTP223センサモジュールの説明です。

画像
 

ジャンパーランドで、色々と動作モードを切り替えることができるのですね。あとでやってみましょう。

今回は、イワヤ犬を制御するので、大電流をON/OFFするのに適したMOS FETを使います。
まずは、FETの動作についての講義です。

画像
 

トランジスタはベースには流れる電流で制御しますが、MOS FETはゲートに与える電圧を制御します。閾値(今回使うAO3400では約1.5V)以上になればONするので、トランジスタより簡単です。

電流はながれませんがゲート保護のために、Rgゲート抵抗1kΩをつけます。
Rgsブリード抵抗(10-100kΩ)をつけないと、ゲートにたまった電荷でなかなかOFFしないので、必ずつけるようにしましょう。

画像
 

ちょっと説明が長くなりました。原理の説明は眠くなるので、いつものように、ブレッドボードを作ってハンズオンしながら、タッチセンサを理解していきます。

画像
 


まずは、MOS FETを理解してもらうために、FETでモータをON/OFFしましょう。トランジスタを使った場合と比べて、ON抵抗が低く電池電圧3Vがそのままモータにかかるので、軽快に回って素子の発熱もありません。

画像
 

パワーFETは足つきのものが少ないので、SMD SOT23のAO3400を秋月の変換基板に載せて使います。

画像
 

トランジスタを使った場合は、モータがロックして1Aくらい過電流が流れると、トランジスタのCE間の電圧が増えて発熱してトランジスタが破壊、という故障が発生することがあります。


でも、FETではON抵抗が低いので、1Aくらいでは全く問題ありません。
でも、モータの逆起電圧で壊れないように保護ダイオードを忘れないようにしてください。本当は、0.1uFもモータに直接つけた方がいいですね。

 

みなさん、タクトスイッチを押すとモータが回転するようになりました。

おひとりだけ、スイッチ切ってもモータが回り続けています。


配線をチェックするとRgs10kΩがつながってませんでした。
これがないと、ゲート電荷が逃げるところがないですから回り続けますね。

でもセミナーとしては、受講者が間違ったほうが、かえって勉強になります。

 

次は、いよいよ本題のタッチセンサでの動作確認です。
タクトスイッチをタッチセンサTTP223に変えてみましょう。

画像
 
画像
注:TTP223は、この絵と逆にピンを立てた方がジャンパランドをつけやすいです

いつものように、思惑通りいかないことが起きました。
「先生、タッチしても、モータが回転しません!」

 

タッチした時にTTP223のLEDは点灯しますか?
FETのゲート電圧を調べてください。 1.5V以上になればモータが回転するはずです。

画像
 

「タッチした時にTTP223のLEDは点灯しますか?」「FETのゲート電圧を調べてください。 1.5V以上になればモータが回転するはずです。」「電圧が出てません!」


という掛け合いがあったあと、「TTP223を予備のものに交換してください」「動きました!」で解決しました。

これが、AliExpressで購入する部品が5個とか10個入っている理由ですね。
不良品も混じっているので、悪かったら交換しろ!ってことですよね。


1個しか入ってなかったらこまります(笑)

つぎに今日のメインイベント、イワヤ犬をTTP223タッチセンサで動かす、です。

まず、BDスイッチというものを作って、イワヤ犬の電池ボックスに入れます。薄い樹脂版の両面に銅箔を貼って、電線を出す形です。


こちらに作り方の資料があります。
BDアダプターを作ってみました
スイッチでなくおもちゃ側にはモノラルソケットをつけて、スイッチ側はモノラルジャックをつけて、おもちゃに差し込むことが多いようです。


今回は直結なので、BDスイッチですね。

画像
 

こんな回路で、タッチスイッチでイワヤ犬が動きました!


でも、電池の+/-を間違うと動かないのが悩みです。
どちらでも動作するように回路を考えると、複雑な回路になりますしね。

画像
 


TTP223のジャンパーランドでオルタネートを選ぶと、タッチするたびに動いたり、止まったりします。

タイマーがあると、タッチして10秒動いたりして楽しめるかもですね。
つぎは、タイマーIC NE555の説明をしましょうかね?

ちなみに今回のセミナー資料は下のGoogleドライブに入れています。
https://drive.google.com/file/d/1IeYtqnMxHOHXlkxCNWfnUmfLnrZh8Vi1/view?usp=drive_link

来月のお題はなんにしましょうかね?
いちおうモータ制御を入れていますが、タイマICも作ってみましょうか?

 

以下、note記事からの転載です。
前回 【電子工作】「信号だす蔵」AVR64DD14 超小型ファンクションジェネレータの製作(その2)  の続きで最終回です。 

前回は20ピンのAVR32DD20を使って、DDSを実装できました。
今回は、14ピンのAVR64DD14に移植して、動作を確認します。


うまくいったら、タカチのSW53ケースに組み込みを行います。
最後に仕上げと動作確認をします。

 

AVR64DD14への移植

今回のソフトの最新版はこちらのGistに置いてます。
DD14_FG_Sig_DDS_Dasuzo4

AVR32DD20からの変更点ですが、主な変更ははピンアサインの変更(PA5、PA6デバッグ用ピンの削除)、コメントの英語統一化、起動シーケンスの見直しといったところで、大きな変更はありません。

最終のピンアサインは下記main.cのコメントに書いてある通りです。
14ピン版では、空きピンがなくなってしまいました。

画像
 

ビルドした結果はこちらです。

画像
 

64KBのフラッシュは9.5kB(14.6%)使用とのことで、余裕です。
8KBのRAMは1.2kB(14.2%)使用でこちらも余裕です。


ATTINY1614ではそれぞれ16KB、2KBしかないので苦労しましたが、
さすがAVR64DD14ですね。EEPROMでの設定を保存など、今後の機能拡張を考えても問題はなさそうです。

 

基板加工

ケースは前回の信号みえ太と同じ、いつものタカチのSW53を使います。
タカチのSW53の外形はこんな形です。
外形 WDH=36mmx53mmx11mm、内径 WDH=29.2mmx46.2mmx5.9mm

画像
 

基板は秋月の薄型(1mm厚)のフリスク基板 56.5x32mmを
SW53の内径 46x29mmに合わせてカットします。

今回は、新兵器のHOZAN K-111 基板カッターを導入しました。
これがあると、あっという間に切断できるので、基板作成も楽しくなりますね。  
(掃除機を近くに用意して、粉塵の処理には注意してくださいね)

画像
 

      あっという間に加工できました。

画像
 

今回の回路図はこちらになります。

画像
 

3接点のジョグスイッチを使って設定を切り替えますが、電源ON/OFF用のタクトスイッチは別に付けました。これで使い勝手が良くなると思います。

液晶表示は、信号みえ太の128x64 0.96”より薄型の128x32 0.93”を使います。これはtechnoblogyさんの記事と同じです。

DDSの出力にはショート防止を兼ねて470Ωをつけました。
スピーカチェッカなどに使う場合は、100Ω位に減らすといいかもです。
 

基板組み立て

切り出した基板に配線をしていきます。
信号みえ太と同じように、CR2032ボタン電池のソケットを左側において
中央にマイコン基板を置きます(14ピンのDIP変換基板)。
右上に3接点のジョグタイプのスイッチを置きます。右下は電源用のトグルスイッチです。

画像
 

基板の配線ができました。次はケースを加工しますね。

画像

 

ケース加工

前回の信号みえ太のケース加工を参考にしてください。
【電子工作】コンパクトな簡易オシロ付きロジックチェッカの製作(その3 ケースに組込)

この記事と同様に、イラストレータで部品配置と穴開け図を作ります。

 

画像
 

この図をケースに貼り付け、穴あけを行います。
 

画像
 

 ドリルで小さい穴を開けて、クラフトカッターで穴をつなげて、ヤスリ
 で角穴を形にしていきます。

画像
 

結構大変ですが、丁寧にやっていきましょう。
こんな形になれば、完成です。(製品用のラベルに貼り換えました)

画像

 

動作確認

ケースに組み込んだ状態で動作を確認しました。

AVR64DD14のDACで動かす超小型Function Generator「信号だす蔵」のDDSが動作しました!


(パート1周波数変更)

 

(パート2 波形変更)


完成した写真はこちらです。

画像
 

製品ぽいおしゃれな外装になりましたね。これでファイナルアンサーでしょうか?

 

電流測定

動作時は、9mA前後になりました。

画像
 

電源スイッチを押してスリープ時は1.3uA

画像
 

ATTINY1614の時より、AVR64DD14のほうがのほうが、少しスリープ電流は流れるようですが、このレベルであれば電池の寿命に対して問題ないはずです。


今回のまとめ

  • AVR64DD14に移植して、SW53ケースに組み込んで動作確認しました。
    3接点のジョグスイッチで、周波数の切り替えと波形の切り替えがスムーズにいくようになりました。

  • 電源のON/OFFは専用のタクトスイッチを使うようにしました。

  • 動作時の電流は9-10mA前後、スリープ電流は1uA程度を確認しました

  • 「信号だす蔵」としての使い勝手は良好です。これからいろいろと評価して改善していきますね。 

    AVR64DD14への移植により、手のひらサイズのケースに収まり、電池駆動も可能な超小型ファンクションジェネレータが完成しました。アイデア次第で、現場で気軽に使える測定ツールとして活躍してくれそうです。

    今後も、このサイズのツールをいろいろと作っていきますね。
    ご期待ください!
     

参考資料

今回はtechnoblogyさんより、下記の記事を参考にしました。
Davidさんの素晴らしい仕事に感謝です!

Tiny Function Generator  http://www.technoblogy.com/show?20W6
Tiny Function Generator Sine Wave http://www.technoblogy.com/show?22HF
Two TFT Graphics Libraries http://www.technoblogy.com/show?5N9Y
Smooth Big Text http://www.technoblogy.com/show?3AJ7

 

最近は電子工作の記事をNoteにまとめています。

はじめに

前回 「信号だす蔵」AVR64DD14 超小型ファンクションジェネレータの製作(その1)
の続きです。

前回は128x32 oled LCDモジュールを使ってUIを設計しました。

今回はいよいよDDSを使った波形生成を実装したのでその報告です。
前回同様、ATMEL StudioでAVR32DD20のデバイスを使って開発しました。
これでOKなら、14ピンのAVR64DD14に移植します。

DDSの実装

今回のファームは下記のGistに入れてます。
3_AVR64DD14 Compact Function Generator "Shingo Dasuzo"

① DDSの基本原理

DDSの仕組みはシンプルです。32bitの位相アキュムレータ(phase_acc)に、周波数に応じたtuning_word(ジャンプ幅)をサンプリング周期ごとに加算し続けます。phase_accの上位ビットを波形テーブルの参照や演算に使うことで、様々な波形を生成します。

tuning_word(ジャンプ幅) = freq_hz × 2³² / F_SAMPLE

という式で、目的の周波数からtuning_word を事前計算しておきます
あとはISR内で下式の加算を32bitでするだけ、という仕組みです。

phase_acc += tuning_word;

下図の円周で説明します。位相が1周回ると1周期の波形が出力されます。
サンプリング周波数が一定だと、高い周波数ほどジャンプ量が大きくなり、1周期が早く回ることになりますが、波形の生成は荒くなります。

画像
 

上図はアナデバの下記URL記事を参考に作成しました。
アプリケーション・エンジニアに尋ねる―33 ダイレクト・デジタル・シンセシスのすべて

以下、エヌエフ回路設計ブロックの記事の説明を加えます。
エヌエフ回路設計ブロック DDS(ディジタル直接合成発振器)

ちなみにこの方式は業界的には「DDS(Direct Digital Synthesizer、ディジタル直接合成発振器)」と呼ばれる一般的な信号生成方式で、加算器とラッチで位相アキュムレータを構成し、周波数設定値をクロックに同期して累積していく点は今回の実装と同じです。

画像
エヌエフ回路設計ブロックのDDSブロック図

発振周波数の式で書くと、発振周波数 = 周波数設定値 × クロック周波数 ÷ 2ⁿとなり、これは①で書いたtuning_wordの式と本質的に同じ関係です。

DDS使用上の注意点
アキュムレータの出力は、周波数が高くなるに従い、飛び飛びの値を取るようになります。つまり、波形ROMを読み出すアドレスが飛び飛びになります。上図のN=3波形のように、周波数が高くなるとデータ点が間引かれて、ギザギザの波形が出力されることになります。

「信号だす蔵」DDS基本実装方針
今回の「信号だす蔵」でのDDS実装方針を下図に示します。
基本はTechnoblogyのDavidさんの下記記事を参考にさせて貰っています。
Tiny Function Generator

画像
 

② サイン波テーブルの生成

サイン波はMinskyアルゴリズムを使い、起動時にRAM上へ256点のテーブルとして計算生成しています。

画像
 

DavidさんのTiny Function Generatorと同じ係数・初期値を使っていますが、今回はDAC書き込み値まで事前計算してテーブルに格納しているのがポイントです。
ISR側では単にテーブルを参照するだけなので、加算やシフトの手間がありません。

画像
 

③ のこぎり波・三角波・矩形波の生成
のこぎり波はphase_accの上位8bitをそのままDAC値にしています。

画像
 

三角波はDavidさんの方式、最上位bitでXOR的な折り返し処理を使います。

画像
 

矩形波は最上位ビットの判定だけで生成しています。

画像
 

いずれの処理も割り込み処理で行われるため、処理時間の短縮が重要です。当初は6bitシフト演算等が入っていました。
AVRは8bitCPUのため、半端なビット数のシフトは1bitずつのシフト命令を複数回実行する必要があるので処理時間が長くなります。
そこで8bitちょうどの境界に揃えることで、シフト命令を使わずバイトの移動(またはキャスト)だけで済むように変更し、処理時間を短縮しました。

④ 関数ポインタテーブルでISRの分岐を排除
4つの波形関数をwave_table[]にまとめ、ISR内ではswitch文を使わず関数ポインタで直接呼び出しています。
これにより、どの波形を選んでもISRの実行時間がほぼ一定になります。
ここもtechnoblogyのDavidさんのコードを参考にしています。

⑤ ISR本体とDDS_SetFreq/DDS_Stop

ISRの中身は「phase_accに加算」「波形関数を呼ぶ」「割り込みフラグクリア」の3行だけです。重い計算(tuning_wordの64bit演算)はDDS_SetFreq()側、つまり周波数変更時にしか行わないようにして、ISRは最軽量に保っています。

⑥ 割り込み処理
割り込み処理は、前回説明の・キー入力割り込み に加えて、
・ タイマーのためのTCB0でのmillis()実装
・DDSサンプリング周波数のTCB1タイマー設定  です。

・タイマーのためのTCB0でのmillis()実装

画像
 

1mS毎に割り込みが入り、ms_countを+1していきます。

・DDSサンプリング周波数のTCB1タイマー設定

DDS.hの設定

画像
 

DDS.cの設定

画像
 

クロックが24MHzでするから、TOPを74にすると320kHzで割り込み
TOPを239にすると100kHzで、100uS毎に割り込みになります。

⑦ サンプリング周波数の実測と見直し
DDSのサンプリング周波数は、dds.hのここで設定します。

画像
 

実際にTCB1タイマーを設定するのは、dds.cのここになります。
サンプル周波数に合わせて、例えば74という値が設定されると、24MHzのクロックを75回カウントして320kHz、3.125uS毎に割り込みを出します。

画像
 

当初はF_SAMPLE=320kHzで試しましたが、実際にPA5/PA6にTCB0・TCB1の割り込みタイミングをデバッグ出力し、オシロで処理時間を実測して決定しました。

オシロで割り込み処理オーバヘッドの測定
TCB1割り込みハンドラに入るときPA6ポートを”H"、抜けるとき”L"にする。
これでTCB1割り込みが入るタイミングと割込み処理時間の測定をします。

画像
 

TCB0割り込みはmillis()タイマーの割り込みで、1mS毎にで発生する。
TCB0割り込みハンドラに入るときPA5ポートを”H"、抜けるとき”L"にする。
これでTCB0割り込みが入るタイミングと割込み処理時間の測定をします。

画像
 

TCB0割り込みとTCB1割り込みが同時に入るところが一番処理時間が厳しいので、割り込み処理が間に合っているかは、このタイミングで測定します。

画像
 

まずは、上のCH1にはTCB0 1ms毎の割り込み、下のCH2はTCB1 DDSサンプル周波数の割り込みが入ります。

画像
 

モードは条件が厳しいサイン波です。時間軸を拡大します。
320kHzで割り込みが3.2uS毎に入るはずなのに、6.4uS毎の割り込みになってます。”H"になっている時間も3uS程度かかってます。
CH1の1mS毎のTCB0割り込みが重畳すると、12uSくらいに延長されます。これでは、波形にジッタがでてしまいますし、そもそも設定周波数で波形が出ませんね。

画像
 

結局、F_CLOCKは100kHz, 10uSでようやく遅延なく(ジッタなく)割り込み処理ができるようになりました。
しかしmillis()用のTCB01mS毎の割り込みの処理時間が長いため、これでもジッタが発生しています。

画像
 

それで、TCB0の割り込みを見てみました。
諸般の事情で、LEDの点滅処理を入れていました。

bitシフトをなくし軽量版ですが、それでも、オーバヘッドは発生します。
ISR(TCB0_INT_vect)

画像
 

ISR(TCB0_INT_vect)の短縮形
millis()のためのms_count++だけにする

画像
 

代わりに、LEDの点滅はリアルタイム性が不要なメインループに移動しました。

画像
 

これで、再度 割り込みタイミングを確認しました。millis()用のTCB01mS毎の割り込み割込み時間が1uS以下に減りました。このため、TCB1 DDSサンプル周波数F_CLOCKの100kHz / 10uS毎の割り込み周期は、測定ポイントで
9.82uS, ほぼ10uSで安定してジッタは出なくなりました。

画像
 

サイン波の再現を垂直感度を拡大(100mV/div)して確認します。
1mS割り込みの前後でジッタ的なものは認められませんね。
1mS位置のノイズは、オシロのプローブへのノイズが飛び込みのようです。

画像
 

そこで最終的にF_SAMPLE=100kHz(MAX_FREQ=10kHz)に落とし、当初計画していた仕様に近い形に落ち着きました。ついでにrender_square()等も32bit判定から8bit判定に変更し、処理時間を詰めています。

⑧ UIとの統合
DDSの波形生成はTCB1の割り込みで動いていますが、これをUI側の処理と何も考えずに両立させると、表示が乱れることがあります。

そこで今回は、キー入力処理(process_keys())やOLEDのRedraw処理中はTCB1.CTRLA = 0でDDSの割り込みを一時停止し、処理が終わったらDDS_SetFreq()を呼び直してTCB1を再始動する、という方式にしました。

キー入力の場合

画像
 

LCDのRedrawの場合

画像
 

理由は単純で、I2C通信中にDDSのISRが割り込んで実行されると、表示が乱れたりI2Cのタイミングが崩れたりする可能性があるためです。

DDS自体は数μs単位の細かい処理ですが、周波数を変更するタイミングくらいは多少止まっても実用上問題ないので、「表示・入力処理中は止める、それ以外は動かし続ける」という単純な排他制御にしています。

なお、Sleepに入る際も同様にTCB1を止めていますが、この辺りの詳しい話は次回のAVR64DD14移植編で改めて扱う予定です。
 

動作確認

実際にAVR32DD20の評価ボードで動作させ、オシロスコープで出力波形を確認しました。

デフォールトの1000Hzで、サイン波、のこぎり波、三角波、矩形波です。

画像
 

いずれの波形も期待通りの形状で出力されており、周波数を変更した際も波形が崩れることなく追従しました。特にサイン波は256点テーブルの直接参照で、かなりなめらかに見える波形になっています。

なお、YouTube動画でも動作確認を説明しています。
パート1:周波数の変更

最高10kHz、最低1Hzまで周波数を変更する動作の確認をしました。

 

パート2:波形の変更

<

サイン波、のこぎり波、三角波、矩形波、またサイン波に変更する動作の確認をしました。
 

まとめ・次回予告

今回は信号だす蔵のDDS部分を実装し、以下のポイントを確認しました。

  • 位相アキュムレータ方式によるDDSの基本原理と、tuning_wordの計算方法

  • サイン波テーブルをMinskyアルゴリズムで起動時にRAM生成し、DAC書き込み値まで事前計算しておくことでISRを軽くする工夫

  • 関数ポインタテーブルで波形ごとの分岐をなくし、ISRの実行時間を波形に関わらず一定にする設計

  • 当初320kHzで計画していたサンプリング周波数を、実際にデバッグピンでISR実行時間を実測した上で100kHzに見直した経緯

  • 32bitのままの半端なビットシフトを避け、8bit境界に揃えることで処理を高速化した最適化

次回は、このAVR32DD20でのテストファームを、実際に使用する14ピンのAVR64DD14へ移植する話をする予定です。ピン数が減ることでの制約や、Sleep/wake周りの実装、I2C通信の安定化など、UIとDDSを両立させる上で出てきた課題についても触れていきたいと思います。

それでは、次回はSW53ケースに組み込んでいきますね。こうご期待!

参考資料

今回はtechnoblogyさんより、下記の記事を参考にしました。Davidさんの素晴らしい仕事に感謝です!
Tiny Function Generator  http://www.technoblogy.com/show?20W6
Tiny Function Generator Sine Wave http://www.technoblogy.com/show?22HF
Two TFT Graphics Libraries http://www.technoblogy.com/show?5N9Y
Smooth Big Text http://www.technoblogy.com/show?3AJ7