У меня возникли проблемы с символами мусора и странными данными, поступающими через последовательное соединение, которое я пытаюсь настроить между ардуином и raspi. Ардуино используется для сбора данных с разных датчиков и передает его в raspi как разделительную линию, однажды на "фрейм" (не идеально, но все же более чем достаточно быстро для моих нужд)
При использовании последовательного интерфейса arduino на моем компьютере с Windows или при использовании "sudo screen/dev/ttyACM0 115200, cs8" на raspberrypi данные проходят через штраф, поэтому я уверен, что ардуино не проблема.
У меня есть следующий код, чтобы установить соединение на стороне raspi:
int serial::openPort(std::string portName)
{
int serialPort;
serialPort = open(portName.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if (serialPort == -1)
{
std::cout << "open_port: Unable to open " << portName;
}
else
{
struct termios portOptions;
//set up the port so reading nothing returns immediately, instead of blocking
fcntl(serialPort, F_SETFL, FNDELAY);
// Fetch the current port settings
tcgetattr(serialPort, &portOptions);
// Flush the port buffers (in and out) before we start using it
tcflush(serialPort, TCIOFLUSH);
// Set the input and output baud rates
cfsetispeed(&portOptions, B115200);
cfsetospeed(&portOptions, B115200);
// c_cflag contains a few important things- CLOCAL and CREAD, to prevent
// this program from "owning" the port and to enable receipt of data.
// Also, it holds the settings for number of data bits, parity, stop bits,
// and hardware flow control.
portOptions.c_cflag |= CLOCAL;
portOptions.c_cflag |= CREAD;
// Set up the frame information.
portOptions.c_cflag &= ~PARENB;
portOptions.c_cflag &= ~CSTOPB;
portOptions.c_cflag &= ~CSIZE;
portOptions.c_cflag |= CS8;
// Now that we've populated our options structure, let push it back to the
// system.
tcsetattr(serialPort, TCSANOW, &portOptions);
// Flush the buffer one more time.
tcflush(serialPort, TCIOFLUSH);
}
return serialPort;
}
И следующее должно прочитать все данные в буфере:
std::string serial::readData(int serialPort)
{
char buffer[64];
int bytesRead = 0;
std::string returnString;
do
{
bytesRead = read(serialPort, buffer, sizeof(buffer));
if(bytesRead > 0)
returnString.append(buffer, bytesRead);
} while (bytesRead == sizeof(buffer));
return returnString;
}
который затем обрабатывается в этом цикле: (я использую только последний "фрейм" данных, которые поступают, потому что данные от arduino поступают намного быстрее, чем я могу отображать его на raspi)
gaugeDataBuffer += serial::readData(port);
std::cout << gaugeDataBuffer;
while(true)
{
newLineLocation = gaugeDataBuffer.find("\r\n");
if (newLineLocation == std::string::npos)
break;
gaugeDataStrings = utility::split(gaugeDataBuffer.substr(0, newLineLocation), ',');
gaugeDataBuffer = gaugeDataBuffer.substr(newLineLocation + 2);
}
Проблема здесь, когда данные попадают на консоль (cout в последнем блоке кода), иногда это искажает. Я бы ожидал красивой упорядоченной серии строк данных, но иногда я получаю странные управляющие символы, буквы, строки данных, которые усекаются и т.д.
У меня такое ощущение, что это происходит во втором, чтобы последний блок кода, где я добавляю какие-либо новые данные в returnstring, но я не уверен, что это так, или как это исправить.
Любая помощь будет принята с благодарностью.
как оказалось, изменение функции, которая извлекает данные:
std::string serial::readData(int serialPort)
{
char buffer[1];
int bytesRead = 0;
std::string returnString;
do
{
bytesRead = read(serialPort, buffer, 1);
if(bytesRead > 0)
{
returnString += buffer[0];
}
} while (bytesRead == sizeof(buffer));
return returnString;
}
похоже, устраняет проблему. Не уверен, что это идеальный, но он работает для меня.
Убедитесь, что ваши устройства говорят о том же напряжении. Я последовательно подключил Arduino к Pi с преобразователем уровня, потому что Pi - это устройство на 3,3 В, а Arduino - 5в.
Вот конвертер уровня: http://www.adafruit.com/product/757
Простая связь по RS232 не является надежной связью. Даже если 2 устройства работают правильно, может произойти ошибка связи (из-за плохих проводов, паразитов,...). Вы должны добавить механизм, который позволяет, по крайней мере, обнаруживать плохие кадры (контрольная сумма, crc,...) и игнорировать их.