Некоторые проблемы с протопотоками Arduino - PullRequest
7 голосов
/ 03 июня 2011

Я делаю проект по управлению двумя датчиками (ультразвуковым и инфракрасным), управление ими с помощью Arduino. Приемник IR имеет систему фильтров внутри, поэтому он принимает сигналы с частотой 36 кГц. Я использую модуль srf04 для обработки ультразвукового материала. Если я делаю программу, которая должна управлять только одним датчиком, она работает. Но я должен интерполировать два сигнала в один результат. Так что я использовал протопотоки! Но это не работает ... В чем ошибка?

Вот код:

#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 метр, «дистанция» составляет максимум 15 см. В чем ошибка?

Ответы [ 3 ]

6 голосов
/ 03 июня 2011

В irthread() второй аргумент макроса PT_WAIT_UNTIL всегда имеет значение true:

PT_WAIT_UNTIL(pt, 1>0);

Таким образом, программа застрянет в бесконечном цикле irthread (), потому что часть результата макроса PT_WAIT_UNTIL в этом случае выглядит как if(!(1>0)) return 0;; утверждение return 0 никогда не вызывается.


Работает для usthread() и leggithread(), так как второй аргумент равен false для первых 200 миллисекунд , а переменные установлены так, что они снова будут ложными для другого 200 миллисекунд после того, как истинно в течение одного времени .

Некоторая справочная информация находится в Как на самом деле работают протопотоки .

0 голосов
/ 06 февраля 2016

Почему вы положили 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();
0 голосов
/ 05 июня 2011

Таймеры в leggithread() и usthread() мешают друг другу. Они используют одну и ту же переменную, timer. Когда время истекло, примерно через 200 миллисекунд с момента последнего времени, скажем, leggithread(), переменная сбрасывается. Это означает, что условие в другой функции, usthread() (которая вызывается сразу после), будет ложным, даже если условие там должно было быть истинным. Таким образом, по крайней мере еще 200 миллисекунд пройдет до того, как usthread() сможет выполнить работу (вывод 10-микросекундного импульса на порт 12).

Нет гарантии, что обе функции будут вызваны. Если вам не повезло, может быть вызван только один из них, если он является детерминированной системой (управляемой из тех же часов, кристаллом микроконтроллера).

Может быть случайным, какой из них вызывается, или может иметь место какое-то наложение между несколькими частотами (например, одна частота, представленная количеством выполненных инструкций для каждого цикла - эта частота будет меняться при изменении программы).

Если вы хотите, чтобы и leggithread(), и usthread() выполняли работу пять раз в секунду, то каждый из них должен иметь независимый таймер, используя отдельные переменные, например, timer1 и timer2.

...