コンテンツへスキップ

フィラメント菅時計

時計って家にあります? 私,引っ越したので無かったんです。

PCかスマホ見ればいいですし,時計を持ってない人は多いかも。 しかし,朝はギリギリまで寝ているので,スマホをわざわざポケットから取り出す時間すら勿体なかったりします。

時計が欲しい! しかもなるべくカッコイイ時計が欲しい!

そこで,欲求を整理した結果,自分が欲しい時計がamazonでは見つかりませんでした。なんてこった!! そんなわけで時計を作りました。

作ったの半年くらい前なんですけどね。作り方をざっくり紹介します。

ガラスの加工がうまくいかなかったのが残念。

目次

  • 欲求の整理
  • 全体構想と仕様追加
  • 開発環境
  • 回路の部品一覧
  • 回路とソースコード
  • タイマモジュールの使い方
  • GPSの使い方
  • IOエキスパンダ―のつなぎ方
  • フィラメント間の使い方
  • 木枠
  • 回路発注
  • 完成!
  • 雑記

欲求の整理

時計を作るにあたって,求める機能を羅列していきます。

  • 見た目をカッコよくしたい → 木材で枠を作る。フィラメント菅を使用。
  • 電池交換したくない → コンセントから給電
  • 手動で時間を合わせるのが面倒 → 電波等で時間を公正

ニキシー菅を使って作りたかったけど,ニキシー菅はかなり高電圧らしい。5Vで作れた方が安心なので,フィラメント菅に変更しました。敗北 +1。

全体の構想と仕様追加

また,基本的な部品はこれを使用。これにGPSをくっつけます。 6桁表示・フィラメント管時計キット -nixie-tube.com さん

コントローラ(マイコン)部分は私が慣れているRaspberry Pi Picoを使用します。

全体の構成はこんな感じ。

電波で公正ですが,なるべく簡単に作りたいという気持ちがあり,GPSでやります。

GPS受信キット 1PPS出力尽き 「みちびき」2機受信対応

GPSから時刻を取得して時刻表示を更新するタイミングは下記にします。

  • 電源投入時
  • スイッチ(SW)押下時
  • 内部で持っている時刻が12時0分0秒の時

開発環境

  • 開発PC: windows
  • 開発対象: Raspberry Pi Pico
  • 言語: MicroPython
  • 開発環境: Thonny
  • その他: Mini GPS_r1.20 (GPSの設定に使う)
  • その他: Power GPS_r1.00 (GPSの設定に使う)

回路の部品一覧

NAMEQuantitymemoURL
Raspberry Pi Pico1https://akizukidenshi.com/catalog/g/gM-16132/
IV-96フィラメント菅https://nixie-tube.com/shop/1_76.html
5V2A11Aで十分https://akizukidenshi.com/catalog/g/gM-01801/
DCジャック12.1mmhttps://akizukidenshi.com/catalog/g/gC-09408/
タクトスイッチ4色は何でもhttps://akizukidenshi.com/catalog/g/gP-03647/
ボタン電池11.5Vhttps://www.amazon.co.jp/dp/B003X5WJR6?tag=amz-mkt-edg-jp-22
電池ホルダ(LR44用)1https://akizukidenshi.com/catalog/g/gP-08208/
ICソケット18pin1https://akizukidenshi.com/catalog/g/gP-00008/
ICソケット8pin1https://akizukidenshi.com/catalog/g/gP-00017/
ICソケット28pin3https://akizukidenshi.com/catalog/g/gP-00013/
DS1307+1RTC(タイムキーパー)https://akizukidenshi.com/catalog/g/gI-06949/
MCP230173I/Oエキスパンダーhttps://akizukidenshi.com/catalog/g/gI-09486/
水晶発振子32.768kHz1https://akizukidenshi.com/catalog/g/gP-04005/
10kΩ5https://akizukidenshi.com/catalog/g/gR-25103/
1kΩ2I2Cバス用https://akizukidenshi.com/catalog/g/gR-25102/
15Ω6https://akizukidenshi.com/catalog/g/gR-09429/
0.1µF6https://akizukidenshi.com/catalog/g/gP-00090/
M3ねじ適量
スペーサー適量
GOS受信機キット1https://akizukidenshi.com/catalog/g/gK-09991/
ボタン電池1予備https://amzn.to/3oIKaik
基板1PCBwayでプリントしてもらいました。

過不足あるかもしれないけど御愛嬌。

回路とソースコード

私のgithubで公開したはず

回路は watch.pdfです。

タイマモジュール

DS1307+を使います。どうやら内部のメモリに格納された値が時間の初期値で,そこからカウントアップしていく感じらしいですね。

時間を合わせるには,このメモリに時間を上書きしてあげます。

ドライバーですが,Micropythonで簡単に使えるライブラリがgithubに上がってるので使わせていただきます。

書き込みなどは下記のgithubの関数を使うのが簡単です。

micropython-tinyrtc-i2c -github

使い方は簡単,「ds1307.py」をクローンして,picoに保存してあげましょう。それで準備完了。あとは main.py 内でインクルードしたりして,普通に関数をコールすればOK。

下記も参照。

注意点ですが,タイマモジュールに時間を書き込むときは2進化10進法表記の整数にしないといけません。この後出てくるGPSはASCIIで時刻を取得するので,変換してあげましょう。

なお,メモリの値は,電源供給が絶えると消えてしまいます。が,私の設計ではGPSで取得して上書きするので,電池追加等はしていません。

GPS

下記を設定

  • 5Hzで時刻を受信
  • GPZDAモード

GPZDAモードは日付と時刻だけが流れてきます。受信データはASCIIコード。 ホットスタンバイで,ずーっと受信します。消費電力など知るか。

仕様について。下記の3つの条件が一つでも満たされたとき,GPS情報を読み込むように設計しました。

  • 電源投入時
  • タイマモジュール が保持している時刻が0時0分0秒のとき
  • push switch が押下されたとき

GPSの使い方

GPSは色々と受信できます(位置情報とか)が,日付と時刻のみのモードに設定します。ボーレートや更新周波数も設定します。

GPS受信キット 1PPS出力尽き 「みちびき」2機受信対応

秋月のサイトに,GPS設定用ソフトのリンクが張ってあります。

受信するデータの形状はこんな感じの33文字です。ただし,時間は本初子午線基準なので,日本時間にするためには 9 時間足してあげる必要があります。

$GPZDA,131003.400,28,10,2022,,*5B

githubで共有した302行目でGPSを読み込んでいます。 次の行のcorrect_time(buff, rtc_write)の引数ですが,buffは302行目で読み込んだ値,rtc_writeは書き込み先(つまりタイマモジュールに対応するオブジェクト)です。

IOエキスパンダ―

GPIOピンを増やすICです。下記のようにI2Cで結線してあげればOKです。

I2Cの結線
回路一部抜粋

A0, A1, A2 の3ピンでスレーブアドレスを指定できます。Highが1, Lowが 0で,3bitなので最大で8個のMCP23017が繋げるってことですね。 (A0, A1, A2)=(0,0,0)の時,アドレスは0x20になります。

フィラメント菅の使い方

※フィラメント菅の回路図記号が分からなかったので(存在するんですか?)代わりに7セグで作りました。

回路一部抜粋

フィラメント菅には制御ピン8本と電源ピン(コモン)1本の計9ピンあります。

電源は5VでOK。コモンに5Vを供給しておいて,制御ピン(IOエキスパンダ―MCP23017に繋いである)を0Vにすると,電流が流れて対応するセグメントが光ります。

フィラメント菅の実験

木の枠

やっぱり3Dプリンタより木の方がカッコイイよね。

ところで,趣味で CAD 使う時って皆さん何を使ってるんですか?

こんなに単純ならCAD要らんやろって? CADなしで物を作るなどありえん……

自分は oneshapeを使ってみました。 インストール不要ですし,履歴型なので操作感がsolidworksに似ていて使いやすい。長さの測定方法がよく分からなかったのでそこだけイマイチでした。

多分下記リンクで飛べば,自分が作ったデータが見れるはず。

onshape

CAD

これに合わせて切っていきました。切る/穴を空ける/削る。 ドリルとのこぎりと,ガラスカッターが必要です。

水溶性ニス(ダークブラウン) ガラス切る

ガラスはガラスカッターで傷を付けた後,板チョコのように割って加工するんですが,上手くカットできませんでした。当然です,板チョコですら上手く割れないじゃないですか。

自分はガラスカッター以外はホームセンターで全部買いました。

・ガラスカッター & オイル(左端2個): 使いやすかったかと言われると微妙。普通なのでは。

・ニス(真ん中): 二度塗りしました。塗って乾かすだけなので楽でした。色も良い感じ。

・ドリル(右端): ドリルって何が良いんだか分からないのでとりあえず BOSCH にしました。小さい木材を削る分には全く問題無い,使い勝手がいいドリルと言う印象でした。

・ドリルスタンド(右端): ドリルを固定してボール盤みたいにして使ってます。小さい木材を固定するのはちょっと工夫が必要ですが,まぁ大丈夫でしょう。

金が溜まったら卓上フライスが欲しい。

回路発注

PCBway で注文しました。注文時にオペレーターにチャットで繋がって基板チェックが入って,新鮮でした。後でメールでやり取りとかしないんだなぁと。一発OKだったのでほぼ会話なしでしたし,届くまでも1週間しなかったので,かなり良かったです。 ただし,たしか 5枚 $30 くらいだったんですが,ちょうど円安の時期だったので5500円くらいに…。

んで,出来た。

完成!

部品値段 [円]
プリント基板5493
フィラメント菅時計キット11600
GPS受信機キット2200
木材・ハケ・ニス・ガラス1526
合計13419

他にのこぎりとかドリルとか買ったので結構な額が動いた。

夜の姿はこんな感じ。

夜のフィラメント菅の暖かい輝き
夜のフィラメント菅

雑記

利用させてもらった ds1307.py は MITライセンス。こういう無償で公開しているコードってすごく有難いですし有難すぎて投げ銭したい気持ち。github さんスパチャ機能を実装してくれないかな。

追記 (2023/5/13)

みちびき受信キット (GPS) の電池が無くなると動作がおかしくなります。

詳細ですが,GPS はホットスタンバイでずっと正確な時間を受信しており,ラズピコが時々読みに行くという設計です。GPS は受信する信号の種類やボーレートを設定する必要があり,秋月のページに載っている設定ソフトであらかじめ設定します。そして,設定を保持するために,ボタン電池が付いています。この電池が無くなると,設定が初期化されて,ラズピコが読みたいデータ形式ではなくなってしまい,結果,動作がおかしくなってしまいます。(たぶん 11:59:59 から時間が更新されなくなります。)

つまり,「電池交換したくない → コンセントから給電」という要求は達成できていません!!! くやしい!!!!! 

とはいえ,正確な時間 or 停止 なので異常が分かり易くて使い勝手は良いのかなと思います。「いつの間にか時計が30分遅れていた! 遅刻だ!」が一番ヤバいと思いますので。なので,いったんは保留にして,今後もし Ver 2. を設計することになったら修正したいと思います。

本記事は学校の課題をプログラムで楽してこなそうとした際のメモを編集したものです。

2020/04/11
本記事は学校の課題をプログラムで楽してこなそうとした際のメモを編集したものです。レポートの面影はありません。

目次

  • 運動方程式を求める
    • モデル
    • 式変形用コード
    • 運動方程式
  • シミュレーションしてみる
    • 順運動学、逆運動学
    • 順逆動力学計算用コード
    • 特異点
  • 雑記

運動方程式を求める

※参考1-1のままやって一致すれば正しく出来ました、ということにしています。

モデル

2リンクマニピュレータ。x-y軸の原点をアームの根元に一致させた。

上図のような2リンクマニピュレータを考えます。G_0=(x_0,y_0), G_1=(x_0,y_1), m_0, m_1, l_0, l_1をそれぞれ第一リンク、第二リンクの重心、質量、長さとします。また、リンク端からそれぞれの重心までの長さをそれぞれl_g0, l_g1としています。

$$l_{gi}=\frac{1}{2}l_i  (i=0,1)$$

ラグランジュの運動方程式に当てはめて運動方程式を求めます。

ラグランジュの運動方程式:

$$ \frac{d}{dt}(\frac{\partial L}{\partial\dot q_i})-\frac{\partial L}{\partial q_i}= Q_i (i =1,2,..,f)$$


$$L=T-U$$

あるいは、

$$ \frac{d}{dt}(\frac{\partial T}{\partial\dot q})-\frac{\partial T}{\partial q_i}+\frac{\partial U}{\partial q_i}+\frac{\partial D}{\partial \dot{q_i}}= Q_i (i =1,2,..,f)$$

L:ラグランジアン

Q:非保存力による一般化力

f:自由度

q:一般化座標

式変形用コード

ラグランジュ~でやると無限微分地獄で計算ミスのリスクが高いですね。少しの変更でものすごく時間がかかるのは嫌なので、Pythonで式変形する方法をやってみたいと思います。こういうときはmatlabっぽく書けるSimPyが便利 (雑記1.)。

  • 式変形
simplify()
>from sympy import *
>x, y, z = symbols('x y z')
>init_printing(use_unicode=True)
>simplify(sin(x)**2 + cos(x)**2)
1
>simplify((x**3 + x**2 - x - 1)/(x**2 + 2*x + 1))
x - 1
>simplify(gamma(x)/gamma(x - 2))
(x - 2)⋅(x - 1)

式を単純化する関数で、計算量が不必要に大きくなることがあることに注意が必要です。神。

Simplification -SymPy1.5.1

  • 解く
sp.solve (Eq)

引数に=0になる関数を入力します。

Solvers -SymPy 1.5.1

  • 微分
diff(func, t)

第二引数に何で微分するのかを入れます。

Calculus -SymPy 1.5.1

参考=>1-2、1-3、1-4

  • コード

環境:

  • Python 3.7.3
  • numpy 1.16.4
  • sympy 1.4

https://github.com/inomatly/robot_arm/blob/master/solv_lagrange.ipynb

一応.pyも置いてありますが jupyter notebok で見ることを前提にしています。

式を単純化するだけのコードです。計算結果はTEXで出しています。

運動方程式

2リンクマニピュレータ(再)

各リンクのx軸とのなす角τ_0, τ_1は

$$\tau_0=\theta_0 ...(1-1)$$

$$\tau_1=\theta_0+\theta_1 ...(1-2)$$

です。 また、第一リンクの重心位置(x_0, y_0)は

$$\begin{bmatrix}x_0 \cr y_0\end{bmatrix}=\begin{bmatrix}l_{g0}cos\theta_0\cr l_{g0}sin\theta_0\end{bmatrix} ...(1-3)$$

で表せます。また、第二リンクの重心位置(x_1,y_1)は

$$\begin{bmatrix}x_1 \cr y_1\end{bmatrix}=\begin{bmatrix}l_{g0}cos\theta_0+ l_{g1}cos(\theta_0+\theta_1)\cr l_{g0}sin\theta_0+ l_{g1}sin(\theta_0+\theta_1)\end{bmatrix} ...(1-4)$$

で表せる。各リンクの運動エネルギー、位置エネルギー、損失エネルギー、一般化力をT_0, T_1, U_0, U_1, D_0, D_1, Q_0, Q_1、一般化座標q_0, q_1として、ラグランジュの運動方程式

$$ \frac{d}{dt}(\frac{\partial T}{\partial\dot q})-\frac{\partial T}{\partial q_i}+\frac{\partial U}{\partial q_i}+\frac{\partial D}{\partial \dot{q_i}}= Q_i (i =1,2) ...(1-5)$$

を用いて各リンクの運動方程式を求める。

ここで、一般化座標はq_i=θ_i (i=0,1)である。各リンクの慣性モーメントをI_0, I_1,関節の粘性摩擦係数をd_0, d_1としてT_0, T_1, U_0, U_1, D_0, D_1を求める。

$$T_0=\frac{1}{2} \left(I_{0} + l_{g0}^{2} m_{0}\right) \left(\frac{d}{d t} {q_{0}}{\left(t \right)}\right)^{2} ...(1-6)$$

$$U_0=g l_{g0} m_{0} \sin{\left({q_{0}}{\left(t \right)} \right)} ...(1-7)$$

$$D_0=\frac{d_{0} \left(\frac{d}{d t} {q_{0}}{\left(t \right)}\right)^{2}}{2} ...(1-8)$$

$$T_1=\frac{1}{2} I_{1} \left(\frac{d}{d t} {q_{0}}{\left(t \right)} + \frac{d}{d t} {q_{1}}{\left(t \right)}\right)^{2} \\+ \frac{1}{2} m_{1} \left(l_{0}^{2} \left(\frac{d}{d t} {q_{0}}{\left(t \right)}\right)^{2} + 2 l_{0} l_{g1} \cos{\left({q_{1}}{\left(t \right)} \right)} \left(\frac{d}{d t} {q_{0}}{\left(t \right)}\right)^{2} \\+ 2 l_{0} l_{g1} \cos{\left({q_{1}}{\left(t \right)} \right)} \frac{d}{d t} {q_{0}}{\left(t \right)} \frac{d}{d t} {q_{1}}{\left(t \right)} + l_{g1}^{2} \left(\frac{d}{d t} {q_{0}}{\left(t \right)}\right)^{2} \\+ 2 l_{g1}^{2} \frac{d}{d t} {q_{0}}{\left(t \right)} \frac{d}{d t} {q_{1}}{\left(t \right)} + l_{g1}^{2} \left(\frac{d}{d t} {q_{1}}{\left(t \right)}\right)^{2}\right) ...(1-9)$$

$$U_1=g m_{1} \left(l_{0} \sin{\left({q_{0}}{\left(t \right)} \right)} + l_{g1} \sin{\left({q_{0}}{\left(t \right)} + {q_{1}}{\left(t \right)} \right)}\right) ...(1-10)$$

$$D_1=\frac{d_{0} \left(\frac{d}{d t} {q_{1}}{\left(t \right)}\right)^{2}}{2} ...(1-11)$$

また、全体の運動エネルギー、位置エネルギー、損失エネルギーT, U, Dは

$$T=T_0+T_1 ...(1-12)$$

$$U=U_0+U_1 ...(1-13)$$

$$T=D_0+D_1 ...(1-14)$$

これより、

$$\frac{\partial T}{\partial \dot{q_0}}=I_{1} \left(\frac{d}{d t} {q_{0}}{\left(t \right)} + \frac{d}{d t} {q_{1}}{\left(t \right)}\right) + m_{1} \left(l_{0}^{2} \frac{d}{d t} {q_{0}}{\left(t \right)} \\+ 2 l_{0} l_{g1} \cos{\left({q_{1}}{\left(t \right)} \right)} \frac{d}{d t} {q_{0}}{\left(t \right)} + l_{0} l_{g1} \cos{\left({q_{1}}{\left(t \right)} \right)} \frac{d}{d t} {q_{1}}{\left(t \right)} + l_{g1}^{2} \frac{d}{d t} {q_{0}}{\left(t \right)} \\+ l_{g1}^{2} \frac{d}{d t} {q_{1}}{\left(t \right)}\right) +  \left(I_{0} + l_{g0}^{2} m_{0}\right) \frac{d}{d t} {q_{0}}{\left(t \right)}  ...(1-15)$$

$$\frac{d}{dt}(\frac{\partial T}{\partial \dot{q_0}})=I_{1} \left(\frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} + \frac{d^{2}}{d t^{2}} {q_{1}}{\left(t \right)}\right) + m_{1} \left(l_{0}^{2} \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} \\- 2 l_{0} l_{g1} \sin{\left({q_{1}}{\left(t \right)} \right)} \frac{d}{d t} {q_{0}}{\left(t \right)} \frac{d}{d t} {q_{1}}{\left(t \right)} - l_{0} l_{g1} \sin{\left({q_{1}}{\left(t \right)} \right)} \left(\frac{d}{d t} {q_{1}}{\left(t \right)}\right)^{2} \\+ 2 l_{0} l_{g1} \cos{\left({q_{1}}{\left(t \right)} \right)} \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} + l_{0} l_{g1} \cos{\left({q_{1}}{\left(t \right)} \right)} \frac{d^{2}}{d t^{2}} {q_{1}}{\left(t \right)} + l_{g1}^{2} \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} \\+ l_{g1}^{2} \frac{d^{2}}{d t^{2}} {q_{1}}{\left(t \right)}\right) +  \left(I_{0} + l_{g0}^{2} m_{0}\right) \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} ...(1-16)$$

$$\frac{\partial T}{\partial q_0}=0 ...(1-17)$$

$$\frac{\partial U}{\partial q_0}=g \left(l_{g0} m_{0} \cos{\left({q_{0}}{\left(t \right)} \right)} + m_{1} \left(l_{0} \cos{\left({q_{0}}{\left(t \right)} \right)} + l_{g1} \cos{\left({q_{0}}{\left(t \right)} + {q_{1}}{\left(t \right)} \right)}\right)\right) ..(1-18)$$

$$\frac{\partial D}{\partial \dot{q_0}}=d_{0} \frac{d}{d t} {q_{0}}{\left(t \right)} ...(1-19)$$

$$∴ Q_0=I_{1} \left(\frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} + \frac{d^{2}}{d t^{2}} {q_{1}}{\left(t \right)}\right) + d_{0} \frac{d}{d t} {q_{0}}{\left(t \right)} \\+ g \left(l_{g0} m_{0} \cos{\left({q_{0}}{\left(t \right)} \right)} + m_{1} \left(l_{0} \cos{\left({q_{0}}{\left(t \right)} \right)} + l_{g1} \cos{\left({q_{0}}{\left(t \right)} + {q_{1}}{\left(t \right)} \right)}\right)\right) \\+ m_{1} \left(l_{0}^{2} \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} - 2 l_{0} l_{g1} \sin{\left({q_{1}}{\left(t \right)} \right)} \frac{d}{d t} {q_{0}}{\left(t \right)} \frac{d}{d t} {q_{1}}{\left(t \right)} - l_{0} l_{g1} \sin{\left({q_{1}}{\left(t \right)} \right)} \left(\frac{d}{d t} {q_{1}}{\left(t \right)}\right)^{2} \\+ 2 l_{0} l_{g1} \cos{\left({q_{1}}{\left(t \right)} \right)} \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} + l_{0} l_{g1} \cos{\left({q_{1}}{\left(t \right)} \right)} \frac{d^{2}}{d t^{2}} {q_{1}}{\left(t \right)} + l_{g1}^{2} \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} \\+ l_{g1}^{2} \frac{d^{2}}{d t^{2}} {q_{1}}{\left(t \right)}\right) +  \left(I_{0} + l_{g0}^{2} m_{0}\right) \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} ...(1-20)$$

$$\frac{\partial T}{\partial \dot{q_1}}=I_{1} \left(\frac{d}{d t} {q_{0}}{\left(t \right)} + \frac{d}{d t} {q_{1}}{\left(t \right)}\right) \\+ l_{g1} m_{1} \left(l_{0} \cos{\left({q_{1}}{\left(t \right)} \right)} \frac{d}{d t} {q_{0}}{\left(t \right)} + l_{g1} \frac{d}{d t} {q_{0}}{\left(t \right)} + l_{g1} \frac{d}{d t} {q_{1}}{\left(t \right)}\right) ...(1-21)$$

$$\frac{d}{dt}(\frac{\partial T}{\partial \dot{q_1}})=I_{1} \left(\frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} + \frac{d^{2}}{d t^{2}} {q_{1}}{\left(t \right)}\right) + l_{g1} m_{1} \left(- l_{0} \sin{\left({q_{1}}{\left(t \right)} \right)} \frac{d}{d t} {q_{0}}{\left(t \right)} \frac{d}{d t} {q_{1}}{\left(t \right)} \\+ l_{0} \cos{\left({q_{1}}{\left(t \right)} \right)} \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} + l_{g1} \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} + l_{g1} \frac{d^{2}}{d t^{2}} {q_{1}}{\left(t \right)}\right) ...(1-22)$$

$$\frac{\partial T}{\partial q_1}=-  l_{0} l_{g1} m_{1} \left(\frac{d}{d t} {q_{0}}{\left(t \right)} + \frac{d}{d t} {q_{1}}{\left(t \right)}\right) \sin{\left({q_{1}}{\left(t \right)} \right)} \frac{d}{d t} {q_{0}}{\left(t \right)} ...(1-23)$$

$$\frac{\partial U}{\partial q_1}=g l_{g1} m_{1} \cos{\left({q_{0}}{\left(t \right)} + {q_{1}}{\left(t \right)} \right)} ...(1-24)$$

$$\frac{\partial D}{\partial \dot{q_1}}=d_{0} \frac{d}{d t} {q_{1}}{\left(t \right)} ...(1-25)$$

$$∴ Q_1= I_{1} \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} + I_{1} \frac{d^{2}}{d t^{2}} {q_{1}}{\left(t \right)} + d_{0} \frac{d}{d t} {q_{1}}{\left(t \right)} +\\ g l_{g1} m_{1} \cos{\left({q_{0}}{\left(t \right)} + {q_{1}}{\left(t \right)} \right)} +  l_{0} l_{g1} m_{1} \sin{\left({q_{1}}{\left(t \right)} \right)} \left(\frac{d}{d t} {q_{0}}{\left(t \right)}\right)^{2} +\\ l_{0} l_{g1} m_{1} \cos{\left({q_{1}}{\left(t \right)} \right)} \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} +  l_{g1}^{2} m_{1} \frac{d^{2}}{d t^{2}} {q_{0}}{\left(t \right)} + l_{g1}^{2} m_{1} \frac{d^{2}}{d t^{2}} {q_{1}}{\left(t \right)} ...(1-26)$$

以上を行列式の形にすると、

$$\begin{bmatrix}Q_0 \cr Q_1\end{bmatrix}=\\ \begin{bmatrix}I_0+m_0l_{g0}^2+I_1+m_1(l_0^2+l_{g1}^2+2l_0l_{g1}cos\theta_1)& I_1+m_1(l_{g1}^2+l_0l_{g1}cos\theta_1)\cr I_1+m_1(l_{g1}^2+l_0l_{g1}cos\theta_1)& I_1+m_1 l_{g1}^2\end{bmatrix}\begin{bmatrix}\ddot{\theta_0} \cr \ddot{\theta_1}\end{bmatrix}\\+\begin{bmatrix}d_0& 0\cr 0& d_1\end{bmatrix}\begin{bmatrix}\dot{\theta_0} \cr \dot{\theta_1}\end{bmatrix}\\+\begin{bmatrix}-m_1l_0l_{g1}(2\dot{\theta_0}\dot{\theta_1}+\dot{\theta_1}^2)sin\theta_1& m_0gl_{g0}cos(\theta_0)+m_1g(l_{0}cos\theta_0+l_{g1}cos(\theta_0+\theta_1))\cr m_1l_0l_{g1}\dot{\theta_0}^2sin\theta_1& m_1gl_{g1}cos(\theta_0+\theta_1)\end{bmatrix} \\...(1-27)$$

参考資料と一致しました。OK!! (雑記2.)

simplyfy式変形後は順番がめちゃくちゃなので綺麗に行列の形に直すのはかなり面倒です。気をつけてください。(雑記3.)

ここまでの参考

シミュレーション

動く図を作っていきます。

順運動学と逆運動学

第二リンクの先端位置(x_0,y_0)は

$$\begin{bmatrix}x_0 \cr y_0\end{bmatrix}=\begin{bmatrix}l_{0}cos\theta_0\cr l_{0}sin\theta_0\end{bmatrix} ...(2-1)$$

第二リンクの先端位置(x_1,y_1)は

$$\begin{bmatrix}x \cr y\end{bmatrix}=\begin{bmatrix}x_1 \cr y_1\end{bmatrix}=\begin{bmatrix}l_{0}cos\theta_0+ l_{1}cos(\theta_0+\theta_1)\cr l_{0}sin\theta_0+ l_{1}sin(\theta_0+\theta_1)\end{bmatrix}...(2-2)$$

これを解いていきます。移項して,

$$x-l_{0}cos\theta_0= l_{1}cos(\theta_0+\theta_1)...(2-3)$$

$$y-l_{0}sin\theta_0= l_{1}sin(\theta_0+\theta_1) ...(2-4)$$

どちらも両辺2乗し、2式を足し合わせます。

$$x^2+y^2+l^2_0-2l_0(xcos\theta_0+ysin\theta_0)=l^2_1...(2-5)$$

cos,sinに関してまとめると,

$$\sqrt{x^2+y^2}cos(\theta_0+\alpha)=\frac{x^2+y^2+l^2_0-l^2_1}{2l_0}...(2-6)$$

ただし,

$$tan( \alpha)=\frac{y}{x}...(2-7)$$

$$∴ \theta_0=-\alpha\pm cos^{-1}(\frac{x^2+y^2+l^2_0-l^2_1}{2l^2_0\sqrt{x^2+y^2}})...(2-8)$$

次にθ_1を求めます。

(2-3)/(2-4)より,

$$\frac{y-l_{0}sin\theta_0}{x-l_{0}cos\theta_0}=tan(\theta_0+\theta_1)...(2-9)$$

$$∴\theta_1=-\theta_0+tan^{-1}(\frac{y-l_{0}sin\theta_0}{x-l_{0}cos\theta_0})...(2-10)$$

  • 参考

2-1.2リンクマニピュレータの軌道追従制御 -qiita

2-2.【Python】2リンクマニピュレータの逆運動学シミュレーション -西住工房

2-3.大分大学工学部福祉環境工学科メカトロニクスコース松尾研究室ゼミ資料"MATLAB による 2 リンクロボットマニピュレータ制御のシミュレーション"

順逆運動学計算用コード

  • そも
%matplotlib inline 
%matplotlib notebook

って何ですか、ということ。jupyter内で図を見えてくれるinlineは良く使います。使わなくても出るような気がするけど、出ない時にはとりあえず書き加える感じ。

一方notebookは編集可能らしい。アイコンをタッチしてから右クリックでドラッグしたり、いろんな操作ができ図を弄れる、上の電源ボタンみたいなもので画像を固定できる。

=>参考2-1、2-2

  • wedget

jupyter widget

公式のUsing~を見てみます。

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

@interact(amp=(0.1, 4.0, 0.1), omega=(0.1, 4.0, 0.1), phase=(-np.pi, np.pi, 0.1), 
          fn = {'sin': np.sin, 'cos': np.cos, 'tan': np.tan})
def h(amp=1.0, omega=1.0, phase=0.0, fn=np.sin):
    domain=[-np.pi, np.pi]
    x = np.linspace(domain[0], domain[1], 100)
    y  = amp * fn(omega * x + phase)
    plt.plot(x, y)
    plt.plot(-phase/omega, 0, 'or')
    plt.xlim(domain)
    plt.ylim([-4, 4])

x=(最小,最大,ステップ)はinteractでも設定でき、初期設定としてinteractを使用したい場合はデコレータとして使用出来る。辞書型で与えると選択肢に出来る。

  • コード 2

https://github.com/inomatly/robot_arm/blob/master/arm_sim.ipynb

一応.pyも置いてありますが jupyter notebok で見ることを前提にしています。

動いている様子:

楽しい。でもめっちゃ重い。(雑記3.)

このとき、(2-9)の±によって解(すなわち姿勢)は2通りあります。たとえば(1,1)は間接が(1,0)にある場合と(0,1)にある場合が考えられます。今回は計算を簡単にする為に1通りに統一しています。

特異点に関して

ヤコビ行列=0になるような姿勢は特異姿勢と呼ばれ、その点は特異点と呼ばれる。

(1)式を微分するとヤコビ行列Jは

$$\begin{bmatrix}\dot{x} \cr \dot{y}\end{bmatrix}=\begin{bmatrix}-l_{0}sin\theta_0 - l_{1}sin(\theta_0+\theta_1) & - l_{1}sin(\theta_0+\theta_1) \cr l_{0}cos\theta_0+ l_{1}cos(\theta_0+\theta_1) & l_{1}cos(\theta_0+\theta_1)\end{bmatrix}\begin{bmatrix}\dot{\theta_0} \cr \dot{\theta_1}\end{bmatrix}...(1)$$

$$∴ J=\begin{bmatrix}-l_{0}sin\theta_0 - l_{1}sin(\theta_0+\theta_1) & - l_{1}sin(\theta_0+\theta_1) \cr l_{0}cos\theta_0+ l_{1}cos(\theta_0+\theta_1) & l_{1}cos(\theta_0+\theta_1)\end{bmatrix}$$

特異点では

$$det J = l_0l_1sin\theta_1=0$$

$$∴ \theta_1=n\pi$$

n=0,1,2。この場合、たとえば(x,y) = (-2/√2,-2/√2)の伸びきった姿勢のような姿勢や、(0,0)のような縮こまった姿勢を示します。それ以上伸びたり縮んだり出来ない出来ませんから、一般に特異点では自由度が下がってることになります。

目標点が特異点を通る場合は問題ありませんが、特異点付近を通るときはアームが急激に動くため注意が必要です。(雑記5.)=>2-3

参考 2

2.1 Jupyter Notebookにおけるmatplotlib -Pythonオンライン学習サービスPyQ(パイキュー)

2-2 jupyter notebookにmatplotlibを使ってグラフを描画する -山本隆の開発日誌

2-3「ロボット工学 ー機械システムのベクトル解析ー, 広瀬茂男著 裳華房 2003年」の10章

雑記

  1. コードに関して、「pythonじゃなくてmatlabとかmathematicaでいいんじゃないの」とも思いますが。新しく覚えるおが面倒なのと、学生のうちは安価ですが将来的には金がかかりますのでなるべくオープンソースを使っていきたいという意思表示です。オープンソース贔屓です。判官贔屓的な。
  2. 「まだ微分で消耗してるの?」正月休みの1/3に手でゴリゴリ計算して、参考にしたのが正しいっぽいことを確認してからコード書いたので二度手間ですが、今後はラグランジュ方程式を使いまわせるのでOKということにしました。TEXコードまで出してくれるの神ですね。禁断の果実という感じがします。
  3. ラグランジュ方程式は使えるようになったかな(わからないけど)と思いますが、お恥ずかしながらベクトル的な解法に苦手意識があります。これからやっていきたいと思います。
  4. シミュレーションは、jupyter上の位置の問題なのか、かくかくしますね。難しい。動かしているときめっちゃチカチカするのは何故なのか。計算が重いんだろうか?だれかプログラミングおしえて。
  5. ひよこの真似やワクワクっ!な動作のように脇を開閉する動きはこの類い...ではないですね。人間の腕は自由度のバケモノですから。ワクワクの時の手首が特異点かと言えばそんなわけない。

画像から、全体の中心点と模様展の半径、角度を取得してファイルで出力する方法です。opencvを使用します。

画像から、全体の中心点と模様(濃い青丸)の半径、角度を取得したので、メモを修正して公開します。最終的に極座標グラフにします。

目次

  • 目的
  • 手順
  • 環境
  • コード
  • 解説

目的

最近、画像から半径と角度をたくさん取得する必要に駆られました。その作業はかなり手間なので自動化してやろうというのが目的です。

私の使用する画像をそのまま使うわけにはいかないので、似たような画像をいらすとやで拾ってきました。輪郭があんまり丸くなかったので加工しています。

螺旋の貝殻のイラスト

この画像から全体の中心点と模様(濃い青丸)の半径、角度を取得します。

手順

  1. グレースケール&位置座標を取得
  2. 円の取得の中心点の座標を取得
  3. 中心点を基準にして (rcosθ,rsinθ)で表現
  4. 各点(0~i)を(r, θ)で表記
  5. csvで出力

環境

  • Python 3.8.0
  • conda 4.8.0
  • opencv 4.1.2
  • matplotlib 3.1.2
  • numpy 1.17.3

コード

import cv2
import matplotlib.pyplot as plt
import numpy as np
import csv
import math
import sys

"""
あらかじめ同じフォルダに「white.png」と「読み込み対象.png」をおいておく必要がある。
芯の中心を原点にして各点(小円)の半径、角度を取得する。
"""
#input
input='rasen'
img = cv2.imread('input'+input+'.png',cv2.IMREAD_COLOR)#ndarray.グレイスケールで読み込みとエラー。
white = cv2.imread('white.png',0)#ndarray

#事前処理
img = cv2.medianBlur(img, 5) #メディアンフィルタを用いて画像を平滑化
cv2.imwrite("output/img.png",img)#debag1。outputフォルダに作成される。
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imwrite("output/gray.png",gray)#debag2
edge = cv2.Canny(gray, 20, 40)
cv2.imwrite("output/edge.png",edge)#debag3
#中心円の取得
circles = cv2.HoughCircles(edge, cv2.HOUGH_GRADIENT, 1, 1200, param1=60, param2=20, minRadius = 800, maxRadius =1000)
#print(circles)
circles = np.uint16(np.around(circles))
x_c=np.int64(circles[0][0][0])
y_c=-np.int64(circles[0][0][1])
r_c=np.int64(circles[0][0][2])
center =[x_c,y_c]
norm_c= np.linalg.norm(center, ord=2)
for i in circles[0,:]:
    # 円を描く
    cv2.circle(img,(i[0],i[1]),i[2],(0,0,0),4)
#小円の取得
circles = cv2.HoughCircles(edge, cv2.HOUGH_GRADIENT, 1, 200,param1=60,param2=20, minRadius = 15 ,maxRadius = 50) #param1は色の違い、param2は形の雑さ
circles = np.uint16(np.around(circles))#整数になり、16bitに変換された配列になる。
j=0
for i in circles[0,:]:
    # 小円を描く
    j+=1
    cv2.circle(img,(i[0],i[1]),i[2],(0,0,0),4)
print(str(j)+"points")

#データの整形
#radiusは不要
radius=circles[:,:,2]
radius=np.array(radius[0,:])
x=circles[:,:,0]
x=x[0,:]
y=circles[:,:,1]
y=y[0,:]

#csvファイルの作成
xs=[]
ys=[]
points=[]
with open('output/'+input+'_x-y.csv', 'w') as f:
    writer = csv.writer(f, lineterminator='\n')
    writer.writerow(center)
    for i in range(len(x)):
        xs.append(np.int64(x[i]))
        ys.append(-np.int64(y[i]))
        points.append([xs[i],ys[i]])# points=[x,y]
        writer.writerow([xs[i],ys[i]])

# L2ノルム(距離)の取得とCSVファイルの生成
ds = []
Theta=[]
cos=[]
with open('output/'+input+'_d-Theta.csv', 'w') as f:
    writer = csv.writer(f, lineterminator='\n')
    writer.writerow(['Radius','Deg[deg]'])#ラベル
    for i in range(len(xs)):
        X = np.array([xs[i]-x_c,ys[i]-y_c])#中心からのベクトル
        norm = np.linalg.norm(X, ord=2)#中心からの距離
        ds.append(norm)
        cos.append(X[0]/norm)#cos = X[0]/SQRT(X[0]^2+X[1]^2)
        if ys[i]>y_c:#芯の中心より上側。
            Theta.append(360-math.degrees(math.acos(cos[i])))
        else:        #芯の中心より下側。
            Theta.append(math.degrees(math.acos(cos[i])))
        writer.writerow([ds[i],Theta[i]])

cv2.imwrite('output/'+input+'circle.png',img)# debag4

なお、角度は時計回りに作っています。

メモ:

画像は、色情報の2次元マトリックスになっており、画像処理の基本は左上から右上まで走査したあと一個下の行を走査するイメージです。取得した各点の順番は左上が先だと思います。

解説

1. グレースケール&xy座標で画像を取得

読み込み

cv2.imread(img,flag)
  • - cv2.IMREAD_COLOR : カラー画像として読み込む.画像の透明度は無視される.デフォルト値
  • - cv2.IMREAD_GRAYSCALE : グレースケール画像として読み込む
  • - cv2.IMREAD_UNCHANGED : アルファチャンネルも含めた画像として読み込む 上記のフラグを使う代わりに,単に1, 0, -1 の整数値を与えて指定することもできます.

画像を扱う -OpenCV より

フィルタリング

ここではあまり働いてませんが、やると精度が上がります。下の関数はC++(のはず)の記法ですが、引数の参考まで。

medianBlur(const Mat& src, Mat& dst, int ksize)

画像フィルタリング -openCV

グレイスケール

cv2.cvtColor(img, code)
  • code – 色空間の変換コード.説明を参照してください

色空間の変換 -OpenCV

debag2: グレイスケールまでの画像

エッジ処理

輪郭を取得します。

cv2.Canny

Canny -openCV

debag3 :エッジ検出までの画像

2. ハフ変換で円を検出する

ハフ変換は画像中の直線や円などを検出する操作です。ここでもpython用のサイトより見やすかったのでC++(のはず)へのリンクを張っておきます。

HoughCircles(Mat& image, vector<Vec3f>& circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0)¶

検出された円の (中心の x 座標, 中心の y 座標, 半径) のタプルを返します。

  • - image – 8ビット,シングルチャンネル,グレースケールの入力画像.
  • - circles – 検出された円を出力するベクトル.各ベクトルは,3要素の浮動小数点型ベクトル (x, y, radius) としてエンコードされます.
  • - method – 現在のところ, CV_HOUGH_GRADIENT メソッドのみが実装されています.基本的には 2段階ハフ変換 で,これについては Yuen90 で述べられています.
  • - dp – 画像分解能に対する投票分解能の比率の逆数.例えば, dp=1 の場合は,投票空間は入力画像と同じ分解能をもちます.また dp=2 の場合は,投票空間の幅と高さは半分になります.
  • - minDist – 検出される円の中心同士の最小距離.このパラメータが小さすぎると,正しい円の周辺に別の円が複数誤って検出されることになります.逆に大きすぎると,検出できない円がでてくる可能性があります.
  • - param1 – 手法依存の 1 番目のパラメータ. CV_HOUGH_GRADIENT の場合は, Canny() エッジ検出器に渡される2つの閾値の内,大きい方の閾値を表します(小さい閾値は,この値の半分になります).
  • - param2 – 手法依存の 2 番目のパラメータ. CV_HOUGH_GRADIENT の場合は,円の中心を検出する際の投票数の閾値を表します.これが小さくなるほど,より多くの誤検出が起こる可能性があります.より多くの投票を獲得した円が,最初に出力されます.
  • - minRadius – 円の半径の最小値.
  • - maxRadius – 円の半径の最大値.

cv::HoughCircles¶ -OpenCV より

出力は中心位置と半径です。単位は画素だと思われます。

メモ:

上記コードでは以下のように使用しています。

circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 180, param1=60, param2=40, minRadius = 800, maxRadius =1100)

上のコードでは入力画像は2504*2607です.minRadius = 800なので、画像の半分以上を覆うような大きい円だけを検出しています。 param2は経験上、円の雑さに関するパラメータで、小さいほど歪な円を検出します。

円を描画

void circle(Mat& img, Point center, int radius, const Scalar& color, int thickness=1, int lineType=8, int shift=0)¶
  • - img – 円を描画する画像.
  • - center – 円の中心座標.
  • - radius – 円の半径.
  • - color – 円の色.
  • - thickness – 円の枠線の太さ.負の値の場合,円が塗りつぶされます.
  • - lineType – 円の枠線の種類, Line() の説明を参照してください.
  • - shift – 中心点の座標と半径の値において,小数点以下の桁を表すビット数

cv::circle -OpenCV より

debag4: ハフ変換までの画像

3. 円の中心点の座標を取得

各点は(x,y,r)を取得します。芯の位置ベクトル($x_c,y_c$)から、中心点からの各点の位置ベクトル(x_i,y_i)=(x-x_c,y-y_c)を求めます。x軸単位ベクトルを(x_e,y_e)=(1,0)とすると、内積から、

$$cos\theta = \frac{(x-x_c)x_e+(y-y_c)y_e}{\sqrt{x_c^2+y_c^2}\sqrt{(x-x_c)^2+(y-y_c)^2}}$$

$$cos\theta = \frac{x-x_c}{\sqrt{(x-x_c)^2+(y-y_c)^2}}$$

$$\theta = deg(arccos(\frac{x-x_c}{\sqrt{(x-x_c)^2+(y-y_c)^2}}))[deg]$$

【NumPy入門】ベクトルの大きさ(ノルム)を計算するnp.linalg.norm

np.linalg.norm(X, ord=2)

L2ノルム(ユークリッドノルム)は一般的な"長さ"です。

ノルムの意味とL1,L2,L∞ノルム -高校数学の美しい物語

グラフにして確認

結果が正しいかを確認します。アバウトでOKなので、画像とグラフを重ねていきます。

細かいことはかつて書きました=>[python]データのインポートと極座標系のグラフを表示- イノマタの趣味部屋

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

"""
CSVファイルから極座標系のグラフをプロットする
入力:(CSVファイル名, 出力画像ファイル名,半径,角度)
出力:出力画像ファイル名.png
"""
def polar(in_file,out_file,param_r,param_theta):    
    df = pd.read_csv("output/"+in_file)#ファイル読み込み
    r = df[param_r]
    deg = df[param_theta]
    radian = np.deg2rad(deg)#
    Len=len(r)

    fig = plt.figure(figsize=(10, 10))#新しい図面
    ax = fig.add_subplot(111, projection='polar')#軸の表示
    ax.set_theta_direction(-1)#時計回り
    #ax.plot(radian,r, '-o')
    ax.plot(radian,r, 'or')
    
    i=2
    #while i < Len:
    #    ax.plot([radian[i],radian[i-1]],[r[i], r[i-1]], 'xr-')
    #    i +=2
    plt.savefig(out_file)
    plt.show()

polar('0%_d-Theta.csv','0%.png','Radius','Deg[deg]')
取得した数値からグラフを作成

なお、画像は下記サイトで背景を透明にしました。

画像に透明色を設定する -peko step

はじめの画像と重ね合わせると、うまくグラフにできていることが確認できます。 取得したCSVは正確みたいですね。

グラフと元々の画像を重ねた画像

もともとの画像を修正したりエッジを強調したりすれはもっといい結果が得られるはずです。

雑記

パラメータの変更も自動化できれば良かったですが、できませんでした。

目的は達成したものの、手で測定するのと同じくらい時間がかかってしまったのも悲しいです。追加があれば効果が発揮できるんですが。

参考

画像処理の基本は、古い本ですがこの本が良いと思います。

コンピュータ画像処理 田村 秀行 (著) オーム社

他に、最新のアルゴリズムとか実用的な部分はOpenCVを見るのが早いでしょう。

python、anacondaで仮想環境を作る理由と方法を書きました。ほぼ日記です。

私と同じような初心者向けにpython、anacondaで仮想環境を作る方法を書きました。ほぼ日記です。(2019/11/13)

注: winndows上でlinaxやりたい、というようなものでは無い気がします。

conda 4.7.12

目次

  • なぜ仮想環境を作るのか
  • anacondaで仮想環境を作る方法
  • 参考
  • 感想

仮想環境をなぜ作るのか

頻度は違えど、 ライブラリ等は日々更新されています。

例えば、自分がRequestsというライブラリを使っているとします。Requestsというのは、webページから情報をもらってくるソフトが入っているサードパーティライブラリで、webスクレイピングするときなどに使われます。長期間使用していると、Webページの構造(アバウトな話)もRequestsも更新されていくことが予想されますが、一部のページでは昔のままで使用していることもあります。新しいバージョンでは目的のページから情報がもらえない、しかしやらなければならない、そいうとき、大変困ります。

そんな時に、かつて使っていた状態のままで残していると便利なわけです。

というようなことを先日参加したPython boot campで聞きました。そこで、研究で使っているezdxfを見てみたところ、最新版が更新されていて危機感を感じました。 外部で勉強するのって大事ですね。

研究で使用しているDXF自動描画プログラムが使えなくなるととてつもなく困るので、仮想環境を作成しておきたいと思います。

Anacondaで仮想環境を作る方法

私はanacondaを使用しているので、anacondaでやります。下記はanaconda promptで作業しています。

condaのバージョンが新しくなっていたのでそれもアップデートしています。

まずは一応、現在自分の環境に入っているパッケージを確認します。

>conda list

 current version: 4.7.11
  latest version: 4.7.12
  ~沢山のパッケージ~
ezdxf                     0.9                        py_0    conda-forge

次に現在の環境を確認します。私が仮想環境を作るのは初めてなのでbaseのみでした。

>conda info -e
# conda environments:
#
base                  *  C:\ProgramData\Anaconda3

仮想環境を作成します。環境名はわかりやすい方が良いです(dxf_generatorにした想定です)。なお、環境にあたらしくpythohnをインストールしています。

>conda create -n [環境名] python

起動します。

>conda activate [環境名]

すると、左端のところに環境名が表示されます。

(dxf_generator) C:\Users\user>conda list
# packages in environment at C:\Users\user\.conda\envs\dxf_generator:
#
# Name                    Version                   Build  Channel
ca-certificates           2019.9.11            hecc5488_0    conda-forge
certifi                   2019.9.11                py38_0    conda-forge
openssl                   1.1.1d               hfa6e2cd_0    conda-forge
pip                       19.3.1                   py38_0    conda-forge
python                    3.8.0                hc9e8b01_3    conda-forge
setuptools                41.6.0                   py38_1    conda-forge
sqlite                    3.30.1               hfa6e2cd_0    conda-forge
vc                        14.1                 h0510ff6_4
vs2015_runtime            14.16.27012          hf0eaf9b_0
wheel                     0.33.6                   py38_0    conda-forge
wincertstore              0.2                   py38_1003    conda-forge

numpyなど、使用する上で必要な物を入れていきます。

>conda install [パッケージ名]
>conda install [パッケージ名] ==[バージョン]

仮想環境を終了する場合は

>conda deactivate

参考

【初心者向け】Anacondaで仮想環境を作ってみる

感想

私はezdxfというパッケージを使用する必要がありましたが、一度最新版を入れて実行してみたところ思ったようなデータが生成できませんでした。そこでもともと使っていた0.9を入れ直したところちゃんと動いたので安心です。

皆様もお気を付けください。

PICマイコンを使ってみます。使用するのはpic16f886で、windows10、MPLAB v5.10。

PICマイコンを使ってみます。使用するのはpic16f886で、windows10、MPLAB v5.10

目次

  • PIC開発環境
  • 回路
  • コード
  • 書き込み
  • 動作確認
  • 雑記
  • 参考

PIC開発環境

ソフトウェアでコーディングした後、ライターを用いてマイコンに書き込みます。

  • ソフト (MPLAB X IDE + MPLAB XC8コンパイラ)

IDEは統合開発環境で、エディタ、デバッカ、シミュレータなどほとんどのプログラムを内蔵しています。MPLAB X IDEは8bit~32bitマイコンで共通で使用できます。 コンパイラはC言語のようなコンパイラ言語をコンパイルして機械語に翻訳するプログラムです。Cコンパイラは別にインストールし、MPLAB X IDE に統合します。

私はwindows10ですが、macでもlinuxでも同様の環境でOKみたいです。

コンパイラはいくつかありますが、microchip社が比較的新しく発表したのが MPLAB XC8コンパイラです。 MPLAB IDE8.84迄のバージョンには既にHI-TECH Cが同梱されているみたいです。

・ MPLAB X IDE | Microchip Technology


MPLAB XC Compilers| Microchip Technology

  • 書き込み機(ライター)

記事によって互換品の付属のアダプタが危険っぽかったので別途用意しました。ネタバレですが、書き込み機の一部機能が壊れてました。

回路

2つLEDをつけて交互に点滅させます。 簡単で良いです。実験中に電源が入っているかを確認するためのLEDと、電源を外したときに瞬間的にマイコン電源がなくなるのを防ぐために (一応)つけているコンデンサが加わっています。

回路図

データシートを見ながら回路を組み立てます。リンクは秋月さんのとこのです。

マイコンのpin

コード

PICに書きこむ例としてリモコンのコードを見ながら、自分でコードを書いていきたいと思います。

プロジェクト

file/New Projectから作成します。MicrochipのStandalone Projectを選択します。

new project

今回使うpic16f886を選択します。

ライターは使用するPickit3を選択します。

コンパイラはXC8を選択します。

ファイル名は適当に決めます。

sourceフォルダの中に1つmainのファイルが必要です。

cファイルを開き、コードを書いていきます。

設定

production/set configuration bit の設定をしていきます。 なお、このマイコンはMCC対応してません。MCCは、簡単に設定できる超便利ツール、らしいです。

MPLAB® Code Configurator -microchip

set configuration bit

出来たら、generate source codeをクリックしてコードをコピペします。

configuration

設定は秋月のリモコンと一緒にします。今回は関数など使ってないので、I/Oさえ間違わなければ問題ないと思われます。

// CONFIG1
#pragma config FOSC     = INTRC_NOCLKOUT    // 発振回路設定 Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE     = OFF               // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE    = OFF               // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE    = ON                // 外部リセット/汎用入力の選択で外部リセット有効化 RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)
#pragma config CP       = OFF               // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD      = OFF               // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN    = OFF               // Brown Out Reset Selection bits (BOR disabled)
#pragma config IESO     = ON                // オシレータのスタートアップとコード実行の潜在時間を最小化Internal External Switchover bit (Internal/External Switchover mode is enabled)
#pragma config FCMEN    = ON                // オシレータの故障の場合さえ、デバイスが作動し続けるのを許容するように設計Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
#pragma config LVP      = OFF               // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)

// CONFIG2
#pragma config BOR4V    = BOR40V            // リセットしきい値を4V Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT      = OFF               // Flash Program Memory Self Write Enable bits (Write protection off)

BORとは: 事故時などに信号が不安定になるとマイコンによくありません。そこで、一定のしきい値を設定し、4Vなら4V±0.2Vを下回るとリセットを書ける機能を設定します。そのような機能をブラウンアウトリセット機能(BOR)と呼びます。

main関数

I/Oポートを設定します。クロック周期設定 I/Oポートの指定は、init関数の中で行っています。関数の使い方が解らなかったので、0~9999まで数え上げさせて時間を作る雑なコードになりました。すべてPortAの8pinすべて出力にしています。RA2=1;は、RA2が割り当てられたpinに電圧をかける指令です。

void init(){
    OSCCON = 0b01110000; //8MHz
    ANSEL = 0b00000000; //
    TRISA = 0b00000000;//
    TRISB = 0b00000000;
    TRISC = 0x00;
    PORTA = 0b00000000;
}

void main(void){
    int i=0;
    init();
   
    while(1){
        
        i=0;
        while (i <10000){
            i++;
        }
        RA2 = 1;
        RA3 = 0;
        
        i=0;
        while (i <10000){
            i++;
        }
        RA2 = 0;
        RA3 = 1;
    } 
}
portA

書き込み

繋いだらメニューバーの下の△をクリックします。

警告がでました。C:\Program Files (x86)\Microchip\xc8\v2.05\pic\includeやC:\Program Files (x86)\Microchip\xc8\v2.05\pic\include\c99に入っているヘッダファイルを開きます。私の場合はなぜかここにありましたが、多くの場合はProgram Files (x86)じゃなくProgram Filesだと思います。 C標準ライブラリ -PICマイコンによる開発手法

なんだかよく分からないままひたすら関係ありそうなヘッダファイルを開いて確認していくと、xc.hがインクルードしているalloca.hが入っていない。

MPLAB X IDE v5.xxの注意点 -サヌキテックネット にしたがって、projectのプロパティから、XC8 Global OptionsでC99をC90に変更するとビルドに成功しました。警告は無視。

BUILD SUCCESSFUL (total time: 6s)

書き込んでいきます。

電源供給するように設定します(私のライターは安く買ったからか電源を供給する機能がうまくいきませんでした)。マイコンは電源がないと動作しませんので、ライターか回路から電源を供給して下さい。 project上右クリックでpropaties、hardware toolからPICkit3を選択、pickit3からpowerで、チェックボックスにチェック。マイコンのデータシートにWide Operating Voltage Range (2.0V-5.5V)とあったので、5.0Vの電圧を供給します。

電源がない場合はコンピュータがデバイスを見つけられない、とか、以下のようなメッセージが表示されます。

PICkit 3 is trying to supply 5.250000 volts from the USB port, but the target VDD is measured to be 4.875000 volts. This could be due to the USB port power capabilities or the target circuitry affecting the measured VDD.

私はライターが壊れていたので、無理やり外部から接続できるようにしました。

Programming...

The following memory area(s) will be programmed:
program memory: start address = 0x0, end address = 0xfff
configuration memory
Programming/Verify complete

ライターの画像です。Vddに電源+、VssにGNDを接続します。(Vssは本来電源がマイナスになり得る場合のマイナス側です。)ライター付属の紙より転載。

PICkit3

動作確認

チカチカした。

Lチカ
Lチカ

雑談

MCCという便利機能があるんですが、Tools/Embedded/MPLAB Code Configuratorで見たところ、最新版でもサポートしているデバイスが少なく今回使用したPIC16F886もサポートされていませんでした。悲しい。

参考

Blumaという使いやすいCSSワークフレームがあると聞いて使ってみました。

Webアプリを作るには画面表示も必要。使いやすいCSSワークフレームがあると聞いて使ってみました。

目次

  • 目的
  • bluma
  • 作ったもの(例)
  • おまけEmmet
  • 参考

目的

Railsでwebアプリを作ろうと思っているんですが、その後のビューを作成することが目的です。グラフを表示するのが機能のメインなんですが、使いやすいCSSワークフレームがあると聞いたので周りのデザインを先に作ってしまおうと思います。 構成は以下のようになっています。

構成

  • top画面
  • アプリ紹介画面
  • 詳細ページ1
  • 詳細ページ2
  • 詳細ページ3

Bluma

Bluamaは、FlexboxをベースにしたフリーのCSSフレームワークです。下の公式ページからダウンロード出来ますが、CDNから利用すればダウンロードする必要がありません。 CDNとは、デジタルコンテンツをネットで大量に配信するためのネットワークの事です。これを利用するとURLを貼ることでダウンロードしなくてもBlumaを利用できます

BLUMA

ビューをHTMLとCSSで書いていきます(おまけも参照)。 Blumaを使用する準備は、該当のURLを貼るだけです。

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.1.2/css/bulma.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">
<a href="#" >HELLO!</a>
<a href="#" class="button">HELLO!</a>
<a href="#" class="button is-primary is-large">HELLO!</a>
<a href="#" class="button is-primary is-medium">HELLO!</a>
<a href="#" class="button is-primary is-small">HELLO!</a>
<a href="#" class="button is-info is-small">HELLO!</a>
<a href="#" class="button is-success is-small">HELLO!</a>
<a href="#" class="button is-warning is-small">HELLO!</a>
<a href="#" class="button is-danger is-small">HELLO!</a>
<a href="#" class="button is-white is-small">HELLO!</a>
<a href="#" class="button is-black is-small">HELLO!</a>
Bluma test: button color size

classを割り当てることで、ボタンなどを表示できます。色や大きさはis-large,is-primaryなどで指定できます。

   <div class="columns">
        <div class="column">
            <div style="background-color: #42afe3">
            左サイド
            </div>
        </div>
        <div class="column">
            <div style="background-color: #f68b39">
            まんなか
            </div>
        </div>
        <div class="column">
            <div style="background-color: #fce473">
            右サイド
            </div>
        </div>
        <div class="column">
            <div style="background-color: #fce473">
            追加
            </div>
        </div>
    </div>
Bluma test: column

columsで囲ったcolumnは均等に並べられます。

    <div class="columns">
      <div class="column is-2">
        <div style="background-color: #f68b39">
          ウィンドウ幅1/12サイズの要素
        </div>
      </div>
      <div class="column is-4">
        <div style="background-color: #fce473">
          ウィンドウ幅2/12サイズの要素
        </div>
      </div>
    </div>
    <div class="columns">
      <div class="column is-6">
        <div style="background-color: #42afe3">
          ウィンドウ幅6/12サイズの要素
        </div>
      </div>
    </div>

    <div class="columns">
      <div class="column is-4">
        <div style="background-color: #f68b39">
          ウィンドウ幅4/12サイズの要素
        </div>
      </div>
      <div class="column is-4">
        <div style="background-color: #fce473">
          ウィンドウ幅4/12サイズの要素
        </div>
      </div>
    </div>
    <div class="columns">
      <div class="column is-4">
        <div style="background-color: #42afe3">
          ウィンドウ幅4/12サイズの要素
        </div>
      </div>
    </div>
Bluma test: column x/12

columnに大きさの指定をしてみます。この場合、左から12に対していくつの割合なのかを指定できます。うまく並ばなかったので端までは並ばないかもしれません。下のように分数で与えるとより細かく指定できます。

   <div class="columns">
      <div class="column is-two-thirds">
        <div style="background-color: #f68b39">
          ウィンドウ幅2/3サイズの要素
        </div>
      </div>
      <div class="column is-one-thirds">
        <div style="background-color: #fce473">
          ウィンドウ幅1/3サイズの要素
        </div>
      </div>
    </div>
    <div class="columns">
      <div class="column is-one-quarter">
        <div style="background-color: #42afe3">
          ウィンドウ幅1/4サイズの要素
        </div>
      </div>
      <div class="column is-half">
        <div style="background-color: #f68b39">
          ウィンドウ幅1/2サイズの要素
        </div>
      </div>
    </div>
Bluma test: column x/y

作った物(例)

bluma以外のCSSの色はこちらを見ました。=> HTML,CSS ホームページの背景色や文字色 (フォントカラー) -ホームページ 作成、運営管理ガイド

全体的にダサいのはフレームワークが悪いのではなくて(略)

例 アプリ紹介画面
例 詳細画面

グラフはcanvas.jsで書きました。今回はメインと離れるので割愛します。

<header class="nav">
      <div class="nav-left">
          <span class="nav-item">
              <i class="fas fa-bolt"></i>APP NAME
          </span>
      </div>
      <section class="level">
            <div class="level-left">
            </div>
            <div class="level-right">
                <div class="level-item tabs">
                <ul>
                    <li><a>TOP</a></li>
                    <li  class="is-active"><a>About</a></li>
                    <li><a>Daily</a></li>
                    <li><a>Weekly</a></li>
                    <li><a>Mounthly</a></li>
                    </ul>
                </div>
            </div>
            
        </section>
  </header>

navコンポーネントでナビゲーションとして仕様したい要素を囲う事でnavとして使用可能になります。 は実際に表示されるものをしていするときに使用すると、上下方向をちょうど良くしてくれます。

levelは水平に並べるコンポーネントで、tabに内包されたlistがタブとして表示されます。例の右上の部分になります。 is-activeは現在表示しているものの色を変えるなどするためのものです。JavaScriptは使っていないため、動くわけではありません。

<span class="nav-item">
            <p>ログイン</p>
            </span>

control has-addonsは調節機能であり、今回は隣のボタンと連なって見えるように調節してくれます。 場所はleft、rightなどで調節できます。
"fa fa-〜"はアイコンを表示してくれます。Font Awesome に一覧がのっています。 これもheadでURLを指定すればすぐに使えます。

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">

main

HEROエリアには最も目立たせたいものを配置します。

    <div class="hero is-success is-small">
        <div class="hero-body">
            <div class="container">
                <h1 class="title"> About</h1>
                <h2 class="subtitle"> </h2>
            </div>
        </div>
    </div>

"hero-head"はヒーローエリアのトップに、 "hero-body"はヒーローエリアの中心に、 "hero-foot"はヒーローエリアの底部に表示されるエリアです。"hero-body"の主コンテンツは垂直方向にセンタリングされます。

"is-bold"モディファイアーはヒーローエリアの背景色をグラデーションにします。"container"モディファイアーは内包するコンテンツを水平方向にセンタリングします。 heroを変な場所に置くと、clumonに組み込まれつつ大きく表示したりするのでレイアウトがおかしくなります。

<main class="columns">
    <div class="submenu column is-2 is-large">
              
    </div>

    <div class="column is-8"> 
          <div class="box media">
            <figure class="media-left">
                <i class="fab fa-earlybirds"></i>
            </figure>
            <div class="media-content">
                <div class="content">
                    <p><strong>24時間監視</strong><br>
                      サーバーが24時間常に監視し続けます。
                    </p>
                </div>
            </div>
          </div>  

          <div class="box media">
            <!--同様-->
          </div>  

          <div class="box media">
             <!--同様-->       
          </div>   
                  
        </div>      
    </div>        
  </main>

boxは四角で囲うためのものです。clumns内部のclass="submenu column is-2 is-large",class="column is-8"がそれぞれ指定した大きさで並んでいます。class="column is-8"内部でmediaが縦に並んでいます。

<figure class="media-left">
      <p class="image is-64x64">
         <img src="http://placehold.it/128x128">
      </p>
</figure>

mediaはtwitterのようなメディアをイメージしたものです。アイコンに画像を入れるとそれっぽくなりますが、使いませんでした。

<main class="columns">
         <div class="submenu column is-2">
            
            <aside class="box">
                <p class="menu-label">
                    datas(average)
                </p>
                <ul class="menu-list">
                    <li>monday</li>
                    <li>Tuesday</li>
                    <li>Wednesday</li>
                    <li>Thursday</li>
                    <li>Friday</li>
                    <li>Saturday</li>
                    <li>Sunday</li>   
                </ul>
            </aside>
        </div>
        
        <div class="submenu column is-8">
          <aside class="box">
              graph             
              <canvas id="canvas2" height="300" width="300"></canvas>
          </aside>
        </div>

    </main>

menuは縦に並べる要素で、menu-listのlistが並びます。labelはキーワードなど、分類を書く部分です。

    <footer class="footer">
        <div class="container">
            <div class="content has-text-centered">
            <i class="far fa-copyright"></i> Copyright 2019 Inc.Monsters
            </div>
        </div>
    </footer>

footerは画面下部にかかれる要素です。特に書くことがありませんが、一応copyrightを書いておきます。「著作権はこちら、使うときはここに言って」という事です。

おまけ Emmet

HTMLをまずは書くわけですが、便利な機能を見つけたので使います。 VScodeで拡張機能のEmmetをインストールし、左下の歯車をクリックして設定を開きます。ここで、 下記を追加します。

"emmet.triggerExpansionOnTab": true,
    "emmet.variables":{
        "lang": "ja"
    }

設定した後で、HTMLファイルを作成して!でTabを押すと

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>

これが一気に表示されます。素晴らしい。

コマンド一覧 =>Emmet Documentation

参考

CDNについて

Bulmaについて

Emmetについて

ラズパイ上でruby on Railsをやるのが楽なのでは?と思って環境構築したときに詰まったことを書きます。

IoT的なシステムを作る上で、センサ情報をラズパイが取得し、webアプリへ送信するものを作るならラズパイ上でruby on Railsをやるのが楽なのでは?と思って環境構築したときに詰まったことを書きます。

目次

  • 目的
  • 環境構築
  • 参考

目的

ラズパイ上でRuby on Rails環境を作ります。現在の環境は以下。

  • raspberry pi 3 B +
  • ubuntu MATE

Railsとは

Ruby on RailsはRubyで書かれたwebアプリケーションフレームワークであり、webアプリケーションを他のフレームワークよりも少ないコードでかけるように設計されています。 Model View Controllerアーキテクチャに基づいて構築されています。

Model View Controller
  • model:処理
  • view:画面表示部分
  • controller:modelとviewをつなぐ処理 modelとviewへの命令に変換する

modelとviewの中間処理をcontrollerに書く、というような思想がModel View Controllerです。図はwikipediaを参考にしました。

環境構築

普段通りアップデートを確認した後、以下のコマンドを打っていきます。先にnode.jsをインストールしているのは、これがないとjavascriptがないと怒られるからだそうです。

$sudo apt-get install nodejs 

次に参考で見たのでは以下のようにやっていましたが、rbenv install -listで入れたいバージョンが出てこないエラーが発生しました。

$sudo apt-get install rbenv ruby-build 

理由についていろいろと調べたところ、知人によってsudoでrbenvを入れたせいでroot権限が付与されたのではないかと指摘されますた。 ですので、試行錯誤の結果、gitからcloneでインストールしたら成功しました。APPはお好きな名前に変更してください。

$sudo rm -rf ~/.rbenv
$git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build //続いているので注意
$rbenv install -l 
$rbenv install 2.5.0
$rbenv rehash
$sudo reboot
$gem install bundler
$gem install rails
$ sudo apt-get install libsqlite3-dev
$ sudo reboot
$ mkdir rails
$ cd rails
$ rails new APP —skip-bundle //APPアプリを作成。
$ cd APP

ここで、ラズパイと相性が悪い部分があるので、エラー回避のため、config/boot.rbの以下を削除(コメントアウト)します。

#require ‘bootsnap/setup’

ラズパイの接続状況を調べて、以下のように書きます。右上の有線・無線マークの接続情報から見られます。

$ rails s -b (ラズパイの現在のPIアドレス) -d

これにて成功です。http://(ラズパイのIPアドレス):3000 を開いて確認します。

Railsのhello

成功ではありますが、chromium-driver-helperがサポート終了するらしいので、webdriberに移行して欲しいというメッセージが現れます。

+--------------------------------------------------------------------+
 |                                                                    |
 |  NOTICE: chromedriver-helper is deprecated after 2019-03-31.       |
 |                                                                    |
 |  Please update to use the 'webdrivers' gem instead.                |
 |  See https://github.com/flavorjones/chromedriver-helper/issues/83  |
 |                                                                    |
 +--------------------------------------------------------------------+

rails/Gemfileを以下のように変更して、

group :test do
 # Adds support for Capybara system testing and selenium driver
 gem 'capybara', '>= 2.15'
 gem 'selenium-webdriver'
 # Easy installation and use of chromedriver to run system tests with Chrome
 gem 'chromedriver-helper' => gem 'webdrivers'  //ここ
end
$bundle install

同様にサーバーを立てて動作を確認しましょう。 アプリケーションを作るたびにこの設定をした方がいいと思います。このときもconfig/boot.rbの設定変更を忘れずに。

雑記

以前windowsに入れたときにめちゃくちゃ大変だった記憶があります。rubyのバージョンが合わないとすぐエラー!要注意。

参考

KiCADを使用してプリント基板を注文するところまでやります。届いたら追記します。 使用するKiCADは5.0.2です。

目次

  • kicadとは
  • インストール
  • 基板データの作成
  • 製造データの出力
  • Elercowに注文
  • 雑談

KiCADとは

KiCADとは、回路図とプリント基板のレイアウトを作れるEDA(Electronic Design Automation、電子設計自動化ツール)で、無料で使用することが出来ます。CADの一種です。=>KiCad EDA

用途

回路を作るとき、部品の数がめちゃくちゃ多いだとか、回路を小さく軽くしたいというようなことがあります。そういうとき、プリント基板で作るということがあります。プリント基板というのは、配線が銅などでプリントしてある基板で、部品をつけるだけでいいという優れものです。KiCADはそのプリント基板を設計するときに活躍するツールで、なんとタダ!素晴らしいですね。

実際に作るときには、データを作って、そのあと外注するか自分でプリントすることになります。今回は注文してみたいと思います。

機能

KiCADは以下のCADがセットになっています。

  • KiCad プロジェクト・マネージャ
  • Eeschema 回路図エディタ (回路図とコンポーネント)。
  • CvPcb フットプリント・セレクタ。部品の足下の穴の位置や大きさ、銅の形などの情報を制作する。
  • Pcbnew PCB レイアウト。回路図にしたがってフットプリントが現れ、それを配置したり配線したりする。
  • GerbView ガーバー・ビューア。制作した製造データを確認する。
  • Bitmap2Component ビットマップをコンポーネントやフットプリントに変換。
  • PCB Calculator コンポーネント、線幅、電気的安全間隔、カラーコード等のための計算機。
  • Pl Editor 図枠エディタ。

kicadことはじめから抜粋

インストール

インストーラにした従えばオッケーです。Download | KiCad EDA

基板の設計

回路図の作成

私は今後つくるラジコンに搭載する赤外線受信回路をプリント基板にします。なるべく小さく、軽くし、かつ今後使いまわしできるようにするためです。動作確認とかやってないので今後変わる可能性は大ですが、まあとりあえずやってみようということで。 やり方は前述のkicadことはじめPDFにそって作業すればオッケーでしたので、申し訳ありませんが詳細は書きません。

  • オペアンプマークでコンポーネント(部品)を選び、緑の線で配線します。GNDマークから電源の類いが選べます。回路図が完成したらてんとう虫マークでチェックします。電源、GNDがついていないとここでエラーをはきますので注意してください。
  • ライブラリにない部品は自分で作らなければいけません。下記リンクで大量のコンポーネントを作ってくださった方のgitに飛べます。ダウンロードしたら、設定/パスの設定 からパスを設定できます。 nosuz/kicad-lib - GitHub GitHubからダウンロードする方法

回路図が完成したらてんとう虫マークでチェックし、問題がなければNETと書いてあるマークでネットリストを作成します。問題なければシンボルをフットプリントと関連付けます。それぞれの部品を調べながらフットプリントを選びます。新しいコンポーネントを作った場合、ここでフットプリントが見つからない場合は設定/パスの設定 からパスを設定できます。

必要なら部品表を作成しますが、私は部品表を作成できませんでした。なんででしょうね。バージョンに問題あるっぽい?です。

新規コンポーネントの作成

私の場合、秋月の変圧器はライブラリに無かったのでコンポーネントを新しく作る必要がありました。(5V出力昇圧DCDCコンバーター)。新規コンポーネントを作成する場合、回路図とフットプリントをそれぞれ作成して関連付けをします。Eeschema(回路図エディター)の上側ツールバーのオペアンプマークからシンボルライブラリーエディターを呼び出して回路図を作ります。

ファイル/新規ライブラリー か ファイル/ライブラリーの追加 からスタートします。作成するときの注意点は2つです。1つはパス、もう1つはピンのエレクトリックタイプです。

  • パス:回路図、フットプリントで関連付けるため、どのフォルダに入れたのかを覚えておきましょう。回路図エディターの 設定/パスの設定 からパスを設定できます。権限がありませんというメッセージが出てきたら、windowsの場合KiCADを起動するときに 右クリック/その他/管理者権限で実行 から開きます。
  • ピンのエレクトリックタイプ :ICなどは、動作に関係があるpinの他に電源供給用のpinやGNDのpinがあります。pinごとに、入力専用、出力専用、入出力兼用などという設定をしておくと回路図のエレクトリックルールチェックでミスがわかりやすくなります。ただ、ライブラリーを作成する時点で間違えると正しくてもエラーが出るので注意が必要です。よくわからないうちは パッシブ にしておけば大丈夫です。
新しく作った回路記号

回路記号ができたら、フットプリントを作成していきます。作業しやすいように下のようにしてすぐ保存できるようにするといいと思います。(参考にしたトラ技の丸パクリ)

  1. 回路図エディターのicマークでエディタを開き、ファイル/新規作成 から作成します。
  2. 名前をつけて、ツールバー左から3番目の 新規ライブラリを作成して,現在のモジュールを保存 でフットプリントをわかりやすいところ(mylib)に保存します。
  3. ファイル/アクティブなライブラリー で今作成したライブラリを選択します。ここで出てこない場合は 設定/パスを設定 でフォルダの場所を教えてあげます。
  4. ICとフォルダのマークからライブラリーから フットプリントをロード を選択して今保存したフットプリントを開きます。

あとは作りたい図面を探してきて、大きさに注意して作成するのみです。まずはアンカーを配置しておきましょう。中心線をフットプリントの中心に合わせなくても、後で配置するときに動かすので大丈夫だと思います。ほぼ直観的にできましたが、注意すべきポイントは2つです。

  • 単位 大きさはmmで統一しましょう。inchも選べます。1inch=25.4mm です。すべてのパーツをinchで作ると25.4倍の大きさで作れるのでうれしくなってしまいます。
  • クリアランス クリアランスはパターンとパターンの距離です。細かすぎるプリントは製造できません。P板.comではパッド-マスク(レジスト)のクリアランス設定 0.1mm 以上みたいなので参考にしましょう。
この章の参考

基板レイアウトの設計

回路図エディタの基板マークの 基板レイアウトの実行 をクリックします。部品がごちゃごちゃに並んでいるので、交差ができるだけ少なくなるように並べます。自動配線ツールがあるらしいですので興味がある方は調べてみてください。レイアウトはノイズ対策や高周波対策、熱などめちゃめちゃ細かいポイントがあるらしいですが、高周波ではないし複雑ではないレイアウトの場合に注意するポイントは2点です。

  • 直角に曲げない 電磁波が変な動作を引き起こすかもしれません
  • クリアランス パターン間が近すぎると製造できません。

わかりずらい項目についてメモしておきます。

  • 右上のアイコン F.Cuは表面の銅線のパターン、B.Cuは裏面の銅線のパターンです。各層ごとに決めていきます。F.Silksはメモのように使われてるはずです。
  • 配線 GNDは最後に配線します。
  • ビア 表と裏を貫通する穴です。ビアを経由することで表と裏の配線を繋げられます。

最後にてんとう虫マークの デザインルールチェックの実行 をします。設定をして「DRCの開始」ボタン。

私の場合ここでエラーが出たので書いておきます。 修正したかったがなぜか同じconn3は全部一緒のはずなのに配線できませんでした。コネクタ部品の穴につながりません。なんでだかわからないものの、問題があるのはこの部品だけなのでこのままやっちゃおうと思います。配線を別なところで作って移動させました。

悪知恵の写真

以上で基板のデータができました。最後に、データの出力の準備をします。

ドリルの配置をします。メニューバーの配置/ドリルと配置のオフセット から、基板外形の左隅におきます。これ、P版のサイトによると左下が安定らしいです。 セットアップ/パット -レジストのクリアランスで以下のように設定して保存します。P版では0.1mm以上を基準にしていました。配線/寸法線から寸法が測れます。

完成品の画像。ファイル/3Dビューア で3Dで見られます。

3Dビュー
この章の参考

プリント基板を作る

最後にメーカーに送るデータを作成します。作るのは「ガーバーファイル」と「ドリルファイル」です。

世の中には自作しているヒトも居ますので参考にしながら作ることもできそうです。が、今回私が作りたいのはかなり小さい基盤なのでプロにお願いしようと思っています。日本の企業もいくつかありますが、ちょっと高い。そこで今回はELECROW に注文します。

ガーバーデータとドリルデータ

ガーバーデータは各層のプリントの様子を、ドリルデータは穴の様子をまとめたデータです。

ガーバーデータとは、プリント基板を製造するためのデータです。ガーバーは元々基板のアートワークフィルムの作画に用いられるグラフィック・フォーマットでした。フィルム作画機メーカの Gerber System社の独自規格でしたが業界標準として広く普及したため、1979年にEIA (米国電子工業会)で RS-274D として規格化されました。

ガーバーデータとは -アロケートドットコム

データの出力

製造ファイル(ガーバーデータ)を出力

ガーバーデータを出力してみます。 ファイル/プロットで、写真のように設定して、製造ファイルの出力を押します。このようにファイルが出ます。 同じ画面で、ドリルデータの出力から、このように設定して、出力します。ついでにマップも出しておきます。

(追記) 裏面ソルダマスク のデータを送っていないことに気づきました。製造ファイル作成時にB.Maskにチェックを入れ、下の表の最終列のように編集してください。必須です。ありがとう、アニーさん。

ドリルファイルを生成

んで、elecrowの送るためにはデータの名前を変える必要があります。

Elecrowさんより抜粋

で、これを以下のように変更します。ファイルの名前が上の写真では「plane_SpeedControllReciever」になっていますが、表では「NAME」にまとめました。

layerbeforeafter
TopNAME-F.Cu.gbrNAME.GTL
BottomNAME-B.Cu.gbrNAME.GBL
Solder Stop Mask topNAME-F.Mask.gbrNAME.GTS
Silk TopNAME-F.SilkS.gbrNAME.GTO
NC DrillNAME.drlNAME.TXT
NC Drill-NPTHNAME-NPTH.drlNAME-NPTH.TXT
Mechanical layerNAME-Edge.Cuts.gbrNAME.GML
Solder Stop Mask BottomNAME-B.Mask.gbrNAME.GBS

-F.CtrYd,-F.Fabは参考にしたサイトでも使ってないし、部品を囲う線なのでプリントする必要もないものですので、送りませんでした。あと、NAME-NPTH.drlがありません。この基板はノンスルーホールを作ってません。

ガーバービューアで見てみたらこんな感じです。ドリルもあいてるっぽいですね。 これをzipにします。

B.Maskのガーバービュー

Elecrowに注文

Elecrowに注文します。この会社のはかなり安い!でも基本的に英語です。日本語のぺージもありますが翻訳が雑なので注意です。 Elecrow PCB Manufacturingから注文します。

このように設定して注文しました。

  • Haslは半田レベラーのことで、Hasl(lead free)は無鉛半田です。
  • 端面スルーホールは、ありにするとエッジの穴が銅メッキされます。
  • 銅箔厚は、銅の厚さです。基板全体の重量のうち、銅の重量の割合が大きいほど電気特性が向上しますが、エッジングするのが難しくなるそうです。1mil=0.0254mmみたいです。とりあえず1ozで行きます。
  • PCBステンシルというのは、基板の型(メタルマスク)を製造するか、ということです。有料です。
  • 生産時間は、急ぎじゃないので4-7working days。
  • 国家は、とりあえずjapan、Registered Airmail(書留郵便) $4.98。
  • 注文画面でまた発送方法が出てきたのがよく分かりませんが、とりあえず安定のANA。

初めての注文で500ポイントがついてきたので196points(-$1.96)適用して全体で$16.17。日本円で1800円くらい。かなり安い!

(追記)基板が届きました!

3/27にデータを送り直して4/1に発送のメールが届き、4/2には基板が届いていました。予想よりだいぶ早かったです。(小さいからでしょうか?)
3Dビューワーで見たとおりにできあがっていましたね。小さく作る事が目的だったので素晴らしい!30mm*35mmくらいです。10枚注文しましたが12枚入っててラッキーでした。基板の導通状態を何枚か確認しましたが大丈夫そうでした。使うときにもう一度確かめるつもりです。満足!!

この章の参考

雑談

発注した基板がとどいたら届くまでの時間や反省をまとめて追記します。このブログが正しいのかはそれまで解りません。

追記(2019/3/27): B.Maskのファイルを追加するように追記しました。
追記(2019/4/8):届いた基板について追記しました。

アフィリエイトをしばらくやっているけど、広告を改良しようと思っても毎回忘れている。個人的メモを兼ねたまとめ。 なお、このブログはwordpressで実践したことをまとめています。一部無料ブログでは貼り付けられませんのでご注意ください。
追記(2019/3/18) ドメインについて書くのを忘れていました。アフィリエイトをやるなら独自ドメインがあったほうがいいと思います。私はレンタルサーバ+独自ドメインでやっています。サーバというのはざっくりいうとPCで、ドメインというのはサイトの住所で、ユーザー目線ではURLの一部です (inopage.comというやつです) 。どちらも有料なので気を付けてください。

目次

  • アフィリエイトとは
  • Google Adsense
  • Google Adsense を登録する
  • Google Adsense を貼り付ける
  • AMPについて
  • Amazon アソシエイト
  • Amazon アソシエイトを利用する
  • 参考

アフィリエイトとは

アフィリエイトとは成功報酬型のインターネット広告です。

アフィリエイト商品を売る人をアフィリエイター、アフィリエイターと広告主を仲介する企業をASP(Affiliate Service Provider)と呼びます。 アフィリエイターは企業の広告をし、商品を売ることで報酬が得られます

このブログは部品等の資金稼ぎのために導入していますが、対策してないのでかなり雑です。文章間に広告が無理矢理入っている始末。

Google Adsense

Google AdSenseとは、Googleの提供しているコンテンツ連動型広告配信サービスです。ブログ記事でよく見かける広告はGoogle Adsenseです(多分)。

PPC(Pay Per Click)広告という方式で、クリック数で報酬が入るようになっています。Google Adsenseではクローラーが巡回し、内容に合った広告が表示されるようになっています。この報酬のメリットは初期コストが低いことデメリットはクリックして貰えないと報酬が貰えないことです。

このブログでは電気製品、ブログ、ゲームなどが出ているみたいです。「みたいです」というのも、管理者(私)が口出しできるのは広告の場所や大きさ、分野までなので出た広告を見てみないとわらないからです。

Google Adsenseには基本的な広告の他に、自動広告があります。自動広告はgoogleがページをスキャンして自動で広告を選んで貼ってくれます。

自動広告のメリット

  • かなり楽! 掲載したい各ページに同じコードを 1 つずつ設置するだけで、自動広告を表示できます。 広告の掲載と最適化が自動的に行われますので、手作業にかかる時間を節約できます.
  • 増収が見込める レイアウト、コンテンツ、既存の Google 広告に基づいてページを分析してくれます

自動広告のデメリット

  • 予期しない位置に広告が出る 段落に注意しないと広告によって読みづらくなります。スキャンを意識した構成にしなければなりません。

詳細は公式を参照してください。 自動広告について -AdSenseヘルプ

Google Adsenseを登録する

このサイトで登録して、アドセンスアカウントを取得しましょう。このあたりは何もスクショ取ってませんので丸投げです。 Gogle Adsense

このあと、審査がはいります。長い人は1ヶ月以上掛かります。このブログに導入した2019/2ごろに調べたところによると、審査が厳しくなったとのことです。内容や記事数などが基準になるという噂。以下参考までに当時のことを書いておきます。

  • 1度目落ちたとき
  • この記事は10記事くらい。多くは1記事2000文字行かないくらいでした。

  • 受かったとき
  • オリジナル文章の文字数が重要なのではと考え、以降6000文字程度の記事を1つ書きました。この時点で11記事くらいでした。このときの投稿はこれです。

Google Adsense を貼り付ける

受かったら広告を貼っていきます。基本的にHTMLを書き加えるので、wordpress内部にカスタムHTMLとして挿入すれば表示はさせるはず、ですが正直毎回入れるのは面倒。なので、一括で全体に表示できる方法をやります。プラグインWordPress Ad Manager & AdSense Ads – Ad Inserterというのを使っています。

広告に限らず、PHPやHTMLをいじらないといけないことがよくあると思いますが、元コードに直接やって居るときに操作をミスすると突然全く動かなくなる、表示すらされなくなる事故が起きる危険がありますので、直接手を加えるのはおすすめしません。そこで登場するのがプラグインです。この Ad Inserter は、対応するタブにコードを書き加えるだけでheaderやfooterを編集できるので便利です。画像のプラグインをインストールして有効化します。

次にGoogle AdSenseのページからコードを取得します。

  • 自動広告

Google AdSenseの「自動広告を設定」を押すとコードが出てくるので、それをコピーします。

次にwordpressの設定/Ad Inserterを開き、設定(歯車マーク)をクリックしてheaderを開きます。コードをコピペしてsave settingで終了です。

これによってすべてのページのheaderに自動広告のタグが貼り付けられました。しばらく待つと広告がでます。私はsaveし忘れて表示されずに慌ててたので、時間は全然計ってません。たぶん30分くらいじゃないかと。

  • その他の広告

広告ユニットを開きます。今回は「テキスト広告とディスプレイ表示」で作ってみます。「テキスト広告とディスプレイ表示」を選択 わかりやすい名前をつけます。広告サイズは推奨のままで行きます。広告のスタイルはサイトのデザインも考慮しつつテキトーにきめます。 最後に保存すると、コードが出てきます。これをコピーします。

次にwordpressの設定/Ad Inserterを開き、bookにコピペして保存します。このとき、コードの一番下に<p>スポンサーリンク</p>と書くことをおすすめします。

自分のページを別なタブでひらいて上のAdInserterを開くと、ページ内のどこがどういう名前か確かめることができます。

外観/ウィジェットから、Ad Inserterでメインサイドバーを選択します。すると右側のメインサイドバーの一番下にAd Inserterと言うのができますので、先ほどコピペした先のbook(私はbook5)を選択します。わかりやすいようなtitleを記入。

すると、自分のページのメインサイドバーに表示されるであろう枠が表示されています。

しばらく待つと表示されると思います。お姉さんの笑顔がまぶしいですね。

AMPについて

自動広告のページにAMP自動広告というのがあります。AMP(Accelerated Mobile Pages)とはGoogleとTwitterで共同開発されている、モバイル端末でウェブページを高速表示するためのプロジェクト、またはそのためのフレームワーク(AMP HTML)のことです。

公式Accelerated Mobile Pages Project – AMP

これはGoogleが推奨しているもので、SEOも表示速度を判断材料の1つにしているといううわさもあります。このブログは大学生を対象にしているので、スマホに特化させようと思い、AMP化しようとしてみました。そのときのことについて書き残しておきます。

これはネタバレなんですが、AMP化しないことにしました。AMPとはざっくり言うと、サイトを読み込むときに不要なものを読み込まないような作りみたいです。それで、このブログは数式も表示しているんですが、AMP化HTMLを読み込むときに、数式を綺麗に表示するためのプラグインが読み込まれないらしいんです。それに画像も表示されませんでした。数式を表示するにはMathMLというHTMLの数式版に書き換えたりしないといけないんですが、それをする労力とAMPのメリットが釣り合うかと考え、断念することにしました。

Amazon アソシエイト

このAmazonアソシエイトはamazonが提供するアソシエイトプログラムで、商品が売れたとき、自分が紹介した商品の値段の何割かが報酬として受け取れます。何を隠そうこのページの収入の本命はAmazonさんです。以下が紹介料率です。

以下のリンクからサインインしてください。申込画面はこれまたスクショしてなかったので丸投げです。頑張ってください。

amazon アソシエイト

Amazon アソシエイトはちまたの噂ではgoogle Adsenseよりも審査基準が厳しいみたいです。合格時のこのブログについて参考までに書き残しておきます。なお私はamazon prime 会員です。

  • 2度落ちたとき 10記事くらい。多くは1記事2000文字行かないくらいでした。1記事増やして再度申し込み、落ちました。
  • 合格したとき オリジナル文章の文字数が重要なのではと考え、以降6000文字くらいしたところ、受かりました。このときのサイトはこれです。(確かjupyter)。Google Adsenseとほぼ同時期に受かってます。二日後くらいに合格のメールが来ました。

Amazon アソシエイトを利用する

アソシエイトのページからやる場合と、ツールバーからやる場合が有ります。いずれにせよHTMLコードが表示され、wordpressのカスタムHTMLとして貼り付けるようになります。商品リンクの表示は「テキスト」、「画像」、「テキストと画像」の3つから選べますが、「テキストと画像」はなぜか画像が表示されないので使わない方がいいかも知れません。 プラグインもありますが、HTMLを貼り付けするだけなので全く問題なく使えてます。私は部品や参考本の紹介として使っているので今のところ「テキスト」を使うことが多いです。

商品リンク/商品リンクから商品検索をします。 出てきた商品の横のリンク作成を押すと、作成画面へ移動します。

テキストでリンクを作成する場合、テキストのみのタブを選択し、各種項目を適宜変更します。リンクテキストは表示される文字で、リンク先ページは商品紹介ページか出品一覧ページから選べます。 最後に、HTMLを取得します。

HTMLはテキスト+リンク+文字の大きさなどその他情報がすでに入力されていて、URL、短縮URLはリンク先の情報しかありません。特に目的がないときはHTMLをそのままコピーします。wordpressにもどり、カスタムHTMLとしてコピペします。プレビューはこんな感じ。

  • ツールバーから

自分のamazonアカウントでログインすると一番上にツールバーが表示されています。表示されていない場合は先ほどのアソシエイトのページから、ツール/アソシエイト・ツールバーでアソシエイト・ツールバーの設定はこちらから表示をオンにします。

以降は ページから と同様です。

amazonにログインして商品を検索染します。ツールバーの「テキスト」、「画像」、「テキストと画像」のうちテキストを選びます。出てくるURLをwordpressでいつものようにクリップのようなマークでリンクにすればOKです。

「画像」、「テキストと画像」を選んだ場合はHTMLがそのまま出てくるので、ページからで紹介した方法と同じようにカスタムHTML表示にしてコピペすればOKです。

追記(2019/3/18) 新しく投稿したら、Google consoleでインデックス登録とサイトマップの更新を忘れずに。

雑記

なんでも世の中の1/3のサイトはwordpressで作られているとのことです。もしwordpressに重大なエラーがあったり攻撃されたりした場合、世界中のサイトの1/3が動かなくなるというわけですね。あるいは、wordpressの学習だけに力を入れて脆弱性を調べれば儲かるかもと考えている怖い人が世界中にいると考えられます。セキュリティについても無関心ではいられませんね。

参考 WordPress(ワードプレス)とは? -wordpress超初心者講座
追記(2019/3/18) ドメイン、Google consoleでの更新について追記しました。

参考

pythonでグラフを表示するまでの流れを紹介します。グラフは自由振動、減衰振動、強制振動、倒立振り子(倒立振子、縦棒制御)の制御っぽいことをして時間変化をグラフで表示しました。おまけでCR回路の電圧の充電具合をプロットしました。 グラフを表示するのはCとかでも簡単にできますが、機械学習やってみたいのでpythonに触れる機会にします。

目次

  • 目的
  • グラフの様子
  • pythonとは
  • 環境とインストール
  • Jupyter Notebookの使い方
  • 振動の基礎とコード
  • 倒立振り子の運動方程式
  • 雑記
  • 参考

目的

思いのままのグラフを表示します。多項式だけではなく行列やベクトル、微分方程式も扱えるようになりたいと思います。

グラフの様子

今回は2つの似たような数式モデルをプロットしました。

図1:倒立振り子
  • 倒立振り子(縦棒制御)

手の上で箒のバランスを取るやつです。振動の中でも強制振動です。ニュートンの運動方程式を立てると、次のようになります。振り子は2l[m]、棒はm[kg]、台車はM[kg]です。このとき、角度Θを十分に小さいとして 近似してかなり簡単な式にまとめてあります。導出過程はページ最後に書きました。

$$\dot \theta_1(t)=\theta_2 \\ \dot \theta_2(t) = \frac{3}{l(4M+m)}(-L\theta_2+{g(M+m)-K}\theta_1)$$

簡単のためにl=1[m],M=2/3[kg],m=1/3[kg]を選ぶと、

$$\dot \theta_1(t)=\theta_2 \\ \dot \theta_2(t) = -L\theta_2+(g-K)\theta_1$$

この式で常微分方程式を解くと下記のような美しいグラフに!!コードが汚いのは御愛嬌ということで。python初めてだったのでほぼパクリです。減衰比については振動の基礎の項目に軽く書いています。

図2:倒立振り子の角度制御
from sympy import *      # sympyライブラリから全ての機能をimoprt
import numpy as np       #ベクトルや行列を表すのに使うライブラリnumpy
from scipy.integrate import odeint #scipyに含まれる常微分方程式を解く関数
import matplotlib.pyplot as plt #グラフを書くためのライブラリ
%matplotlib inline     #jupyter notebook内で表示させるため

"""
2階微分方程式 倒立振子 
"""
#シンボル定義
x=Symbol('x')                  # 文字'x'を変数xとして定義
t=Symbol('t')                  # 文字 't'を変数tとして定義

g = 9.8     #重力加速度
La = 0.89   #減衰比0.7のグラフのフィードバックゲイン
Ka = 10.2  
Lb = 1.0    #減衰比1.0のグラフのフィードバックゲイン
Kb = 10.05  
Lc = 0.0    #減衰比0.0のグラフのフィードバックゲイン
Kc = 10.0   
Ld = 1.0    #減衰比0.3のグラフのフィードバックゲイン
Kd = 12.57  

def func1(x, t, K):
    x1,x2=x
    dxdt=[x2,(-La*x[1])+((g-Ka)*x[0])]
    return dxdt
#同じことを複数書いているので省略

x0 = [10.0,2.0] # 初期条件 [x(0), dx(0)/dt]を表す

t=np.linspace(0,30,1000) # 時間 0から10までを101等分する
sol1=odeint(func1, x0, t, args=(k,)) # 微分方程式を解く 
#同じことを複数書いているので省略

#グラフ表示
plt.plot(t, sol3[:,0], linewidth=1,label='ζ=0.0') #  角度を図示。
plt.xlabel('time t[s]', fontsize=18)
plt.ylabel('angle θ[rad]', fontsize=18)
plt.legend(loc='upper right')
plt.savefig('huriko1.jpg')
plt.show()
  • LCR回路

そしてもう一つの式がこれです。回路のキャパシタはダンパー、インダクタはばねと同じです。

$$ E = v_R + v_C + v_L \\ E = L\frac{di(t)}{dt}+Ri(t)+\frac{1}{C}\int i(t)dt $$

これをキャパシタ電圧でまとめると

$$ i = C\frac{d}{dt}v_C \\ \frac{d^2}{dt^t} v_c = -\frac{R}{C} \frac{d}{dt}v_c -\frac{1}{LC}v_c + \frac{E}{LC}$$

これは強制振動の式と同じ形なので、同じようなグラフがかけます。

図3:LRC回路のVcの時間応答

python とは

今回のpythonは読みやすく、それでいて効率もよいコードをなるべく簡単に書けるように作られたプログラミング言語です。言語自体も書きやすいように作られていますが、ライブラリやワーススペースが豊富で、だいたい何でも出来るみたいです。最近ではAIや機械学習が人気ですが、そういう事をするためのライブラリが豊そろっているみたいで、最近活躍している言語です。 2系と3系は全然違うので注意が必要です。

ライブラリというのは、

ライブラリとは、複数のプログラムが共通して利用するコードをまとめたファイルである。 ライブラリ自体は単独で実行することはできない。 from I-8-8. ライブラリとプログラムの関係 | 日本OSS推進フォーラム

というものです。必要なときに呼び出すと自分の仕事だけやって帰って行きます。

ちなみに、初学者へ。世の中のホームページやアプリの画面表示は別な言語で書いています。pythonとかCとかは計算処理をやってくれるものなので、これだけやっても画面表示は出来ません。注意してください。勉強しはじめたころの私はこのあたりよく分かって無かったために時間が掛かってしまったので一応書いておきました。

環境とインストール

環境はAnacondaでまとめてインストールしてJupyter Notebookで書きます。 python公式でインストールしても良いんですが、他にもいろいろまとめてインストール出来るらしいDownloads - Anacondaでインストールした方が楽みたいです。デフォルトのままで良いので指示に従うだけです。

Jupyter Notebookの使い方

インストールしたらJupyterNotebookを起動します。するとコマンドコマンドプロンプト(っぽいなにか)が出てきますので、そこに書かれているURLをブラウザで開いてください。

ユーザーのフォルダの中身が表示されますので、好きなのを選んで右上のnewからpython3をクリック。すると、プログラムを書くためのセルが出てきます。

今数字が書いてある色塗りの部分を押すとコマンドモードになり数式やらがかけます。In[]やOut[]と書いている部分はエディットモードで、コピーやらが出来ます。エディットモードでHを押すとヘルプが出ます。

コマンドモードで上のcodeの部分をmorkdownにすると、morkdownで文章を書けます。 morkdownは私がこのブログの下書きやメモに普段使いしているマークアップ言語(HTMLの仲間)で、# ABC と書くとタイトル的な大きな文字、## ABCと書くと1段階小さい文字、なにもつけないと普通の文字、- と書くと箇条書き、というようにかなり使いやすい言語です。

pythonの記法はすっ飛ばします。numpyというライブラリを読みこんでベクトル(1次元配列)や行列(2次元配列)を表せます。 スライシング。bool。

コマンドプロンプトでサーバーをlocalhostで立てて、ブラウザで表示しているんじゃないかと思います(このあたりよく解ってませんが。たぶん。。なので、ブラウザで開いている間にJupyterNotebookを消すとエラーをはきます。

発生したエラーについて

  • 保存した画像が真っ白になっている。jupyterにはグラフが出力されている

Python matplotlibのグラフが保存できない(windows+anaconda) teratail

振動の基礎とコード

図4:線形振動系の力学モデル

機械屋さんにとってのかなり基本的なモデル(らしい)で考えます。ニュートンの運動方程式を立てます。

$$ f(t)= m\frac{d^2x(t)}{dt^2}+c\frac{dx(t)}{dt}+kx(t) $$

これは強制振動を表しています。

振動は、自由振動、減衰振動、強制振動の3つに分けられます。自由振動は正弦波などのように振動し続けます。減衰振動は自由振動が次第に減衰していきます。強制振動は減衰振動に外力を加えている場合です。 日常生活では大概空気抵抗などで減衰するので減衰振動がイメージしやすいかと思います。一方、制御するときはモータが動いているので強制振動です。

外力をf(t)と書いていますから、f(t)=0なら減衰振動、f(t)の項が有れば強制振動になります。

上の式を作為的に以下のように変形します。

$$ f(t)= \frac{d^2x(t)}{dt^2}+2\zeta\omega_n\frac{dx(t)}{dt}+\omega_n^2 \ \\減衰比\zeta = \frac{c}{2\sqrt{km}}, 固有振動数\omega_n = \sqrt{\frac{k}{m}} $$

減衰比ζは減衰具合、固有振動数ω_nは振動時の周波数に対応しています。これが減衰振動の基本的なモデルです。ζ=0のとき全く減衰しないのでsin波のような自由振動をし、ζ=1の時過不足無く(クッションに沈むように)目標値に到達します。実際には誤差や外乱が入るので制御系を作るときには0.7くらいにするそうです。

今回はpythonで解きたいので、ここから変形していきます。本当はいろんな方法が有るみたいなんですが、そのうちやると言うことにして、今回は参考本と同じ方法で解いていきたいと思います。

常微分方程式を解きます。二次方程式は大変なので、以下のように書きかえます。

$$\frac{dx_1(t)}{dt}=x_2 \\ \frac{dx_2(t)}{dt} = -\frac{c}{m}x_2-\frac{k}{m}x_1 +f(t)$$

これを行列を用いたベクトル表現にすると、

$$ \frac{d}{dt} \left[ \begin{array}{rrr} x_1 \\ x_2 \end{array} \right] = \left[ \begin{array}{rrr} 0 \ & 1 \ \\ -\frac{k}{m} & -\frac{c}{m} \\ \end{array} \right] \left[ \begin{array}{rrr} x_1 \\ x_2 \end{array} \right] + \left[ \begin{array}{rrr} 0 \\ 1 \end{array} \right] f(t)$$

この式のように変数の位置x(t)を配列としてpythonで定義すると、以下のようになります。

m = 1.0 #質量
c = 0.5 #粘性減衰
k = 1.0 #ばね定数

def func(x, t, k):
    x1,x2=x
    dxdt=[x2,-c/m*x[1]-k/m*x[0]+sin(t/2)]
    return dxdt

x0 = [0.0,0.0] # 初期条件 [x(0), dx(0)/dt]を表す.今は初速0.

t=np.linspace(0,50,100000) # 時間 0から10までを101等分する
sol=odeint(func, x0, t, args=(k,)) # 数値的に微分方程式を解き, x(t)とx'(t)をsolのリストの[:,0]、[:,1]成分へ格納する。

以上のような感じで、パラメータをいじることで自由振動、減衰振動、強制振動がそれぞれ再現出来ました。

  • 自由振動(図5) 初期x=0.0, 初期x' = 1.0, m = 1.0, c = 0.0, k = 1.0
  • 減衰振動(図6) 初期x=0.0, 初期x' = 1.0, m = 1.0, c = 0.5, k = 1.0
  • 強制振動(図7) 初期x=0.0, 初期x' = 0.0, m = 0.0, c = 0.5, k = 1.0 f(t) = sin(t/2)
  • 強制振動(図8) 初期x=0.0, 初期x' = 0.0, m = 1.0, c = 0.5, k = 1.0 f(t) = 1
図5:自由振動
図6:減衰振動
図7:強制振動
図8:強制振動

倒立振り子の運動方程式

再度掲載

台車と振り子を図に示します。 粘性摩擦係数をB、 軸の粘性摩擦係数をCとおきました。ここから、下の4つの式が立てられます。

振り子について

$$J\ddot \theta = Vlsin\theta - Hlcos \theta - C\dot \theta …(1)\\ (J=\frac{ml^2}{3})\\ m\frac{d^2}{dt^2}(x + lsin\theta)= H…(2) \\ m\frac{d^2}{dt^2}(lcos\theta)=V - mg…(3)$$

台車について

$$M \ddot x = f(t) - B \dot x - H…(4)$$

簡単のためにC = 0, B = 0とします。ここからH,Vを消去します。

$$H = m \ddot x + ml \ddot \theta sin\theta - ml (\dot \theta)^2 sin\theta…(5) \\ V = -ml \ddot \theta sin \theta - ml(\dot \theta) cos \theta +mg…(6)$$

これを(1)(4)に代入してまとめると、

$$ J\ddot \theta= -ml^2 \ddot \theta - lmcos\theta \ddot x + mglsin\theta…(7) \\ (M+m) \ddot x = -ml\ddot \theta cos\theta + ml(\dot \theta)^2 sin\theta+f(t)…(8)$$

この式からxの2階微分を消去して、Θが十分小さいとして線形化すると

$$cos\theta\approx 1,sin\theta\approx\theta, (\theta)^2 \approx 0 \\ \ddot \theta l (4M+m)-3(M+m)g \theta = -3f(t)…(9)$$

f(t)に角度と各速度についてフィードバックさせます。

$$ f(t)= L \dot \theta + K \theta\ $$

簡単のために l = 1[m], M = 2/3[kg], m = 1/3[kg]とおくと、以下のようにかけます。プログラムで解けるように一階化します。

$$ \dot \theta_1 = \theta_2 \\ \dot \theta_2 = -L \theta_2 + (g-K)\theta_1$$

一応全体の全体をラプラス変換して伝達関数の式を求めます。(せっかく導出したから書きたい。)

$$L{\theta(t)}=\Theta(s),L{f(t)}=F(s)として\\ \frac{\Theta(s)}{F(s)}=\frac{-3}{(4M+m)ls^2+3ls-3(M+m)g+K}$$

雑記

プログラミング系のサイトは最近公開されたものを見るように気をつけるようになりました。機械系や電気系の、特に理論はかなり成熟しているのでふるいサイトでも何でも読みやすくわかりやすければ良いんですが、情報系はツールがどんどん更新されていくので最新のを見ないと妙なところで躓いてしまいます。 おかげで私のPCちゃんはパスとかアプリとか訳が分からない感じになっています。情報系の特にweb系のブロガーさんは情報収集がすごいので、最新のでも誰かしら先にやっていますので安心ですね。先人は偉大です。 それと、解析力学が難しいですね。もう少し時間をかけないとわからないです。ラグランジュ難しい。制御はやって行きたいので、のんびり本を読んでいきます。
追記(2019/3/20)参考リンクをリストにしました。Amazonリンクを増やしました。

参考