車輪エンコーダーをテストするクラス | |
---|---|
namespace WheelEncoderTest1 { public partial class Program { public void main() { AnalogInput RightSpin = new AnalogInput(CPU.P2); AnalogInput LeftSpin = new AnalogInput(CPU.P3); const int SpinThreshold = 500; BoeBotInterface jbot = new BasicBoeBot(new FixedMovementBoeBot()); jbot.move(BoeBotInterface.continuousForward); Boolean rState = RightSpin.Read() > SpinThreshold; for (int count = 1; count < 48; ) { if ((RightSpin.Read() > SpinThreshold) != rState) { rState = !rState; count++; } } jbot.stop(); } } } |
1 2 3 部分クラス 4 5 Mainから呼ばれる 6 7 右の車輪のエンコーダー 8 左の車輪のエンコーダー 9 光の閾値を500に設定する 10 固定動作のBasicBoeBotオブジェクトをBoeBotInterface型で作る 11 12 前進させる 13 次の穴からカウントスタート 14 15 穴が48回通過するまでループする 16 つまり、48/8=6回転 17 18 19 20 21 22 23 停止する 24 25 26 27 |
車輪エンコーダーをテストするクラス |
---|
namespace WheelEncoderTest2 { public partial class Program { AnalogInput RightSpin = new AnalogInput(CPU.P2); AnalogInput LeftSpin = new AnalogInput(CPU.P3); const int SpinThreshold = 500; public Boolean checkSensor(AnalogInput pin) { int value = pin.Read(); return (value < SpinThreshold); } public void main() { BoeBotInterface jbot = new BasicBoeBot(new FixedMovementBoeBot()); int rightCount = 0; int leftCount = 0; Boolean rightState = checkSensor(RightSpin); Boolean leftState = checkSensor(LeftSpin); //jbot.move(BoeBotInterface.continuousForward); jbot.move(BoeBotInterface.continuousBackward); while (true) { if (rightState != checkSensor(RightSpin)) { rightState = !rightState; ++rightCount; } if (leftState != checkSensor(LeftSpin)) { leftState = !leftState; ++leftCount; } Debug.Print(rightCount + " " + leftCount); } } } } |
車輪エンコーダーをテストするクラス |
---|
namespace WheelEncoderTest3 { public partial class Program { public void main() { WheelEncoderTest3 encoder = new WheelEncoderTest3(); encoder.runTest(); } } /** * 車輪エンコーダーをテストするクラス * * 直進するための初期車輪エンコーダーテストプログラム */ public class WheelEncoderTest3 : BasicBoeBot { AnalogInput RightSpin = new AnalogInput(CPU.P2); AnalogInput LeftSpin = new AnalogInput(CPU.P3); const int SpinThreshold = 500; int rightCount = 0; int leftCount = 0; int rightRatio = 1; int leftRatio = 1; int rightSpeed = 100; int leftSpeed = 100; int rightAdjust = 0; int leftAdjust = 0; int leftStep = 20; int rightStep = 20; int leftLimit = 40; int rightLimit = 40; int leftOdometer = 0; int rightOdometer = 0; Boolean transition = false; public WheelEncoderTest3() : base(new FixedMovementBoeBot()) { } public Boolean checkSensor(AnalogInput pin) { int value = pin.Read(); return (value < SpinThreshold); } public void runTest() { Boolean rightState = checkSensor(RightSpin); Boolean leftState = checkSensor(LeftSpin); setSpeed(leftSpeed, rightSpeed); leftCount = leftRatio; rightCount = rightRatio; int i = 0; // テストのみに対して while (true) { if (rightState != checkSensor(RightSpin)) { transition = true; rightState = !rightState; --rightCount; ++rightOdometer; } if (leftState != checkSensor(LeftSpin)) { transition = true; leftState = !leftState; --leftCount; ++leftOdometer; } if (transition) { // 遷移が起こった。フラグをリセットし、補正する。 transition = false; // テストが終わった時に出る i++; if (i > 200) { break; } if (rightCount == 0) { if (leftCount == 0) { // 同期の際、変化無し、カウンターをリセット leftCount = leftRatio; rightCount = rightRatio; } else { // 左側は右より遅い if (leftCount >= leftRatio) { // 調節: 左車輪が遅い if (leftAdjust == 0) { // 左の調節はない。右側の車輪を遅くする if (rightAdjust < rightLimit) { rightAdjust += rightStep; } } else { // 左車輪が調節される。値を減らす leftAdjust -= leftStep; } // 新しいスピードに設定する setSpeed(leftSpeed - leftAdjust, rightSpeed - rightAdjust); } // カウンターをリセットする leftCount += leftRatio; rightCount = rightRatio; } } else { if (leftCount == 0) { // 右側は左より遅い if (rightCount >= rightRatio) { // 調節: 右車輪は遅い if (rightAdjust == 0) { // 右の調節は無し、左の補正を変える if (leftAdjust < leftLimit) { leftAdjust += leftStep; } } else { // 右車輪を補正する。それを減らす rightAdjust -= rightStep; } // 新しいスピードに設定する setSpeed(leftSpeed - leftAdjust, rightSpeed - rightAdjust); } // カウンターをリセットする leftCount = leftRatio; rightCount += rightRatio; } } // テスト時のみ String output = "rightOdometer:" + rightOdometer + " "; output += "rc:" + rightCount+" "; output += "rightSpeed - rightAdjust:" + (rightSpeed - rightAdjust); output += " ... "; output += "leftOdometer:" + leftOdometer + " "; output += "lc:" + leftCount+" "; output += "leftSpeed - leftAdjust:" + (leftSpeed - leftAdjust); Debug.Print(output); } } stop(); } } } |
変数 | 説明 |
---|---|
transition | エンコーダーの遷移が起こったことを示す |
leftState, rightState | 車輪エンコーダーからの最後の入力値 |
leftCount, rightCount | 車輪エンコーダーのカウンター |
leftRatio, rightRatio | 他の側に関係するステップ数 |
leftSpeed, rightSpeed | スピード・パーセンテージ(-100%~100%) |
leftAdjust, rightAdjust | スピード調節 |
LeftStep, rightStep | スピード調節に対する増減 |
leftLimit, rightLimit | 最大のスピード調整値 |
leftOdometer,rightOdometer | 距離計のカウンタ |
if ( rightState != CPU.readPin(rightPin)) { transition = true ; rightState = ! rightState ; -- rightCount ; ++ rightOdometer; } |
// 左側は右より遅い if ( leftCount >= leftRatio ) { // 調節: 左車輪が遅い if ( leftAdjust == 0 ) { // 左の調節はない。右側の車輪を遅くする if ( rightAdjust &;t; rightLimit ) { rightAdjust += rightStep ; } } else { // 左車輪が調節される。値を減らす leftAdjust -= leftStep ; } // 新しいスピードに設定する setSpeed ( leftSpeed - leftAdjust, rightSpeed - rightAdjust ) ; } // カウンターをリセットする leftCount += leftRatio ; rightCount = rightRatio ; |
車輪エンコーダーを用いたBoe-Bot車輪制御 |
---|
using System; using BoeBotLib; using SecretLabs.NETMF.Hardware; namespace BoeBotLib { /** * 車輪エンコーダーを用いたBoeBot車輪制御 * * 閉じたフィードバックループを用いてサーボモータを制御する * バックグラウンドタスクはマルチタスクをサポートする */ public class WheelEncoderBoeBot : RampingBoeBot { protected _Timer sensorTimer = new _Timer(); protected int rightAdjust = 0; // パーセント補正 protected int leftAdjust = 0; // 動作定数 /** * 前進/後進動作に対する遷移/cm * 21cmの円周で6.67cmの車輪を仮定します。 * 車輪には8個の穴があります。一回転に16回の遷移があります * 0.76 = 16 / 21 */ static public int transitionsPer10Cms = 7; // = 16 / 21*10 /** * 左/右旋回に対する遷移/旋回ステップ */ static public int transitionsPer10Pivot = 25;//31 static public int transitionsPer10TurnSm = 35; static public int transitionsPer10TurnLg = 100; static public int turnRatioSm = 1; static public int turnRatioLg = 10; static public int adjustStep = 20; // percent, ステップを補正 static public int maxAdjust = 40; // percent, 最大補正 //protected int rightPin = CPU.P10 ; //protected int leftPin = CPU.P11 ; AnalogInput RightSpin = new AnalogInput(CPU.P2); AnalogInput LeftSpin = new AnalogInput(CPU.P3); const int SpinThreshold = 500; protected int _leftOdometer = 0; // 距離計のサポート protected int _rightOdometer = 0; protected int leftStop = 0; // 距離計停止点 protected int rightStop = 0; protected int rightCount; // 車輪エンコーダ // フィードバック protected int leftCount; protected int rightRatio; protected int leftRatio; protected Boolean rightState; // 最後に検出した // 車輪エンコーダの状態 protected Boolean leftState; protected Boolean transition; // 遷移が起こった /** * デフォールトのピンを用いて * 車輪エンコーダーBoeBotサーボモーター制御オブジェクトを作る * * 入力: Event startEvent: 開始時に通知するイベント */ public WheelEncoderBoeBot(eEvent startEvent) : base(startEvent) { } /** * 車輪エンコーダーBoeBotサーボモーター制御オブジェクトを作る * * 入力: Event startEvent: 開始時に通知するイベント * 入力: int msecPerCm: 直線運動に対する1cmあたりのmsec数 * 入力: int msecPerPivot:旋回単位あたりのmsec数 * 入力: int msecPerTurn:回転単位あたりのmsec数 * 入力: BasicWheelServo leftWheel:左車輪のBasicWheelServo * 入力: BasicWheelServo rightWheel:右車輪のBasicWheelServo * 入力: int leftInput:左車輪のエンコーダーの入力ピン * 入力: int rightInput:右車輪のエンコーダーの入力ピン */ public WheelEncoderBoeBot (eEvent _event , int msecPerCm , int msecPerPivot , int msecPerTurn , BasicWheelServo leftWheel , BasicWheelServo rightWheel , int leftInput , int rightInput) : base( _event, msecPerCm, msecPerPivot, msecPerTurn, leftWheel, rightWheel) { //rightPin = leftInput ; //leftPin = rightInput ; // 車輪エンコーダーセンサーのLEDを点灯させる //CPU.writePin(rightPin,true); //CPU.writePin(leftPin,true); sensorTimer.mark(); } /** * 車輪エンコーダーセンサーをチェックする * * 入力:int pin:センサーに繋がっているCPU.pin * * 戻り:もし穴が検出された場合falseを返す */ public Boolean checkSensor(AnalogInput pin) { int value = pin.Read(); return (value < SpinThreshold); } /** * 動作が終わったかどうかチェックする。 * これはtrueが戻されるまで呼ばれるべきである。 * * 戻り:boolean: 待ち動作完了した時trueを返す */ public override Boolean movementDone() { // すでに完了しているかどうかチェックする if (base.movementDone()) { return true; } // センサーのコンデンサが充電されているかどうかをチェックする if (sensorTimer.timeout(1)) { // 次のタイムアウトに対して設定する sensorTimer.mark(); // 遷移をチェックする transition = false; // 右車輪のエンコーダー入力をチェックする if (rightState != checkSensor(RightSpin)) { transition = true; rightState = !rightState; --rightCount; ++_rightOdometer; // 遷移が起こった。距離計の停止をチェックする if ((rightStop > 0) && ((--rightStop) == 0)) { // 望まれた距離を移動した getNextMovement(); return false; } } // 左車輪のエンコーダー入力をチェックする if (leftState != checkSensor(LeftSpin)) { transition = true; leftState = !leftState; --leftCount; ++_leftOdometer; // Transition occurred. Check for odometer stop if ((leftStop > 0) && ((--leftStop) == 0)) { // 望まれた距離を移動した getNextMovement(); return false; } } // 遷移が起こった時にスピードを補正する if (transition) { // 走り続ける。補正が必要かどうかチェックする if (rightCount == 0) { if (leftCount == 0) { // カウンターをリセットする。 leftCount = leftRatio; rightCount = rightRatio; } else { // 左側が右より遅い if (leftCount >= leftRatio) { // 補正: 左車輪が遅い if (leftAdjust == 0) { // 左車輪の補正は無い。右側を遅くする if (rightAdjust < maxAdjust) { rightAdjust += adjustStep; } } else { // 左車輪は補正された。左側をスピードアップする leftAdjust -= adjustStep; } // 新しいスピードに設定する adjustSpeed(leftAdjust, rightAdjust); } // カウンターをリセットする leftCount += leftRatio; rightCount = rightRatio; } } else { if (leftCount == 0) { // 右側は左より遅い if (rightCount >= rightRatio) { // 補正: 右車輪が遅い if (rightAdjust == 0) { // 右の補正は無い。左側を遅くする。 if (leftAdjust < maxAdjust) { leftAdjust += adjustStep; } } else { // 右車輪が補正された。右車輪をスピードアップする。 rightAdjust -= adjustStep; } // 新しいスピードに設定する adjustSpeed(leftAdjust, rightAdjust); } // カウンターをリセットする。 leftCount = leftRatio; rightCount += rightRatio; } } } } return false; } /** * 減速に対するrampingを開始する */ protected override void rampDown() { // 減速を設定する base.rampDown(); // 減速中にカウントダウンのため停止することを防ぐ leftStop = 3; rightStop = 3; } /** * 車輪動作パラメータを得る * * 入力:int movement: 動作番号 * 入力:int steps: 動作するためのステップ数 */ protected override void getMovementSpeed(int movement, int steps) { int leftRatio; int rightRatio; int leftStop; int rightStop; // エンコーダーが動作を停止するようにramping動作を設定する base.getMovementSpeed (movement , steps + ((steps == 0) ? 0 : ((steps > 0) ? 2 : -2))); switch (movement) { default: case movementMove: leftRatio = 1; rightRatio = 1; leftStop = steps * transitionsPer10Cms; rightStop = leftStop; break; case movementPivot: leftRatio = 1; rightRatio = 1; leftStop = steps * transitionsPer10Pivot; rightStop = leftStop; break; case movementTurn: leftRatio = turnRatioSm; rightRatio = turnRatioLg; leftStop = steps * transitionsPer10TurnSm; rightStop = steps * transitionsPer10TurnLg; break; } // パラメータを設定する leftStop = (leftStop > 0) ? leftStop : -leftStop; rightStop = (rightStop > 0) ? rightStop : -rightStop; this.leftStop = (leftStop + 5) / 10; this.rightStop = (rightStop + 5) / 10; this.leftRatio = leftRatio; this.rightRatio = rightRatio; // 動作を設定する //rightState = CPU.readPin(rightPin); rightState = checkSensor(RightSpin); //leftState = CPU.readPin(leftPin); leftState = checkSensor(LeftSpin); rightAdjust = 0; leftAdjust = 0; leftCount = leftRatio; rightCount = rightRatio; } /** * 距離計をリセットする */ public void resetOdometer() { _leftOdometer = 0; _rightOdometer = 0; } /** * 左の距離計の読みを得る * * 戻り:int: 距離計の値を返す */ public int leftOdometer() { return _leftOdometer; } /** * 右の距離計の読みを得る * * 戻り:int: 距離計の値を返す */ public int rightOdometer() { return _rightOdometer; } } } |
車輪エンコーダークラスをテストする |
---|
namespace WheelEncoderTest4 { public partial class Program { public void main() { new WheelEncoderTest_4(); Task.TaskManager(); Debug.Print("All Done"); } } /** * 車輪エンコーダークラスをテストする * * WheelEncoderJBotとWheelEncoderTaskクラスをテストする */ public class WheelEncoderTest_4 : eEvent { WheelEncoderBoeBot jbot; int state; int i; const int moveForward = 0; const int pivotLeft = 1; const int done = 2; /** * テスト(イベント)オブジェクトを作る */ public WheelEncoderTest_4() { jbot = new WheelEncoderBoeBot(new MultitaskingBoeBot()); state = moveForward; i = 0; jbot.setNextEvent(this); } /** * このメソッドはWheelEncoderJBotオブジェクトが動作を完了した * ことをこのオブジェクトに通知するために呼ばれます。 */ public override void notify(Object _object) { switch (state) { case moveForward: if (i < 4) { ++i; // 更新カウンター jbot.move(20); // 正方形の端に沿って動く state = pivotLeft; // 次の状態は旋回(pivot) } else { jbot.stop(); state = done; } break; case pivotLeft: jbot.pivot(2); // 正方形の角で回る state = moveForward; // 次の状態は直進 break; } } } } |