Очистить существующий массив при получении новой последовательной команды
Я начинаю создавать свой первый проект Arduino, но у меня возникли проблемы с последовательным соединением.
Я получаю последовательные данные с консоли и сохраняю их в массиве символов под названием «данные».
Затем, когда я отправляю новое консольное сообщение в Arduino, я хочу, чтобы он очистил существующий массив «данных» и сохранил в этом массиве только новые данные.
Я не совсем понимаю, что не так с моим кодом: я считаю, что эти вложенные операторы Serial.available() не работают, но у меня нет идей, как исправить код.
Данные правильно сохраняются в Arduino, но новая строка объединяется со старой.
int count = 0;
char data[30];
boolean dataComplete = false;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0){
if (dataComplete == true){
Serial.println("There is data already, clearing...");
char data[30];
dataComplete = false;
}
if (dataComplete == false){
Serial.println("New command, collecting...");
while (Serial.available()>0){
char character = Serial.read();
data[count] = character;
count++;
}
dataComplete = true;
}
}
Serial.print("Command received: ");
Serial.println(data);
delay(1000);
}
Заранее спасибо!
@squeck, 👍7
5 ответов
Лучший ответ:
Чтобы очистить массив, вы должны сделать следующее:
for( int i = 0; i < sizeof(data); ++i )
data[i] = (char)0;
или
memset(data, 0, sizeof(data));
, который делает то же самое, используя библиотечную функцию.
Однако, поскольку строки символов (здесь не относящиеся к объектам String) завершаются нулевым байтом, обнуляться необходимо только первый байт:
data[0] = (char)0;
сделаю это.
Вероятно, это не делает то, что вы намеревались сделать:
Serial.println("There is data already, clearing...");
char data[30];
В выводе говорится, что вы очищаете массив data
, но вы этого не делаете. Фактически вы объявляете новую локальную переменную с именем data
, которая не зависит от глобальных data
, которые вы уже объявили в верхней части вашего файла. программа. Локальные переменные существуют только в той области, в которой они объявлены (внутри ближайшего к ним {
).
Вместо этого ваша переменная count
отслеживает объем полученных вами данных. Поэтому, возможно, сделайте следующее:
Serial.println("There is data already, clearing...");
count = 0;
Это не единственное, что может привести к неожиданной работе вашей программы, но это должно, по крайней мере, решить проблему, указанную в вашем вопросе.
Прежде всего, это отличный пример важности пробелов. Ваш код действительно трудно читать, поскольку, просматривая его, кажется, что второй оператор if находится за пределами первого.
Фиксированный код:
int count = 0;
char data[30];
boolean dataComplete = false;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0){
if (dataComplete == true){
Serial.println("There is data already, clearing...");
char data[30];
dataComplete = false;
}
if (dataComplete == false){
Serial.println("New command, collecting...");
while (Serial.available()>0){
char character = Serial.read();
data[count] = character;
count++;
}
dataComplete = true;
}
}
Serial.print("Command received: ");
Serial.println(data);
delay(1000);
}
Кроме того, кажется, что он печатает «Команда получена:» на каждой итерации, независимо от того, есть ли новые данные или нет (хотя это может быть запланированной функцией).
Как уже упоминалось, вы не очищаете переменную, а просто создаете новую. Чтобы устранить эту проблему, вам потребуется очистить и сбросить count
. Однако простой сброс счетчика не сработает, если вторая команда короче предыдущей.
Кроме того, зачем вы усложняете код переменной dataComplete
? Я упростил код ниже:
int count = 0;
char data[30];
boolean dataComplete = false;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available()){
Serial.println("New command, collecting...");
count = 0;
data[] = "";
while (Serial.available()){
char character = Serial.read();
data[count] = character;
count++;
}
}
Serial.print("Command received: ");
Serial.println(data);
delay(1000);
}
Чтобы рассказать о сути вопроса и о том, чего пытался достичь автор.
Ни один из этих кодов на самом деле не работает в целом. Данные будут перезаписаны и будут продолжать непрерывно работать в цикле... в любом случае, вот рабочий пример исходного кода.
Я предпочитаю этот метод очистки массива:
for( int i = 0; i < sizeof(data); ++i )
data[i] = (char)0;
Вот рабочий пример. (Обязательно выберите «Возврат каретки» на последовательном мониторе)
char message[32];
uint8_t incomingByte = 0;
uint8_t BufferPos = 0;
int clearbyte = 0;
void setup() {
Serial.begin(9600);
Serial.println("\n String conversion testing");
}
void loop() {
if (BufferPos >= 32) {
Serial.print("Buffer Full\n");
BufferPos = 00;
incomingByte = 0;
}
if (Serial.available()) {
incomingByte = Serial.read();
message[BufferPos++]= incomingByte;
switch(incomingByte)
{
case '\n':
case ' ':
break;
case '\r':
Serial.println(message);
for( int i = 0; i < sizeof(message); ++i )
message[i] = (char)0;
BufferPos= 0;
incomingByte= 0;
}
}
}
Я прочитал все комментарии по этому вопросу, но все коды оказались настолько многословными. После этого я создаю код с простыми функциями и меньшим количеством строк. в данном случае, я думаю, этот код будет работать нормально
если вы установили скорость передачи данных ниже 115200, необходимо добавить задержку() для сохранения сообщения в массив символов
void loop() {
char data[255];
uint8_t k = 0;
while (Serial.available()) {
data[k] = Serial.read();
k++;
}
for (int i = 0; i < k; i++) {
Serial.print(data[i]);
data [i] = '\0';
}
//delay(50);
}
char data[] = {};
даст вам массив нулевой длины. Попытка поместить в него данные — плохая идея., @Nick Gammon
Я согласен с @NickGammon. Пожалуйста, отредактируйте свой ответ, заменив «Я думаю... будет работать нормально» на однозначное да/нет после того, как вы протестируете код., @MichaelT
@NickGammon спасибо за исправление, я пересматривал свой код, @Ashif Riady
- Как разделить входящую строку?
- Как вывести несколько переменных в строке?
- В чем разница между Serial.write и Serial.print? И когда они используются?
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- Программы построения последовательных данных
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Использовать все контакты как цифровые входы/выходы
Также для данных необходим нулевой терминатор: добавьте
data[count]='\0';
послеdataComplete = true;
, @CraigДа, это правда, но более серьезная проблема заключается в том, что у отправителя нет другого способа указать конец передачи данных, кроме как приостановить ее. А поскольку это последовательный файл, между *каждым* передаваемым символом будет достаточно длинная пауза., @Greg Hewgill
Спасибо вам обоим, ребята. Мой код был неправильным, и его изменение на «count = 0» сработало. Я также добавил разделитель, обозначающий конец команды ввода, и теперь он работает так, как задумано. Однако единственным способом очистить массив «данные» было использование цикла for, как указано @JRobert: таким образом новые команды работают, даже если они короче старых., @squeck