2016-11-27 7 views
1

私はArduinoとC/C++にはとても新しいので、私と一緒に裸にしてください。実際には、Arduino IDEを使用していますが、コードを実行するデバイスはESP8266です。コールバック関数を使用してwhileループを中断する最善の方法は何ですか?

私は自分のコードを間違って構造化していると確信していますが、私は最良の方法が不明です。うまくいけば、誰かが私を正しい方向に向けることができます。基本的な例に私が持っているシナリオをダウン沸騰さ

私の主ループ()関数は、単純に各パスにコールバック()関数(PubSubClient MQTT)を実行します。このコールバック関数は、まずグローバルブール変数 "run"をfalseに設定し、次に3つのうちの1つを実行します。

  1. 「1」を受け取ると、action1()という関数が実行されます。
  2. '2'が受信された場合、action2()という関数が実行されます。
  3. '3'が受信されている場合、シリアルに行が印刷されます。
  4. 何か他のものが受信された場合、何も受信されない場合、何も行われません。ここで
    void action1() { 
        run = true;    // Do this once to start the loop 
        while (run == true) { 
        // Do some stuff 
        callback();   // To check for new messages 
        } 
    } 
    

    が問題だ:

    (アクション1の場合)が実行されていると、コールバック(

どちらのアクション1()とアクション2()関数は、次のようになり、ループしています)recieves '3'はすべてOKです。コールバックは、 "実行"変数をfalseに設定し、シリアルに行を出力してから、break(ループ)に戻り、すべてがloop()に戻ります。

action1()が実行されていて、callback()がaction2()を開始するコマンドを受け取った場合、action2()が開始され、action1()は返されるのを待っているだけです。

だから、action1()とaction2()の間を前後にフリックすると、ループが重ね合わされてメモリの問題が発生する可能性があります。私はこれを十分に行うと、デバイスがクラッシュするのを見ています。

私はたぶんcallback()がaction1()またはaction2()をキューに入れ、メインループ()でそれらを実行させる必要があるかもしれません。このようにして、常にメインループ()に戻り、他のすべてのループを終了します。私は確かに良い解決策があると確信しています。

ご協力いただければ幸いです。

+0

「main」のように見えますが、ループは1つだけです。そして、コールバックは0と3の間の値を返し、 'main'が残りを処理するようにします。 – user3386109

答えて

2

あなたのコードの構造は確かに正しいではありません。

  • コールバックへの呼び出しが山積みされます。多くのコールバックイベントがある場合は、スタックオーバーフローが発生する可能性があります。
  • グローバルrun変数を使用するとcallback()がリエントラントにならず、処理が早すぎることがあります。実際に

、あなたはすでにキューに拠点を指摘したようになり、イベントループ、より良いオプトたい:

  • callback()はAIアイテムアイテムを受信したときにのみ呼び出されますがアイテムをキューに入れてリターンします。
  • あなたのメインループは各繰り返しで、利用可能な場合は何かをキューから読み込み、正しい動作を呼び出します。
  • 必要に応じて、ポーリング機能を呼び出すこともできます。
  • 必要に応じて、現在の状態を反映する出力関数を呼び出すこともできます。

メインループが永遠に実行されるのか、何か特別な入力が受信されるまで、またはキューが空になるまでは、明確ではありません。決定するまで。

arduinoモデルでコールバックがどのようにトリガされるのかわかりません。しかし、実行中のプロセスが中断した場合は、ロックなど、キューに競合状態がないことを確認する必要があります。

0

ループは一般的に悪い設計ですが、ループ()関数があります。

最後に受信した有効なコマンドを覚えて、対応するaction_x()を繰り返し呼び出します。この関数は「いくつかのことを行います」とかなり高速に戻りますので、その必要はありませんcallback()

多くの場合、action_x()がタスクを完了したことを示すステータスを返すと便利です。

関連する問題