Последовательный буфер остается пустым, как только он становится пустым один раз.

У меня вопрос относительно чтения последовательного буфера.

При запуске программы я посылаю последовательную команду датчику, который 1. активирует его и 2. позволяет ему отправлять данные - это работает. Когда я отключаю датчик, последовательный буфер остается пустым, и программа переходит в состояние else цикла void. Но если я снова подключу датчик, последовательный буфер должен снова заполниться, и программа должна перейти в состояние if цикла void. Но это не так.

Я добавил переменную i, потому что последовательный буфер слишком быстро опустошается, и программа затем снова отправляет команду запуска условия else, даже если датчик подключен и все еще работает. Тогда показания путаются... это тоже работает.

Почему программа не возвращается в состояние if цикла void, когда датчик снова подключается после того, как он был отключен некоторое время? Тогда Serial.available() должен быть больше 0 и должен считывать данные?

#include <SoftwareSerial.h>
int i = 0; 

void setup()  {
    Serial.begin(9600);
    Serial1.begin(9600);
    Serial1.write(Send Start Sequence);
    Serial1.write(Start continuously read out sensor data);
}

void loop() {
  if (Serial1.available() > 0) {
    char incomingByte = Serial1.read();
    Serial.write(incomingByte);
  i = 0; 
  }
  else {
    i++; 
    if (i > 5) {
      Serial1.write(Send Start Sequence);
      Serial1.write(Start continuously read out sensor data);
    }
  }
}

, 👍0


2 ответа


0

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


Предлагаю другой способ восстановления после отключения датчика:

#include <SoftwareSerial.h>

void setup()  {
    Serial.begin(9600);
    Serial1.begin(9600);
    Serial1.write("Send Start Sequence");
    Serial1.write("Start continuously read out sensor data");
}

unsigned long lastDataReceived;

void loop() {
  if (Serial1.available() > 0) {
    char incomingByte = Serial1.read();
    Serial.write(incomingByte);
    lastDataReceived = millis ();
  }
  else {
    if ((millis() - lastDataReceived) > 5000) {
      Serial1.write("Send Start Sequence");
      Serial1.write("Start continuously read out sensor data");
      lastDataReceived = millis ();
    }
  }
}

Это позволит подождать 5 секунд перед отправкой новой стартовой последовательности. При скорости 9600 бод ваш цикл будет намного быстрее, чем входящие байты. Это будет надежнее.

,

Спасибо за ваш комментарий. Но я думаю, что это проблема, потому что последовательность запуска также дает мне ответ от датчика. Затем я каждый второй цикл получаю неправильный вывод: не значение от датчика, а ответ начальной последовательности. ATM получаю следующее: Sensordata, 1, 2, Sensordata, 1, 2, Sensordata и так далее. Так что мне > 2 было бы достаточно, но чтобы наверняка.., @Gymknopf

Смотрите мой отредактированный ответ (это был не комментарий)., @Nick Gammon


1

Я поддерживаю Ника Гэммона в том, что он рекомендует условие, основанное на времени, а не подсчет итераций цикла. Вы можете сделать это неблокирующим способом хотя:

  • отслеживайте, когда вы в последний раз общались с датчиком
  • если это было слишком давно, повторите команду «начать последовательность».

Обратите внимание, что отправка команды считается событием связи, которое перезагружает таймер. В противном случае вы бы неоднократно отправляли команду слишком быстро.

// Предположим, что после этой задержки мы потеряли датчик.
const unsigned long timeout = 200;

// Последний раз мы общались с датчиком.
unsigned long last_comm_time;

void loop() {
    // Проверьте часы.
    unsigned long now = millis();

    // Обработка входящих данных.
    if (Serial1.available() > 0) {
        last_comm_time = now;
        char incomingByte = Serial1.read();
        Serial.write(incomingByte);
    }

    // Попытаемся разбудить датчик, если мы его потеряли.
    if (now - last_comm_time >= timeout) {
        last_comm_time = now;  // считаем это событием связи
        Serial1.write(start_sequence);
        Serial1.write(continuously_read_out_sensor_data);
    }
}

Потенциально у вас могут быть отдельные тайм-ауты для «датчик просто прекратил отправку данных» и «датчик должен обрабатывать начало команду, которую мы только что отправили». Хотя это было бы немного сложнее, требуется некая машина состояний. Если вы можете использовать один тайм-аут значение, все проще.

,

Ах, Эдгар! Ты опередил меня на несколько секунд! В любом случае, вы правы. :), @Nick Gammon