Возникла проблема с правильной передачей значений массива.

Я впервые задаю здесь вопрос, заранее извините, если это неправильный способ задать этот вопрос.

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

Похоже, что мой цикл Serial.available() == 4 препятствует работе моего цикла Serial.available() == 5. Могу ли я внести простую модификацию, позволяющую получать 5-значный результат из 5-значного ввода и 4-значный результат из 4-значного ввода? Я пробовал много вещей, и Chat GPT, кажется, думает, что текущий код должен работать, но это не так. Вот код:

int fiveArray[5];
int fourArray[4];
const char* colors[] = {"black ", "brown ", "red ", "blue ", "yellow ", "orange ", "white ", "gold ", "green ", "purple "};

void setup() {
  Serial.begin(9600);

  Serial.print("Input a number value: ");
  Serial.println();
}

void loop() { 
  if (Serial.available() ==5 ) { 
    char tempArrayFive[6]; 
    Serial.readBytes(tempArrayFive, 6); 
    tempArrayFive[5] = '\0';

    for (int i = 0; i < 5; i++) {
      fiveArray[i] = tempArrayFive[i] - '0';
    }

    Serial.print("Color Value: ");
    for (int i = 0; i < 5; i++) {
      Serial.print(colors[fiveArray[i]]);
    }
    Serial.println();

  }
  if (Serial.available() == 4 ) {
    char tempArrayfour[5];
    Serial.readBytes(tempArrayfour, 5);
    tempArrayfour[4] = '\0';

    for (int i = 0; i < 4; i++) {
      fourArray[i] = tempArrayfour[i] - '0';
    }

    Serial.print("Color Value: ");
    for (int i = 0; i < 4; i++) {
      Serial.print(colors[fourArray[i]]);
    }
    Serial.println();
  }
}

, 👍-1

Обсуждение

«Похоже» — отличное наблюдение, отправка одного байта (10 бит со стартовым и стоповым битами) со скоростью 9600 бод в секунду занимает около 1 мс. С другой стороны, Arduino на частоте 16 МГц за это время может обрабатывать 16 000 циклов команд — я предполагаю, что это более 200 циклов() между 4-м и 5-м символом..., @KIIV

Можете ли вы приложить образец того, что вы отправляете из последовательного монитора, и какое окончание строки вы там установили? Ваш текущий код не имеет для меня особого смысла. Как писал KIIV, у вас есть состояние гонки между двумя операторами if, но вы также читаете 6 (и 5) байтов, но перезаписываете последний нулём для завершения строки. Вы говорите о байтовых данных, но из вашего кода кажется, что вы используете текст в кодировке ASCII (важная разница при обработке данных), @chrisl

ОТ по поводу ChatGPT: Никогда не доверяйте чат-боту, он понятия не имеет о программировании, просто хорошо умеет складывать слова. Не смешивайте идеальную грамматику и формулировку со знаниями!, @the busybee

«_Я впервые задаю здесь вопрос_»: Поскольку вы предположительно умный человек, вы хотите совершить [экскурсию] и прочитать «[спросить]», а также другие страницы [помощи]., @the busybee


2 ответа


2

Да, если вы отправите 5 байт в Arduino, они будут приходить по одному. Когда поступает 4-й байт, оператор if (Serial.available() == 4 ) становится истинным и запускает этот код. Этот код считывает данные из буфера, а это означает, что часть, проверяющая 5 байтов, никогда не сможет работать. Прежде чем станет 5, всегда будет 4.

Лучше было бы отправлять байты с маркерами начала и конца. Программа на Arduino будет читать байты и собирать их в массив, пока не увидит маркер конца. Затем вы можете подсчитать, сколько байт вы получили, если хотите предпринять разные действия в зависимости от этого числа.

Вот хорошая тема по обработке последовательных данных: https://forum.arduino.cc/ t/serial-input-basics-updated/382007

,

2

У меня есть сообщение здесь, в котором обсуждается обработка входящих последовательных данных. Также здесь, на Stack Exchange.

Для обработки последовательного ввода, как вы пытаетесь это сделать, я предлагаю использовать «маркер конца строки»; например символ новой строки (который Терминальный монитор в IDE сделает за вас автоматически).

Тогда это просто случай просмотра того, что у вас было, до новой строки. Пример кода:

/*
Пример обработки входящих последовательных данных без блокировки.

Author:   Nick Gammon
Date:     13 November 2011. 
Modified: 31 August 2013.

Released for public use.
*/

// сколько последовательных данных мы ожидаем перед переводом строки
const unsigned int MAX_INPUT = 50;

void setup ()
  {
  Serial.begin (115200);
  } // конец настройки

// здесь для обработки входящих последовательных данных после получения терминатора
void process_data (const char * data)
  {
  // пока просто отображаем это
  // (но вы можете сравнить его с каким-то значением, преобразовать в целое число и т. д.)
  Serial.println (data);
  }  // конец Process_data
  
void processIncomingByte (const byte inByte)
  {
  static char input_line [MAX_INPUT];
  static unsigned int input_pos = 0;

  switch (inByte)
    {

    case '\n':   // конец текста
      input_line [input_pos] = 0;  // завершающий нулевой байт
      
      // терминатор достигнут! обработать input_line здесь...
      process_data (input_line);
      
      // сбрасываем буфер для следующего раза
      input_pos = 0;  
      break;

    case '\r':   // отбрасываем возврат каретки
      break;

    default:
      // продолжаем добавлять, если не заполнено... разрешаем завершающий нулевой байт
      if (input_pos < (MAX_INPUT - 1))
        input_line [input_pos++] = inByte;
      break;

    }  // конец переключателя
   
  } // конец процессаIncomingByte

void loop()
  {
  // если серийные данные доступны, обработаем их
  while (Serial.available () > 0)
    processIncomingByte (Serial.read ());
    
  // выполняем здесь другие действия, например, проверяем цифровой ввод (нажатие кнопок) ...

  }  // конец цикла

В вашем случае вы должны поместить код в функцию process_data, чтобы преобразовать входной текст в число, а затем что-то сделать с этим числом.

Я удивлен, что ChatGPT не указал на мой код <grin> но, возможно, вы задали слишком конкретный вопрос.


Я бы просто отметил, что без символа завершения строки (например, новой строки) ваш код будет постоянно не соответствовать входящим данным, если он начинается не в том месте. Например:

123456789

В зависимости от скорости доставки, увидим ли мы 123, за которым следует 456? Или 12, а затем 34? Или 1234, а затем 5678? Разделитель в конце строки очень важен, чтобы избежать такой двусмысленности.

Или, если код начнет выполняться после того, как вы отправили 1, но до 2, он будет думать, что вы отправили 234, а не 123, и тогда все остальные числа будут отставать на одну позицию.

,