ESP8266 с HC05 : ожидаю получить больше байтов, чем 63 полученных

Я пытаюсь прочитать Ant BMS 32H с помощью ESP8266 и модуля HC05. BMS отправляет 146 байт, когда запрашивает их, отправляя DB DB 0 0 0 0 (ШЕСТНАДЦАТЕРИЧНЫЙ) Я провел тест с помощью своего телефона Android и приложения "Последовательный терминал Bluetooth", и я получаю/вижу 146 байт. При выполнении этого с ESP8266/HC05 я получаю только 63 байта. Я уже видел, что не следует использовать задержки перед чтением последовательного буфера, так как это может привести к переполнению буфера.

Я понятия не имею, в чем может быть причина ... надеюсь, у кого - то есть больше знаний, чем у меня ... Пожалуйста, посмотрите мой код, который я использую ( я не публиковал процедуру Process_Data (), как она называется впоследствии ) Сначала я попробовал без косметической визуализации ( дополнительные строки кода, для выполнения которых требуется цикл процессора), и это дало тот же результат

Результат, который я получаю :

---------------------------------------------------
Sending request (6 bytes) : DB DB 0 0 0 0  Answer :
00:AA 01:55 02:AA 03:FF 04:02 05:7B 06:08 07:43 08:08 09:43 
10:08 11:47 12:08 13:41 14:08 15:3B 16:08 17:45 18:08 19:41 
20:08 21:46 22:08 23:43 24:08 25:41 26:08 27:43 28:08 29:46 
30:08 31:44 32:08 33:41 34:08 35:49 36:08 37:41 38:08 39:43 
40:08 41:42 42:08 43:3F 44:08 45:3F 46:08 47:46 48:08 49:44 
50:08 51:4F 52:08 53:38 54:08 55:3E 56:08 57:47 58:08 59:47 
60:08 61:45 62:08 
Bytes received : 63

Мой .ino :

#include <SoftwareSerial.h>;
SoftwareSerial EEBlue(12, 13); // RX | TX // AT command mode
// byte message[] = {0x5A, 0x5A, 0x5A, 0x00, 0x00, 0x5A, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0A };
byte message[] = {0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00 };
byte bms[147]; // 82 + 65 = 147 bytes
int i;
int x;
int highbyte, lowbyte;
uint16_t a16bitvar;
unsigned int BattSOCG;
float BattPowerG;

void setup()
{
  Serial.begin(115200);
  delay(500);
  EEBlue.begin(38400);  //38400 Baud for AT commands , set by command : AT+UART=38400,1,0 or AT+UART=9600,1,0
  delay(500);
  Serial.println();
  Serial.println("Serial and Bluetooth started.");
  Serial.println(); Serial.println("");
}
 
void loop()
{
  AskBMSData();
  GetBMSData();
  Process_Data();
  delay(3000);
}

// ---------------------------------------------------------
void AskBMSData()
{
  Serial.print("Sending request ("); Serial.print(sizeof(message)); Serial.print(" bytes) : ");
  for (i=0; i<sizeof(message); i++)
  {
    Serial.print(message[i], HEX);
    Serial.print(" ");
  }
  
  EEBlue.write(message, sizeof(message));
}

void GetBMSData()
{
  Serial.println(" Answer :");
  // Feed any received bluetooth data to Terminal.
  i=0;
  while (EEBlue.available()) {
    bms[i]= EEBlue.read();
    if(i<10) Serial.print("0");
    Serial.print(i); Serial.print(":");
    if(bms[i]<16) Serial.print("0");
    Serial.print(bms[i], HEX);
    Serial.print(" ");
    x = (i+5)/10; x = 10*x-1; if(i==x) Serial.println();
    i++;
  }
  Serial.println(); Serial.print("Bytes received : ");Serial.println(i);Serial.println();
}

// --------------------------------------------------------

Код изменен на основе ответа Крисла на :

void GetBMSData()
{
  Serial.println(" Answer :");
  // Передать любые полученные данные Bluetooth на терминал.
  i=0;
  if (EEBlue.available()) {
      while (i<146) {
        bms[i]= EEBlue.read();
        i++;
        }
  }

  for (z=0; z<i; z++) {
    if(z<10) Serial.print("0");
    Serial.print(z); Serial.print(":");
    if(bms[z]<16) Serial.print("0");
    Serial.print(bms[z], HEX);
    Serial.print(" ");
    x = (z+5)/10; x = 10*x-1; if(z==x) Serial.println();
  }
  Serial.println(); Serial.print("Bytes received : ");Serial.println(i);Serial.println();
}

в результате :

---------------------------------------------------
Sending request (6 bytes) : DB DB 0 0 0 0  Answer :
00:AA 01:55 02:AA 03:FF 04:02 05:71 06:08 07:23 08:08 09:23 
10:08 11:26 12:08 13:21 14:08 15:1B 16:08 17:25 18:08 19:1E 
20:08 21:27 22:08 23:24 24:08 25:1E 26:08 27:23 28:08 29:27 
30:08 31:25 32:08 33:1F 34:08 35:28 36:08 37:21 38:08 39:22 
40:08 41:22 42:08 43:1C 44:08 45:23 46:08 47:28 48:08 49:26 
50:08 51:31 52:08 53:17 54:08 55:1E 56:08 57:28 58:08 59:29 
60:08 61:25 62:08 63:FF 64:FF 65:FF 66:FF 67:FF 68:FF 69:FF 
70:FF 71:FF 72:FF 73:FF 74:FF 75:FF 76:FF 77:FF 78:FF 79:FF 
80:FF 81:FF 82:FF 83:FF 84:FF 85:FF 86:FF 87:FF 88:FF 89:FF 
90:FF 91:FF 92:FF 93:FF 94:FF 95:FF 96:FF 97:FF 98:FF 99:FF 
100:FF 101:FF 102:FF 103:FF 104:FF 105:FF 106:FF 107:FF 108:FF 109:FF 
110:FF 111:FF 112:FF 113:FF 114:FF 115:FF 116:FF 117:FF 118:FF 119:FF 
120:FF 121:FF 122:FF 123:FF 124:FF 125:FF 126:FF 127:FF 128:FF 129:FF 
130:FF 131:FF 132:FF 133:FF 134:FF 135:FF 136:FF 137:FF 138:FF 139:FF 
140:FF 141:FF 142:FF 143:FF 144:FF 145:FF 
Bytes received : 146

, 👍1

Обсуждение

вы печатаете шесть символов для каждого полученного ... вы можете использовать шестнадцатеричную адресацию, чтобы уменьшить количество напечатанных строк ... первая строка будет 00 : AA 55 AA FF 02 71 08 23 08 23 08 26 08 21 08 1В ... вторая строка 10 : 08 25 08 1E 08 27 08 24 08 1E 08 23 08 27 08 25, @jsotola

Действительно хороший способ визуализировать вывод, но так как мне нравится визуально выделять определенный байт, мне нравится иметь возможность видеть с первого взгляда тот, который мне нужен. Но способ визуализации не меняет/не решает проблему, так как теперь я выполняю визуализацию после того, как у меня есть все байты в переменных., @Bart De Pauw


1 ответ


1

Я вижу 2 вещи, которые могут вызвать у вас проблемы. Во-первых, тот, у которого больше шансов стать важным моментом:

Вы используете

while (EEBlue.available())

в вашей функции GetBMSData (). С последовательным (и особенно по пакетному протоколу, такому как bluetooth) отправитель может вводить паузы в передаче данных (например, когда ему нужно дождаться большего количества данных, выполняя другие задачи, кроме отправки, или когда пакет Bluetooth заканчивается и необходимо отправить новый). Вы не можете контролировать, происходят ли и когда эти паузы. Они могут быть достаточно большими, чтобы ваш цикл while() мог очистить внутренний буфер библиотеки SoftwareSerial, еще не получив полного сообщения.

С помощью serial вы не можете думать о сообщении как об одном блоке данных, которые поступают одновременно. Вам нужно учитывать это, чтобы не торопиться. Например, вы можете выполнить цикл внутри этой функции, пока не получите полное сообщение. Это соответствовало бы вашей текущей структуре кода. Что-то вроде этого:

while(i<146){
  if(EEBlue.available()){
    bms[i]= EEBlue.read();
    i++;
  }
}

Примечание: Если по какой - либо причине будет отправлено меньше ожидаемого количества байтов, этот код будет заблокирован навсегда-или до тех пор, пока он не получит столько байтов.

Или - если вы хотите сделать это неблокирующим (также переписав остальную часть кода), вы можете просто выделить буфер, достаточно большой для всего сообщения, и помещать байты только по мере их поступления в этот буфер. Остальное (например, отправка данных по последовательному каналу) может быть выполнено, когда у вас есть все байты данных сообщения. В этом случае вам не нужен цикл while, так как функция loop() уже обрабатывает цикл. Вы просто проверяете на очень циклической итерации, доступны ли данные, и считываете их. После прочтения байта вы проверяете, завершено ли сообщение. Если да, выполните печать и обработку.


Вторая проблема не столь вероятна, но я все равно хочу включить ее сюда. Вы выполняете довольно большую печать внутри цикла while, печатая не менее 6 байт на каждый полученный байт. Последовательный может занять некоторое время, и если это займет много времени, вы можете заполнить свой буфер в фоновом режиме, эффективно теряя данные. Я бы предложил использовать цикл while, чтобы просто прочитать() байты и сохранить их в вашем массиве. Печать может быть выполнена после получения полного сообщения. Для человека, читающего серийную распечатку, это не будет отличаться, но вы можете предотвратить потерю данных таким образом.

,

Я не знаю точно, как реализовать "Например, вы могли бы выполнить цикл внутри этой функции, пока не получите полное сообщение". Я попытался изменить свой код, см. Редактирование исходного сообщения, @Bart De Pauw

Я добавил небольшой фрагмент кода к своему ответу. Надеюсь, это поможет, @chrisl