guiメモ

技術寄りの雑記(予定)

光造形3Dプリンタを導入した

概要

光造形式の3Dプリンタを導入したので簡単に使用感などを紹介します。

はじめに

FDM方式の3Dプリンタでは精度が足りず、安物のCNCフライスで加工するには小さすぎる部品を作るために光造形方式の3Dプリンタを導入することにしました。FDM機を導入した4年ほど前の光造形方式の3Dプリンタと比べ、現在は性能が高く安価な機種が増えたので導入しやすくなりました。フリーのスライサがあってスタンドアロンで動くのも良いですね。(以前はPCにずっと接続して3DプリンタLCDをサブディスプレイ化して出力、みたいなゴリ押し機種があったような気がします)

使用感

購入した3Dプリンタは日本人ユーザが多く見られるELEGOO Mars 2です。クーポンがあったのでAmazonで購入しました。開封画像や本体の画像については他の方が多数載せているようなので省きます。

セットアップ

自作キットの3Dプリンタと違い組み立てが不要なのでセットアップはすぐに終わりました。z軸の調整はマニュアルに書かれている紙を挟む方法だとプラットフォームから出力物が剥がれやすかったので、レジンタンクをセットした状態でプラットフォームを固定してz=0としました。この方法によりz軸の調整不足による出力物の脱落は大きく減りました。しかし照射時間の試行錯誤はある程度必要のようで、出力途中に出力物が脱落しないようなパラメータを求めるのに多少の労力を要しました。

出力結果

まずはテストデータの出力結果です。FDM方式では難しいような細かい文字も綺麗に出力されました。テスト時の洗浄が不十分だったので溝に付着した余分なレジンが固まってしまいました。手で洗浄するのに限界を感じたので安価な超音波洗浄機を別途購入しました。

f:id:gui_robo:20220321133626j:plain
テストデータ

次にプリント基板用のステンシルを出力しました。1608M程度の穴なら余裕で出力できたので、これは使えそうです。穴などの寸法も問題なさそうです。

f:id:gui_robo:20220321135128j:plain
完成したステンシル
f:id:gui_robo:20220321135148j:plain
寸法チェック

まとめ

光造形3Dプリンタを導入し出力結果について簡単にご紹介しました。出力物については予想よりも精度が良好で、本稿で紹介できなかったロボットパーツについては0.1 mmまで測定できるディジタルノギスで誤差が0になるなど、箱から出したばかりの機械とは思えないような精度が出ました。ただ、レジンの臭気と洗浄液の廃液処理については課題があるので、光造形機のこれからの発展に期待したいところです。

簡易カーブトレーサーの作成

概要

トランジスタダイオードの静特性の測定ができる簡易的な半導体カーブトレーサーを作成してみました。簡易的なものなのでガチガチの測定はできませんが、趣味でちょこっと特性を知りたくなったときに便利なものに仕上がりました。

はじめに

みなさんの部品箱の中に得体の知れない半導体って眠ってたりしませんか?私の場合、秋月のお楽しみ袋に入っていた謎のダイオードやAliexpressで購入した怪しいトランジスタなどがそこそこ眠っています。これらの部品の特性を測定するには電源を用意して回路を組んで測定して…と中々手間がかかってしまいます。特にトランジスタの特性を測定するには電圧源と電流源を用意しなければならないので大変です。そこで、トランジスタダイオードの特性を自動でいい感じに測定できる簡易カーブトレーサーを自作しようと思いました。

設計製作

仕様

本稿で作成する簡易カーブトレーサーの仕様は次のようになっています。トランジスタ用に回路を設計しますが、エミッタ・コレクタ間にダイオードを接続すればダイオードの特性も測定することができます。

  • V_{CE}: 0 V〜5 V(NPN)、0 V〜-5 V(PNP)
  • I_B: 0 mA〜5 mA(NPN)、0 mA〜-5 mA(PNP)
  • I_C: 0 mA〜約500 mA(NPN)、0 mA〜約-500 mA(PNP)

回路設計

マイコンを含むメイン回路です。マイコンをはじめとした半導体が不足しているので、STM32F303K8の(ほぼ)全てのピンを使い過不足ないようにしました。

f:id:gui_robo:20220316134554j:plain
メイン回路

NPN側の測定回路です。オペアンプで定電流回路と定電圧回路を構成するだけの簡単な回路となっています。微小電圧および微小電流を扱うのでオフセット電圧が小さい、いい感じのオペアンプを使います。本稿ではADA4522を採用しました。

f:id:gui_robo:20220316134031j:plain
測定回路(NPN側)

PNP側の測定回路もNPN側と同様の回路になっています。

f:id:gui_robo:20220316134314j:plain
測定回路(PNP側)

AD/DA回路です。コレクタ電流の測定ゲインを2種類用意してダイナミックレンジを確保しつつマイコンのADCポートの保護を行います。DACマイコン側ラベルがNPNとPNPで分けられていますが、基板設計の都合で変更がありベース電流指令値とエミッタコレクタ間電圧指令値が正しいものとなっています。(修正が面倒だったのでラベルがそのままとなっています)

f:id:gui_robo:20220316134853j:plain
AD/DA

最後に電源回路です。測定回路で使用するMOSFETを確実にOFFにするために15 V→12 Vの若干降圧する回路と負電圧を生成する回路が必要となります。加えてマイコン周りで5 Vと3.3 Vが必要になります。

f:id:gui_robo:20220316135442j:plain
電源回路

組み立て

組み立て後の基板はこのようになりました。ZIFソケットトランジスタを刺して測定します。V_{CE}調節用のMOSFETとレギュレータは測定条件によっては発熱するのでヒートシンクを取り付けます。

f:id:gui_robo:20220316140031j:plain
完成した簡易カーブトレーサー

使ってみた

データをCSV形式で出力し、MATLABを使って描画しました。

まずは部品箱にあった怪しい2SA1015(赤線)/2SC1815(黒線)のI_C-V_{CE}特性です。ベース電流は0.1 mA刻みとなっています。コレクタ電流が30 mA付近となるポイントで変な段がありますが、これはコレクタ電流ゲインの切り替えに起因するものと考えられます。

f:id:gui_robo:20220316144824p:plain
怪しい2SA1015/2SC1815のIc-Vce特性

次に同じトランジスタを用いてh_{FE}-I_C特性を測定しました。コレクタ・エミッタ間電圧は1 V刻みとなっています。温度を一定にする機構がないためかプロットがぐちゃぐちゃになってしまいました。

f:id:gui_robo:20220316144957p:plain
怪しい2SA1015/2SC1815のhFE-Ic特性

最後に部品箱にあった謎のダイオードの順方向特性です。綺麗なカーブが得られました。

f:id:gui_robo:20220316145649p:plain
ダイオードの順方向特性

まとめ

本稿では簡易的なカーブトレーサーについて設計および製作し、測定結果について簡単に紹介しました。ハード的にはまだ課題がある一方で、趣味程度なら使えなくはないものに仕上がったと思っています。本稿での仕様だとツェナーダイオードの測定が厳しいので、また作る機会があれば電圧範囲をもっと拡大したいと思います。

オーブントースターリフロー炉の作成(回路編)

概要

オーブントースターを改造してリフロー炉にします。作成記事は

  • 回路編
  • 制御編
  • 実践編

の三編とする予定です。今回はその内の回路編となります。

はじめに

みなさんSMD部品の実装はどのようにしているでしょうか。私は気合いでペースト半田と部品を基板にチマチマ載せてヒートガンでグワっと温める気合いリフローで実装しています。この方法は少ない部品で基板を量産しない場合においてはコスパが良くて問題がないのですが、実装する部品が死ぬほどある場合や基板を量産する場合においては非常にしんどくなります。特にヒートガンでLEDのような極性のある部品が吹っ飛ぶと脳味噌も吹っ飛びそうになります。

既に多くの方々がホットプレートやオーブントースターをリフロー炉に改造しようとチャレンジされているようで、作例がネット上にごろごろ転がっています。これらの方法は温度管理さえ気をつければ勝手に部品が実装されていくので、SMD部品の実装がかなり楽になるような気がします。そこで今回は後者のオーブントースターをリフロー炉にするやつを真似してみようと思います。

回路の設計・製作

回路構成

ざっくりオーブントースターはAC100Vを電熱線に繋いでいるだけの簡単な構造となっています。そのため、庫内温度の制御は電熱線にAC100Vが印加される時間を制御することによって達成できそうです。電熱線にAC100Vが印加される時間の制御法は色々考えられますが、SSRを使うことで比較的安全かつ簡単に実現することができます。SSRを使用した回路構成例は次のようになります。

f:id:gui_robo:20220302214725p:plain
回路構成例

回路設計

回路構成図を基に回路を設計していきます。マイコンはSTM32F303K8を採用し、デバッグ用にUARTで色々吐き出せるようにしておきます。また、スタンドアロンで使用することを想定しているので適当なディスプレイとスイッチを配置し、一応冷却ファン用の端子も出しておきます。回路図は次のようになりました。

f:id:gui_robo:20220302213012p:plain
回路図
回路図に記載していませんが、安全のためにAC電源にはヒューズを取り付けています。

基板の作成と動作確認

KiCadでチャチャッと設計して中国の某基板メーカーに発注しました。

f:id:gui_robo:20220302212441j:plain
発注したプリント基板
ササっと部品を実装します。
f:id:gui_robo:20220302212508j:plain
部品実装後
特に難しい部分は無く、冷却ファン以外の動作確認は一発でできました。(冷却ファンについては家に在庫がないので動作確認していません)

まとめ

本稿ではオーブントースターをリフロー炉化するための回路基板について設計・製作を行いました。次回の制御編では今回作成した回路基板を使用して制御器設計を行う予定です。

アリエクで絶縁アンプを買ったので特性を簡単に測定した

概要

昨年の独身の日セール時にAliexpressで絶縁アンプを購入したので、使える物か否かを調べるために非常に簡単な測定をしました。(測定方法に関しては詳しい人に怒られそうな方法しか使用していないので参考にしない方が良いかもしれません。)

なお、Aliexpressで購入できる任意の絶縁アンプが本稿のような結果を示す保証はできませんので、購入する際は自己責任でお願いします。

絶縁アンプの外見

購入したものはHCPL-7800です。10個入りで購入価格は約900円でした。 私はこのICについて詳しくないので外見だけでの真贋判定ができません。 ただ、ICにはんだ付けされた形跡が確認できないので少なくとも中古品ではなさそうです。

f:id:gui_robo:20220223222748j:plain
購入した絶縁アンプ

電気的特性の測定

測定条件

安物のファンクションジェネレータがどこかへ消えたので、マイコンで吐き出した10 kHzと100 kHzのPWM信号を絶縁アンプに入力して応答を調べました。 10 kHzの信号では立ち上がりと立ち下がりの応答を調べ、100 kHzの信号では出力の振幅から帯域が100 kHz程度まであるのかを簡単に見積もりました。

立ち上がり・立ち下がり波形

10 kHzのPWM信号を入力した結果がこちらになります。部品箱から発掘した変換基板をブレボに刺して気合い(指で絶縁アンプを固定した状態)で測定したので、ノイズ多めな点はご容赦ください。

f:id:gui_robo:20220221205255p:plain
10 kHz入力時

立ち上がりも立ち下がりも見た感じ同様の応答でしたので、若干観測がしやすい立ち下がり波形に注目しました。(今思うと紫色の出力波形を少しずらせば良かった気がしますが、測定方法がアレなので2度目の測定は気が乗りませんでした)

f:id:gui_robo:20220221205720p:plain
立ち下がり波形

50%の伝搬遅延時間は約4 µsといったところでしょうか。概ねデータシート通りとなっています。

帯域

100 kHzのPWM信号を入力した結果がこちらになります。

f:id:gui_robo:20220221211125p:plain
100 kHz入力時

振幅のピーク値が10 kHzの時と大差ないので、帯域については問題なさそうです。

生存していた個数について

今回購入した絶縁アンプは10個入りでしたので、全ての個体について同様の方法で特性を測定しました。 その結果、出力信号が全く出ない個体が1つ、オフセットがやたらとデカい個体が1つありました。残りの8個がまともに使えそうな個体ということで、かなりお得感があって個人的には満足する結果となりました。

まとめ

本稿ではアリエクで購入した絶縁アンプの特性を簡単に(というか雑に)測定し、大半の個体が趣味で使う分には問題なさそうなことが分かりました。この絶縁アンプを使ってモータドライバか何かを作りたいです。

iPhone用中華DACが死んだので分解した

概要

よくある充電しながら音楽が聞けるタイプのiPhone向け中華DACが死んだので分解してみました。 (本稿では分解のみで、特に改造等は行っていません。)

ことの始まり

iPhoneで3.5mmミニジャックが廃止されて幾年も経ちますが、私は未だに有線のイヤホンで音楽を聴きたいタイプの人間なので変換アダプタ的なものを愛用しています。 見た目がAmazonで売ってるそれと同様のものがAliexpressで安価に手に入るので、使い捨て感覚で安価なものを数個まとめて買っては壊してを繰り返してきました。 今回も例によってストックが切れたので新しいものを物色していたところ、死にやすいというレビューがちらほら見られることに気がつきました。そこで、死んだDACを分解して一体全体どこが脆いのか確かめてみたくなったという次第です。

分解

死亡状況

今回分解したのは以下に示す「よくある見た目のDAC」です。

f:id:gui_robo:20220211212318j:plain
死んでしまった「よくある見た目のDAC

接続部に刺激を与えると78%ぐらいの確率で接続が切れるというパターンで死にました。大体毎回このパターンで死にます。稀に充電だけできなくなる、といったところでしょうか。

3.5mmジャック部の分解

まずは如何にも死にやすそうな3.5mmジャックなどが配置されている部分を分解します。白いプラスチックの部分を比較的丁寧にニッパーで剥がします。

f:id:gui_robo:20220211213123j:plain
露わになった3.5mmジャック部1
f:id:gui_robo:20220211213259j:plain
露わになった3.5mmジャック部2

Aliで見た商品説明ではこの部分に様々なチップが配置されていたような気がするのですが、どうやら3.5mmジャックとLightningコネクタしかないようです。一応、拡大して見てみましょう。

f:id:gui_robo:20220211213613j:plain
3.5mmジャック部の拡大図1
f:id:gui_robo:20220211213639j:plain
3.5mmジャック部の拡大図2

どうやら、DACチップ等は別の部分にあるようです。

Lightningコネクタ部の分解

3.5mmジャック部にDACチップが見当たらなかったので、(iPhoneに繋げる方の)Lightningコネクタ部も分解していきます。こちらもニッパーで比較的丁寧に剥がしていきます。

f:id:gui_robo:20220211213949j:plain
露わになったLightningコネクタ部1
f:id:gui_robo:20220211214028j:plain
露わになったLightningコネクタ部2

なんかそれっぽいのが付いてました。基板を見ると半田付けが不要なピンのパッドがシルクで埋められているように見えます。かなり力技に見えます。

6ピンのICは充電用のレギュレータか何かだと思われます。(AliにあるLightningケーブル自作キットに同様の部品が付いているのを発見しました。)

8ピンのICと16ピンのICは正体が分かりません。恐らくどちらかがDACの処理をするマイコンか何かで、他方が音をデカくするアンプか何かだと思います。

死因について

分解を終えてテスターを用いてケーブルの導通をチェックしたところ、なんと全ての線が生きてました。刺激を与えると動作が不安定になっていたので、これは意外な結果でした。しかし、使用時に接続が切れてもイヤホンからはホワイトノイズの様な音が途切れなかったので、ある意味これは納得のいく結果でもあります。

詳しい死因については結局のところ分からず終いで、恐らくLightningコネクタ部の基板(実測で0.3mm厚)が何らかの拍子で撓んで配線が切れてしまったものと思われます。

まとめ

本稿では死んだ中華DACを分解しました。分解と簡単な導通チェックにより、死因についてはレビュー等でよく指摘されているケーブルの断線ではないらしいことが分かりました。内部構造が意外と単純でしたので、手頃なUSB DACを見繕うことができればアダプタ自体を自作した方が安定感があって良いかもしれません。

パルス伝達関数をプログラムに落とし込む


\def\lr#1{{\left( #1 \right)}}
\def\slr#1{{\left[ #1 \right]}}
\def\eq#1{{\begin{align} #1 \end{align}}}
\def\mat#1{{\left[ \begin{array}{cccccccccc} #1 \end{array} \right}} ]

概要

z領域における伝達関数(パルス伝達関数)をプログラムに落とし込めるよう漸化式の形式に変形する方法についてメモしておきます。 パルス伝達関数をプログラムに落とし込むことに焦点を当てるため、z変換の詳細な性質等には触れません。

本稿はesaに投稿した記事を加筆・修正したものです。

サンプル遅延の表現

唐突かつ天下り的ですが、単位サンプル遅延はz^{-1}で表現されます。(詳しい説明は数ある参考書や他のサイト様にお譲りします。) ここでは例を見た方が理解が早いので簡単な例を示します。あるkサンプル目のデータa\slr{k}に対して単位サンプル遅延z^{-1}を作用させると次のようになります。

\displaystyle{
z^{-1}a\slr{k}=a\slr{k-1}
}

対照的に、zを作用させると単位サンプル進みます。

\displaystyle{
za\slr{k}=a\slr{k+1}
}

パルス伝達関数はこれらの関係を利用することで簡単に漸化式へ変形することができます。

漸化式の一般形と実装

漸化式を求めたいパルス伝達関数H\slr{z}とします。ただしH\slr{z}はプロパーな伝達関数(m\leq n)とします。

\displaystyle{
H\slr{z}=\frac{b_{m}z^m+\cdots+b_1z+b_0}{z^n+a_{n-1}z^{n-1}+\cdots+a_1z+a_0}
}

入力をu\slr{k}、出力をy\slr{k}とすると、伝達関数の定義から次のようになります。

\displaystyle{
\frac{y\slr{k}}{u\slr{k}}
=\frac{b_{m}z^m+\cdots+b_1z+b_0}{z^n+a_{n-1}z^{n-1}+\cdots+a_1z+a_0}
}

分母を払うと、次のようになります。

\displaystyle{
y\slr{k}\left(z^n+a_{n-1}z^{n-1}+\cdots+a_1z+a_0\right)
=u\slr{k}\left(b_{m}z^m+\cdots+b_1z+b_0\right)
}

両辺にz^{-n}を作用させて整理すると、漸化式の一般形が得られます。

\displaystyle{
\begin{align}
y\slr{k}=
&b_mu\slr{k-\left(n-m\right)}+\cdots+b_1u\slr{k-\left(n-1\right)}+b_0u\slr{k-n}\\
&-a_{n-1}y\slr{k-1}-\cdots-a_1y\slr{k-\left(n-1\right)}-a_0y\slr{k-n}
\end{align}
}

これをC++風に落とし込んだ例を以下に示します。

float dtf(float input)
{
    constexpr int n = 1;            // 分母多項式の次数(max(1,m)以上)
    constexpr float a[n] = {};      // 分母多項式の係数(最高次数は含まないことに注意)
    constexpr int m = 0;            // 分子多項式の次数
    constexpr float b[m+1] = {};    // 分子多項式の係数
    
    static float u[m+1] = {};
    static float y[n] = {};
    float output = 0.0f;
    u[m] = input;
    
    // 出力値の計算
    for(int i = 0; i <= m; i++)
    {
        output = output + b[i]*u[i];
    }
    for(int i = 0; i <= n-1; i++)
    {
        output = output - a[i]*y[i];
    }
    
    // 保持する値の更新
    for(int i = 0; i < m; i++)
    {
        u[i] = u[i+1];
    }
    for(int i = 0; i < n-1; i++)
    {
        y[i] = y[i+1];
    }
    y[n-1] = output;
    
    return output;
}

一応これでプロパーなパルス伝達関数をプログラムに落とし込むことができますが、ロボットをちょろっと動かす程度では色々効率が悪いコードなので、実際は以後の節で示すような個別の要素毎に実装することが多いです。

要素毎の実装例

積分器の実装

積分器のパルス伝達関数\frac{1}{z-1}となります。前節と同様に変形すると次のようになります。

\displaystyle{
y\slr{k}=x\slr{k-1}+y\slr{k-1}
}

C++風に落とし込むと次のようになります。

float integrator(float input)
{
    static float x = 0.0f;
    static float y = 0.0f;
    
    float res = x + y;
    
    y = res;
    x = input;
    
    return res;
}

ディジタルPID制御器の実装

積分器の実装で用いた考え方を応用します。簡単のため、制御則を次のようにします。

\displaystyle{
u\slr{k}=K_Pe\slr{k}+K_I\frac{z}{z-1}e\slr{k}+K_D\frac{z-1}{z}e\slr{k}
}

ただしe\slr{k}は偏差信号(目標値と出力値の差)とします。

積分項は前節で示した積分器と異なり、1サンプルの遅れがない形式での実装となっています。漸化式は次のようになります。

\displaystyle{
y_I\slr{k}=K_Ie\slr{k}+y_I\slr{k-1}
}

この形式ではパルス伝達関数\frac{K_Iz}{z-1}として見たときのものとなっていますが、次のようにすることで若干見通しが良くなります。

\displaystyle{
\eq{
y_I'\slr{k}&=e\slr{k}+y_I'\slr{k-1}\\
y_I\slr{k}&=K_Iy_I'\slr{k}
}
}

この形式ではパルス伝達関数\frac{z}{z-1}K_I倍している形となり同じ結果となります。

微分項は1サンプル前の偏差信号との差分となっています。よって、漸化式が次のようになります。

\displaystyle{
y_D\slr{k}=K_D\lr{e\slr{k}-e\slr{k-1}}
}

比例項は偏差信号の定数倍なので漸化式については割愛します。以上をまとめると、ディジタルPID制御器の漸化式が次のようになります。

\displaystyle{
\eq{
y_I'\slr{k}&=e\slr{k}+y_I'\slr{k-1}\\
u\slr{k}&=K_Pe\slr{k}+K_Iy_I'\slr{k}+K_D\lr{e\slr{k}-e\slr{k-1}}
}
}

C++風に落とし込むと次のようになります。

float PID(float input, float target)
{
    // input: 出力値
    // target: 目標値
    constexpr float Kp = 0.0f;   // Pゲイン
    constexpr float Ki = 0.0f;   // Iゲイン
    constexpr float Kd = 0.0f;   // Dゲイン

    static float error = 0.0f;   // 偏差信号 e[k]
    static float ierror = 0.0f;  // 積分項 y_I'[k]
    static float derror = 0.0f;  // 1サンプル前の偏差信号 e[k-1]
    static float output = 0.0f;  // 制御入力 u[k]

    error = target - input;     // 偏差信号=目標値-出力値
    ierror += error;            // 積分項の更新

    output = Kp*error + Ki*ierror + Kd*(error-derror);

    derror = error;

    return output;
}

参考まで、先に示したPID制御則の両辺にz-1を作用させることで速度型のPID制御則が得られ、積分項をキャンセルすることができます。一方で逆応答と呼ばれる望ましくない応答を示すことがあり、私は速度型ではない(位置型の)PID制御器を良く用いています。

まとめ

本稿ではパルス伝達関数を漸化式へ変形する方法について検討しました。また、C++風に実装した例も一緒に示しました。内容が基本的すぎるのか、手元にある制御理論の参考書には本稿のようなプログラムに落とし込む方法に関する記述が少ないように見受けられます。実装時に困っている誰かのお役に立てれば幸いです。

MATLABでいい感じにグラフを作る

概要

MATLABでいい感じにグラフを作る方法をいつも忘れてしまうのでメモしておきます。 CSVデータをMATLABに取り込んで、いい感じにグラフ化したものをトリミング済みのPDFで保存するまでの工程についてご説明します。

方法

データの準備

MATLABとグラフ化したいCSVデータを用意します。変なことをしない限り追加のToolbox等は不要であると思います。

なおデータについてはCSV形式でなくてもOKで、例えばSimulinkで何かのシミュレーションをしてワークスペースに持ってきたデータなども使えます。

データの取り込み

新規ライブスクリプトを作成し、CSVデータをreadmatrix関数で読み取ります。この際、'TrimNonNumeric'オプションをtrueにすると変な文字等が無視され、数値だけが読み込まれるようになります。私事ですが、この機能がなければ研究がかなりマズいことになってました。

例としてhoge.csvを取り込んで変数dataに格納する場合、コードは次のようになります。

data = readmatrix('hoge.csv', 'TrimNonNumeric', true);

取り込んだデータの処理

ここでは例としてCSVデータの1列目に時間、2列目に正弦波の振幅データが保存されているとします。 1列目のデータをx軸、2列目のデータをy軸にプロットし、軸ラベルとグリッドを表示するには

data = readmatrix('hoge.csv', 'TrimNonNumeric', true);

plot(data(:,1), data(:,2))
xlabel('Time[s]')
ylabel('Amplitude')
grid on

とします。ここまでのコードを実行すると、次のようなグラフが表示されます。

f:id:gui_robo:20220202223248p:plain
実行結果
データを可視化するだけであればここまでの工程で十分ですが、レポートや論文等に載せるとなると内容的に不足があります。 最低限、凡例を追加してフォントをTimes New Romanに揃えるなどしておきたいです。

グラフをいい感じにする

とりあえず凡例を先に追加しましょう。凡例はlegend関数で追加することができます。凡例内でTeX記法を使いたい場合は'Interpreter''latex'とし、フォントをTimes New Romanにしたい場合は'FontName''Times New Roman'とします。これは軸ラベルでも同様なので、コードを次のように書き換えます。

data = readmatrix('hoge.csv', 'TrimNonNumeric', true);

plot(data(:,1), data(:,2))
xlabel('Time $t$ [s]', 'Interpreter', 'latex', 'FontName', 'Times New Roman')
ylabel('Amplitude', 'Interpreter', 'latex', 'FontName', 'Times New Roman')
legend({'$\sin{t}$'}, 'Interpreter', 'latex', 'FontName', 'Times New Roman')
grid on

すると、次のようなグラフが表示されます。

f:id:gui_robo:20220202224427p:plain
実行結果
データがない部分も表示されてて少々気持ちが悪いので、xlim関数で表示する領域を制限します。ここでは0~2\piの範囲を指定します。

data = readmatrix('hoge.csv', 'TrimNonNumeric', true);

plot(data(:,1), data(:,2))
xlim([0 2*pi])
xlabel('Time $t$ [s]', 'Interpreter', 'latex', 'FontName', 'Times New Roman')
ylabel('Amplitude', 'Interpreter', 'latex', 'FontName', 'Times New Roman')
legend({'$\sin{t}$'}, 'Interpreter', 'latex', 'FontName', 'Times New Roman')
grid on

f:id:gui_robo:20220202225206p:plain
実行結果
これで大分マシなグラフになりました。ちなみにライブエディタ上で凡例をドラッグすると、その位置で凡例を表示するようなコードを生成してくれます。

いい感じにPDFで出力する

いい感じにグラフができたので、次はいい感じにPDFで出力します。グラフが表示されているウィンドウから直接出力しても良いのですが、余白なども一緒に出力されてしまい少々不便なのでexportgraphics関数を使います。ここではfigure.pdfとして出力します。

data = readmatrix('hoge.csv', 'TrimNonNumeric', true);

plot(data(:,1), data(:,2))
xlim([0 2*pi])
xlabel('Time $t$ [s]', 'Interpreter', 'latex', 'FontName', 'Times New Roman')
ylabel('Amplitude', 'Interpreter', 'latex', 'FontName', 'Times New Roman')
legend({'$\sin{t}$'}, 'Interpreter', 'latex', 'FontName', 'Times New Roman')
grid on
exportgraphics(gcf, 'figure.pdf', 'Resolution', 300)

すると、このようなトリミング済みのPDFファイルが出力されます。(以下はPDFファイルをPNGに変換したものです)

f:id:gui_robo:20220202231511p:plain
実行結果
基本的にはこのままで良いのですが、何らかの弾みで目盛のフォントがTimes New Romanではない何かになってしまう場合があるので対策を施す必要があります。ついでにグラフの大きさも比率で指定できるように修正します。フォントの問題はPDFで出力する直前にgca.FontName = 'Times New Roman';とすることで対策ができます。比率はget関数でグラフの位置を取得し、set関数でグラフの位置を改めて指定してあげることで調整することができます。横の長さを0.75倍、縦の長さを0.5倍にする例を以下に示します。

data = readmatrix('hoge.csv', 'TrimNonNumeric', true);

plot(data(:,1), data(:,2))
xlim([0 2*pi])
xlabel('Time $t$ [s]', 'Interpreter', 'latex', 'FontName', 'Times New Roman')
ylabel('Amplitude', 'Interpreter', 'latex', 'FontName', 'Times New Roman')
legend({'$\sin{t}$'}, 'Interpreter', 'latex', 'FontName', 'Times New Roman')
grid on
position = get(gcf, 'Position');
set(gcf, 'Position', [position(1) position(2) position(3)*0.75 position(4)*0.5])
gca.FontName = 'Times New Roman';
exportgraphics(gcf, 'figure.pdf', 'Resolution', 300)

すると、次のように出力されます。(以下はPDFファイルをPNGに変換したものです)

f:id:gui_robo:20220202231410p:plain
実行結果
このように、いい感じの大きさでいい感じにトリミングされたグラフのPDFファイルが得られました。

まとめ

本稿ではMATLABを用いていい感じにグラフを作成し、いい感じにトリミングがされたPDFファイルで出力する方法について説明しました。一度このライブスクリプトを作っておくとCSVファイルからグラフを作りたくなった時に非常に便利ですので、是非作成することをお勧めします。特にオシロスコープから出力される10000行を超えるようなCSVデータをExcelで逐一処理するのは時間的にも精神的にもキツいものがあります。(Excelでもいい感じにできる方法をご存知の方がいらっしゃれば是非教えてください)