簡體   English   中英

arduino至raspberrypi串行通信

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM