2016-10-07 6 views
-2

私が作っているプログラムは、はしごに接続されているステッパーモーターを制御することになっています。私が計算したい変数は、はしごのパーセンテージまでの距離を教えてくれます。ステッピングモーターが23400歩歩いたときのはしごは100%です。なぜパーセントを計算できないのですか?

ステップ変数は、モータのステップ信号が送信されているISRルーチンで増分されています。

ここにISRルーチンがあります。可変step_countとして

ISR(TIMER1_COMPA_vect) 
{ 
    // Holds next delay period. 
    unsigned int new_first_step_delay; 

    // Remember the last step delay used when accelrating. 
    static int last_accel_delay; 

    // Counting steps when moving. 
    static unsigned int step_count = 0; 

    // Keep track of remainder from new_step-delay calculation to incrase accurancy 
    static unsigned int rest = 0; 

    OCR1A = profile.first_step_delay; 
    switch (profile.run_state) 
    { 

    case STOP: 
     profile.moved_steps = step_count; 
     // Stop the timer, No clock source 
     break; 

    case ACCEL: 
     digitalWrite(step_pin,!digitalRead(step_pin)); 
     step_count++; 
     profile.accel_count++; 
     // Do something 
     // Chech if we should start decelration. 
     if (step_count >= profile.decel_start) 
     { 
     profile.accel_count = profile.decel_length; 
     profile.run_state = DECEL; 
     } 

     // Chech if we hitted max speed. 
     else if (new_first_step_delay <= profile.min_time_delay) 
     { 
     last_accel_delay = new_first_step_delay; 
     new_first_step_delay = profile.min_time_delay; 
     rest = 0; 
     profile.run_state = RUN; 
     } 
     break; 
    case RUN: 
     digitalWrite(step_pin,!digitalRead(step_pin)); 

     step_count++; 
     new_first_step_delay = profile.min_time_delay; 
     // Do something 
     if (step_count >= profile.decel_start) 
     { 
     profile.run_state = DECEL; 
     } 
     break; 
    case DECEL: 
     digitalWrite(step_pin,!digitalRead(step_pin));  
     step_count++; 
     profile.accel_count++; 
     // Do something 
     if(profile.accel_count >= 0) 
     { 
     digitalWrite(en_pin,!digitalRead(en_pin)); 
     profile.moved_steps = step_count; 
     moved_to_position=true; 
     profile.run_state = STOP; 
     } 

     break; 

    } 
    profile.first_step_delay = new_first_step_delay; 

    if(moved_to_position==true) 
    { 
     moved_to_position = false; 
    } 
} 

私は範囲外でそれを使用できるよう、profile.moved_steps = step_countに値を格納する理由はISRの範囲内の、それゆえのみ閲覧可能、静的変数です。

profileは、構造体speed_profileのインスタンス化であり、グローバル変数としてインスタンス化され、どこでも読み取ることができます。

構造体は、次のように定義されます

typedef struct 
{ 
volatile unsigned char run_state : 3; // Determining the state of the speed profile 
volatile unsigned char dir: 1; // Determining the direction the motor has to move - Start being CCW 
volatile unsigned int first_step_delay; // Period time for the next timer_delay, determines the acceleration rate. 
volatile unsigned int decel_start; // Determines at which step the deceleration should begin. 
volatile signed int decel_length; // Set the deceleration length 
volatile signed int min_time_delay; //minium time required time_delay for achieving the wanted speed. 
volatile signed int accel_count; // counter used when computing step_delay for acceleration/decelleration. 
volatile unsigned int moved_steps; // Used by ros to publish current tipper position 
volatile unsigned int current_step_position; // contains the current step_position 
volatile unsigned int step_counter; //used for debug purpose 

}speed_profile; 

profile.moved_stepsはパーセンテージを計算するために使用されている、それは常にこの関数内ROSトピックに公開されています。

void compute_speed_profile(signed int motor_steps, unsigned int motor_accel, unsigned int motor_decel, unsigned int motor_speed) 
{ 
    while(global_state == false) 
    { 
    //do nothing 
    status_step_count.data = profile.current_step_position; 
    chatter.publish(&status_step_count); 
    nh.spinOnce();  
    moved_to_position = true; 
    delay(1); 

    } 
    //Setting up timer 

    while(global_state == true) // request received 
    { int temp = 0; 
     cli(); 
     temp = profile.moved_steps; // Keeping ISR disable shortest time possible 
     sei(); 

     if(profile.dir == CCW) 
     { 
     profile.current_step_position -= temp; 
     } 
     else 
     { 
     profile.current_step_position += temp; 
     } 

     status_step_count.data = ((float)(profile.current_step_position/23400.0))*100.0; 
     chatter.publish(&status_step_count); 

     if(moved_to_position == false) // Ensures that I am reading the newest variable 
     { 
     global_state = false; 
     } 

     nh.spinOnce();  
     delay(1); 
    }  
} 

2つのスレッド間の切り替え(1つはglobal_state = stateまたはfalse)。 グローバルノードのステータスは、rosノードが購読しているトピックにメッセージを送信し、モーターが移動した後にglobal_stateがfalseステートに戻り、メッセージを待つときにtrueになります。私はどんな効果を持っていない計算のように思える割合

status_step_count.data = ((float)(profile.current_step_position/23400.0))*100.0; 

を計算したいとき

だから問題があります。それはモーターがステップ数ではなくパーセントで戻ってくるのを維持しますか? - なぜ私はかなり不確かなのですか?

+4

大量のコードの問題は、通常、同じ問題を示す[mcve]を作成する方が良い理由です。 – Rakete1111

+2

'%'が実際に行っていることをよりよく理解するために、膨大な量のコード –

+3

[C++算術演算子を参照](http://en.cppreference.com/w/cpp/language/operator_arithmetic)を読む人はいません。 – WhozCraig

答えて

1

私が集めることができるデバッグ情報から、私は2番目が疑わしいと疑われます。

最初と2番目の公開コール/メッセージから2つの異なる(しかし定数の)値を最初と2番目のループのwhileループに公開することで、これを確認/拒否できます。例えば、整数1および2

代わりにglobal_state変数の値を公開して、trueを取得したかどうかを確認する方が良いかもしれません。

status_step_count.data = global_state; 
chatter.publish(&status_step_count); 
+0

試してみました。それに何も送っていないときに0を出力します。0を送り、何かを送ったときにすぐに1になりますゼロに戻ります。 私はそれがあることを期待していました。 –

+0

@Carlton Banks:まもなく、その出力が1つだけだと言うときは? 1を見ると、フロートがそのまま渡される問題がない限り、元のパーセンテージ値も表示されるはずです。それらをintに切り捨てるか文字列に変換しようとしましたか? – Ma3x

+0

静的な値をどこから読んでいるかの位置のように思えます。 –

関連する問題