UMEHOSHI ITA TOP PAGE COMPUTER SHIEN LAB
次のイメージのように、モータ、ギアなどを取り付けました。
次にこのページで示したように部品を追加した[UMEHOSHI ITA]を取り付けます。
[UMEHOSHI ITA]とスマフォをUSBで接続します。(接続により電源が供給されてD1のダイオードが点灯します。
点灯しなければケーブルの接続が失敗していることとなります。)
そして、このページで紹介したように
「umehoshiアプリ」を起動して、USBを認識させます。
このページで紹介した[UMEHOSHI ITA]のプログラムを
応用して以下のようなプログラムで動作します。
(参考)
Timer2の割り込みは、デフォルトで何もしない処理になっています。
それを置き換えて、一定時間(time2Count のカウントアップがstopCount以上になるまで )経過したら
モータを停止する動作にしています。(コマンドを受信しなくてもこの時間で停止させています)
なお低電圧で比較的大きな電流を使うモータを使うと、一方のモータにエネルギーが偏って、一方のモータしか回らないケースがあるようです。
それに対応するようにCN6、CN6のモータ交互にONする方法ができるように の部分を追加しています。
この部分でTimer2の割り込みでoneMCountもカウントアップしています。
oneMCountの値はoneCN6の負〜oneCN7の正の値の間で行われおり、
oneMCountが負であればCN6が有効(CN7が無効)、正であればCN7が有効(CN6が無効)として、モータを交互に印加する制御です。
このモータ交互制御は、oneCN6に設定を0にすることで無効にできます。
#include <xc.h> // app_pwm.c #include "common.h" #define AdrStart 0x80005000 // アプリの起動時の初期ルーチンのアドレス #define AdrTimer2 0x80005B00 // 指定時間後にモータ停止のTimer2用アドレス #define AdrForward 0x80005200 // モータ前進ルーチンのアドレス #define AdrGoBack 0x80005300 // モータ後進ルーチンのアドレス #define AdrRight 0x80005400 // モータ右回転ルーチンのアドレス #define AdrLeft 0x80005500 // モータ左回転ルーチンのアドレス #define AdrUpLeft 0x80005600 // モータ左デューティ幅アップ #define AdrDownLeft 0x80005700 // モータ左デューティ幅ダウン #define AdrUpRight 0x80005800 // モータ右デューティ幅アップ #define AdrDownRight 0x80005900 // モータ右デューティ幅ダウン #define AdrStop 0x80005A00 // モータ停止 #define UPDAOWN 0x1000 // デューティ幅の変更で使う値(この値を加算又は減算) // 左右のモータで、進行にバラツキがある場合、下記初期設定を調整して合わせる。 int cn6PWM = 0x0DFFF; // 現在の左デューティ幅で、初期設定 int cn7PWM = 0x0FFFF; // 現在の右デューティ幅で、初期設定 int time2Count = 0;//Timer2割り込みでカウントアップ(下記stopCountまでカウント) int stopCount = 0x500;// time2CountがstopCount以上で、time2CountがをゼロにしてモータをOFF // 上記設定値で、モータを動かしてから止めるまでの時間が決まります // 下記は、モータを片方ずつ交互に使う時に0以外を指定する。(低圧高電流型モータで使う場合あり) int oneMCount = 0;// oneCN6〜oneCN7の間で、oneCN6が負でTimer2でカウントアップ int oneCN6 = -50;// CN6のONタイミングを負のTimer2でカウント数で指定 int oneCN7 = 50; // CN7のONタイミングをTimer2でカウント数で指定 void setCN6(int d);// 左用 CN6コネクタの制御 dの値 0停止, 1:正転, -1:逆転 void setCN7(int d);// 右用 CN7コネクタの制御 dの値 0停止, 1:正転, -1:逆転 void stop();// PWM を停止 __attribute__((address( AdrStart ))) void start (void); void start() { PORTBCLR = 0b0110000000001100;//モータ関連ポート(14,13,3,2)をゼロにする // 初期化ルーチン(リセット時の処理)を設定 ( (uint32_t *)_HANDLES)[_IDX_INIT_SUB_FUNC] = (uint32_t ) AdrStart; __asm__ ("NOP"); IEC0CLR = 0x00000200;//T2IE Timer2 Enable(割込みを不可)"); ( (uint32_t *)_HANDLES)[_IDX_TIMER_2_FUNC] = (uint32_t ) AdrTimer2;//割り込み処理の置き換え PR2=0x8FFF;// 上記割り込み処理の周期設定 IEC0SET = 0x00000200;//T2IE Timer2 Enable(割込み許可)"); _set_pwd_mode(1); // PWM モードへ変更 T2CONbits.ON = 1; //Timer2の機能を有効 time2Count =0; _RB15 = 0; } // タイマーで(stopCount 値に達するまで)の時間ごとに、モータを停止する。 // (モータがオンで、移動し続けないようにする考慮で、無くてもよい処理?) __attribute__((address( AdrTimer2))) void timer2(void); void timer2() { IFS0CLR = 0x00000200; // Clear the timer interrupt status flag if( ++time2Count >= stopCount ){ stop();// PWM パルス幅を0 _RB15 = 0; // LED1消灯 } // CN6,CN7のモータを交互に使う if(oneCN6 < 0 && oneMCount++ < 0){ OC5CONbits.ON=OC1CONbits.ON=1; // PWM CN6有効 OC3CONbits.ON=OC4CONbits.ON=0; // PWM CN7無効 } else if(oneCN6 < 0 && oneCN7 > 0){ OC5CONbits.ON=OC1CONbits.ON=0; // PWM CN6無効 OC3CONbits.ON=OC4CONbits.ON=1; // PWM CN7有効 if( oneMCount > oneCN7){ oneMCount = oneCN6; } } } // モータを停止する。 __attribute__((address( AdrStop))) void stop(void); void stop() { //time2Count = 0; OC5RS = OC1RS = OC4RS = OC3RS = 0;// モータすべてをOFF } // モータ前進ルーチン __attribute__((address( AdrForward ))) void forward(void); void forward() { time2Count = 0; setCN6( 1 );// 左正転 setCN7( 1 );// 右正転 _RB15 = ! _RB15;//確認用のLED1点灯反転 } // モータ後進ルーチン __attribute__((address( AdrGoBack ))) void goback(void); void goback() { time2Count = 0; setCN6( -1 );// 左逆転 setCN7( -1 );// 右逆転 _RB15 = ! _RB15;//確認用のLED1点灯反転 } // モータ右回転ルーチン __attribute__((address( AdrRight ))) void right(void); void right() { time2Count = 0; setCN6( 1 );// 左正転 setCN7( -1 );// 右逆転 _RB15 = ! _RB15;//確認用のLED1点灯反転 } // モータ左回転ルーチン __attribute__((address( AdrLeft ))) void left(void); void left() { time2Count = 0; setCN6( -1 );// 左逆転 setCN7( 1 );// 右正転 _RB15 = ! _RB15;//確認用のLED1点灯反転 } // モータ左デューティ幅アップルーチン __attribute__((address( AdrUpLeft ))) void upleft(void); void upleft() { _send_hex_low( cn6PWM ); if( cn6PWM +UPDAOWN <= 0x0ffff){ cn6PWM += UPDAOWN ; _send_string(" Left UP\r\n"); } else { _send_string(" Left FULL\r\n"); } _RB15 = ! _RB15;//確認用のLED1点灯反転 } // モータ左デューティ幅ダウンルーチン __attribute__((address( AdrDownLeft ))) void downleft(void); void downleft() { _send_hex_low( cn6PWM ); if( cn6PWM - UPDAOWN >= 0){ cn6PWM -= UPDAOWN ; _send_string(" Left DOWN\r\n"); } else { _send_string(" Left Minimum\r\n"); } _RB15 = ! _RB15;//確認用のLED1点灯反転 } //モータ右デューティ幅アップ __attribute__((address( AdrUpRight ))) void upright(void); void upright() { _send_hex_low( cn7PWM ); if( cn7PWM +UPDAOWN <= 0x0ffff){ cn7PWM += UPDAOWN ; _send_string(" Right UP\r\n"); } else { _send_string(" Right FULL\r\n"); } _RB15 = ! _RB15;//確認用のLED1点灯反転 } // モータ右デューティ幅ダウン __attribute__((address( AdrDownRight ))) void downright(void); void downright() { _send_hex_low( cn7PWM ); if( cn7PWM -UPDAOWN >= 0){ cn7PWM -= UPDAOWN ; _send_string(" Right DOWN\r\n"); } else { _send_string("Right Minimum\r\n"); } _RB15 = ! _RB15;//確認用のLED1点灯反転 } // CN6(左側) コネクタの制御 dの値 0停止, 1:正転, -1:逆転 void setCN6( int d){ time2Count=0; OC5RS = 0x0; // CN6[1-2]制御(RB2) OC1RS = 0x0; // CN6[3-4]制御(RB3) if(d==1){ OC5RS = cn6PWM; // CN6[1-2]制御(RB2) OC1RS = 0x0; // CN6[3-4]制御(RB3) } else if(d==-1){ OC5RS = 0x0; // CN6[1-2]制御(RB2) OC1RS = cn6PWM; // CN6[3-4]制御(RB3) } } // CN7(右側) コネクタの制御 dの値 0停止, 1:正転, -1:逆転 void setCN7( int d){ time2Count=0; OC4RS = 0x0; // CN7[3-4]制御(RB13) OC3RS = 0x0; // CN7[1-2]制御(RB14) if(d==1){ OC4RS = cn7PWM; // CN7[3-4]制御(RB13) OC3RS = 0x0; // CN7[1-2]制御(RB14) } else if(d==-1){ OC4RS = 0x0; // CN7[3-4]制御(RB13) OC3RS = cn7PWM; // CN7[1-2]制御(RB14) } }
上記のcn6PWMとcn7PWMのそれぞれが、CN6とCN7のデューティ幅で、初期設定が異なっていますが、
これは、モータやギアの違いを吸収させるために、存在しています。作成したマシンによって左右の違いがある場合、
この設定で変更できるようにしてみました。
別途に、それぞれのPWMのデューティ幅を増減するメソッドを用意してみました。
下記はビルドして[UMEHOSHI ITA]とUSBで繋いだ後、プログラムを転送して0x80005000番地のstart関数を[Excute]ボタンで実行し、
次に[Execte Address]の設定を0x80005200番地に変更してから[Excute]ボタンクリックしているイメージです。(これでforward関数が実行します)
(なお、下記ではExcuteボタン左のコンボボックスに#defineで定義される各関数のエントリーポイントのアドレスが並んでいます。
しかし実際にはこのような並びではありません。一度実行したアドレスだけが並びます。)
モータが繋がっていれば、
上記実行により2つのモータが前進の回転を一定時間回転して止まるはずです。
一定時間とは、=1/(40e6)*(PR2+1)*stopCount=1/(40e6)*(0x8fff+1)*0x500=約1.2秒です。
次に、ここで示したように、「umehoshi」ツールが受け取る形式(.umh)にします。
(.umh)のファイル形態にすることで、次のように「umehoshi」ツールを介して[UMEHOSHI ITA]のWifi環境で遠隔操作ができるようになります。
このWifiによりTCPで、(.umh)のファイル転送の遠隔操作をするためには、この拡張子の先頭行にボタンの表示文字列の1行を書いて、
次行に送信したい命令を列挙するだけです。
例えば、「PWM_LOAD」の表示文字列の1行を書いて、上記でビルドしたコード(app.pwm.c.hex)の内容をコピー貼り付けし、
最後に「R00800050000061」の文字列を追加した次の「uPwmLoad.umh」を作ります。
この正確なコードは このページに示します。
PWM_LOAD
S048000800000FFDF000083
・・・ここは省略してます・・・
S108000538C001480008008000000000000000000000024
R00800050000061
これは「umehoshi」ツールにおいて、「PWM_LOAD」ボタン操作でプログラムをロードしてそのstart()関数を実行させる内容です。
このコード内の0x80005200番地にあるforward関数を実行する時に使うuGoForward.umhを示します。(前進のボタン用です)
Forward
R0080005200005F
上記のR0080005200005Fは、「UME専用Hexコマンド」の文字列で、
0x80005200番地の関数を実行させるコードです。
このコードは、次のように「umehoshiEdit」ツールで、[communication]メニューの[Command exec]を選んで、
Execute Addressの箇所を0x80005200の表現に編集して、[Excute]ボタンをクリックすると、「message」タグに現れるので、
それをコピー貼り付けするとよいでしょう。
同様に作った、後進、右回転、左回転、・・・の各コードのファイルもこのページに示します。
このようなファイルを用意すれば、ここで示したように
「umehoshiEdit」ツールから「umehoshiアプリ」へ、
または
「umehoshiアプリ」から他の「umehoshiアプリ」へTCP通信へファイル転送することで遠隔操作ができるようになります。
下記で動かしているyoutube動画リンクです。