การส่งข้อมูลอนุกรมจำนวนมาก


13

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

ฉันได้พิจารณาแล้วว่าโครงสร้างการส่งอาจเป็นวิธีที่ง่ายกว่าในการส่งข้อมูล ไม่มีใครรู้วิธีอื่นใดที่อาจมีประสิทธิภาพมากขึ้น?

โปรดจำไว้ว่าฉันจะต้องส่งข้อมูลสำหรับมอเตอร์ 4 ตัว, คอมเพรสเซอร์, อุณหภูมิที่แตกต่างกัน, สิ่งที่สุ่มและแขน 3 ส่วน

คำตอบ:


9

ด้วยความคิดส่วนตัวของฉันเกี่ยวกับโครงสร้างเป็นวิธีที่มีประสิทธิภาพมากที่สุดในการส่งตัวแปรที่แตกต่างกันมากมายฉันได้สร้างห้องสมุดขึ้นมาเพื่อช่วยให้ง่ายต่อการส่ง structs และตัวแปรไปตามลำดับ รหัสแหล่งที่มา

ในไลบรารีนี้ทำให้การส่งผ่านอนุกรมทำได้อย่างง่ายดาย ฉันใช้กับฮาร์ดแวร์และซอฟต์แวร์อนุกรม ปกติแล้วสิ่งนี้จะถูกใช้ร่วมกับ xbee's ดังนั้นฉันจึงสามารถส่งข้อมูลแบบไร้สายไปและกลับจากหุ่นยนต์ได้

เมื่อส่งข้อมูลจะทำให้ง่ายขึ้นเพราะช่วยให้คุณสามารถส่งตัวแปรหรือ struct (มันไม่สนใจ)

นี่คือตัวอย่างของการส่งถ่านธรรมดาผ่านอนุกรม:

// Send the variable charVariable over the serial.
// To send the variable you need to pass an instance of the Serial to use,
// a reference to the variable to send, and the size of the variable being sent.
// If you would like you can specify 2 extra arguments at the end which change the
// default prefix and suffix character used when attempting to reconstruct the variable
// on the receiving end. If prefix and suffix character are specified they'll need to 
// match on the receiving end otherwise data won't properly be sent across

char charVariable = 'c'; // Define the variable to be sent over the serial
StreamSend::sendObject(Serial, &charVariable, sizeof(charVariable));

// Specify a prefix and suffix character
StreamSend::sendObject(Serial, &charVariable, sizeof(charVariable), 'a', 'z');

ตัวอย่างของการส่ง int อย่างง่ายผ่านอนุกรม:

int intVariable = 13496; // Define the int to be sent over the serial
StreamSend::sendObject(xbeeSerial, &intVariable, sizeof(intVariable));

// Specify a prefix and suffix character
StreamSend::sendObject(xbeeSerial, &intVariable, sizeof(intVariable), 'j', 'p');

ตัวอย่างของการส่งโครงสร้างผ่านอนุกรม:

// Define the struct to be sent over the serial
struct SIMPLE_STRUCT {
  char charVariable;
  int intVariable[7];
  boolean boolVariable;
};
SIMPLE_STRUCT simpleStruct;
simpleStruct.charVariable = 'z'; // Set the charVariable in the struct to z

// Fill the intVariable array in the struct with numbers 0 through 6
for(int i=0; i<7; i++) {
  simpleStruct.intVariable[i] = i;
}

// Send the struct to the object xbeeSerial which is a software serial that was
// defined. Instead of using xbeeSerial you can use Serial which will imply the
// hardware serial, and on a Mega you can specify Serial, Serial1, Serial2, Serial3.
StreamSend::sendObject(xbeeSerial, &simpleStruct, sizeof(simpleStruct));

// Send the same as above with a different prefix and suffix from the default values
// defined in StreamSend. When specifying when prefix and suffix character to send
// you need to make sure that on the receiving end they match otherwise the data
// won't be able to be read on the other end.
StreamSend::sendObject(xbeeSerial, &simpleStruct, sizeof(simpleStruct), '3', 'u');

รับตัวอย่าง:

รับถ่านที่ถูกส่งผ่าน Streamsend:

char charVariable; // Define the variable on where the data will be put

// Read the data from the Serial object an save it into charVariable once
// the data has been received
byte packetResults = StreamSend::receiveObject(Serial, &charVariable, sizeof(charVariable));

// Reconstruct the char coming from the Serial into charVariable that has a custom
// suffix of a and a prefix of z
byte packetResults = StreamSend::receiveObject(Serial, &charVariable, sizeof(charVariable), 'a', 'z');

การรับ int ที่ถูกส่งผ่าน StreamSend:

int intVariable; // Define the variable on where the data will be put

// Reconstruct the int from xbeeSerial into the variable intVariable
byte packetResults = StreamSend::receiveObject(xbeeSerial, &intVariable, sizeof(intVariable));

// Reconstruct the data into intVariable that was send with a custom prefix
// of j and a suffix of p
byte packetResults = StreamSend::receiveObject(xbeeSerial, &intVariable, sizeof(intVariable), 'j', 'p');

การรับโครงสร้างที่ถูกส่งผ่าน StreamSend:

// Define the struct that the data will be put
struct SIMPLE_STRUCT {
  char charVariable;
  int intVariable[7];
  boolean boolVariable;
};
SIMPLE_STRUCT simpleStruct; // Create a struct to store the data in

// Reconstruct the data from xbeeSerial into the object simpleStruct
byte packetResults = StreamSend::receiveObject(xbeeSerial, &simpleStruct, sizeof(simpleStruct));

// Reconstruct the data from xbeeSerial into the object simplestruct that has
// a prefix of 3 and a suffix of p
byte packetResults = StreamSend::receiveObject(xbeeSerial, &simpleStruct, sizeof(simpleStruct), '3', 'p');

เมื่อคุณอ่านข้อมูลโดยใช้StreamSend::receiveObject()คุณจำเป็นต้องทราบว่าข้อมูลนั้นเป็น GOOD, Not Found หรือ BAD

ดี = สำเร็จ

ไม่พบ = ไม่พบอักขระนำหน้าใน ostream ที่ระบุ

ไม่ถูกต้อง = มีการพบอักขระนำหน้า แต่ข้อมูลไม่ครบถ้วน โดยปกติจะหมายถึงไม่พบอักขระต่อท้ายหรือข้อมูลไม่ได้ขนาดที่ถูกต้อง

การทดสอบความถูกต้องของข้อมูล:

// Once you call StreamSend::receiveObject() it returns a byte of the status of
// how things went. If you run that though some of the testing functions it'll
// let you know how the transaction went
if(StreamSend::isPacketGood(packetResults)) {
  //The Packet was Good
} else {
  //The Packet was Bad
}

if(StreamSend::isPacketCorrupt(packetResults)) {
  //The Packet was Corrupt
} else {
  //The Packet wasn't found or it was Good
}

if(StreamSend::isPacketNotFound(packetResults)) {
  //The Packet was not found after Max # of Tries
} else {
  //The Packet was Found, but can be corrupt
}

SteamSend Class:

#include "Arduino.h"

#ifndef STREAMSEND_H
#define STREAMSEND_H


#define PACKET_NOT_FOUND 0
#define BAD_PACKET 1
#define GOOD_PACKET 2

// Set the Max size of the Serial Buffer or the amount of data you want to send+2
// You need to add 2 to allow the prefix and suffix character space to send.
#define MAX_SIZE 64


class StreamSend {
  private:
    static int getWrapperSize() { return sizeof(char)*2; }
    static byte receiveObject(Stream &ostream, void* ptr, unsigned int objSize, unsigned int loopSize);
    static byte receiveObject(Stream &ostream, void* ptr, unsigned int objSize, unsigned int loopSize, char prefixChar, char suffixChar);
    static char _prefixChar; // Default value is s
    static char _suffixChar; // Default value is e
    static int _maxLoopsToWait;

  public:
    static void sendObject(Stream &ostream, void* ptr, unsigned int objSize);
    static void sendObject(Stream &ostream, void* ptr, unsigned int objSize, char prefixChar, char suffixChar);
    static byte receiveObject(Stream &ostream, void* ptr, unsigned int objSize);
    static byte receiveObject(Stream &ostream, void* ptr, unsigned int objSize, char prefixChar, char suffixChar);
    static boolean isPacketNotFound(const byte packetStatus);
    static boolean isPacketCorrupt(const byte packetStatus);
    static boolean isPacketGood(const byte packetStatus);

    static void setPrefixChar(const char value) { _prefixChar = value; }
    static void setSuffixChar(const char value) { _suffixChar = value; }
    static void setMaxLoopsToWait(const int value) { _maxLoopsToWait = value; }
    static const char getPrefixChar() { return _prefixChar; }
    static const char getSuffixChar() { return _suffixChar; }
    static const int getMaxLoopsToWait() { return _maxLoopsToWait; }

};

//Preset Some Default Variables
//Can be modified when seen fit
char StreamSend::_prefixChar = 's';   // Starting Character before sending any data across the Serial
char StreamSend::_suffixChar = 'e';   // Ending character after all the data is sent
int StreamSend::_maxLoopsToWait = -1; //Set to -1 for size of current Object and wrapper



/**
  * sendObject
  *
  * Converts the Object to bytes and sends it to the stream
  *
  * @param Stream to send data to
  * @param ptr to struct to fill
  * @param size of struct
  * @param character to send before the data stream (optional)
  * @param character to send after the data stream (optional)
  */
void StreamSend::sendObject(Stream &ostream, void* ptr, unsigned int objSize) {
  sendObject(ostream, ptr, objSize, _prefixChar, _suffixChar);
}

void StreamSend::sendObject(Stream &ostream, void* ptr, unsigned int objSize, char prefixChar, char suffixChar) {
  if(MAX_SIZE >= objSize+getWrapperSize()) { //make sure the object isn't too large
    byte * b = (byte *) ptr; // Create a ptr array of the bytes to send
    ostream.write((byte)prefixChar); // Write the suffix character to signify the start of a stream

    // Loop through all the bytes being send and write them to the stream
    for(unsigned int i = 0; i<objSize; i++) {
      ostream.write(b[i]); // Write each byte to the stream
    }
    ostream.write((byte)suffixChar); // Write the prefix character to signify the end of a stream
  }
}

/**
  * receiveObject
  *
  * Gets the data from the stream and stores to supplied object
  *
  * @param Stream to read data from
  * @param ptr to struct to fill
  * @param size of struct
  * @param character to send before the data stream (optional)
  * @param character to send after the data stream (optional)
  */
byte StreamSend::receiveObject(Stream &ostream, void* ptr, unsigned int objSize) {
    return receiveObject(ostream, ptr, objSize, _prefixChar, _suffixChar);
}
byte StreamSend::receiveObject(Stream &ostream, void* ptr, unsigned int objSize, char prefixChar, char suffixChar) {
  return receiveObject(ostream, ptr, objSize, 0, prefixChar, suffixChar);
}

byte StreamSend::receiveObject(Stream &ostream, void* ptr, unsigned int objSize, unsigned int loopSize, char prefixChar, char suffixChar) {
  int maxLoops = (_maxLoopsToWait == -1) ? (objSize+getWrapperSize()) : _maxLoopsToWait;
  if(loopSize >= maxLoops) {
      return PACKET_NOT_FOUND;
  }
  if(ostream.available() >= (objSize+getWrapperSize())) { // Packet meets minimum size requirement
    if(ostream.read() != (byte)prefixChar) {
      // Prefix character is not found
      // Loop through the code again reading the next char
      return receiveObject(ostream, ptr, objSize, loopSize+1, prefixChar, suffixChar);
    }

    char data[objSize]; //Create a tmp char array of the data from Stream
    ostream.readBytes(data, objSize); //Read the # of bytes
    memcpy(ptr, data, objSize); //Copy the bytes into the struct

    if(ostream.read() != (byte)suffixChar) {
      //Suffix character is not found
      return BAD_PACKET;
    }
      return GOOD_PACKET;
  }
  return PACKET_NOT_FOUND; //Prefix character wasn't found so no packet detected
}


boolean StreamSend::isPacketNotFound(const byte packetStatus) {
    return (packetStatus == PACKET_NOT_FOUND);
}

boolean StreamSend::isPacketCorrupt(const byte packetStatus) {
    return (packetStatus == BAD_PACKET);
}

boolean StreamSend::isPacketGood(const byte packetStatus) {
    return (packetStatus == GOOD_PACKET);
}

#endif

3
คำตอบทั้งหมดของรหัสเช่นเดียวกับคำตอบทั้งหมดลิงก์จะหมดกำลังใจ เว้นแต่รหัสของคุณมีตันของความคิดเห็นผมจะแนะนำให้ใส่คำอธิบายของสิ่งที่เกิดขึ้นบาง
TheDoctor

@TheDoctor ฉันได้อัปเดตรหัสแล้ว ควรมีความคิดเห็นเพิ่มเติมในตอนนี้
Steven10172

1

หากคุณต้องการส่งอย่างรวดเร็วจริงๆ ฉันขอแนะนำ Full Duplex Serial (FDX) มันเป็นโปรโตคอลเดียวกันกับที่ USB และอีเธอร์เน็ตใช้และมันเร็วกว่า UART มาก ข้อเสียคือมันมักจะต้องใช้ฮาร์ดแวร์ภายนอกเพื่ออำนวยความสะดวกในอัตราข้อมูลสูง ฉันได้ยินมาว่าซอฟต์แวร์ใหม่ส่วนสนับสนุนรองรับ FDX แต่อาจช้ากว่าฮาร์ดแวร์ UART สำหรับข้อมูลเพิ่มเติมเกี่ยวกับโปรโตคอลการสื่อสารดูวิธีการเชื่อมต่อ Arduino สองตัวที่ไม่มีตัวป้องกันได้อย่างไร


เสียงนี้น่าสนใจ ฉันจะต้องดูต่อไป
Steven10172

" ฟูลดูเพล็กซ์อนุกรม " จะเป็น "เร็วกว่า UART มาก" ในความเป็นจริงแล้วการสื่อสาร UART มาตรฐานเป็นอย่างไร
David Cary

UART เป็นการสื่อสารที่มีอัตราคงที่ FDX ส่งข้อมูลเร็วที่สุดและส่งข้อมูลที่ไม่ได้ทำอีกครั้ง
TheDoctor

ฉันชอบที่จะหาข้อมูลเพิ่มเติมเกี่ยวกับโปรโตคอลนี้ คุณสามารถเพิ่มลิงค์ไปยังคำตอบของคุณที่อธิบายถึงโปรโตคอลที่เร็วกว่า UART ได้หรือไม่? คุณกำลังพูดถึงแนวคิดทั่วไปเกี่ยวกับคำขอทำซ้ำอัตโนมัติโดยใช้ACK-NAKหรือมีโปรโตคอลเฉพาะที่คุณนึกไว้หรือไม่? ดูเหมือนว่าไม่มี Google ในการค้นหา "FDX" หรือ "full duplex serial" ที่ตรงกับคำอธิบายของคุณ
David Cary

1

การส่งโครงสร้างนั้นค่อนข้างง่าย

คุณสามารถประกาศโครงสร้างตามปกติแล้วใช้ memcpy (@ myStruct, @ myArray) เพื่อคัดลอกข้อมูลไปยังตำแหน่งใหม่จากนั้นใช้สิ่งที่คล้ายกับรหัสด้านล่างเพื่อเขียนข้อมูลเป็น datastream

unsigned char myArraySender[##];   //make ## large enough to fit struct
memcpy(&myStruct,&myArraySender);  //copy raw data from struct to the temp array
digitalWrite(frameStartPin,High);  //indicate to receiver that data is coming
serial.write(sizeof myStruct);     //tell receiver how many bytes to rx
Serial.write(&myArraySender,sizeof myStruct);   //write bytes
digitalWrite)frameStartPin,Low);   //done indicating transmission 

จากนั้นคุณสามารถแนบรูทีนการขัดจังหวะเข้ากับหมุดบนอุปกรณ์อื่นที่ทำสิ่งต่อไปนี้:

volatile unsigned char len, tempBuff[##];   
//volatile because the interrupt will not happen at predictable intervals.

attachInterrupt(0,readSerial,Rising);  

// บอก mcu ให้เรียก fxn เมื่อ pinhigh สิ่งนี้จะเกิดขึ้นในช่วงเวลาใดก็ได้ หากไม่ต้องการลบออกขัดจังหวะและเพียงแค่มองหาตัวละครใหม่ในห่วงผู้บริหารหลักของคุณ (หรือที่เรียกว่าการสำรวจ UART)

void readSerial(unsigned char *myArrayReceiver){
    unsigned char tempbuff[sizeof myArrayReceiver];
    while (i<(sizeof myArrayReceiver)) tempBuff[i]=Serial.read();
    memcpy(&tempbuff,&myArrayReceiver);
    Serial.flush();
}

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

การใช้ bitfields ก็จะใช้งานได้เช่นกันโปรดทราบว่าไส้ปากกาจะดูเหมือนถอยหลัง ตัวอย่างเช่นการพยายามเขียน 0011 1101 อาจส่งผลให้ 1101 0011 ปรากฏที่ปลายอีกด้านหนึ่งหากเครื่องจักรต่างกันตามลำดับไบต์

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


1

หากคุณสามารถทนต่อปริมาณข้อมูลการดีบัก communicatons นั้นง่ายกว่ามากเมื่อส่งสตริงมากกว่าเมื่อส่งไบนารี sprintf () / sscanf () และตัวแปรของพวกเขาคือเพื่อนของคุณที่นี่ ล้อมรอบการสื่อสารในฟังก์ชั่นเฉพาะในโมดูลของตนเอง (ไฟล์. cpp) หากคุณต้องการเพิ่มประสิทธิภาพของช่องสัญญาณในภายหลัง - หลังจากคุณมีระบบที่ใช้งานได้ - คุณสามารถแทนที่โมดูลที่ใช้สตริงเป็นรหัสเดียวสำหรับข้อความขนาดเล็ก

คุณจะทำจำนวนมากในชีวิตของคุณง่ายขึ้นถ้าคุณยึดแน่นกับรายละเอียดโปรโตคอลในการส่งและการแปลความหมายของพวกเขามากขึ้นอย่างอิสระในการรับเรื่องเกี่ยวกับความกว้างของเขตข้อมูล, ตัวคั่นปลายเส้นศูนย์ไม่มีนัยสำคัญการปรากฏตัวของ+สัญญาณ ฯลฯ


แต่เดิมรหัสนั้นถูกเขียนขึ้นเพื่อส่งข้อมูลกลับในวงเสถียรภาพของ Quadcopter ดังนั้นจึงต้องรวดเร็ว
Steven10172

0

ฉันไม่มีหนังสือรับรองอย่างเป็นทางการที่นี่ แต่จากประสบการณ์ของฉันสิ่งต่าง ๆ ได้ค่อนข้างมีประสิทธิภาพเมื่อฉันเลือกตำแหน่งอักขระบางตัวเพื่อควบคุมสถานะของตัวแปรเพื่อที่คุณจะได้กำหนดตัวอักษรสามตัวแรกเป็นอุณหภูมิและถัดไป สามเป็นมุมของเซอร์โวและอื่น ๆ ในตอนท้ายของการส่งฉันจะบันทึกตัวแปรแยกจากกันแล้วรวมเข้าด้วยกันเป็นสตริงเพื่อส่งตามลำดับ ในตอนท้ายที่ได้รับฉันจะมีสตริงที่แยกออกจากกันรับตัวละครสามตัวแรกและเปลี่ยนเป็นสิ่งที่ฉันต้องการตัวแปรประเภทจากนั้นทำเช่นนั้นอีกครั้งเพื่อให้ได้ค่าตัวแปรต่อไป ระบบนี้จะทำงานได้ดีที่สุดเมื่อคุณทราบจำนวนอักขระที่แน่นอนแต่ละตัวที่จะใช้และคุณจะมองหาตัวแปรเดียวกัน (ซึ่งฉันหวังว่าจะได้รับ) ทุกครั้งที่ข้อมูลอนุกรมวนซ้ำ

คุณสามารถเลือกตัวแปรหนึ่งตัวที่จะใส่ความยาวไม่ จำกัด ระยะสุดท้ายจากนั้นรับตัวแปรนั้นจากตัวอักษรตัวแรกไปยังจุดสิ้นสุดของสตริง จริงอยู่ที่สตริงข้อมูลอนุกรมอาจยาวมากขึ้นอยู่กับชนิดตัวแปรและจำนวนเต็มที่ของมัน แต่นี่คือระบบที่ฉันใช้และจนถึงตอนนี้ความพ่ายแพ้เพียงอย่างเดียวที่ฉันได้รับคือความยาวอนุกรมดังนั้นนั่นเป็นข้อเสียเดียวของฉัน รู้


คุณใช้ฟังก์ชั่นประเภทใดในการบันทึกจำนวน x ของอักขระลงใน int / float / char?
Steven10172

1
คุณอาจไม่ทราบเรื่องนี้ แต่สิ่งที่คุณอธิบายเป็นว่าวิธีการที่structจะจัดในหน่วยความจำ (ไม่คำนึงถึง padding) และผมคิดว่าฟังก์ชั่นการถ่ายโอนข้อมูลที่คุณใช้จะคล้ายกับคนที่กล่าวถึงในคำตอบของสตีเฟน
asheeshr

@AsheeshR จริง ๆ แล้วฉันมีความรู้สึกเป็นโครงสร้างอาจเป็นแบบนั้น แต่โดยส่วนตัวแล้วฉันมักจะตีกำแพงเมื่อพยายามฟอร์แมตโครงสร้างอีกครั้งแล้วอ่านพวกเขาอีกด้านหนึ่ง นั่นคือเหตุผลที่ฉันคิดว่าฉันจะทำสิ่งนี้เพื่อให้ฉันสามารถแก้จุดบกพร่องได้อย่างง่ายดายหากสิ่งที่ได้อ่านผิดและเพื่อให้ฉันสามารถอ่านข้อมูลอนุกรมตัวเองถ้าฉันกำหนดเช่น "MOTORa023 MOTORb563" และอื่น ๆ โดยไม่ต้อง ช่องว่าง
Newbie97

@ Steven10172 ดีฉันยอมรับว่าฉันไม่ได้ติดตามฟังก์ชั่นที่เฉพาะเจาะจง แต่ฉัน google ฟังก์ชั่นเฉพาะในแต่ละครั้ง สตริง int, String ลอยและสตริงถ่าน โปรดจำไว้ว่าฉันใช้วิธีการเหล่านี้ใน c ++ ปกติและยังไม่ได้ลองใน Arduino IDE ด้วยตัวเอง
Newbie97

0

ส่งข้อมูล struct ข้ามอนุกรม

ไม่มีอะไรแฟนซี ส่ง struct มันใช้อักขระเลี่ยง '^' เพื่อกำหนดเขตข้อมูล

รหัส Arduino

typedef struct {
 float ax1;
 float ay1;
 float az1;
 float gx1;
 float gy1;
 float gz1;
 float ax2;
 float ay2;
 float az2;
 float gx2;
 float gy2;
 float gz2;

} __attribute__((__packed__))data_packet_t;

data_packet_t dp;

template <typename T> void sendData(T data)
{
 unsigned long uBufSize = sizeof(data);
 char pBuffer[uBufSize];

 memcpy(pBuffer, &dp, uBufSize);
 Serial.write('^');
 for(int i = 0; i<uBufSize;i++) {
   if(pBuffer[i] == '^')
   {
    Serial.write('^');
    }
   Serial.write(pBuffer[i]);
 }
}
void setup() {
  Serial.begin(57600);
}
void loop(){
dp.ax1 = 0.03; // Note that I didn't fill in the others. Too much work. ;p
sendData<data_packet_t>(dp);
}

รหัสหลาม:

import serial
from  copy import copy
from struct import *


ser = serial.Serial(
#   port='/dev/cu.usbmodem1412',
  port='/dev/ttyUSB0',
#     port='/dev/cu.usbserial-AL034MCJ',
    baudrate=57600
)



def get_next_data_block(next_f):
    if not hasattr(get_next_data_block, "data_block"):
        get_next_data_block.data_block = []
    while (1):
        try:
            current_item = next_f()
            if current_item == '^':
                next_item = next_f()
                if next_item == '^':
                    get_next_data_block.data_block.append(next_item)
                else:
                    out = copy(get_next_data_block.data_block)
                    get_next_data_block.data_block = []
                    get_next_data_block.data_block.append(next_item)
                    return out
            else:
                get_next_data_block.data_block.append(current_item)
        except :
            break


for i in range(1000): # just so that the program ends - could be in a while loop
    data_ =  get_next_data_block(ser.read)
    try:
        print unpack('=ffffffffffff', ''.join(data_))
    except:
        continue
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.