ラベル ロボット製作 の投稿を表示しています。 すべての投稿を表示
ラベル ロボット製作 の投稿を表示しています。 すべての投稿を表示

2012/10/20

HEWでprintfを使えるようにする(追記情報)

HEWでprintfを使えるようにする」が人気(?)のようなので,ちょっと追記情報といいますか,使っていて気づいた注意点です。

具体的には,printfの文字列送信にかかる時間と受信エラーの処理についてです。

ターゲットマイコンは,これまで同様SH7125,HEWとコンパイラパッケージは,

  • C/C++ compiler package for SuperH RISC engine family V.9.04 Release 01
  • High-performance Embedded Workshop Upgrade 4.09.01

です。まあ前回とほとんど変わってないんですが,念のため。

2012/05/20

HEWでprintfを使えるようにする・続(scanfを使ってみる)

「HEWでprintfを使えるようにする」で,せっかくgetcharを作ったのに,scanfが使えるか試していませんでした^^;下表のようなプログラムで試してみると,問題なく動作してくれました:)
void main(void)
{
    int a;
    double b;


    printf("input int data->",0);
    scanf("%d",&a);
    printf("%d\r\n",a);
    printf("input float data->",0);
    scanf("%lf",&b);
    printf("%lf\r\n",b);
}

下図は,プログラム実行後に「123」「3.1415926」と入力した結果です。
整数はそのまま表示され,小数は最後の桁が四捨五入されました。これは,printfのデフォルトの設定によるものです。桁数を指定したい場合は,通常のprintfと同様の記述が使えます(%6.4lf など)。
scanfの実行結果
今日はこれだけです。ちょっと手抜き感がありますが^^;

それでは。

2012/05/13

HEWでprintfを使えるようにする

今回は,printfの実装を行いました。
プログラムでprintfといえば,画面に文字や変数の値を表示することが多いですが,マイコンの場合はシリアル通信でPCなどにデータを送るようにします。ターミナルソフトでこのデータを見れば,デバッグに使えるわけです。
(SHには,便利なエミュレータやデバッガがあるらしい?のですが,私は未だにprintfデバッグです^^;)

これまでは自作のprintfを使っていたのですが,今回はHEWのstdio.hで最初から定義されているprintfを使うことにしました。Renesas純正ですから,きっとSH向けに最適化されているだろうと期待してみたり。
プログラム中...
RenesasのFAQユーザーズマニュアルC/C++コンパイラ,アセンブラ,最適化リンケージエディタ ユーザーズマニュアル,p.168あたり)を読みながら格闘すること早半日・・・なんとか実装できました。以下に手順を示します。

なお,HEWとコンパイラパッケージのバージョンは,
  • C/C++ compiler package for SuperH RISC engine family V.9.02 Release 00 (Evaluation Version)
  • High-performance Embedded Workshop Upgrade 4.09.00
ターゲットマイコンはSH7125です。

1.新規ワークスペース作成

まず,HEWの「ファイル」-「新規ワークスペース」から新しいワークスペースを作成します。生成ファイルの設定画面で,「I/Oライブラリ使用」にチェックを入れてください。これによって,標準入出力に必要な関数のほとんどをHEWが用意してくれます。また,「ハードウェアセットアップ関数生成」で「C/C++ source file」を指定すると,パワーオンリセット後のI/Oの初期化関数(HardwareSetup関数)の雛形を生成してくれます。
「I/Oライブラリ使用」にチェック,「ハードウェアセットアップ関数生成」は「C/C++ source file」を指定

2.シリアル通信のための関数作成

ワークスペースができたら,プロジェクトから「lowsrc.src」を削除します。このファイルには,デバッガ用の低水準入出力関数「charget」と「charput」が記述されています。従って,この「charget」と「charput」をシリアル通信の関数に置き換えれば,シリアルポートに対してprintfが使えるようになります。今回作成した関数を下表に示します。割り込みは使わない,最も単純なものです。シリアル通信の初期化関数(sio_init)も作成します。

void sio_init(void){
    STB.CR3.BIT._SCI1=0; // SCIスタンバイ解除
    SCI1.SCSCR.BYTE=0x00; // 送受信割り込み禁止、送受信禁止
    PFC.PACRL1.BYTE.H=0x10; // PA3をRXD1に設定
    PFC.PACRL2.BYTE.L=0x01; // PA4をTXD1に設定
    SCI1.SCSMR.BYTE=0x00; // 通信フォーマット、クロックソースを選択
    SCI1.SCBRR=19; // ビットレート BRR=(25000000[Hz]/(32*38400[bps])) - 1 => 19
    SCI1.SCSCR.BIT.TE=1;   // トランスミットイネーブル:送信動作を許可
    SCI1.SCSCR.BIT.RE=1;   // レシーブイネーブル:受信動作を許可
}

void charput(char c){
    while (SCI1.SCSSR.BIT.TDRE==0);
    SCI1.SCSSR.BIT.TDRE=0;
    SCI1.SCTDR=c;
}

char charget(void){
    char c;
    while ((SCI1.SCSSR.BYTE & 0x40)==0);
    c=SCI1.SCRDR;
    SCI1.SCSSR.BYTE=SCI1.SCSSR.BYTE & 0xBF;
    return(c);
}

追記(2012/10/26):↑のcharget()はエラー処理を省略しており,受信エラー発生時に無限ループになってしまいます。常にデータが送られてくるような用途では,エラー処理を追加することをオススメします。修正版のchargetはこちら

3.シリアル通信初期化関数の呼び出し設定

パワーオンリセット後に,シリアル通信の初期化関数が呼ばれるように設定します。「ハードウェアセットアップ関数生成」を指示しておくと,「hwsetup.c」というファイルが生成され,その中に「HardwareSetup」関数があります。この関数が,パワーオンリセット後に自動的に呼ばれますので,この中でシリアル通信の初期化関数を呼び出すよう変更します。

追記(2012/8/30):sio_init()は,printfを使う前ならば,どこで呼び出してもよいです。HardwareSetup以外でも,mainでもOKです。(HardwareSetupはmainより前に実行されるため,ここに初期化処理をまとめておくと便利です

void HardwareSetup(void)
{
    sio_init();
}

4.完成!

以上で設定は完了です。これで,思う存分にprintfできます。例えば,下表のようにすると・・・

void main(void)
{
    int a=1;
    double b=1;

    a+=1;
    b=3.141592;

    printf("abcdefghijklmnopqrstuvwxyz\r\n",0);
    printf("%d\r\n",a);
    printf("%lf\r\n",b);
}

こんな感じ↓で出力されます。
使ってみて気付いたのですが,このprintfは必ず第二引数まで指定しなければならないようです。
文字列のみをprintfする場合,上の表のように,第二引数に適当な値を指定してください。(第二引数を指定しないと何も出力されません)
TeraTermで確認した結果
手順さえ分かってしまえば,割と簡単にprintfを使えるようになります。ぜひ試してみてください。

余談ですが,現在のプログラムサイズは21.6 kByteでした。SH7125のROMは128 kByteなので,既に20%弱を使ってしまっています。
もう少し削りたいところですね。

それでは-~)ノ~~

2012/03/21

小形ロボットの製作(ハード3)

今回は,ロータリーエンコーダの回路の調整をします。

モータを回して,エンコーダに使用したフォトセンサの出力を見ると,下図のようになります。
フォトセンサの出力(モータを単三電池1本で回した場合)
2個のフォトセンサを少しずらして配置することで,位相が約90°ずれた2相の信号を得ることができています。上の図ではCH2の信号のほうが,位相が進んでいますが,モータの回転方向を逆にすると,CH1のほうが進みます。

この信号をパルス状にするために,オペアンプを使った波形整形回路を使います。
オペアンプを使った波形整形回路
フォトセンサの出力と,可変抵抗で作った基準電圧とを比較することで,フォトセンサの出力をパルス状に整形します。可変抵抗で基準電圧を調整し,Duty比が約50%になるようにしました。
波形整形回路の出力
簡単な回路ですが,うまく動いてくれました:)
これでロータリーエンコーダが使えるようになりました。

これで,ハードの製作はひと段落です。
次回からは,プログラミングをしていきます。

2012/03/16

小型ロボットの製作(ハード2)

今まで怠けてた分,今日は頑張って進めます。

ロボットの頭脳となる,制御回路を作ってベース部分に搭載します。
まずは回路の製作から。
すでに完成した回路
ごめんなさいもうできてます・・・。
製作時間短縮のため,昔作った回路を流用することにしました。(回路図とかは,そのうち作ります)
真ん中に写ってるのが制御回路です。秋月電子通商のSH7125基板を使いました。安くていいですよね。
右に写ってるのは,ロータリーエンコーダに使うラインセンサの出力をロジックレベルにするための回路です。汎用オペアンプのLM324Nをコンパレータとして使った,超簡単な回路です。

これらの回路を乗せる台を,ベース部分に追加します。
今回もMDFを使います。
MDFを加工中
前の記事で書き忘れてましたが,MDFは100円ショップのクリップボードを使ってます。安い,入手しやすい,加工しやすいの3拍子揃ってるので,気に入ってます。

加工したMDF
MDFを切ったら,ホットボンドで固定していきます。ちなみに,ホットボンドも100円ショップで買いました。ホットボンドが100円で買えるってすごいですよね・・・。
MDFをホットボンドで固定
回路を固定するための足を付けて・・・
回路を乗せた様子
ひとまず完成!
電池は,回路の下に入ってます。
リアビュー
フロントビュー
裏側
次回はロータリーエンコーダの調整と動作確認を行います。

小型ロボットの製作(ハード1)

自律ロボットの勉強のために,小型ロボットを作ります。
とりあえず,ロータリーエンコーダを使ったオドメトリ機能は欲しいですね。

市販のロータリーエンコーダは高いので,自作します。
みんな大好き(?)タミヤの工作キットを使います。
楽しい工作シリーズ ダブルギアボックスとトルクチューンモータPRO
モータはトルクチューンPROを使います(トルクがあるほうが制御しやすそうなので…)。このモータは両側にシャフトが出ているので,片側に反射板をホットボンドで取り付けます。
反射板をホットボンドで取り付け
反射板は,モータ1回転で6パルス出るようにしました。ギアボックスのギア比は,12.7:1,38.1:1,114.7:1,344.2:1のいずれかが選べますが,38.2:1に設定すれば,出力軸1回転あたり229.2パルス得られます。軸の回転方向を判別するために,2相のエンコーダにするので,実際の分解能はこの4倍の916.8パルス/回転になります。
出力軸の回転角度を0.4°単位で判別できるので,このくらいで十分でしょう。

反射板の位置を検出するフォトセンサは,SG-2BC(コーデンシ)を使いました。RSで購入できます。ロボットのベースとなる基板をMDFで作り,フォトセンサをホットボンドで取り付けました。右端についてるのは,楽しい工作シリーズのボールキャスターです。
フォトセンサを取り付けたMDF板
 ベース基板にギアボックスとタイヤ(楽しい工作シリーズ スリムタイヤセット)を取り付けて,完成!
ロボットのベース部分
これに電池と回路を乗せていきます。
文章を書くのが意外と大変・・・・