ฉันกำลังพยายามใช้ Arduino สำหรับเอาต์พุตข้อมูลการเร่งความเร็วพื้นฐาน ปัญหาที่ฉันกำลังเผชิญอยู่ในขณะนี้คือการขาดความเข้าใจพื้นฐานเกี่ยวกับวิธีการประมวลผลข้อมูลที่ส่งผ่านพอร์ตอนุกรม ประการแรกนี่คือโปรแกรม Arduino ง่าย ๆ ของฉัน:

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    sendData();
  }

}

void sendData() {
      // read raw accel/gyro measurements from device
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

    writeBuffer[0] = '<';
    writeBuffer[1] = lowByte(ax);
    writeBuffer[2] = highByte(ax);
    writeBuffer[3] = lowByte(ay);
    writeBuffer[4] = highByte(ay);
    writeBuffer[5] = lowByte(az);
    writeBuffer[6] = highByte(az);
    writeBuffer[7] = '>';

    Serial.write(writeBuffer, 8);         
    //Serial.write((uint8_t)(gx >> 8)); Serial.write((uint8_t)(gx & 0xFF));
    //Serial.write((uint8_t)(gy >> 8)); Serial.write((uint8_t)(gy & 0xFF));
    //Serial.write((uint8_t)(gz >> 8)); Serial.write((uint8_t)(gz & 0xFF));

    // blink LED to indicate activity
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);
}

และนี่คือรหัส c ++ ของฉัน:

Serial* SP = new Serial("COM5");    // adjust as needed

    if (SP->IsConnected())
        printf("We're connected!\n");

    char incomingData[8] = "";          // don't forget to pre-allocate memory
    //printf("%s\n",incomingData);
    int dataLength = 8;
    int readResult = 0;

    while (SP->IsConnected())
    {
        readResult = SP->ReadData(incomingData, dataLength);
        //printf("Bytes read: (-1 means no data available) %i\n", readResult);

        if (readResult < 8 || incomingData[0] != '<' || incomingData[7] != '>') {
            continue;
        }

        char low = incomingData[1];
        char high = incomingData[2];

        int ax = (high << 8 | low);

        low = incomingData[3];
        high = incomingData[4];

        int ay = (high << 8 | low);

        low = incomingData[5];
        high = incomingData[6];

        int az = (high << 8 | low);

        printf("ax: %i, ay: %i, az: %i\n", ax, ay, az); 

        //Sleep(500);
    }
    return 0;

และนี่คือวิธีการทำงานของฟังก์ชันอ่าน:

int Serial::ReadData(char *buffer, unsigned int nbChar)
{
    //Number of bytes we'll have read
    DWORD bytesRead;
    //Number of bytes we'll really ask to read
    unsigned int toRead;

    //Use the ClearCommError function to get status info on the Serial port
    ClearCommError(this->hSerial, &this->errors, &this->status);

    //Check if there is something to read
    if (this->status.cbInQue > 0)
    {
        //If there is we check if there is enough data to read the required number
        //of characters, if not we'll read only the available characters to prevent
        //locking of the application.
        if (this->status.cbInQue > nbChar)
        {
            toRead = nbChar;
        }
        else
        {
            toRead = this->status.cbInQue;
        }

        //Try to read the require number of chars, and return the number of read bytes on success
        if (ReadFile(this->hSerial, buffer, toRead, &bytesRead, NULL) && bytesRead != 0)
        {
            return bytesRead;
        }

    }

    //If nothing has been read, or that an error was detected return -1
    return -1;

}

อย่างที่คุณเห็นฉันกำลังทำเครื่องหมายเอาต์พุตอนุกรมของฉันด้วยเครื่องหมายสองตัว "<" และ ">" ปัญหาในฝั่งไคลเอ็นต์คือฉันไม่แน่ใจว่าจะแน่ใจได้อย่างไรว่าอ่านเฉพาะบล็อกเหล่านั้นจริงๆ ฉันจะรู้ได้อย่างไรว่าบล็อกมาถึงแล้ว? ฉันต้องอ่านข้อมูลทั้งหมดลงในบัฟเฟอร์ก่อนแล้วจึงประมวลผลหรือไม่ ถ้าฉันทำเช่นนั้น ฉันจะจัดการกับบล็อกที่ไม่สมบูรณ์ได้อย่างไร (สร้างจากการอ่านก่อนที่จะส่งทั้งบล็อก) ฉันค่อนข้างสับสนว่าแนวคิดนี้ทำงานอย่างไร อาจมีบางคนสามารถอธิบายว่าสิ่งนี้มักจะถูกจัดการอย่างไร ขอบคุณมาก!

ตอบ

ในส่วนที่เกี่ยวกับการอ่านข้อมูลจากพอร์ตอนุกรมปกติ ผ่านสายเคเบิลอนุกรมปกติ สิ่งสำคัญที่สุดที่ต้องทำความเข้าใจคือพอร์ตอนุกรมสามารถมีข้อมูลสูญหายหรือเสียหายได้

ในกรณีของคุณ ไม่น่าจะเป็นไปได้มาก แทบจะเป็นไปไม่ได้เลย - คุณอาจมีอัตรารับส่งข้อมูลต่ำ ส่งสัญญาณไม่บ่อย สายสั้น ฯลฯ ฯลฯ แต่ในกรณีทั่วไป เริ่มมีแนวโน้มที่คุณจะได้รับ ข้อมูลเสียหาย

วิธีที่ฉันพยายามอ่านแพ็กเก็ตนั้นเป็นเครื่องสถานะเล็ก ๆ ที่เพิ่งปล่อยแพ็กเก็ตที่เสียหายลงบนพื้น:

  • วางอักขระจนกว่าคุณจะได้รับ '<'
  • รับอักขระสูงสุด 6 ตัวในบัฟเฟอร์
  • หากอักขระถัดไปคือ > ให้ดำเนินการกับข้อความ
  • รีเซ็ตตัวชี้บัฟเฟอร์แล้วเริ่มใหม่อีกครั้ง