Есть ли способ использовать последовательный порт в качестве источника прерывания?

У меня есть скетч, сделанный для считывания датчика температуры/шума примерно каждые десять секунд. Тем не менее, я хочу ввести источник прерывания для отправки с моей клавиатуры волшебного слова, чтобы датчик считывался именно в этот момент.

Проверив ссылку на attachInterrupt(), я нашел только способы объявления контактов прерывания, но ничего, связанного с последовательным. Что вы можете сказать по этому поводу?

Заранее спасибо.

, 👍1

Обсуждение

'Serial.available()` или сериальные события могут использоваться по существу как прерывание., @dandavis

@дандавис, не совсем так. Это методы *опроса*, а не прерывания. Эти два метода не "прерывают" другие действия, которые может выполнять ваш код. Ваш код должен часто вызывать "доступно", или, если вы используете "serialEvent", вы должны убедиться, что цикл не блокируется. Однако в приложении OP достаточно опроса (см. Ответ gre_gor)., @slash-dev

@slash-dev: независимо от основы, для разработчика они " _ могут использоваться по существу как_"... В частности, здесь нет необходимости в прерывании низкого уровня, когда "основная работа" выполняется только каждые 10 секунд..., @dandavis


3 ответа


0

Вот фрагмент логики, который вы можете использовать:

unsigned long timer = 0;

void loop(){
  readSensors();
  while(millis() - timer < 10000){
    if(stringFromSerial == magicWord){
      readSensors();
    }
  }
}
,

3

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

unsigned long last_measure = 0;

const byte buffer_size = 16;
char buffer[buffer_size] = "";
byte buffer_i = 0;

// setup() и другие вещи

void loop() {
    if (millis() - last_measure > 10000) { // считать температуру, как в примере "мигание без задержки" 
        last_measure = millis();
        int value = readSensor();
        Serial.println(value);
    }
    while (Serial.available()) {
        char c = Serial.read();
        if (c == '\n') { // конец строки, что означает, что мы получили всю строку
            if (strcmp(buffer, "magic") == 0) { // сравнить, соответствует ли оно волшебному слову
                int value = readSensor(); // считывание и печать температуры
                Serial.println(value);
            }
            buffer_i = 0; // reset the index
            buffer[buffer_i] = 0;
        }
        else if (buffer_i < buffer_size-1) { // if the buffer is not full
            buffer[buffer_i++] = c; // добавить символ в буфер
            buffer[buffer_i] = 0; // и null завершают строку
        }
    }
}
,

1

Спасибо вам всем, ребята. Я рассмотрел ваши идеи, а затем закодировал это решение. Это работает нормально, прямо сейчас я считываю показания своего датчика каждые 30 минут (1,800 000 миллисекунд) и всякий раз, когда посылаю волшебное слово. Я надеюсь, что это будет полезно для вас:

void loop(){
if ((millis() - timer < 1800000) && (Serial.available() > 0)){
    magicInput = Serial.readString();
    magicInput.trim(); //даляет входные данные из \n в конце, в противном случае никогда не будет равен magicInput
    if (magicInput.equals(magicWord)){     //Элегантная форма для "=="
      Serial.println();
      Serial.println("  === Your request ==="); //Показывает запрошенное измерение
      Serial.println(millis() - timer); //Время с момента последнего измерения
      measure(); //
    }
  }

  if (millis() - timer >= 1800000){
    Serial.println();
    Serial.println("===== Normal mode =====");  //Указывает, что измерение не было запрошено пользователем
    Serial.println(millis() - timer); //Проверяет, что прошло 30 "точных" минут
    mide();
    timer = millis();
  }
}
,

'Serial.ReadString() по умолчанию имеет тайм-аут в 1 секунду, поэтому ваш ответ имеет ненужную задержку. Вместо этого используйте Serial.readStringUntil('\n')`., @gre_gor