From d1fc5d67223c23d1b27374a0424684cbfdb3e951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Grome=C5=A1?= Date: Sun, 23 Sep 2018 18:56:53 +0200 Subject: [PATCH] [XBee] Optimized UART communication --- src/modules/XBee.cpp | 63 ++++++++++++++++++++++++++------------------ src/modules/XBee.h | 2 ++ 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/modules/XBee.cpp b/src/modules/XBee.cpp index 1aeb87e8..a7f77218 100644 --- a/src/modules/XBee.cpp +++ b/src/modules/XBee.cpp @@ -22,17 +22,7 @@ int16_t XBee::begin(long speed) { _mod->init(USE_UART, INT_NONE); // reset module - pinMode(_mod->int1(), OUTPUT); - delay(10); - digitalWrite(_mod->int1(), HIGH); - delay(500); - digitalWrite(_mod->int1(), LOW); - delay(500); - pinMode(_mod->int1(), INPUT); - delay(500); - - // wait for boot - delay(3000); + reset(); // empty UART buffer (garbage data) _mod->ATemptyBuffer(); @@ -40,7 +30,6 @@ int16_t XBee::begin(long speed) { // send test frame (get baudrate setting) uint8_t frameID = _frameID++; sendApiFrame(XBEE_API_FRAME_AT_COMMAND_QUEUE, frameID, "BD"); - delay(20); // get response code int16_t state = readApiFrame(frameID, 4); @@ -51,6 +40,17 @@ int16_t XBee::begin(long speed) { return(state); } +void XBee::reset() { + pinMode(_mod->int1(), OUTPUT); + delay(10); + digitalWrite(_mod->int1(), HIGH); + delay(500); + digitalWrite(_mod->int1(), LOW); + delay(500); + pinMode(_mod->int1(), INPUT); + delay(500); +} + int16_t XBee::transmit(uint8_t* dest, const char* payload, uint8_t radius) { uint8_t destNetwork[] = {0xFF, 0xFE}; return(transmit(dest, destNetwork, payload, radius)); @@ -71,7 +71,6 @@ int16_t XBee::transmit(uint8_t* dest, uint8_t* destNetwork, const char* payload, uint8_t frameID = _frameID++; sendApiFrame(XBEE_API_FRAME_ZIGBEE_TRANSMIT_REQUEST, frameID, cmd, dataLen); delete[] cmd; - delay(40); // get response code return(readApiFrame(frameID, 5)); @@ -149,7 +148,6 @@ int16_t XBee::setPanId(uint8_t* panId) { // send frame uint8_t frameID = _frameID++; sendApiFrame(XBEE_API_FRAME_AT_COMMAND_QUEUE, frameID, cmd, 10); - delay(40); // get response code int16_t state = readApiFrame(frameID, 4); @@ -195,6 +193,17 @@ int16_t XBeeSerial::begin(long speed) { return(ERR_NONE); } +void XBeeSerial::reset() { + pinMode(_mod->int1(), OUTPUT); + delay(10); + digitalWrite(_mod->int1(), HIGH); + delay(500); + digitalWrite(_mod->int1(), LOW); + delay(500); + pinMode(_mod->int1(), INPUT); + delay(500); +} + int16_t XBeeSerial::setDestinationAddress(const char* destinationAddressHigh, const char* destinationAddressLow) { // enter command mode DEBUG_PRINTLN_STR("Entering command mode ..."); @@ -277,14 +286,7 @@ bool XBeeSerial::enterCmdMode() { DEBUG_PRINT(i + 1); DEBUG_PRINTLN_STR(" of 10 tries)"); - pinMode(_mod->int1(), OUTPUT); - delay(10); - digitalWrite(_mod->int1(), HIGH); - delay(500); - digitalWrite(_mod->int1(), LOW); - delay(500); - pinMode(_mod->int1(), INPUT); - delay(500); + reset(); _mod->ATsendCommand("ATCN"); } @@ -298,7 +300,6 @@ int16_t XBee::confirmChanges() { // save changes to non-volatile memory uint8_t frameID = _frameID++; sendApiFrame(XBEE_API_FRAME_AT_COMMAND_QUEUE, frameID, "WR"); - delay(40); // get response code int16_t state = readApiFrame(frameID, 4); @@ -309,7 +310,6 @@ int16_t XBee::confirmChanges() { // apply changes frameID = _frameID++; sendApiFrame(XBEE_API_FRAME_AT_COMMAND_QUEUE, frameID, "AC"); - delay(40); // get response code state = readApiFrame(frameID, 4); @@ -354,8 +354,9 @@ void XBee::sendApiFrame(uint8_t type, uint8_t id, uint8_t* data, uint16_t length int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos) { // TODO: modemStatus frames may be sent at any time, interfering with frame parsing. Add check to make sure this does not happen. - // get number of bytes in response - uint16_t numBytes = getNumBytes(10000, 5); + + // get number of bytes in response (must be enough to read the length field + uint16_t numBytes = getNumBytes(5000, 3); if(numBytes == 0) { return(ERR_FRAME_MALFORMED); } @@ -363,6 +364,14 @@ int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos) { // checksum byte is not included in length field numBytes++; + // wait until all response bytes are available (5s timeout) + uint32_t start = millis(); + while(_mod->ModuleSerial->available() < numBytes) { + if(millis() - start >= 5000) { + return(ERR_FRAME_MALFORMED); + } + } + // read the response uint8_t* resp = new uint8_t[numBytes]; for(uint16_t i = 0; i < numBytes; i++) { @@ -375,11 +384,13 @@ int16_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos) { checksum += resp[i]; } if(checksum != 0xFF) { + DEBUG_PRINTLN_HEX(checksum); return(ERR_FRAME_INCORRECT_CHECKSUM); } // check frame ID if(resp[1] != frameID) { + DEBUG_PRINTLN(resp[1]); return(ERR_FRAME_UNEXPECTED_ID); } diff --git a/src/modules/XBee.h b/src/modules/XBee.h index 200786ec..fad8d235 100644 --- a/src/modules/XBee.h +++ b/src/modules/XBee.h @@ -38,6 +38,7 @@ class XBeeSerial: public ISerial { // basic methods int16_t begin(long speed); + void reset(); // configuration methods int16_t setDestinationAddress(const char* destinationAddressHigh, const char* destinationAddressLow); @@ -55,6 +56,7 @@ class XBee { // basic methods int16_t begin(long speed); + void reset(); int16_t transmit(uint8_t* dest, const char* payload, uint8_t radius = 1); int16_t transmit(uint8_t* dest, uint8_t* destNetwork, const char* payload, uint8_t radius = 1); size_t available();