FC2ブログ

爪車

あけましておめでとうございます。

ccacheでビルド時間の短縮

最近ccacheというものを知りました。
コンパイル結果をキャッシュすることで再コンパイル時間を短縮してくれます。

使用方法は簡単に

ccache g++ main.cpp

てな感じです。

qmakeで利用する場合は
QMAKE_CXX = ccache g++

cmakeの場合は
set(CXX="ccache g++")

参考ページ
ccacheで再コンパイル処理を高速化

ヒト型ロボット 85 GUI

少しずつ、モーション編集プログラムの開発を進めています。

GUIでカメラ操作。



Qtは楽でいいです。

MMDAgentα版公開

いつの間にやらMMDAgentが公開されていました。
http://www.mmdagent.jp/

Windowsのバイナリ版を試してみましたが、自分の環境ではエラーがでて動作しませんでした。
(Vista 32bit)

OSGメモ 隠れたポリゴンの描写

OpenSceneGraphのメモ

デプステストによって描写されないポリゴンを描写。
試行錯誤で何とかできました。

オブジェクトの描写順に関係なく、描写できると思います。

before


after
Screenshot-20101210-2.png

 #include <osg/Geode>
#include <osg/Geometry>
#include <osg/ShapeDrawable>
#include <osg/CullFace>
#include <osgViewer/Viewer>

osg::Node* createScene()
{
osg::Group* root = new osg::Group;

// box 1
{
osg::Geode* geode = new osg::Geode;
osg::ShapeDrawable* drawable = new osg::ShapeDrawable;
osg::Box* box = new osg::Box;
box->setCenter(osg::Vec3(-1, -1, -1));
box->setHalfLengths(osg::Vec3(0.9, 0.9, 0.9));

drawable->setColor(osg::Vec4(1, 0, 0, 1));

drawable->setShape(box);
geode->addDrawable(drawable);

root->addChild(geode);
}

// box 2
{
osg::Geode* geode = new osg::Geode;
osg::ShapeDrawable* drawable = new osg::ShapeDrawable;
osg::Box* box = new osg::Box;
box->setCenter(osg::Vec3(0, 0, 0));
box->setHalfLengths(osg::Vec3(0.5, 0.5, 0.5));

drawable->setColor(osg::Vec4(0, 1, 0, 0.5));

osg::StateSet* stateset = drawable->getOrCreateStateSet();

// 隠面消去
osg::CullFace* cull = new osg::CullFace;
cull->setMode(osg::CullFace::BACK);
stateset->setAttributeAndModes(cull, osg::StateAttribute::ON);

// DepthTest Off
stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);

//
stateset->setRenderBinDetails(11, "RenderBin");

drawable->setShape(box);
geode->addDrawable(drawable);

root->addChild(geode);
}

// box 3
{
osg::Geode* geode = new osg::Geode;
osg::ShapeDrawable* drawable = new osg::ShapeDrawable;
osg::Box* box = new osg::Box;
box->setCenter(osg::Vec3(1, 1, 1));
box->setHalfLengths(osg::Vec3(0.9, 0.9, 0.9));

drawable->setColor(osg::Vec4(0, 0, 1, 1));

drawable->setShape(box);
geode->addDrawable(drawable);

root->addChild(geode);
}

return root;
}

int main(int argc, char* argv[])
{
osgViewer::Viewer viewer;

viewer.setSceneData(createScene());

return viewer.run();
}

OpenHRP3 + drawstuff

OpenHRP3の敷居を少しでも下げてみたいと思い、いろいろとやってみたのですが、面倒になったので途中で投げ出すことに。
これでいっぱいいっぱいです。申し訳ありません。

OpenHRP3を動力学シミュレータとして利用し、ODE付属のdrawstuffで描写を担当させるサンプル。

・環境
Ubuntu9.10
OpenHRP version 3.1.0-Release バイナリパッケージからインストール
ode-0.11.1

Screenshot-20101029.jpg
実行例

・c++ソース
main.txt
.txtから.cppに変更してください。

・cmake用のCMakeList.txt
CMakeLists.txt

・サーバー群立ち上げのためのスクリプト
openhrp-startup-servers.txt
.txtから.shに変更してください。

・プログラム実行の流れ
スクリプトで
openhrp-model-loader
openhrp-aist-dynamics-simulator
openhrp-collision-detector
らをいっぺんに立ち上げ。
その後、コンパイルしたプログラムを別端末で実行。

・補足
・コードの大部分はOpenHRP3公式サイトからのものです。
・パスは適当に修正してください。
・つぎはぎです。
・不要なコードが混じっているかも。
・ODEに付属のdrawstuffを描写ライブラリとして利用。
・drawstuffの関数は回転行列がR[12]なので、ラップ関数を用意してR[9]に変換。ついでにdouble -> floatへも変換。

メモ makeの並列処理

makeの-jオプションで並列処理ができるようです。

最近初めて知りました。

-jの後に並列実行するジョブの個数を指定します。
デュアルコアの場合は
make -j2
のような感じです。

OpenHRP version 3.1.0 Release

9月21日にOpenHRP version 3.1.0-Releaseがリリースされたようです。

Ver.3.1.0β4からの変更点を確認した後、アップデートしたいと思います。

動作パターン設計ツールの公開は、まだなのかな?
ずっと楽しみに待っているのですが・・・

QtとCORBA

QtとCORBAを組み合わせてみようとしたのですが、どうもうまくいかない。

検索して調べてみたら、QtとCORBAの組み合わせは、よろしくないみたいです。
以前のバージョンのQtではCORBAを扱うモジュールがあったみたいですが、現在では商用版のQtでのみのサポートとなっており、使用は非推奨。

代わりに現在のQtではD-Busを扱うQDBusモジュールが用意されています。
詳しいことはまだ理解していないのですが、D-BusもCORBAと同じように、アプリケーション間のやりとりを行う技術のようです。

やっと・・・

やっとBLACKIIで、まともに加工できるようになりました。



切り込みステップを0.1mm、切削送りを200mm/minの設定で加工。

3本目・・・

エンドミル折れた・・・これで3本目。

アルミの切削は困難を極める。

切削中の筐体のビビリがものすごい。
すさまじい騒音が発生。

切削中に、エンドミルがアルミに引っかかり、スピンドルの回転が止まる。
送りは止まらないので、エンドミルはぽっきりと折れてしまう。

まともに切削できやしない。

心が折れそう。

試切削

BLACKIIで試切削してみました。

とりあえず適当な形をCADで作製。
材料はMDF材です。

初めての切削なので見守りながら開始したのですが、いきなりエンドミルが捨て板を貫通しそうになったので、緊急停止。
切り込み深さの設定をミスっていたようです。

設定しなおして、再び切削。

今度は上手くいきました。



加工時間は20分ほど。
切削粉は掃除機で吸い取りました。

DSCN1306.jpg

綺麗に切削できて喜んでいたのですが、材料の固定に使用した両面テープが強力すぎて、捨て板からはがせない、というなんとも間抜けな事態に。

BLACKII 1520の組み立て完了

ここ一週間ほど忙しくて、しばらく組み立てを放置していましたが、やっと完成。

まとまった時間が取れなかったため、完成が伸びてしまいましたが、一気にやれば2日ほどで組み立てられるのではないでしょうか。
説明書も丁寧なので、難なく組めると思います。

DSCN1295.jpg

設置場所に困っています。

設備投資

オリジナルマインド社のmini-CNC BLACKII 1520を購入しました。



現在、組み立て中。

NaNのメモ

C/C++でNaNを検出するにはisnan()を使えばいいらしい。

Octave高速化

ATLASとやらをインストールすると、Octaveの行列演算が高速化するらしいです。

試してみました。

OctaveもATLASもSynaptic パッケージ・マネージャからインストール。
バージョンは
Octave3.0.5
libatlas3gf-sse2

環境は
OS: Ubuntu 9.10
CPU: AMD Athlon2 X2 240e (2.8GHz)
メモリ: 2.0GB

ATLAS導入前
octave:1> A = rand(2000, 2000);b=rand(2000,1);
octave:2> tic;A\b;toc
Elapsed time is 2.48691 seconds.

ATLAS導入後
octave:1> A = rand(2000, 2000);b=rand(2000,1);
octave:2> tic;A\b;toc
Elapsed time is 1.09443 seconds.

なんと2倍以上高速化。すごい。

参考にさせていただいたサイト様。
Debian(lenny)パッケージによるliboctaveインストールと使い方

操作ハンドルを実装

3DCGソフトでポリゴンの頂点の編集に使う矢印みたいなものを実装しました。
名称がわからないので、操作ハンドルと呼んでいます。

Screenshot-GLWidget-20100425.png

名称がよくわからないものを調べるのは一苦労。
いろいろ調べた結果、マウスピッキング処理で実現するものらしい。

実装にあたっては、こちらのサイトを参考にさせていただきました。
[OpenGL] マウスによる頂点編集

操作ハンドルの実装は長年の夢。やっと実現できました。

シミュレーション表示用のプログラム開発は、だいぶ満足したので、いったん中止。
そろそろヒト型ロボット開発を再開することにします。

Qt4に移植中

OpenGLで書いたシミュレーション表示用のプログラムをせっせとQt4に移植中です。

Screenshot-GLWidget-20100420.png

Qt4には、OpenGLを扱うためのモジュールが用意されているので、glutの代わりにそれを使用します。

gl, gluの関数はそのまま使用できますが、glutの関数を使っていたところはすべて書き直しです。
Qt4に慣れないこともあり、けっこうてこずっています。

Qt4

GUIを扱えるようになりたいので、Qt4(キュート)の勉強を始めました。

Qt4に関する書籍やWebでの情報が少ないので、学習が大変かなと思っていたのですが、QT Createrに大量のすばらしいサンプルプログラムとチュートリアルが付いていました。

単純なボタンから、OpenGL、XML、ネットワーク関連といったものまで、様々なサンプルがありました。
これだけあれば学習には困らないかと。

OpenGLと組み合わせてロボットのシミュレータを作る予定です。

諦める

衝突、無理。

接触のシミュレーションができない

自由落下する剛体運動のシミュレーションはできるようになったのですが、床との接触のシミュレーションが上手くできないです。
本の通りにしても物体が地面に沈み込んでしまいます。
接触力の係数を変えてみたら、今度は物体が吹っ飛んでいってしまいました。

よくわからん。

動力学シミュレータを作り始めました

動力学シミュレータを作り始めました。
「ヒューマノイドロボット」(オーム社)の"6章:動力学シミュレーション"を実装してみたいと思います。

とりあえず環境整備と言うことで、シミュレーション表示用のプログラムを作りました。



以前の3次元プロット用に使っていたものを機能強化。
画面上で文字列の描写ができるようになりました。
シェーディングもできるようになりました。
陰影付けはまだですが、一応使えるものができたので完成です。

これで動力学シミュレーション本体に取り掛かれます。
数式がぜんぜん理解できないのですが・・・

4月中に全部完成すればいいのだけれど・・・

平面2リンクロボットの逆運動学 ヤコビアンを用いた数値解法

平面2リンクロボットの逆運動学問題をヤコビアンを用いた数値解法で求めてみました。
ヤコビアンを用いた数値解法は汎用性があり、平面2リンク以外のロボットでもヤコビアンを計算できれば、容易に逆運動学問題が解けるようになります。

詳しい理論はロボット工学などの文献をご参照下さい。
参考文献
吉川恒夫 : ロボット制御基礎論, コロナ社. (1988).
内山勝, 中村仁彦 : 岩波講座 ロボット学2 ロボットモーション, 岩波書店 (2004)
梶田秀司編者 : ヒューマノイドロボット, オーム社 (2005)
出村公成 : 簡単!実践!ロボットシミュレーション, 森北出版株式会社 (2007)

勝手に制御分析!あのロボットはどう動く?
第3回「操縦者とロボットをつなぐ運動学と,静力学の導入 -スパロボの華麗な操縦と動作を分析-」(前編)


勝手に制御分析!あのロボットはどう動く?
第4回「操縦者とロボットをつなぐ運動学と、静力学の導入
-スパロボの華麗な操縦と動作を分析-(後編)九州大学 田原健二



ヤコビアンを用いた逆運動学の数値解法はいくつか方法があるようです。

今回の方法は、ロボットの手先と目標との位置誤差を、ヤコビアンの逆行列を用いて小さくするな間接角度を求め、収束計算する方法です。

ここでは簡単に手順の説明をします。

リンク1,2の長さ: l1, l2
間接角度: q(1), q(2)

ロボットの順運動学とヤコビアンを求められるように準備しておきます。
原点(0,0)からリンク1の先端位置(x,y) = (p1(1),p1(2))
p1(1) = l1*cos(q(1))
p1(2) = l1*sin(q(1))
リンク2の先端位置(x,y) = (p2(1),p2(2))。これがロボットの手先となります。
p2(1) = l1*cos(q(1))+l2*cos(q(1)+q(2))
p2(2) = l1*sin(q(1))+l2*sin(q(1)+q(2))

ヤコビアンJは
J(1,1) = -l1*sin(q(1))-l2*sin(q(1)+q(2)), J(1,2) = -l2*sin(q(1)+q(2))
J(2,1) = l1*cos(q(1))+l2*cos(q(1)+q(2)), J(2,2) = l2*cos(q(1)+q(2))

Step1. 順運動学で、手先位置p2を求める。
Step2. 手先位置p2と目標位置rdとの位置誤差dpを計算する。
Step3. 位置誤差の大きさ|dp|が許容誤差以下であれば計算終了。そうでなければStep4へ。
Step4. 位置誤差を小さくするための間接角度の修正量dqを計算する。
Step5. 間接角度を更新q = q + dqし、Step1に戻る。

フリーの数値計算ソフトのScilabで計算しました。

// IK.sce


clear;
clf;

l1 = 1.0; // リンク長
l2 = 1.0;

x0 = 1.4;// 目標軌道初期位置
y0 = 1.4;

q = [30*%pi/180;30*%pi/180]; // 初期間接角度

dT = 0.08; // 時間刻み幅

for t = 0:dT:1
rd = [x0;y0-(3-2*t)*(t^2)*y0]; // 目標軌道

for n= 0:1:100

// Step1 位置の計算
p1 = [l1*cos(q(1));l1*sin(q(1))];
p2 = [l1*cos(q(1))+l2*cos(q(1)+q(2));l1*sin(q(1))+l2*sin(q(1)+q(2))];

// Step2 位置誤差の計算
dp = rd - p2;

// Step3 誤差の評価
pe = dp'*dp; // dp(1)^2+dp(2)^2
if pe < 0.1^6
break; // 許容誤差であれば計算終了
end

// Step4 間接角度修正量の計算
// ヤコビアンの計算
J = [-l1*sin(q(1))-l2*sin(q(1)+q(2)), -l2*sin(q(1)+q(2));
l1*cos(q(1))+l2*cos(q(1)+q(2)), l2*cos(q(1)+q(2))];

Kp = 0.2; // 数値計算を安定させるための係数
dq = Kp*inv(J)*dp; // 間接角度修正量の計算

// Step5 間接角度の更新
q = q + dq;

end

// ロボットの描写
plot(rd(1),rd(2), "+r"); // 目標位置
plot(0,0, ".b");
plot(p1(1),p1(2), ".b");
plot2d([0,p1(1)],[0,p1(2)], 1,"011", "", [-2,-2, 2,2]);
plot2d([p1(1),p2(1)],[p1(2),p2(2)], 1,"011", "", [-2,-2, 2,2]);
end



実行結果です。赤い点が目標軌道。
ik_20100220.png

大変なことに・・・

手違いで、ここ数ヶ月間に開発してきたプログラムを消去してしまいました。

都合によりlinuxを再インストールしたのですが、その際に全部消去してしまいました。

再インストールの前にバックアップをとっていたと思っていたのですが、どうやらバックアップをとるディレクトリを間違えていたようで・・・。

以前とったバックアップが他のパソコンにあったのですが、ファイルの最終更新日が12月6日・・・。

あぁ・・・

教育用レゴ拡張セット購入しました

ふと、レゴマインドストームの部品がほしい、いろいろと組み立ててみたい、という衝動に駆られました。
マインドストーム本体はいらない(高いから)、部品だけほしい、と思いネットで探してみるとちょうど欲求を満たしてくれそうなものがありました。
教育用レゴ拡張セット(9648)です。
いろいろなパーツが偏りなく、必要十分にそろっています。値段もあまり高くない(1万円くらい)です。

DSCN1214.jpg

DSCN1211.jpg
部品は袋に入っていたので、開封して適当に分類してみました。

DSCN1218.jpg
転がり間接を組み立ててみました。

C言語でgnuplotを利用してグラフ表示

最近、C言語のプログラム中からgnuplotを呼び出し、グラフの表示をする方法を知りました。
パイプを使ってgnuplotにコマンドを送る方法です。特別なライブラリ等を使用するわけではないので気楽に利用できます。

こちらのページを参考にさせて頂きました。
4 C言語からgnuplotを操作する

いままでは、Cプログラムで計算したデータをファイルに書き出して、エクセルやらgnuplotなどでグラフ表示処理していましたが、プログラム中でグラフを処理できるようになるのでかなり便利です。
プログラムの実効中に逐一データをグラフ処理できるので、リアルタイムでグラフを表示したりできます。
工夫すればグラフのアニメーション表示もできます。

試しに
1.sin(x)をプロット
2.配列のデータを曲線と点で同じグラフに重ねてプロット
3.三次元プロットのアニメーション表示
するプログラムを作成してみました。

以下のプログラムはLinux環境下で実効できます。
あらかじめgnuplotのインストールが必要です。
Windows環境で動かす時は
工学ナビの中の人の研究と周辺 C言語のプログラムでgnuplotにグラフを描かせる(Windows)
を参考にしてください。

// test1.c sin(x)をプロット
#include <stdio.h>

int main(void)
{
FILE *gp;

gp = popen("gnuplot -persist", "w"); // パイプを開き、gnuplotの立ち上げ

fprintf(gp, "plot sin(x)\n"); // パイプを通してgnuplotにコマンドを送る

fprintf(gp, "exit\n"); // gnuplotの終了
fflush(gp);
pclose(gp); // パイプを閉じる

return 0;
}

Screenshot-Gnuplot-test1.gif


// test2.c 配列のデータを曲線と点でプロット
#include <stdio.h>
#include <math.h>
#define N 100

int main(void) {
FILE *gp;

int i;
double x[N], y1[N], y2[N];

// データ生成
for (i = 0; i < N; ++i) {
x[i] = M_PI/18*i;
y1[i] = sin(x[i]);
y2[i] = cos(x[i]);
}

gp = popen("gnuplot -persist", "w"); // パイプを開き、gnuplotの立ち上げ
fprintf(gp, "set multiplot\n"); // マルチプロットモード
fprintf(gp, "set xrange [%f:%f]\n", x[0], x[N-1]); // 範囲の指定
fprintf(gp, "set yrange [-1.2:1.2]\n");
fprintf(gp, "set xlabel \"x\"\n"); // ラベル表示
fprintf(gp, "set ylabel \"y\"\n");

// 曲線のプロット
fprintf(gp, "plot '-' with lines linetype 1\n");
for (i = 0; i < N; ++i) {
fprintf(gp, "%f\t%f\n", x[i], y1[i]);
}
fprintf(gp, "e\n");

// 点のプロット
fprintf(gp, "plot '-' with points pointtype 1\n");
for (i = 0; i < N; ++i) {
fprintf(gp, "%f\t%f\n", x[i], y2[i]);
}
fprintf(gp, "e\n");

fprintf(gp, "set nomultiplot\n"); // マルチプロットモード終了
fprintf(gp, "exit\n"); // gnuplotの終了
fflush(gp);
pclose( gp); // パイプを閉じる

return 0;
}

Screenshot-Gnuplot-test2.gif


// test3.c 三次元プロットのアニメーション表示
#include <stdio.h>
#include <math.h>
#include <unistd.h>
#define N 100

int main(void) {
FILE *gp;

int i;
int j;
double x, y, z, t;

gp = popen("gnuplot -persist", "w"); // パイプを開き、gnuplotの立ち上げ
fprintf(gp, "set xrange [-1.2:1.2]\n"); // 範囲の指定
fprintf(gp, "set yrange [-1.2:1.2]\n");
fprintf(gp, "set zrange [0:10]\n");
fprintf(gp, "set xlabel \"x\"\n"); // ラベル表示
fprintf(gp, "set ylabel \"y\"\n");
fprintf(gp, "set zlabel \"z\"\n");

// 三次元プロットのアニメーション表示
for (j = 0; j < N; ++j) {
usleep(50000); // usec待機
fprintf(gp, "splot '-' with lines linetype 1\n");
for (i = 0; i < N; ++i) {
t = 0.2*i;
x = cos(t+0.1*j);
y = sin(t+0.1*j);
z = t;
fprintf(gp, "%f\t%f\t%f\n", x, y, z);
}
fprintf(gp, "e\n");
}

fprintf(gp, "exit\n"); // gnuplotの終了
fflush(gp);
pclose(gp); // パイプを閉じる

return 0;
}

Screenshot-Gnuplot-test3.gif


パイプを通す方法だと、gnuplotだけでなく、OctaveやScilabもCプログラム中から利用できます。

ODEの導入メモ

ubuntu9.10でODE-0.11.1を使うためのメモです。

こちらのページを参考にさせて頂きました。
BuildOnUbuntu
自分のプログラムをODEで動かす,LinuxとMac OSX


ODEをインストールする前に、OpenGL関連をインストールしておきます。
sudo apt-get install freeglut3 freeglut3-dbg freeglut3-dev

次に、ここからode-0.11.1.tar.gzを適当な場所にダウンロードし、展開します。
展開したディレクトリで
sudo ./configure --enable-double-precision --with-x
sudo make
sudo make install
これでODEのインストールは完了です。
ode/demoにデモプログラムが入っているので、試しに実行してみましょう。

次に、自分でプログラムを作成するためにdrawstuff関連の設定をします。
インクルードファイル・ライブラリファイルのコピー。
sudo cp -r include/drawstuff /usr/local/include/
sudo cp drawstuff/src/libdrawstuff.la /usr/local/lib/
sudo cp drawstuff/src/.libs/libdrawstuff.a /usr/local/lib/
sudo ldconfig

texturesを参照可能な場所に置く。
sudo mkdir /usr/local/share/drawstuff
sudo cp -r drawstuff/textures /usr/local/share/drawstuff/

以上で、自分でODEを使ったプログラムを作製する準備は完了です。

自分でODEを使ったプログラムを作成する際は
#include <ode/ode.h>
#include <drawstuff/drawstuff.h>

textureを利用するときは/usr/local/share/drawstuff/texturesを指定します。

コンパイル・リンク時のオプションは
コンパイル
-I/usr/local/include -DdDOUBLE

リンク
-L/usr/local/lib -lode -ldrawstuff -lglut

とします。コンパイル時のオプションにに-DdDOUBLEをつけないとエラーが発生するようです。

liboctaveの導入メモ

Ubuntu9.10の環境でliboctave(Octave C++)のインストールと利用のメモです。

liboctaveの利用はこちらを参考に。
octave+c++で数値計算
liboctave で数値計算(リンクとインストール)

octaveの最新版は3.2のようだが、ubuntu9.10での公式パッケージは3.0.5なのでこちらを利用。

インストール
sudo apt-get install octave3.0 octave3.0-headers
sudo apt-get install liblapack-dev
sudo apt-get install fftw-dev readline-common
で大丈夫だと思う。もしかしたら他にも必要かも。

/etc/ld.so.confに/usr/lib/octave-3.0.5を追加する。
sudo ldconfig

liboctaveを利用するプログラムには
#include <octave/config.h>
#include <octave/Matrix.h>
として、コンパイルは
g++ -I/usr/octave-3.0.5 -I../include -c test.cpp
g++ -o test test.o -L/usr/lib/octave-3.0.5 -loctave -lcruft -ldl -lfftw3 -llapack -lblas -L/usr/bin/octave/

必要ならば
sudo apt-get install octave3.0-htmldoc
で/usr/share/docにoctave3.0-htmldocがインストールされます。

新しいPC買いました

ロボット開発用に新しくPCを買いました。

CPU: Athlon Ⅱ X2 240e 2.8GHz
メモリ: DDR3-1333 2GB
マザーボード: BIOSTAR TA785G3

あまり考えずに、3年くらい使えればいいと思い、BTOで安い構成で購入したのですが、Linuxの環境を整備するのにかなり手間りました。

Ubuntu8.04を入れ、ART-Linux化して使う予定だったのですが、その前に、試しにUbuntu9.10を入れてみました。
無理だとは思いましたが、だめもとでART-Linux化を試みるものの、インストールの途中でエラーが発生しインストールできませんでした。

仕方がないので、当初の予定どうり、Ubuntu8.04をインストールすることに。

ところが、Ubuntu9.10では自動でつながったインターネットがUbuntu8.04ではつながらず。
いろいろとネットで調てみると、どうやらマザーボードのオンボードLANのドライバがおかしい模様。
別のPC経由で最新のドライバを入手し、試してみるもすもうまくいかず、あきらめてPCIのLANボードを購入することにしました。
近所の家電量販店でLANボードを購入し、取り付け後、再インストールすると、無事接続。

インターネットには接続できるようになったものの、別のところで問題が発生しました。
画面の解像度がモニタに合っていなかったので、設定を変更してみたが直らず。
内臓グラフィックのドライバがうまく有効にならず、画面がおかしくなる。いろいろと試すもどうにもなりませんでした。

結局、ART-Linuxは古いPCで使い続けることにし、新しいPCにはART-Linux化をあきらめ、Ubuntu9.10をインストールすることにしました。

LANボードが無駄に・・・。

Ubuntu9.10だと、LANの問題も、画面の問題も大丈夫です。
起動も8.04のときよりも早くなっているので、9.10をART-Linux化できたら一番よかったんですけどね・・・。

SH7125でPWMサーボの制御

SH7125で16個のPWMサーボの制御です。
需要がありそうなので紹介します。

マイコンでPWMサーボを制御する方法はいろいろありますが、今回の方法は、タイマを使った割り込みで生成したパルスで、16個のPWMサーボを制御します。

けっこう前に書いたプログラムなので、自分でも何でこうなったか忘れてしまっているので、簡単な説明だけしておきます。

タイマはMTU2の0~4チャネルを同期動作で使用。
ポートEのPE0~PE15からパルス出力。
想定している制御周期は20ms。
TCNTオーバーフローで2.5msごとの割り込みが4回、その後10msで割り込み。
2.5msの割り込みで4個ずつまとめてパルスを立ち上げ。コンペアマッチで0出力。
割り込みで呼ばれるのはvoid MTU20_INT_OVF(void);

と言う感じです。

パルスの立ち上げは割り込みで 4つまとめて立ち上げています。立ち下げは割り込みではなく、ハードウェアでそれぞれ処理されるので、割り込みによるジッタの発生が抑えられていると思います。
ServoPuls[]にサーボの指令値を入れます。基準パルス幅1.5msは10進数で2344です。16進数だと0x928です。
秋月電子のAKI-7125を想定しています。
AKI-7125に搭載されているクリスタルは12.5MHzなので、MTU2クロックMPΦは25MHzで使用します。
アルファプロジェクトのSTK-7125などはクリスタルが10MHzなので、プログラムの修正が必要になります。
MPΦ=25MHz/16でカウントするので、1msは1562.5カウントになります。

以下のプログラムは実際のプログラムからの一部抜粋なので、このままでは動きません。
環境はHEW4です。

//プログラムここから

#include "iodefine.h"
#include <machine.h>

volatile unsigned int ServoPuls[16]; // サーボパルス

// main関数の一部
void main(void)
{
IO_init();
MTU2_init();
set_imask(0); // 割り込みマスクの解除

ServoPuls_init(); // ServoPuls初期化
MTU2_syn_start(); // タイマシンクロスタート

while (1) {
}
}

// ServoPulsの初期化
void ServoPuls_init(void)
{
int i;
for (i = 0; i < 16; i++) {
ServoPuls[i] = 0x928; // パルス1.5msにセット
}
}

// IO Portのセット
void IO_init(void)
{

// ------------------------------------------------------------------
// PortE サーボパルス用 [PE15:PE0] MTU2
// ------------------------------------------------------------------
PFC.PECRL4.BIT.PE15MD = 0x01; // PE15 is TIOC4D
PFC.PECRL4.BIT.PE14MD = 0x01; // PE14 is TIOC4C
PFC.PECRL4.BIT.PE13MD = 0x01; // PE13 is TIOC4B
PFC.PECRL4.BIT.PE12MD = 0x01; // PE12 is TIOC4A
PFC.PECRL3.BIT.PE11MD = 0x01; // PE11 is TIOC3D
PFC.PECRL3.BIT.PE10MD = 0x01; // PE10 is TIOC3C
PFC.PECRL3.BIT.PE9MD = 0x01; // PE9 is TIOC3B
PFC.PECRL3.BIT.PE8MD = 0x01; // PE8 is TIOC3A
PFC.PECRL2.BIT.PE7MD = 0x01; // PE7 is TIOC2D
PFC.PECRL2.BIT.PE6MD = 0x01; // PE6 is TIOC2C
PFC.PECRL2.BIT.PE5MD = 0x01; // PE5 is TIOC1B
PFC.PECRL2.BIT.PE4MD = 0x01; // PE4 is TIOC1A
PFC.PECRL1.BIT.PE3MD = 0x01; // PE3 is TIOC0D
PFC.PECRL1.BIT.PE2MD = 0x01; // PE2 is TIOC0C
PFC.PECRL1.BIT.PE1MD = 0x01; // PE1 is TIOC0B
PFC.PECRL1.BIT.PE0MD = 0x01; // PE0 is TIOC0A

PFC.PEIORL.WORD = 0xFFFF; // PE15-PE0 is output
}

// MTU2の初期化
void MTU2_init(void)
{
STB.CR4.BIT._MTU2 = 0; // モジュールスタンバイの解除
MTU2.TSTR.BYTE = 0x00; // タイマ0~4停止
MTU2.TRWER.BIT.RWE = 1; // 3,4のレジスタのリードライトを許可する
MTU2.TSYR.BYTE = 0xC7; // TCNT0~4同期動作

// タイマ0~4同期動作
MTU20.TCR.BYTE = 0x62; // 同期クリア、MPφ/16 1count -> 6.4*10^(-7)s 1ms -> 1562.5count
MTU21.TCR.BYTE = 0x62; // 同期クリア、MPφ/16 1count -> 6.4*10^(-7)s 1ms -> 1562.5count
MTU22.TCR.BYTE = 0x62; // 同期クリア、MPφ/16 1count -> 6.4*10^(-7)s 1ms -> 1562.5count
MTU23.TCR.BYTE = 0x62; // 同期クリア、MPφ/16 1count -> 6.4*10^(-7)s 1ms -> 1562.5count
MTU24.TCR.BYTE = 0x62; // 同期クリア、MPφ/16 1count -> 6.4*10^(-7)s 1ms -> 1562.5count

MTU20.TMDR.BYTE = 0x00; // タイマ通常動作
MTU21.TMDR.BYTE = 0x00;
MTU22.TMDR.BYTE = 0x00;
MTU23.TMDR.BYTE = 0x00;
MTU24.TMDR.BYTE = 0x00;

MTU20.TIER.BIT.TCIEV = 1; // OVFによる割り込み許可
MTU21.TIER.BIT.TCIEV = 1; // OVFによる割り込み許可
MTU22.TIER.BIT.TCIEV = 1; // OVFによる割り込み許可
MTU23.TIER.BIT.TCIEV = 1; // OVFによる割り込み許可
MTU24.TIER.BIT.TCIEV = 1; // OVFによる割り込み許可

INTC.IPRD.BIT._MTU20C = 15; // MTU20 OVF 割り込み優先度 15

MTU2.TOER.BYTE = 0xFF; // 3,4の出力許可

MTU20.TIOR.BIT.IOA = 0x00; // TGRA_0 PE0 コンペアマッチで出力保持
MTU20.TIOR.BIT.IOB = 0x00; // TGRB_0 PE1 コンペアマッチで出力保持
MTU20.TIOR.BIT.IOC = 0x00; // TGRC_0 PE2 コンペアマッチで出力保持
MTU20.TIOR.BIT.IOD = 0x00; // TGRD_0 PE3 コンペアマッチで出力保持
MTU21.TIOR.BIT.IOA = 0x00; // TGRA_1 PE4 コンペアマッチで出力保持
MTU21.TIOR.BIT.IOB = 0x00; // TGRB_1 PE5 コンペアマッチで出力保持
MTU22.TIOR.BIT.IOA = 0x00; // TGRA_2 PE6 コンペアマッチで出力保持
MTU22.TIOR.BIT.IOB = 0x00; // TGRB_2 PE7 コンペアマッチで出力保持
MTU23.TIOR.BIT.IOA = 0x00; // TGRA_3 PE8 コンペアマッチで出力保持
MTU23.TIOR.BIT.IOB = 0x00; // TGRB_3 PE9 コンペアマッチで出力保持
MTU23.TIOR.BIT.IOC = 0x00; // TGRC_3 PE10 コンペアマッチで出力保持
MTU23.TIOR.BIT.IOD = 0x00; // TGRD_3 PE11 コンペアマッチで出力保持
MTU24.TIOR.BIT.IOA = 0x00; // TGRA_4 PE12 コンペアマッチで出力保持
MTU24.TIOR.BIT.IOB = 0x00; // TGRB_4 PE13 コンペアマッチで出力保持
MTU24.TIOR.BIT.IOC = 0x00; // TGRC_4 PE14 コンペアマッチで出力保持
MTU24.TIOR.BIT.IOD = 0x00; // TGRD_4 PE15 コンペアマッチで出力保持

MTU20.TGRA = 0xF0BD + 0x928; // コンペアマッチのセット
MTU20.TGRB = 0xF0BD + 0x928;
MTU20.TGRC = 0xF0BD + 0x928;
MTU20.TGRD = 0xF0BD + 0x928;
MTU21.TGRA = 0xF0BD + 0x928;
MTU21.TGRB = 0xF0BD + 0x928;
MTU22.TGRA = 0xF0BD + 0x928;
MTU22.TGRB = 0xF0BD + 0x928;
MTU23.TGRA = 0xF0BD + 0x928;
MTU23.TGRB = 0xF0BD + 0x928;
MTU23.TGRC = 0xF0BD + 0x928;
MTU23.TGRD = 0xF0BD + 0x928;
MTU24.TGRA = 0xF0BD + 0x928;
MTU24.TGRB = 0xF0BD + 0x928;
MTU24.TGRC = 0xF0BD + 0x928;
MTU24.TGRD = 0xF0BD + 0x928;

MTU20.TCNT = 0x0;

MTU20.TSR.BIT.TCFV = 0; // OVFフラグクリア

}

// MTU20 OVF 割り込み
// intprg.cで
//// 92 MTU2_0 TCIV0
//void INT_MTU2_0_TCIV0(void)
//{
// MTU20_INT_OVF();
//}
void MTU20_INT_OVF(void)
{
volatile static int count = 0;

MTU2.TSTR.BYTE = 0x00; // タイマ0~4停止
MTU20.TSR.BIT.TCFV = 0; // OVFフラグクリア

switch (count) {
case 0:
MTU20.TCNT = 0xF0BD; // 2.5ms セット

MTU20.TIOR.BIT.IOA = 0x05; // TGRA_0 PE0 初期1出力コンペアマッチで0出力
MTU20.TIOR.BIT.IOB = 0x05; // TGRB_0 PE1 初期1出力コンペアマッチで0出力
MTU20.TIOR.BIT.IOC = 0x05; // TGRC_0 PE2 初期1出力コンペアマッチで0出力
MTU20.TIOR.BIT.IOD = 0x05; // TGRD_0 PE3 初期1出力コンペアマッチで0出力

MTU2.TCSYSTR.BYTE = 0xF8; // 0,1,2,3,4 タイマシンクロスタート
count++;
break;
case 1:
MTU20.TCNT = 0xF0BD; // 2.5ms セット

MTU21.TIOR.BIT.IOA = 0x05; // TGRA_1 PE4 初期1出力コンペアマッチで0出力
MTU21.TIOR.BIT.IOB = 0x05; // TGRB_1 PE5 初期1出力コンペアマッチで0出力
MTU22.TIOR.BIT.IOA = 0x05; // TGRA_2 PE6 初期1出力コンペアマッチで0出力
MTU22.TIOR.BIT.IOB = 0x05; // TGRB_2 PE7 初期1出力コンペアマッチで0出力

MTU2.TCSYSTR.BYTE = 0xF8; // 0,1,2,3,4 タイマシンクロスタート
count++;
break;
case 2:
MTU20.TCNT = 0xF0BD; // 2.5ms セット

MTU23.TIOR.BIT.IOA = 0x05; // TGRA_3 PE8 初期1出力コンペアマッチで0出力
MTU23.TIOR.BIT.IOB = 0x05; // TGRB_3 PE9 初期1出力コンペアマッチで0出力
MTU23.TIOR.BIT.IOC = 0x05; // TGRC_3 PE10 初期1出力コンペアマッチで0出力
MTU23.TIOR.BIT.IOD = 0x05; // TGRD_3 PE11 初期1出力コンペアマッチで0出力

MTU2.TCSYSTR.BYTE = 0xF8; // 0,1,2,3,4 タイマシンクロスタート
count++;
break;
case 3:
MTU20.TCNT = 0xF0BD; // 2.5ms セット

MTU24.TIOR.BIT.IOA = 0x05; // TGRA_4 PE12 初期1出力コンペアマッチで0出力
MTU24.TIOR.BIT.IOB = 0x05; // TGRB_4 PE13 初期1出力コンペアマッチで0出力
MTU24.TIOR.BIT.IOC = 0x05; // TGRC_4 PE14 初期1出力コンペアマッチで0出力
MTU24.TIOR.BIT.IOD = 0x05; // TGRD_4 PE15 初期1出力コンペアマッチで0出力

MTU2.TCSYSTR.BYTE = 0xF8; // 0,1,2,3,4 タイマシンクロスタート
count++;
break;
default:
MTU20.TCNT = 0x3D09; // 10ms セット

MTU2.TCSYSTR.BYTE = 0xF8; // 0,1,2,3,4 タイマシンクロスタート

// servo puls set
MTU20.TGRA = 0xF0BD + ServoPuls[0];
MTU20.TGRB = 0xF0BD + ServoPuls[1];
MTU20.TGRC = 0xF0BD + ServoPuls[2];
MTU20.TGRD = 0xF0BD + ServoPuls[3];
MTU21.TGRA = 0xF0BD + ServoPuls[4];
MTU21.TGRB = 0xF0BD + ServoPuls[5];
MTU22.TGRA = 0xF0BD + ServoPuls[6];
MTU22.TGRB = 0xF0BD + ServoPuls[7];
MTU23.TGRA = 0xF0BD + ServoPuls[8];
MTU23.TGRB = 0xF0BD + ServoPuls[9];
MTU23.TGRC = 0xF0BD + ServoPuls[10];
MTU23.TGRD = 0xF0BD + ServoPuls[11];
MTU24.TGRA = 0xF0BD + ServoPuls[12];
MTU24.TGRB = 0xF0BD + ServoPuls[13];
MTU24.TGRC = 0xF0BD + ServoPuls[14];
MTU24.TGRD = 0xF0BD + ServoPuls[15];

count = 0;

break;
}
}

// タイマ0~4シンクロスタート
void MTU2_syn_start(void)
{
MTU2.TCSYSTR.BYTE = 0xF8; // タイマ0~4シンクロスタート
}

// タイマ0~4停止
void MTU2_syn_stop(void)
{
MTU2.TSTR.BYTE = 0x00; // タイマ0~4停止
}

// プログラムここまで

« Prev|Top|Next »

HOME

tsumehashi

Author:tsumehashi
FC2ブログへようこそ!

09 | 2019/10 | 11
- - 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 - -