[英]arduino to raspberrypi serial communication
我一直在嘗試在arduino和raspi之間建立串行連接時遇到垃圾字符和奇怪數據的問題。 arduino用於從各種傳感器收集數據,並將其作為逗號分隔的行傳輸到raspi,每“幀”一次(不理想,但仍然足夠快以滿足我的需求)
當在Windows計算機上使用arduino串行接口時,或者在raspberrypi上使用“ sudo screen / dev / ttyACM0 115200,cs8”時,數據都可以正常通過,因此我可以肯定地確定arduino不是問題。
我有以下代碼在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's 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's 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上,但是不確定是否是這種情況,或如何解決它。
任何幫助將不勝感激。
確保您的設備使用相同的電壓。 我用電平轉換器將Arduino串行連接到Pi,因為Pi是3.3v設備,而Arduino是5v。
這是電平轉換器: http : //www.adafruit.com/product/757
簡單的RS232通信不是可靠的通信。 即使2個設備正常工作,也可能會發生通信錯誤(由於電線,寄生蟲等原因造成的)。 您應該添加一種機制,至少可以檢測到不良幀(校驗和,crc等)並忽略它們。
因此事實證明,將檢索數據的函數更改為此:
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;
}
似乎可以解決問題。 不知道它是否理想,但是對我有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.