При работе с двумя программами, работающими на разных процессорах, они никогда не начнут отправлять / получать одновременно. Вероятно, вы видите не то, что результаты объединены неправильно, скорее, программа чтения запустилась и остановилась на полпути между данными.
При отправке данных по линии лучше всего:
На Ардуино:
- Первый кадр данных.
- Отправить кадр.
В Linux:
- Чтение данных в буфере.
- Поиск в буфере полного кадра и дефрагментации.
1. Обрамление данных
Под формированием данных я имею в виду, что вам нужна структура, которую вы можете распознать и проверить на принимающей стороне. Например, вы можете добавить символы STX и ETX в качестве управляющих символов вокруг ваших данных. Когда длина ваших данных меняется, это также необходимо отправить.
В следующем примере мы берем, что массив данных никогда не длиннее 255 байтов. Это означает, что вы можете хранить длину в одном байте. Ниже вы видите псевдокод того, как может выглядеть кадр:
STX LENGTH DATA_ARRAY ETX
Таким образом, общая длина байтов, которые будут отправлены, равна длине данных плюс три.
2. Отправка
Далее вы используете не println, а Serial.write (buf, len).
3. Прием
На принимающей стороне у вас есть буфер, в который будут добавлены все полученные данные.
4. Deframing
Далее каждый раз, когда добавляются новые данные, ищите символ STX, предположим, что следующий символ - это длина. Используя длину +1, вы должны найти ETX. Если это так, вы нашли правильный кадр и можете использовать данные. Затем удалите его из буфера.
for(uint32_t i = 0; i < (buffer.size() - 2); ++i)
{
if(STX == buffer[i])
{
uint8_t length = buffer[i+2];
if(buffer.size() > (i + length + 3) && (ETX == buffer[i + length + 2]))
{
// Do something with the data.
// Clear the buffer from every thing before i + length + 3
buffer.clear(0, i + length + 3);
// Break the loop as by clearing the data the current index becomes invalid.
break;
}
}
}
Пример, в котором также используется циклическая проверка избыточности (CRC), см. здесь