9

私は2つのセンサー(超音波と赤外線)を制御し、Arduinoでそれらを管理するプロジェクトを行っています。IR受信機は内部にフィルターシステムを備えているため、36kHzの周波数で受信します。私はモジュールsrf04を使用して超音波を処理します。1つのセンサーだけを制御する必要があるプログラムを実行すると、それは機能します。しかし、2つの信号を1つの結果に補間する必要があります。だから私はプロトスレッドを使用しました!しかし、それは機能しません...エラーは何ですか?

コードは次のとおりです。

#include <pt.h>

int iro = 8, iri = 4, us = 12, distanza, us_vcc = 13, ir_vcc = 7;
long durata;

static struct pt pt1, pt2, pt3;

static int irthread(struct pt *pt) {
  PT_BEGIN(pt);
  while(1) {
    PT_WAIT_UNTIL(pt, 1>0);
    digitalWrite(iro, HIGH);
    delayMicroseconds(9);
    digitalWrite(iro, LOW);
    delayMicroseconds(9);
  }
  PT_END(pt);
}

static int usthread(struct pt *pt) {
  static unsigned long timer = 0;
  PT_BEGIN(pt);
  while(1) {
    PT_WAIT_UNTIL(pt, millis() - timer > 200);
    timer = millis();
    pinMode(us, OUTPUT);
    digitalWrite(us, LOW);
    delayMicroseconds(5);
    digitalWrite(us, HIGH);
    delayMicroseconds(10);
    digitalWrite(us, LOW);
    pinMode(us, INPUT);
    durata = pulseIn(us, HIGH);
    distanza = durata/58;
  }
  PT_END(pt);
}

static int leggithread(struct pt *pt) {
  static unsigned long timer = 0;
  PT_BEGIN(pt);
  while(1) {
    PT_WAIT_UNTIL(pt, millis() - timer > 200);
    timer = millis();
    Serial.print(distanza);
    Serial.print("cm ");
    if (digitalRead(iri) == LOW)
      Serial.println("ir si");
    else
      Serial.println("ir no");
  }
  PT_END(pt);
}

void setup() {
  pinMode(iro, OUTPUT);
  pinMode(iri, INPUT);
  pinMode(us_vcc, OUTPUT);
  digitalWrite(us_vcc, HIGH);
  pinMode(ir_vcc, OUTPUT);
  digitalWrite(ir_vcc, HIGH);
  Serial.begin(9600);

  PT_INIT(&pt1);
  PT_INIT(&pt2);
  PT_INIT(&pt3);
}

void loop() {
  irthread(&pt1);
  usthread(&pt2);
  leggithread(&pt3);
}

各スレッドのコードの単一部分が機能します。


アップデート

私は自分の問題を解決し(削除しましirthread()た)、コードは次のようになりました:

#include <pt.h>

int iro = 8, iri = 4, us = 12, distanza, us_vcc = 13, ir_vcc = 7;
long durata;

static struct pt pt1, pt2;

static int usthread(struct pt *pt) {
  static unsigned long timer = 0;
  PT_BEGIN(pt);
  while(1) {
    PT_WAIT_UNTIL(pt, millis() - timer > 200);
    timer = millis();
    pinMode(us, OUTPUT);
    digitalWrite(us, LOW);
    delayMicroseconds(5);
    digitalWrite(us, HIGH);
    delayMicroseconds(10);
    digitalWrite(us, LOW);
    pinMode(us, INPUT);
    durata = pulseIn(us, HIGH);
  }
  PT_END(pt);
}

static int leggithread(struct pt *pt) {
  static unsigned long timer = 0;
  PT_BEGIN(pt);
  while(1) {
    PT_WAIT_UNTIL(pt, millis() - timer > 200);
    timer = millis();
    distanza = durata/58;
    Serial.print(distanza);
    Serial.print("cm ");
    if(digitalRead(iri) == LOW)
      Serial.println("ir si");
    else
      Serial.println("ir no");
  }
  PT_END(pt);
}

void setup() {
  pinMode(iro, OUTPUT);
  tone(iro, 36000);
  pinMode(iri, INPUT);
  pinMode(us_vcc, OUTPUT);
  digitalWrite(us_vcc, HIGH);
  pinMode(ir_vcc, OUTPUT);
  digitalWrite(ir_vcc, HIGH);
  Serial.begin(9600);

  PT_INIT(&pt1);
  PT_INIT(&pt2);
}

void loop() {
  usthread(&pt1);
  leggithread(&pt2);
}

今問題は超音波センサーです。プロトスレッドを使用せずに単一のプログラムで制御すると、3メートルの距離にあるオブジェクトに到達できます。今、私が1メートルに何かを置いたとしても、「距離」は最大15cmです。エラーは何ですか?

4

3 に答える 3

9

irthread()マクロの2番目の引数では、常にPT_WAIT_UNTILtrueと評価されます。

PT_WAIT_UNTIL(pt, 1>0);

したがって、この場合のマクロPT_WAIT_UNTILの結果の一部は次のようになるため、プログラムはirthread()の無限ループでスタックしif(!(1>0)) return 0;ます。ステートメントreturn 0が呼び出されることはありません。


これはusthread()、最初の200ミリ秒の間leggithread()は2番目の引数がfalseであり、変数が設定されているため、1回だけtrueになった後、さらに200ミリ秒の間はfalseになります。

いくつかの背景情報は、プロトスレッドが実際にどのように機能するかを示しています。

于 2011-06-03T19:28:31.830 に答える
1

タイマーが入りleggithread()usthread()互いに干渉します。それらは同じ変数を使用しますtimer。時間が経過すると、前回から約200ミリ秒後に、たとえばleggithread()、変数がリセットされます。これは、他の関数usthread()(直後に呼び出される)の条件が、真になりそうだったとしても、偽になることを意味します。したがって、作業を実行できるようになるまでに、少なくともさらに200ミリ秒が経過usthread()します(ポート12で10マイクロ秒のパルスを出力します)。

両方の関数が呼び出されるという保証はありません。運が悪ければ、それが決定論的システム(同じクロック、マイクロコントローラーの水晶から駆動される)であれば、そのうちの1つだけが呼び出される可能性があります。

どちらが呼び出されるかはランダムであるか、複数の周波数間にエイリアシングが存在する可能性があります(たとえば、各ループで実行される命令の数で表される1つの周波数-プログラムが変更されると、その周波数は変化します)。

両方が必要で、1秒間に5回作業leggithread()を行う場合は、それぞれに独立したタイマーが必要です。たとえば、となどの個別の変数を使用します。usthread()timer1timer2

于 2011-06-05T14:32:01.757 に答える
-1

なぜあなたwhile(1)はあなたの機能を入れたのですか?1は常に真なので-

    while(1) {
        // The code in it will repeat forever
    }
    // And the Arduino will never get here

1の代わりにロジック(while(x > 10)、など)を配置するか、ステートメントwhile(task_finished)にコードを配置しないでください。while


    static int usthread(struct pt *pt) {
        static unsigned long timer = 0;
        PT_BEGIN(pt);
        while(1) { // <<<<<<<<< Fault 1
            PT_WAIT_UNTIL(pt, millis() - timer > 200);

    PT_BEGIN(pt);
    while(1) { //<<<<<<<<< Fault 2
        PT_WAIT_UNTIL(pt, millis() - timer > 200);
        timer = millis();
于 2016-02-06T11:23:21.090 に答える