エンコーダーを使って絵を描きたかった…話

こんにちは misosoupsite です。今年もアドベントカレンダー無事開催できましたね。うれしい限りです。

さて久々と投稿となるのでまず最近の自分の活動について述べておくと、川崎ロボットコンテスト、飛行ロボットコンテストも終わり(無事おわったとはいってない。)、していない広報のお仕事もやる気のある広報に引継いだところで、I’mフリーダム!とは残念ながら、なりませんでした。どうやら某ロボットコンテストに出ようなんて企画が持ち上がったようで、まあそれにむけてそれなりに頑張っております。

さてここで今日の本題にはいります。このお話は2日目の後輩君がしてくれたエンコーダーのおはなしの続きとして書こうと思います。このお話については下のURLをみてみてください。

https://keiorogiken.wordpress.com/2017/12/08/%e3%83%ad%e3%83%bc%e3%82%bf%e3%83%aa%e3%83%bc%e3%82%a8%e3%83%b3%e3%82%b3%e3%83%bc%e3%83%80%e3%81%ae%e8%a9%b1/

ここで後輩君がmbedのライブラリを使った簡単なエンコーダーの読み取り方を書いてくれました。これでエンコーダーが何カウントしたか読み取ることができますね。じゃあ今度はそれを使って何ができるかということを考えてみましょう。ここで紹介するのはエンコーダーを3つと測定輪としてオムニホイール3つを使った位置推定器を作り、ロボっトの2次元の位置と姿勢を推定する手法です。ときたまエンコーダー2つでそれぞれx座標,y座標とればいいじゃん。という人がいるのですが、それでは自由に動く場合は回転移動とななめ移動を区別できませんね。もちろんたとえば普通の自動車のようなモデルを考える場合など拘束条件が加われば、2つでもオドメトリ法などを用いて位置および姿勢推定することができるのですが、最近よくロボコンで使われるメカナムホイールや、オムニホイールは自由に動き回るので、そうはいかない…というのが大変なところです。

さてそこで次のようなオムニホイールを使った測定器のモデルを考えてみましょう。

ブログ用20171211

青線がオムニホイール、赤線が中心からそれぞれのオムニホイールまでの距離です。これは計算を簡単にするためにすべてLとしておきましょう。測定器の重心座標を3つの赤線の交点、角度を \theta で示しています。赤線間の角度はすべて120度としておきます。また、それぞれのオムニホイールにはロータリーエンコーダーが接続されています。さてここでオムニホイールの速度V1,V2,V3と重心位置(x,y)および角度 \theta は次のような式で表されます。(長くなってしまうので導出は省きますごめんなさい。)

\left( \begin{array}{ccc} \dot{x} \\ \dot{y} \\ \dot{\theta} \end{array} \right)= \dfrac{1}{3sin(\frac{2}{3}\pi)L} \left( \begin{array}{ccc} L(cos(\theta+\frac{2}{3}/pi)-cos(\theta+\frac{4}{3}\pi))& L(cos(\theta+\frac{4}{3}\pi)-cos(\theta))& L(cos(\theta)-cos(\theta+\frac{2}{3}\pi)) \\ L(sin(\theta+\frac{2}{3}\pi)-sin(\theta+\frac{4}{3}\pi)& L(sin(\theta+\frac{4}{3}\pi)-sin(\theta))& L(sin(\theta)-sin(\theta+\frac{2}{3}\pi)) \\ sin\frac{2}{3}\pi & sin\frac{2}{3}\pi & sin\frac{2}{3}\pi \end{array} \right) \left( \begin{array}{ccc} V1\\ V2 \\ V3 \end{array} \right)

したがってV1,V2,V3がわかればx座標y座標,また姿勢角Θの微分が得られるということがわかります。V1,V2,V3はオムニホイールにとりつけられた、エンコーダーの任意時間のカウント数なり、エンコーダーから得られる信号のパルス間の時間から得ることができますね。これを用いて得られたx座標,y座標、姿勢角Θの微分を積分していけば位置および姿勢を推定することが可能ということです。

さてここでようやく本題の絵を描く話に入ります。これはどうやって書くかというと、多分多くの方は想像がついていると思いますが、上の位置推定機を実際に絵をかくように、動かしながら、推定した位置の座標をグラフ上にプロットしていくという方法です。今回は比較のために測定器にペン先をとりつけて実際に書かれた絵と比較してみました。
今回は三角形、8の字、うずまきの3種類の絵をかいてみました。(絵というか記号だけど)まだハードができたばっかりなので、すごくおおざっぱな計算手法を用いてますが…。
まずは単純な△。上が元の図で、下がプロットした図です。(写真きたなくてごめんなさい…)

3んかくもと

 

△うんまあまあ
次は8の字

8のじもと

8の字

うんなんともいえないけどまあ一応OK

次うずまき、

うずまきもと

 

うんこ

?!
ひどいですね。これはもはや渦巻というよりう〇こです。
見る前から明らかなことではあるのですが、x座標,y座標を算出する際、角度θを用います。ところがθも当然のことながら、積分して得られた推定量です。誤差付きの速度に誤差付きの速度を積分して得られた、角度をかけているのですから、いったいどのくらい誤差が出るのやら。これを今後ほかのジャイロセンサーや距離センサー、ラインセンサといったさまざまなセンサー類と組み合わせつつ、うまい統計処理を見つけ出して、補正していければなと思います。

さてこの話はここまでにしておきます。サークルの技術力もまだまだですが、某ロボットコンテストの出場に向けた取り組み、他さまざまな取り組みを通じて、なんとか技術力を高めていきたいですね。それでは明日以降のAdventcarenderもお楽しみください。

広告

それ糞コードじゃない??

どうもこんにちはsyuntoku14です。アドベントカレンダー9日目ですね。

今回はもやし炒めの話過去に書いた糞コードの話をしようと思います。

さて、自分は大学に入ってからパソコンを触りだしたくそ雑魚ですが、2年生になってからというもの結構頑張ったので少しは成長した気がします(技術力的に)。

過去に自分が書いたコードを見ると非常に読みづらく、ブチギレそうになります。読みづらいコードを書いてしまうと、他の人が見たときに苦労するだけでなく、自分でさえもコードの意味が分からなくなり非常に非効率的です。分かりやすいコードはやる気を向上させ、効率的なデバッグに繋がり、無限の進捗を生み、あなたのストレスを軽減し、ロボコンで全てを破壊したくなる衝動を抑えます

今日はそんな糞コードを供養し、どうすれば読みやすくなるか考え、改善する手法の例を挙げてみます。

例えば、今年のF^3RC(新入生用のロボコン)の自動機用に書いたコードがこんな感じです。(長いので下まで飛ばしてください。コードの糞さを示しているので読む必要は全くないです。)

見てもらえれば分かりますが、読み直す気も起きないですし、こう長いとエラーが怖くて書き直す気力もわかないです。糞めんどくさいです。

この糞コードは何とか良くならないかな?へなちょこコーダーなりに改善点を考えてみました。

その① コードを分割しよう

このコードの構成のめんどくさい部分として、

似たような関数がたくさん→グローバル変数でなんかよくわかんない変数がいくつか→似たような関数がたくさん→メイン関数

の糞ムーブをかましていることが原因として挙げられます。ソースファイルを分割しましょう。上のコードをよく見ると、メイン関数の部分は案外短く収まっていることが分かります。邪魔な関数はソースコードを分割することで可読性を上げたほうが読みやすいです。

その② クラスを使おう

プログラミング始めたての時は、クラス使わなくても案外かけるしよくない?と思ってしまいがちです。でも積極的に使ってみるととても便利で、コードの可読性がとても上がることに気づくと思います。個人的な意見として、そもそもグローバル変数を多用するのが良くないです。どこに何の変数を書いたかいちいち探し出すのはとても効率が悪いですしし、似たような変数をいちいち書くのもあほらしいです。クラスを使えば似たような制御の内容をまとめて書くことができるので、後で読みやすいし直すべき部分を見つけやすいです。

その③ #defineは多用しない

今回はあんまり使っていないですが、例えば

#define PWM_DUTY 0.8

などとするのはあんまりよくない気がします。#defineによる定数の定義は予期しないエラーを生じさせるので、定数はconst 修飾子を使って定義したほうが良いです。せっかくconst 修飾子なんて素晴らしいものがあるので、そっちを使いましょう。

その④  命名規則を確認しよう

ここから先の話はいろんな派閥があるので、ここでの話が完全に正しいわけではありません。詳しい話はググってみてほしいです。とりあえず簡単に言いますと、命名規則というのは、変数や関数の名前を統一された規則に則って命名することで、コードを読みやすくしてくれます。例えば、

関数や変数の名前はexampleFunctionのように小文字大文字にし(camelCaseといいます)、

クラスの名前はExampleClassのように大文字大文字に(PascalCase)、

マクロ名はEXAMPLE_MACROのように全て大文字にするなど、名前付けの規則を首尾一貫して行うと、読みやすいコードに繋がります。どれがマクロで、どれが変数なのか分かりやすくなっているとデバッグもしやすいです。

その⑤ 変数、関数名は分かりやすく

変数名、関数名が分かりやすければ、それを説明するためのコメントが短くなり、読みやすくなります。例えば、上で示したコードにこんな関数がありました。

//ライントレーサのカウントをする関数
//緑→白を検知すると1を返す
//白→緑やほかの状態だと0を返す
int count_t(){
…….
}

countという単語を使っているのはいいことだと思います。何をする関数なのかが分かりやすいです。しかし、_tという部分を読み解くのに少々時間がかかります。過去の自分は_tをトレーサの略として使ったみたいですが、これはタイムとごっちゃになったり紛らわしいです。この部分は例えばcount_lineなどにすることで、ラインの数をカウントする関数であることが一目でわかるようになります。こうすると、1行目の //ライントレーサのカウントをする関数 というコメントが不要であることが分かります。一目で理解できるコードを心がけることで、コードの可読性がぐんと向上します。

その⑥ コメントは大事

コメントは大事です。とりあえずコメント書いときましょう。

複雑なコードにコメントを書く場合は、長ったらしい文章でダラダラ説明するより、使用例をコメントとして残しておくと一発でわかるので良いと思います。

 

おわりに

もっと書きたいことはありますが、眠いのでこの辺にします。今回の記事は間違った内容を含んでるかもしれないので、まあ詳しいことはググってください。

なんとなく初学者なりに思ったこととして、新入生でプログラミング始めて暫くたった人は、ソースコードを分割し、クラスを使う練習をすると、少し良いプログラミング生活を送れると思います。あんまりソースコードを分割しすぎるのはコンパイルとかなんとかかんとかの関係で良くないっていう話も聞いたことがあるような気がしますが、まあ最初の内は気にしなくて大丈夫でしょう。プログラミングの基本的な文法を抑えたら、コードの可読性を上げる努力は良いアプローチだと思います。リーダブルコードを読みましょう。素晴らしい本です。Effective c++を読みましょう。まだ読んでないです。プログラミングコンテストに手を出してみるのもいいかもしれません。でも何でもかんでも手を出しすぎてしまうと中途半端に終わってしまうかもしれないので注意です。自分はTOEFLと機械学習とロボコンとプロコンを同時に手を出して全てがまだ中途半端です。

最後に、最近加工に行けてなくて(バイトなどで)チームの皆さんに多大な迷惑をかけている気がしますが、頑張りますので許してください。ほんとに申し訳ない。

今回の記事はこんな感じで終わりたいと思います。

追記:誰かwordpressでソースコードを張る便利な方法おちえて...

ロータリーエンコーダの話

こんばんは。1年のkoke688です。10月から副代表に就任しました。よろしくお願いします。

現在NHKロボコン出場目指して頑張っているところです。

 最近、オムロンのE6A2-Cシリーズのロータリエンコーダを使っているのでその話をしようと思います。

ロータリーエンコーダとは?

モータの回転数、回転速度などを測定するときに用います。詳しい、原理構造が気になる方は調べてください。とりあえずエンコーダの軸を回転させると位相差を持った二つの連続的な矩形波(A相、B相といいます)が出てくるという認識で不自由ないと思います。
エンコーダ1

 エンコーダの軸を時計回りにまわすのか、反時計回りに回すのかで上図の波形が左から流れるのか、右から流れるのかが変わります。左から流れる場合と右から流れる場合の区別をするには、A相の立ち上がり時(OFF→ONになったとき)にB相がONなのかOFFなのかを見てあげれば大丈夫です。
 エンコーダ2
 
 上の図の場合A相の立ち上がり時B相はOFFになっていますね。回転方向が逆転した場合、A相の立ち上がり時にB相はONになります。このようにしてモータの回転数とその向きを知ることができます。

エンコーダ周りの回路について

 現在使っているエンコーダはオムロンのE6A2-CW3Zcで出力形式はオープンコレクタ出力となっています。僕の理解が正しければオープンコレクタ出力はこんなイメージです。

エンコーダ信号増幅回路3

 上の図のスイッチがオンかオフかがさっき述べた矩形波のオンオフに一致します。上の図にはエンコーダ以外の回路も描かれています。これは先輩が使っていた回路を参考にしました。(使うマイコンがnucleoのため電圧を3.3Vに落とす必要があるのだと思います。)左側のFETはNch、右側のFETはPchです。
ON時
エンコーダ信号増幅回路1
 エンコーダがオン時は左側のFETのゲート・ソース間電圧が閾値電圧を超え、ドレイン・ソース間に電流が流れます。(ドレインソース間の抵抗がほぼゼロになる)すると右側のFETのゲート・ソース間電圧が低下し(図では見ずらいですが-3.3Vと書いてあります。ここは自身がありません)、ゲート・ソース間抵抗が下がり、マイコンには3.3Vが出力されます。

OFF時
エンコーダ信号増幅回路2

(図の抵抗という漢字が間違っています)

エンコーダの値を読み取ろう!

 エンコーダの信号をマイコンで読み取れる状態になりました。次はエンコーダの信号を読み取るためのマイコンのプログラムの話(mbed)になります。
 先ほど述べたように、A相の立ち上がりを検出し、そのときにB相がHIGHなのかLOWなのかを読み取るのが基本方針です。なお、AB相の立ち上がり立下り時すべてに割り込みをかけることで、分解能が4倍になります。
・分解能1倍
エンコーダプログラム1倍
シリアルモニタで表示させればエンコーダのカウント数が表示されます。

・分解能4倍
エンコーダプログラム4倍.PNG

最後に、、

 すでにエンコーダを使ったことある人にとってはわかりきった話だったと思いますが、これから使ってみようという方の参考になればと思います。
明日はshuntoku14さんです。去年は「美味しいもやし炒め」についての記事を書かれていました。今年はどんな記事になるか、みんなもチェックしよう!

ゲートドライバからのMDで優勝せえへん?

この記事は2017年慶應ロ技研Advent calender7日目になります
←6日目|8日目→

2回目の登場となりますishtarmk2です。あと5日で21歳になるので何か欲しいです。

さて今日はゲートドライバというICのモータドライバへの実装についてお話ししようと思います。

ゲートドライバとは

そもそもドライバICというのは何かしらの素子に電流電圧を供給するためのICです。例えばロボコンに出たことがあるなら一度は使ったであろうモータドライバICはモータにそれらを供給するためのものです。他にもLEDドライバ等が存在します。そしてゲートドライバはFET(本記事ではMOSFETに絞る)のゲートに十分な電圧を供給するためのものです。ゲートをドライブしているので実質1秒毎に世界線を超えています。後述するハーフブリッジ回路やフルブリッジ回路等のパワー供給回路に使います。

何故要るのか

例えばモータドライバにありがちな下記のようなNchFET4つのフルブリッジ回路を考えてみましょう(モータドライバがどういうものなのかはググるか去年の記事見てくだしあ)。

hbrucke

右上と左下、左上と右下のFETをそれぞれセットで駆動することでモータをそれぞれ正転逆転の両方向に回せるわけですが、VCC寄りの方のFET(ハイサイドといいます、GND寄りのほうはローサイド)に注目してみましょう。NchMOSFETはG-S間に電圧をかけることでD-S間が導通する素子です。D-S間が導通するということはD-S間はほぼ等電位です。つまりVccとも等電位なわけです。要するにGにVcc以上、すなわちバッテリ電圧以上の電圧をかける必要が生じます。昇圧回路を組む必要があり面倒なのですがその面倒を解決してくれるのがゲートドライバです。また、G-S間はコンデンサのような構造になっており、電荷が充電されることで電圧が高まっていきます。そのためドライバはゲートに十分な電流を流せるる必要があります。ちなみにPN混合型のモータドライバの場合はこういったゲートドライバよりもプッシュプル回路の入った応答速度の良いフォトカプラが使われる傾向にあると思っています。

ハーフブリッジとフルブリッジ

ゲートドライバにはハーフブリッジドライバとフルブリッジドライバの2種類が存在します。ハーフブリッジ回路というのは↓のような

halfbridge

回路(IR2302のデータシートより抜粋)で1方向のみの電流電圧を制御します。フルブリッジ回路はモータドライバでよく見る所謂Hブリッジで、フルブリッジドライバを使う以外にハーフブリッジドライバを2つ使うことでもゲート電圧をかけることができます。

使い方

正直なところデータシートの例を真似て電源やゲートなどに配線していくだけ(データシートがだいたい英語なのでそこが一番めんどい)なのですが注意点をいくつか。ゲートドライバの多くの昇圧回路はブートストラップ回路というダイオードやコンデンサを用いたもので、入力がHIGHとLOWの間で切り替わることによりコンデンサの放充電が行われ、昇圧が実現します。そのため回転指示の信号としてPWMを入力する必要があります。HIGHだけ、すなわちDuty比1だとうまく昇圧されません。また、基板設計時にパワー側とロジック側のGNDは絶縁しましょう。ノイズがロジック側に流れ込み破損の危険があります。

べんりな機能

しかしながら単に昇圧するだけであれば、自分でブートストラップ回路を組んで昇圧すればいいだけなのですが、多くのゲートドライバが生産されているのはそれだけ便利な機能を兼ね備えているからであります。その一部を紹介していきましょう。

デッドタイム生成

デッドタイムの詳細については先ほどの去年の記事に示してあります、多くのゲートドライバはこのデッドタイムを自動的に確保してくれます。生成されるデッドタイムは固定だったり可変だったり様々です。固定の場合ローサイドとハイサイドで違うこともあります。可変の場合は可変抵抗等で調整します。

チャージポンプ

上でブートストラップ回路にはPWMを入力しないと昇圧に失敗すると述べましたが、これがついているとDuty比1でも昇圧が行われます。制御が快適になるはずです。

レビュー

では最後に私が使用経験のあるゲートドライバの紹介です。どちらも秋月で売っています

IR2302

I-06208.JPG

DIP8ピンスルーホールのハーフブリッジドライバです。デッドタイムは540ns固定で、シンプルな上に作例もネットに転がっているので初めて使うには良いかもしれません。ただゲートに供給できる電流が若干弱いらしいです

A3921

I-12293

こちらは表面実装28ピンのフルブリッジドライバです。デッドタイムは可変で、可変抵抗により調整できます。チャージポンプもついており至れり尽くせりの美味しいゲートドライバです。実装パターンはTSSOP28で、これくらいなら手はんだでの実装も十分可能です。今年の高専ロボコンで2チーム全国大会出場を果たした長岡高専でも使われてるとか。なお、ロジック入力の電圧が高めのA3941という兄弟機も存在しますがA3921で良さそうという気がします。
MD_nhksisaku
↑私がA3921を用いて作ったモータドライバです

時間がなく駆け足で書いたので不備があるかもしれませんが私自身モータドライバを自作するにおいて情報収集に苦労したので初めてモータドライバを作ってみようというような方の参考になれば幸いです。明日以降の記事にもご期待ください。

 

プログラム初心者による、初心者あるある

この記事は慶應ロ技研アドベントカレンダー4日目です。

1日目

←3日目5日目→

 

・はじめに

こんにちは。明日に中間試験を控える広報、keitakatzです。プログラムを書く能力は初心者以上中級者以下って感じですかね。つまり、実質的に初心者。今回は、プログラムを書くときに初心者がやりがちなことについて3つほどの例を書いていこうと思います。 続きを読む