Как изменить этот код, чтобы использовать последовательное событие для действия после возврата каретки?
В части кода, используемого с UNO, я хочу отправить число A и число B одновременно как A, B на плату Arduino, если есть возврат каретки. Итак, в данный момент в HyperTerminal, когда я набираю: 100,0,5, плата Arduino немедленно реагирует, x становится 100, а n становится 0,5. Следующие части относятся к чтению с последовательным событием:
void loop() {
if (stringComplete){
delay(1000);
Mwrite(level);
sendFrequency(n);
delay(100);
stringComplete = false;
}
}
и в последовательном событии:
void serialEvent() {
while (Serial.available()) {
slevel = Serial.readStringUntil(',');
Serial.read(); //следующий символ - запятая, поэтому пропустите его, используя этот
x = Serial.readStringUntil(',');
level = slevel.toInt();
n = x.toDouble();
stringComplete = true;
}
}
Но я хочу, чтобы плата считывала последовательные данные только в том случае, если я нажимаю возврат каретки. Поэтому я должен ввести 100,1, а затем нажать возврат каретки, чтобы Arduino отреагировал на последовательные данные.
Как можно изменить этот код для достижения этой цели?
@GNZ, 👍-1
Обсуждение1 ответ
Есть несколько способов решить эту проблему. Самый простой способ сделать это — просто добавить еще одну строку в свой код.
static bool stringComplete = false;
String x;
String slevel;
static int level;
static int n;
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (stringComplete)
{
Serial.println(level);
Serial.println(n);
stringComplete = false;
}
}
void serialEvent()
{
while(Serial.available())
{
slevel = Serial.readStringUntil(',');
//Серийный.читать(); // <-- Вам не нужна эта строка. readStringUntil() будет читать ','
x = Serial.readStringUntil(',');
level = slevel.toInt();
n = x.toDouble();
Serial.readStringUntil('\r'); // <--------- Добавляем эту строку
stringComplete = true;
}
}
Но это, вероятно, неправильный способ сделать это. Во-первых, serialEvent() выполняется между loop(), то есть вот как это выглядит:
while(1)
{
loop();
serialEvent();
}
Таким образом, функция не будет вызываться во время последовательного события. Он просто выполняется сразу после loop(). Также readStringUntil() имеет время ожидания (по умолчанию: 1 с). Поэтому, если ваш символ «до» не появляется в течение одной секунды после вызова функции, он вернется с тем, что у него есть. Чтобы проверить это, просто введите один символ на вашем HyperTerminal, подождите хотя бы секунду и посмотрите результат.
В идеале вы должны обрабатывать входящий байт серийного номера следующим образом:
- Проверить, доступен ли последовательный байт для чтения
- Если есть, прочитайте один байт и сохраните его в буфере/строке. (Я не очень люблю переменные String, но в примере я буду использовать String, потому что вы использовали String)
- Если байт, который вы только что прочитали, является разделителем (например, CR или '\r'), укажите в основном цикле, что строка завершена.
- В основном цикле анализируется вся строка.
Вот как выглядит код с указанными выше пунктами:
static bool stringComplete = false;
String x;
String slevel;
static int level;
static int n;
String rxString = "";
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (stringComplete)
{
// Разбираем rxString
int index1 = rxString.indexOf(','); // находит местоположение первого ,
slevel = rxString.substring(0, index1); // фиксирует первую строку данных
int index2 = rxString.indexOf(',', index1 + 1); // находит местоположение секунды,
x = rxString.substring(index1 + 1, index2); // захватывает вторую строку данных
level = slevel.toInt();
n = x.toDouble();
Serial.println(level);
Serial.println(n);
// Сбросить строку
rxString = "";
stringComplete = false;
}
}
void serialEvent()
{
while(Serial.available())
{
// получаем новый байт:
char inChar = (char)Serial.read();
// добавляем его в rxString:
rxString += inChar;
// если входящий символ является возвратом каретки, указать основной цикл
if (inChar == '\r')
{
stringComplete = true;
}
}
}
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Использовать все контакты как цифровые входы/выходы
- Float печатается только 2 десятичных знака после запятой
- Arduino как USB HID
- Serial1' was not declared in this scope
- Очень простая операция Arduino Uno Serial.readString()
- AT-команда не отвечает на последовательный монитор
Забудьте
serialEvent()
. Это то, что Arduino *никогда* не должен был включать в API. Это идиотская функция, которая в реальности не имеет смысла. Помещение содержимогоserialEvent()
вloop()
точно такое же (и часто гораздо более удобное)., @Majenkohttps://majenko.co.uk/blog/reading-serial-arduino, @Majenko
SerialMonitor ничего не отправляет, пока вы не нажмете «Отправить». Рекомендуется выбрать
новую строку
в качестве дополнительного символа-разделителя при отправке. В дополнение к строке чтения Majenko: есть функция strtok, которую вы можете использовать., @DataFiddlerнастроить терминал на отправку при вводе, а не каждый символ. кстати. readStringUntill удаляет терминальный символ из приемного буфера. и не должен ли ваш второй readStringUntil читать до '\ n'?, @Juraj
@ Маженко, нет, это не идиотизм, это просто неправильно поняли. Я признаю, что у него ограниченные варианты использования, но это может быть большим подспорьем. Например, это очень помогло при разработке моей [библиотеки радиоуправляемых самолетов](https://github.com/PowerBroker2/ArdUAV)., @P_B
Задумка может и имеет смысл, но реализация идиотская. Теперь, если бы они подключили его к прерыванию RX, это могло бы быть полезно. Как то это идиотизм. И я придерживаюсь этого слова., @Majenko