Невозможно сохранить данные в переменной из Serial.read()

У меня есть реле и модуль Bluetooth, подключенные к Arduino Uno. Я отправляю данные, такие как цифра 1, на модуль Bluetooth и просматриваю их в последовательном мониторе. Если я отправлю 1 с последовательного монитора, я напечатаю 4910.

Я хотел бы включить реле и оставить его включенным до тех пор, пока я не отправлю другую цифру. Однако в моем коде ниже это не работает, реле не остается включенным.

Только если я помещу digital.write в while(Serial.available()), это сработает.

const int ledPin =  11;
int relayOn;

void setup() {

  //инициализируем последовательный порт для журналов
  Serial.begin(9600);

  pinMode(ledPin, OUTPUT);

}

void loop() {

  while (Serial.available()) {

      Serial.println("Data: ");

      Serial.println(Serial.read());

      if(Serial.read())
      {
        relayOn = Serial.parseInt(); 
      }

      while (relayOn > 1)
      {
        digitalWrite(ledPin, HIGH);

      }

    }

}

, 👍1

Обсуждение

Вы можете упростить задачу, используя команды, состоящие всего из 1 символа. Например, «1» или «А», чтобы включить его, и «0» или «а», чтобы выключить. Начните с хорошего описания команд и средств связи. Serial.read() читает символ, и вы не можете прочитать его снова с помощью другого Serial.read()., @Jot

Но могу ли я хранить данные из Serial.read() внутри переменной без необходимости непрерывной отправки данных? Я хочу, чтобы реле оставалось включенным до тех пор, пока я не отправлю разные данные 0 или 1 и т. д., @condo1234

@condo1234 Ты мчишься вперед. Сначала опишите данные/команды, которые вы передаете. Хотите, например, усложнить себе задачу и иметь возможность отправить число «15»? Затем пошагово пропишите это в коде, если возможно, без parseInt., @Jot

Теперь я посылаю цифру 5 для включения реле и 0 для выключения. Имеет ли значение отправка 1 для включения? Я также пытался назначить переменную RelayOn в своем коде с помощью Serial.read() и определить ее как char, но все равно не совпало. Есть ли у вас пример кода? Я немного не понимаю, как сохранить реле включенным после отправки данных через Bluetooth., @condo1234

каково значение relayOn, когда вы вводите 1, а также когда вы вводите 0?, @jsotola

@jsotola, когда я отправляю 1, я получаю 0 при выполнении Serial.printIn(relayOn), @condo1234

Serial.println(Serial.read()); удаляет данные из последовательного буфера. if(Serial.read()) всегда будет ложным, @Dorian

На самом деле второй «Serial.read()» всегда будет возвращать -1, это следует интерпретировать как true., @Dorian

@Дориан, ты прав!! В этом была проблема, @condo1234


3 ответа


Лучший ответ:

1

Введите «5\n» с «\n» в качестве окончания строки в последовательном мониторе.

В коде сначала указывается Serial.println(Serial.read());. Он прочитает и распечатает цифру «5». Тогда у вас есть if(Serial.read()). Он будет читать '\n'. Это не 0, поэтому следующая строка — relayOn = Serial.parseInt(). Он не обнаружит никаких входных данных и таймаут вернет 0.

если вы хотите использовать parseInt():

void loop() {
  if (Serial.available()) {
    Serial.print("Data: ");
    relayOn = Serial.parseInt(); 
    Serial.println(relayOn);
    if (relayOn > 1) {
      digitalWrite(ledPin, HIGH);
    }
  }
}
,

Хорошо, спасибо, это имеет смысл, я попробую отправить с 1 и 0 и посмотрю, сработает ли это., @condo1234

Извините, я имел в виду, что уже пробовал Serial.parseInt() и выводит 0, когда выходное реле включено в последовательном мониторе, попробовал то же самое, что и ваш приведенный выше код., @condo1234

дело не в том, какой номер вы отправляете, а в том, как вы его читаете. ответ объясняет 0, @Juraj

Я изменил отправку 1 и использовал ваш код с Serial.parseInt(), и когда я вывожу Serial.printIn(relayOn), я получаю 0, а Serial.printIn(Serial.read()) получаю -1., @condo1234

замените функцию цикла() на функцию цикла() из моего ответа, @Juraj

Хорошо, я сделал это, и теперь он выводит 0, если я отправлю 1, @condo1234

Я использовал в void setup() { Serial.begin(9600);}. В последовательном мониторе я использую 9600, это странно, когда я ввожу 1 из последовательного порта, я каждый раз получаю вывод 4910 внутри Serial.printIn(Serial.read()), @condo1234

49 — это ascii-код символа «1». 10 – это ascii-код символа '\n' (новая строка)., @Juraj

Итак, что мне сделать, чтобы реле включалось и оставалось включенным, а затем выключалось, когда я отправляю другой символ... это все, что мне нужно сделать... есть идеи по коду? спасибо за вашу помощь. Я отправляю 1 из последовательного монитора и приложения Android, похоже, оба не отправляют целое число., @condo1234

Итак, в операторе if я проверяю строку, т.е. if (relayOn == '1') вместо этого? И нужно ли мне изменить реле с int на char?, @condo1234

Несправедливо удалять ответ с полезными комментариями из ОП, а затем, после того, как проблема была решена, появиться с ним. Когда я оставлял свои комментарии, ответа не было., @Dorian

@Дориан, мне очень жаль. Я удалил ответ, потому что ОП указал, что проблема в чем-то другом, и ответ ее не решил. Я сначала написал аналогичный комментарий, потом ваш. Это был третий или четвертый комментарий, и он был полностью проигнорирован ОП и другими комментаторами. Потом я написал ответ и удалил комментарий. Тогда ответ, казалось, был неверным..., @Juraj

Это была, по крайней мере, часть решения, я бы проголосовал за ваш ответ, если бы нашел его, как я сделал с ответом Кускуса, опубликованным вскоре после моего комментария, чтобы дать понять, что здесь действительно есть проблема., @Dorian

@Дориан, извини. это было плохое решение, @Juraj


0

Попробуйте использовать последовательное прерывание в Arduino

void loop() {
}

void serialEvent() 
{
  while (Serial.available()) 
    {
       char inChar = (char)Serial.read();
      Serial.print("Data: ");
      Serial.println(inChar);
       if (inChar == '1') 
        {
              digitalWrite(ledPin,HIGH);
              break;
        }
       else
        {
              digitalWrite(ledPin,LOW);
              break;
        }
     }
}
,

это не прерывание. https://github.com/arduino/ArduinoCore-avr/blob/5755ddea49fa69d6c505c772ebee5af5078e2ebf/cores/arduino/main.cpp#L45, @Juraj

но в arduino действует как последовательное прерывание, @Vaibhav


3

Вы можете попробовать что-то вроде (не проверялось):

void loop() {
 if(Serial.available()){
   input = Serial.parseInt();
   Serial.print("Data: ");
   Serial.println(input);
   if(input == 1){
      digitalWrite(RELAY, HIGH);
      digitalWrite(LED, HIGH);
   }
   else if(input == 2{
      digitalWrite(RELAY, LOW);
      digitalWrite(LED, LOW);
   }
 }
}

не забудьте объявить входную переменную, используйте 1 для включения, 2 для выключения :)

,