Hatena::ブログ(Diary)

熊工房 ohgumaの腹凹ませたい日記

2004 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2015 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2016 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2017 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2018 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |

2015-07-31

[]続・LiFeバッテリー

自作LiFeバッテリーパック以外にも、HYPERIONの市販のLiFeバッテリーももう3年ほど使っている。もともと近藤科学の2足歩行ロボットのKHRベースのロボットで使っていたため、コネクタはJSTのVHコネクタに替えている。

f:id:ohguma:20150801010831j:image

f:id:ohguma:20150801010847j:image

こちらは、AmazonブランドNiMH単三。1900mAh 8個パックで1,580円。

型番(HR-3UTG-AMZN)から初代eneloop(HR-3UTG)のOEMと思われる。

f:id:ohguma:20150801010905j:image

f:id:ohguma:20150801010914j:image

f:id:ohguma:20150801010923j:image

小さな電池を、マメに変えるのも良いと思う。

2015-07-29

[]LiFeバッテリー

2008年自作したLiFeバッテリーのバランス端子を短絡させないように、慎重に交換する。当時、バランス端子が6セル向けのもしか入手できず、いままで無駄に大きなコネクタを使っていたのが、やっと改善できた。

f:id:ohguma:20150729105848j:image:w360

2015-07-27

[]C-Styleで独自関数定義

ふと思いついたことを試す。

▼NewFile-00

f:id:ohguma:20150728080952p:image

▼NewFile-01

f:id:ohguma:20150728080953p:image

・「}」で始める。

・「}」で終わらない。


ビルドするとビルドパス中のUser.cはこうなり、エラーにならず成功する。

サブルーチン中で関数定義するのがミソ。

#include "D_Main.h"
#include "D_I2C.h"
#include "D_SIO.h"
//--------------------------------------------------------------------------------
// Functions
//--------------------------------------------------------------------------------
void user_sub_1(void);
void user_main(void);
//--------------------------------------------------------------------------------
// Program Name : NewFile-01.C
//--------------------------------------------------------------------------------
void user_sub_1(void)
{
      	// 自作関数定義の為のダミーサブルーチン
    }
    void disp_var(BYTE x) {
        char str[16+1];
        sprintf(str, "[%c]%ld", 'A' + x, gV[x]);
        tx_puts(str);
    }
    void disp_ln() {
        tx_putc('\r');
        tx_putc('\n');
}
//--------------------------------------------------------------------------------
// Program Name : NewFile-00.C
//--------------------------------------------------------------------------------
void user_main(void)
{
    while (TRUE) {
        gV[VAR_C] = 1023;
        gV[VAR_A] = gV[VAR_C] - gAD[CN3];
        gV[VAR_B] = gV[VAR_C] - gAD[CN4];
        disp_var(VAR_A);
        disp_var(VAR_B);
        disp_ln();
        wait_ms(1000);
    }
    user_sub_1();
}
//--------------------------------------------------------------------------------

こうまでしてC-Styleを使う意味はないかもしれないが、変数の値を表示するなど汎用的に使う構文はサブルーチン中でCの関数として定義しておくと大変便利。

2015-07-25

[]続・クロックポジションのススメ

id:ohguma:20150629ベクトル化で三角関数を使い角度を求める場合、C-Styleでid:ohguma:20150607のmath.hの対応必要になるが、クロックポジションを求める場合は、30度ごとの区切り計算をより単純な式に近似することでmath.hを使わずに済む。

f:id:ohguma:20150726060328j:image

x>=0,y>=0の部分のみ考える。

0・1時の区切りのと、2・3時の区切りは、座標軸から15度離れているが、これらは赤色のy=4x,y=x/4に近い。この1度のズレが許容できるならば、

1・2時の区切りになるy=xと、近似したy=4x、y=x/4を使い、ベクトル(x,y)がどのクロックポジションに含まれるか判断できる。

2015-07-24

[]クロックポジションのススメ

個人的な好みになるが、ロボットの向きや移動方向の表現に、正面を0時とするクロックポジションをススメてみる。

ロボット制御するマイコン三角関数などがバリバリ使えるのであれば、0〜359度で表現すれば良いが、非力なマイコンを使うTJ3Bや、プログラミング制限の強いC-Style上では向きの計算が簡単になるため使いやすいと思う。デメリットは30度刻みの大雑把な制御になることが挙げられるが、TJ3Bを使う場面や、プログラムのしやすさを考えると些細なことだと思う。


f:id:ohguma:20150725034316j:image

ロボット真正面を基準に左右に15度の範囲内を0時とし、あとは時計回りに30度ごとに1時、2時、と進める。

図では15度の範囲内としたが、プログラム上で−15〜15度とすると31度分の幅があるので、ここでは−15度〜14度の範囲を0時方向とする。同様に1時方向=15〜44度、2時方向=45〜74度、3時方向=75〜104度、と続く)

HMC6352デジタルコンパスを使う例。

f:id:ohguma:20150725034317j:image

(Whileの中の説明)

  • M=M-D でMがマイナス値(例:Dir(HMC)=10、D=350の場合など)にならないよう、今の向きを測った際には360を足しておく。
  • クロックポジション0時方向は−15度〜14度としたが、−15度は345度と同じ。Mに15足せば、0時方向の範囲は0〜29度となる。
  • Mが360度を超えないよう(例:Dir(HMC)=350、D=10の場合など M=350+360-10+15=715)、360で割った余りに変換(715 % 360 = 355)する。この時Mの値は0〜359のどこかになる。
  • Mを30で割れば0〜11のクロックポジションになる。(C-Styleでの割り算は少数以下を切り捨てる)

実際にMが意図する値になっているかはTeraTermで確認する。

f:id:ohguma:20150725093341j:image

  • 無条件ループ中の途中までのプログラムの動きを確認する場合には、continueを入れるとよい。それ以後のプログラムは無視して、Whileに戻る。以後のプログラムが無いときはWendがくる。
  • 砂時計は、プログラムをゆっくり動かすために入れたもので、なくても良い。TeraTermで確認しやすいように調整する。

f:id:ohguma:20150725093342j:image

2015-07-23

[]C-Styleでのコメントアウト

デバッグ中に一時的機能を止めたい場合、その部分をコメント化することは一般的だと思うが、C-Styleでは各行を簡単に「コメント化⇔非コメント化」の切り替えができない。


Sub-8を一時的に実行しないようにする場合

f:id:ohguma:20150724011132p:image

if文を追加し、条件を「C code」にし、

f:id:ohguma:20150724011131p:image

「C code」には「false」とのみ記入する。

f:id:ohguma:20150724011133p:image

一時的に止めたい機能(ここではSub-8)をif文の中に貼り付ける。

f:id:ohguma:20150724011134p:image

「false」は常に「いいえ」の状態であるので、if文の中は実行されない。

逆に一時的に条件分岐を無視して常に「はい」の状態にする場合は「C code」を「true」にする。

2015-07-20

[] C-Styleでコンパス活用

以前の向き(例えばスタート時)を基準(=0度)とみなし、相対的に今の向きを表現するには、「(今の向き計測値)−(以前の向き計測値)」という計算を考える。

コンパスセンサの計測値は北を0度として、時計回りに0〜359度で表現される。

(今の向き計測値)>(以前の向き計測値)の場合は上の引き算の答えは正の値になるが、逆の場合(例:今が10度で以前が350度の場合)は負の値になり(例の場合:−340度)都合が悪いので、今の向きに360度を足してから引き算する。(例の場合:10+360−350=20度)。

まが、今の向きに360度を足した時、(今の向き計測値)>(以前の向き計測値)の場合の引き算の答えは360度超える(例:今が30度で以前が20度の場合、(30+360−20=370度)が、360の剰余(割った余り 例の場合:370÷360=1余り10度)を計算すれば、都度if文で360以上かどうかを判断する必要がない。剰余はC-Styleでは演算子「%」で計算できる。

2015-07-16

[]続・C-Style の elseif 活用

if 〜 else if 〜 else 〜 end ifの構文は、

  • ifの条件が成立するなら、ifの下を実行し、else if 以下はキャンセル
  • ifの条件が成立せず、else ifの条件が成立するならば、else ifの下を実行し、else以下はキャンセル
  • else ifの条件も成立しないなら、elseの下を実行。

となるので、

f:id:ohguma:20150715081920p:image

プログラムした場合、Aの値は以下のように1,2,4,8のどれかとなり、意図する値を取得できない。

f:id:ohguma:20150715082718j:image

センサ1〜4は、それぞれが独立して動くものであるので、それどれ独立したif文で状態を判断する必要があるので、正しくはこうなる。

f:id:ohguma:20150716044245p:image

これで変数Aは

となる。


変数Aの値をもとに実行する処理を切り替える場合、実際にはセンサの配置などで、ありえない組み合わせもあるので、それらはelseでひとまとめにして処理して、有効な組み合わせのみをif 〜 else if 〜 で判断する。

この時に変数Aを1から順番に判断する必要はなく、分かりやすい順番にまとめればよい。多くのelse ifがある場合、下になればなるほど何度も条件判断することになり、その分処理が遅くなるので、よくある組み合わせをなるべく先に判断する。

f:id:ohguma:20150716044246p:image

愛媛ノード愛媛ノード 2016/04/10 20:29 すいません、2進法と十進法は理解できたのですが、
なぜ、cコードをプログラムに記述するのかが理解できません。お願いします。

愛媛ノード愛媛ノード 2016/04/10 20:42 すいません、理解しました!
ごめんなさい

2015-07-15

[]C-Style の elseif 活用

状態がON/OFFの2通りを取得できるセンサ複数使う場合

  • 1個だと ON/OFF の2通りの状態
  • 2個だと、(ON,ON)(ON,OFF)(OFF,ON)(OFF,OFF)の4通りの状態
  • 3個・4個は下の表参照(1=ON, 0=OFF)

f:id:ohguma:20150715004049j:image

センサが1つ増えるたびに全センサのON,OFFの状態の組み合わせは2倍づつ増えていく。


これを単純にifのセンサーチェックで判断すると、

▼1個の場合

f:id:ohguma:20150715013115p:image

▼2個の場合

f:id:ohguma:20150715013116p:image

▼3個の場合

f:id:ohguma:20150715013117p:image

▼4個の場合(下の画像2つ分)

f:id:ohguma:20150715013118p:image

f:id:ohguma:20150715013119p:image

とだんだん手に負えなくなる。


そこで、変数を導入し、それぞれのセンサのON/OFF値を0/1に置き換えて2進数で状態を表現する。

f:id:ohguma:20150715080739j:image

普段目にする金額などの10進数は0〜9までの10個の数字で1桁を表すが、 2進数は0と1の2つの数字で1桁を表す。

世の中には他にも、分と秒は60進数(60秒=1分、60分=1時間)、時間は24進数(24時間=1日)などの「進数」がある。

2進数10進数をならべるとこのようになる。

f:id:ohguma:20150715075845j:image

ここで注目したいのは、2進数のうち桁中に「1」が1つだけ含まれる数値で、10進数では1,2,4,8,...と倍々に増えている。

2進数の1桁目をセンサ1、2桁目をセンサ2、3桁目をセンサ3、4桁目をセンサ4の状態として考えれば、状態を示す変数「A」

と変化させれば、全状態を一つの変数で網羅できる。


と、ここでこうプログラムすると、これは間違い。

f:id:ohguma:20150715081920p:image


(続く)

2015-07-11

[]続・オムニホイールの使い方 ブレーキについて

ダイセンの6Chコントローラにはブレーキモードがある。

値0でRev/BrkをONにするか、変数で128をセットする。

f:id:ohguma:20150711124300p:image

ブレーキ効果プログラムせずともモーターのケーブルショートさせてホイールを手で回してみれば確認できる。

f:id:ohguma:20141219021336j:image:w360

この保持力を活かしたブレーキターンを思いついたので試してみた。

f:id:ohguma:20150711124301p:image

ブレーキを掛けたホイールを軸にターンできるのではと思ったが。

D

最初のターンは、右前ホイールが停止状態。

2度めのターンが、右前ホイールブレーキ状態。

うーん、微妙。ATのターンピックを使ったようなターンは無理か。

[]続・オムニホイールの使い方 6Chコントローラについて

ダイセンの6Chコントローラは使い方によっては不具合があることが、ダイセンからも報告されている。

こちらに、まとめられた記事がある。

特に大電流を流せるリチウム系のバッテリーを使う場合は発熱だけで済まずに、煙を吹いて回路自体が損傷し、火災危険性もあるので十分に注意する。

不具合を避ける方法として、上記ダイセンの報告では正転から逆転する切り替える前に待ち時間を入れることが推奨されている。

以下は、うちの6Chで試しているアイデアであり、ダイセン推奨の対策とは違うので試す場合は十分にやっていることを考慮の上、自己責任対応してください。

上記紹介ページにもあるように6CHコントローラは、Hブリッジという回路でモーターの正転・逆転を制御している。また、以前にもid:ohguma:20141218で取り上げたがブレーキモード存在するので、Hブリッジの状態は

の4通りが存在する。

f:id:ohguma:20150711095615j:image

(上記図のブレーキは「−」側の2つのSWがONにしているが、6CHコントローラの内部では「+」側の2つのSWがONになっているかもしれない。)

個々のSWは実際にはFETという半導体実装されており、マイコンからの指示でFETがON/OFFを切り替えるが、FETにはその動作にタイムタグがある。

左右片側の「+」側「−」側の2つのFETが同時にON状態になってしまうと、電源の「+」「−」がショートした状態になり、最悪、大電流でFETが焼けて煙を吹くという事故が発生する。

そこで、「+」側「−」側の2つのFETが同時にONにならないように、正・逆転・ブレーキが切り替わる場合は、間に意図的に「停止」状態を入れ全FETをOFFにすることで、ショート状態を回避する。

ブレーキを使わない場合、今回の3状態(正・逆・停止)と前回ループ時の3状態の組み合わせは9通り。

f:id:ohguma:20150711105023j:image

ブレーキありの場合、今回の4状態(正・逆・ブレーキ・停止)と前回ループ時の4状態の組み合わせは16通り。

f:id:ohguma:20150711111549j:image

前回ループ時のX,Y,Zの値を別の変数V,U,Wに保存しておき、今回値と前回値を比較して「停止」が必要かどうか判断し、モーターのいづれか1つでも停止が必要なら、一瞬だけ全停止を実行する。

サブルーチンを使う例

f:id:ohguma:20150711012602p:image

▼メインプログラムの6CHコマンドの直前でサブルーチン実行

f:id:ohguma:20150711012604p:image

2015-07-10

[]続・オムニホイールの使い方

もう少し複雑に動かす。

f:id:ohguma:20150710125556j:image

f:id:ohguma:20150710125833p:image

D

2015-07-09

[]続・オムニホイールの使い方

これまでのプログラムでは、whileループ中で進行方向Bを変化させていないため、直進しかできなかったが、ループ中でBを変化させることで複雑な動きが実現できる。


とりあえず、0.2秒毎に進行方向を1時間分(30度)づつ増やして回転するサンプル。12方位(0〜11時)の移動ができるようにしたので、Bを1づつ足しているが、6方位(0,2,4,6,8,10時)の移動しかできない場合でも、Bを2づつ足せば6角形を描いて移動できる。

また、このように12通りの状態がある場合、1〜12でなく、0〜11で状態を区別すると「%(剰余:割った余り)」の演算子が有効活用できる。(1〜12ではif分が必要になる)

f:id:ohguma:20150710004843p:image

プログラムを整理して、以下の2箇所はサブルーチンにしてみた。このような構造にしておけば、Bを決める部分のみ作りなおせばよいので、後が楽になる。

  • 進行方向Bからモーター値XYZ決定
  • コンパス補正値C・スタート時向きDでモーター値XYZ補正
    • スタート時右手方向は、サブルーチン内で毎回(D+90)を計算することにし、変数Eは廃止

サブルーチンを使う場合、サブルーチン内で必要な変数を上書きしない用に注意する。上記のサンプルでは、変数A,C,Dがプログラム中で書き換えてしまうと、意図する動作をしなくなる。書き換えては行けない変数と、書き換えてもよい変数を意識して使い分ける。

▼動作例

D

2015-07-08

[]続・オムニホイールの使い方

昨日のプログラムに、id:ohguma:20150620コンパス活用方法プログラムを合体させる。

f:id:ohguma:20150709011347p:image

正面の判定をする誤差や、コンパス補正で足す回転の方向のモーター値はあくまで一例なので、よりよい値を試行錯誤で探すこと。

if 分は、プログラムの見やすさを考慮すれば、判断一回分の時間が無駄になるが、あえて何もしないという処理もありだと思う。

スピードAとコンパス補正値Cを足し引きしてモーター値X,Y,Zを作るため、A+Cが100を超えないようにする。

2015-07-07

[]続・オムニホイールの使い方

f:id:ohguma:20150707054257j:image

進行方向の合成ができるなら、コンパスセンサによる向き補正も直進と回転の合成でできる。


ここでパワー設定と回転方向を確認しておく。

変数でモーター1,2,3のパワーを設定する場合、全ての変数が+なら右回転などと動く向きを決めておくと、後で悩まずにすむ。以下、例。

f:id:ohguma:20150708124457p:image

このように変数で6chコントローラを動かように設定しておけば、不幸にも6chコントローラの5番が焼けた場合でも、モーター3を6番に繋ぎ替えた時でも、6chの設定部分の変更で対応できる。

f:id:ohguma:20150708124458p:image

こちらは、モーター1、2、3を1,2,3番の順に繋ぐときの例。

f:id:ohguma:20150708124459p:image

コンパス補正はまた後でまとめる。

2015-07-06

[]続・オムニホイールの使い方

3輪オムニのうちの2輪を動かせば、偶数時(0,2,4,6,8,10時)方向の6方向へは動かせた。

次に真横も含む、奇数時(1,3,5,7,9,11時)への移動を考える。


2時方向と4時方向に同じ時間進めば、到着地点は3時方向になる。(実際には加減速の関係でズレが生じるが、ここでは無視する)

f:id:ohguma:20150707024939j:image

プログラムの例。

f:id:ohguma:20150707030732p:image:w360


上のプログラムを直し、変数X:モーター1、変数Y:モーター2、変数Z:モーター3の3変数で6chコントローラの値をセットし同じように動かしてみる。

f:id:ohguma:20150707030733p:image:w360


移動距離は「速度(=モーター値)×時間」なので、上の動きは「2時方向×時間+4時方向×時間」と書ける。数学的に時間でくくるとこの式は「(2時方向+4時方向)×時間」とも言える。

それをプログラムに反映。

f:id:ohguma:20150707030734p:image:w360

最初の図で、ACCBの距離は等しく、ABの距離はそれに比べ長い

√3≒1.732倍。ACの中点をDとしたとき、三角形ACDは正三角形の半分なので、CDの長さはACの半分。ピタゴラスの定理から、

 AC*AC=CD*CD+AD*AD

CD=0.5*ACなので、

 AD*AD=AC*AC-0.25*AC*AC=3/4*AC*AC

両辺の平方根を計算すれば、

 AD=√3/2*AC

となり

 AB=2*AD=√3*AC

分、「(2時方向+4時方向)=(3時方向)」としたときの速度は早くなるので、「(2時方向+4時方向)÷√3」とすれば同じ速度になる。C-Styleでは整数しか扱えないので、正しく計算しようとすると(1÷√3)≒0.58≒(6/10)と近似して「(2時方向+4時方向)×6÷10」のように計算する。さらに計算を楽にするなら「(2時方向+4時方向)÷2」もありと思う(この場合、X=A/2,Y=A/2,Z=-A)。


(注意)

3番めのプログラムを実験するときは、モーター3の値Zは「−A×2」となっている。6chコントローラでセットする値は−100から100までなので、「−A×2」が範囲外にならないようにすること。

(注意2)

これまでのプログラムにはモーターの個体差がないものとして考えているので、実際に動かした際には個体差により真っ直ぐす進まないことが多いと思う。この時に個体差を考慮してプログラムをすると、モーター交換時や、モーターがヘタった場合の再調整が大変面倒なので、その点はコンパスセンサを使った向き補正で対応したほうがよいと考える。

(注意3)

平方根(√)とは、a=b*bの時のaに対するbのこと。(例:9の平方根は3および-3)

2015-07-05

[]続・オムニホイールの使い方

【注意】本サイトの内容は著者個人の思い込みで書かれており、他にもっと良い方法もあると思われるので、鵜呑みにはしないでください。こんな方法もあるのか程度に捉えて、参考にする場合もっとよいものを作ってください。



3輪オムニのうち、2輪を動かす組み合わせは、

の3通り。

f:id:ohguma:20150706002317j:image

それぞれの組み合わせで、モーターを逆転させることで2通りの動きがある

ので組み合わせると6方向への移動となる。

オムニホイールが120度毎の配置になっていれば、正面を基準に60度毎の方向の動きとなる。この動く向きを正面を0時とするクロックポジションで表すとこうなる。

方位順に並べ直すと

予めプログラム中には6方向分の動きを仕込んでおき、変数で進む方位を変えるプログラムを考える。このような複数の状態の切り替えには、「elseif」を使うとよい。

f:id:ohguma:20150706002510p:image:w360

2015-07-04

[]オムニホイールの使い方

前進とは反対向きに進む(後進)場合は6chコントローラにセットする値を逆転させる。

f:id:ohguma:20150705043911p:image

[]オムニホイールの使い方

6chコントローラには数値だけでなく、変数もセットできる。

から移動スピードを簡単に変えられるように前回のプログラムをこう直しておく。

f:id:ohguma:20150703130837p:image

2015-07-02

[]オムニホイールの使い方

オムニホイールを使ったロボット制御方法について少しずつ考える。

【前提】

  • ホイールは120度毎の配置の3輪オムニ。前2輪は中心から左右60度に等間隔に配置。後ろ1輪は背面の中心に配置。
  • 6CH コントローラの 1, 3, 5chに、左前、右前、後ろモータを接続。(順番は右回り
  • 原則、回転禁止。(オムニの基本と考える)
  • 原則、砂時計禁止。(思考停止しないようにする)

3輪オムニはとりあえず2輪を同じパワーで動かせば6方向には動かすことができる。

2秒前進するプログラムはこう書ける。

f:id:ohguma:20150702125621p:image

が、砂時計は禁止なので、タイマーを使い、こうする。

f:id:ohguma:20150702125622p:image