Отсутствующие байты, отправленные через последовательный порт из приложения С#

Я пытаюсь сохранить значения, отправленные приложением C#, в EEPROM через Arduino UNO. Вот код C#, который читает байты из файла (я на 100% уверен, что там есть и всегда будет 256 байт) и отправляет буфер через SerialPort

        SerialPort port = new SerialPort("COM3", 9600);
        const string fileName = @"filepath";
        port.Open();
        byte[] buffer = File.ReadAllBytes(fileName);
        port.Write("W");
        port.Write(buffer, 0, buffer.Length);

Вот код Arduino

int flag;
int datasize = 256;
byte byteBuffer[256];

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

  //read_write();
}


void loop() {
  readEEPROM();
  writeEEPROM();
  delay(500);
}

void readEEPROM() {
  if (Serial.available()) {
    flag = Serial.read();
    if (flag == 'R') {
      for (int i = 0; i < datasize; i++) {
        byteBuffer[i] = ME.read(i);
      }
      flag = 'S';
      Serial.write(byteBuffer, datasize);
    }
  }
}
void writeEEPROM() {
  if (Serial.available()) {
    flag = Serial.read();
    if (flag = 'W') {
      int bytesRead = 0;
      digitalWrite(LED_BUILTIN, HIGH);
      delay(500);
      while (bytesRead < 256) {
        if (Serial.available() > 0) {
          byteBuffer[bytesRead] = Serial.read();
          bytesRead++;
        }
      }
  digitalWrite(LED_BUILTIN, LOW);

  for (int i = 0; i < datasize; i++) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(50);
    ME.writeEnable();
    ME.write(i, byteBuffer[i]);
    ME.writeDisable();
    digitalWrite(LED_BUILTIN, LOW);
    delay(50);
  }
  flag = 'S';
   }
  }
 }

Как вы можете видеть в функции writeEEPROM, arduino включает BUILTIN_LED до того, как начнет считывать последовательный порт, к сожалению, светодиод никогда не выключается, что заставляет меня думать, что никогда 256 байт в SerialPort, более того, когда я снова включаю программу c#, arduino успешно выходит из цикла while, но данные деформируются, я имею в виду, что значения другие.

, 👍0

Обсуждение

почему вы не знаете, получено ли через последовательный порт 256 байт?, @jsotola

Не забывайте, что Arduino перезагружается каждый раз, когда вы открываете последовательный порт с компьютера, и загрузчик запускается на секунду или две, поглощая любые последовательные данные, которые вы отправляете..., @Majenko

@jsotola Что ж, чтобы выйти из цикла while, arduino нужно войти в if(Serial.available()) 255 раз, прямо сейчас он не выходит из цикла while, поэтому я предполагаю, что не хватает пары байтов или что-то в этом роде. что :/, @Shizzle

@Majenko Как я могу решить это тогда? :), @Shizzle

Либо установите задержку после открытия последовательного порта, чтобы дать загрузчику возможность завершить работу, либо напишите правильный протокол, который включает возможность определения готовности Arduino к приему данных. Может быть, отправить "?" и если Arduino ответит «Y», значит, он работает, и вы можете отправлять данные., @Majenko

Но если в моем примере arduino входит в Flag = 'W', разве он уже не может прочитать данные? Я имею в виду, что для запуска функции нужно прочитать серийный номер :) В любом случае, я попытался отложить программу C # после открытия порта, это не помогло., @Shizzle

Это не может не попасть в "w" - вы присваиваете =, а не сравниваете с ==., @Majenko

@Shizzle, причина, по которой я спросил вас, почему вы не знаете, были ли получены 256 байтов, заключалась в том, чтобы заставить вас подумать: «Как я могу убедиться, что 256 байтов были отправлены без ошибок?» .... вы можете отладить свой код, удалив код EEPROM и заменив его кодом, который отправляет данные обратно отправителю ... таким образом вы можете сузить область сбоя, @jsotola


1 ответ


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

3

Здесь две основные ошибки.

Во-первых, это ваш способ открытия последовательного порта и немедленной отправки данных. Arduino сбрасывается, когда вы открываете последовательный порт и запускается загрузчик. Это занимает около секунды, и в течение этого времени все отправляемые вами данные теряются.

Во-вторых, вы не проверяете флаг "W", а вместо этого присваиваете флагу "W", что всегда завершается успешно.

Линия

if (flag = 'W') {

следует прочитать

if (flag == 'W') {

Чтобы обойти первую проблему, вы можете либо просто поставить задержку (как вы делаете это в C#) после открытия порта и перед отправкой «W», либо вы можете реализовать «Вы там?» рукопожатие для поиска Arduino.

Одним из примеров может быть добавление дополнительного флага (скажем) "?" на что Arduino просто отвечает «Y».

Затем компьютер отправляет "?" и, если он не получает «Y» в течение определенного тайм-аута, он зацикливает отправку «?» снова.

После того, как он получит «Y», он узнает, что Arduino готов к приему данных, поэтому вы можете отправить команду «W» и данные.

,