0

Stack Overflow と Google で調査した結果、Arduino での時間管理について多くの質問がありました。そのため、あなたに助けを求めることにしました。

目標は、特定のサブルーチンを特定の時間 (たとえば 3 分間) 実行する "void loop()" 内に switch case ループを作成することです。私が考えた疑似コードは次のとおりです。

void setup() {
    Serial.begin(9600);
    Serial.println("Waiting for command");
}

void loop() {
    // This is where the "polling" occurs
    if(Serial.available()){
        char ch=Serial.read();
        switch(ch)
        {
            case '1':
            // do something
            break;

            case '2':
            //do something
            break;

            case '3':
            void Tempfunct();
            break;

            default:
            Serial.print(ch);
            Serial.println(" : unknown command!");
        }
    }
}

// Function to be called
void Tempfunct() {
    //Do something for  3*60*60*1000 s and return to switch case selection
}

割り込みを含むソリューションがより良いソリューションになると思うので、このソリューションを出発点と考えています。具体的には、次の擬似コードのようなものを期待しています:

void setup() {
    Serial.begin(9600);
    Serial.println("Waiting for command");
}

void loop() {
    // This is where the "polling" occurs
    if(Serial.available()){
        char ch=Serial.read();
        switch(ch)
        {
            case '1':
                // Do something
                break;

            case '2':
               // Do something
               break;

            case '3':
                void Tempfunct();
                break;

            default:
                Serial.print(ch);
                Serial.println(" : unknown command!");
        }
    }
}

// Function to be called
void Tempfunct() {
   //Do something until an interrupt condition is received 
   //from Serial (such a key pressed by user) and then 
   //return to switch case selection.
}

どうすればいいですか?

私にとって、この状況は、「ケース」の 1 つの中に一種の「測定ループ」があるようなものです。Arduinoはあらかじめ設定された「スタートキー」(スタート文字)を受け取ると計測を開始します。ユーザーがシリアル モニター (またはハイパー ターミナル) で別のボタンを押すと、プリセットの「ストップ キー」(停止文字) が Arduino に送信されます。Arduino は外部割り込みが発生したように感じ、測定を停止して void に戻ります。 loop(){...} サイクル。

4

3 に答える 3

1

おそらく、あなたが何をしようとしているのか理解できませんが、非常に単純な有限状態マシンと、基本的にアプリの「状態」に基づく switch ステートメントのようなものをお勧めします。

特定の期間何かを行うことに関しては、現在のミリ秒を変数にキャプチャしてから、プログラムの実行時に、現在のミリ秒 - 保存されたミリ秒 >= 遅延期間であるかどうかをテストできます。

ここにいくつかのコードがあります:

#define IDLE  0; //better to use enum; oh well
#define RED   1;
#define BLUE  2;

int programState;
long delayPeriod;
long startTime;

void setup() {
  Serial.begin(9600);
  Serial.println("Waiting for command");

  programState = IDLE;
  delayPeriod = (1000 * 60) * 3; // 3 minutes
}

void loop() {

  switch(programState){
  case IDLE:
    checkSerial();
    break;

  case RED:
    // need to handle millis rollover eventually, depending on
    //what the program is doing
    if (millis() - startTime >= delayPeriod){
      programState = IDLE;
    } 
    else {
      //do your thing 

      // to make this interruptable move the 'checkSerial()' call
      // out of the switch - so that it gets called every loop
    }
    break;

  case BLUE:

    break;
  }
}


void checkSerial(){
  // this is where the "polling" occurs
  if(Serial.available()){
    char ch=Serial.read();
    switch(ch){
    case '1':
      programState = RED; //set state
      startTime = millis(); //store current milisecond
      break;

    default:

    }    
  }
}
于 2012-11-28T04:57:03.130 に答える
0

キーに応じて、コードのさまざまな部分を実行する一連のコマンド (シリアル ポートから利用可能) が必要だと思います。したがって、何らかのスタッフの作業 (つまり、関数「Tempfunct」の実行) を開始した場合、問題は、スイッチ部分 (ユーザー入力を処理する) に戻るために何をしているのかを中断する方法です。

あなたの質問を書き直したいと思います。あなたが知りたいのは、コードを実行すると同時にユーザー入力を処理する方法です。一般的な解決策は、割り込みを使用することです。新しい文字が来るたびにトリガされるべき割り込みベクトル(割り込みを処理する関数、AVR-Compilerでは予約語SIGNALを使用できます)を指定する必要があります。

あなたの質問には簡単に答えることができます: Arduino のシリアル ライブラリは既にシリアル ポートの割り込みを利用しています。この Libraryの実装を見れば、それがどのように機能するかがわかります。読み取れなかった文字を格納するリングバッファがあります。新しい文字が来るたびに割り込みがトリガーされ、割り込みベクトルによって文字がこのリング バッファーに保存されるため、後で Serial.read() 関数を使用して読み取ることができます。マイクロコントローラ (どの Arduino ボードを使用していますか?) によっては、より多くの割り込みが発生する場合があります。たとえば、Arduino Mega (4 シリアル ポート) には、SIG_USART0_RECV、SIG_USART1_RECV、SIG_USART2_RECV、および SIG_USART3_RECV の 4 つのシリアル割り込みベクトルが必要です。

この割り込みベクトルをプロジェクト (現在のスケッチ) で再度書き直し、内部にカスタム コードを追加する必要があります。割り込みベクトルは、他の関数と同様です。コードを追加しすぎないように注意してください。定期的なチェックだけを行ってください。

100% 確実ではありませんが、同じプロジェクトに 2 つの割り込みベクトルを含めると、2 つ目 (メイン コード) が最初のもの (ライブラリ) を上書きすると思います。でも、念のため、まずは試してみることをお勧めします。

幸運を!

于 2012-11-27T23:15:47.700 に答える
0

あなたが何を求めているのかを正しく理解している場合は、シリアルモニターに「スタートキー」を入力すると、Arduinoが測定状態またはループに入るようにしたいと思います。これを行うには、if ステートメントを記述します。Serial.read() コマンドを使用してシリアル モニターから入力を取得し、それを変数に保存します。次に、ifステートメントを使用して変数の内容を確認し、それが開始キーになりたいものである場合は、ifステートメントに入り、ループして測定を行うifステートメントにループを含めることができます. 測定を終了する準備ができたら、同様のプロセスを実行します。変数に保存する Serial.read() 関数を用意し、別の if ステートメントを用意して、決定した「終了キー」が押されたときに測定ループから抜け出すようにします。すなわち:

 input = Serial.read();
    if(input == '1')
    {
      while(true)
      {
      measurment();
      input_2 = Serial.read();
      if(input_2 == '2')
        break;
      }
    }
于 2012-11-28T02:57:42.317 に答える