LowPowerLab Forum

Hardware support => Moteino => Topic started by: bobleponge on June 14, 2014, 10:31:52 AM

Title: [SOLVED] Long ACK with RF69(H)W
Post by: bobleponge on June 14, 2014, 10:31:52 AM
Hi,

  I'm experiencing long delay for 2 moteino for sending and getting back an ACK.
Typically, the histogram for the send + waitACK is like this:

The code for the gateway is like this:

void setup()
{
  Serial.begin(SERIAL_BAUD);

#ifndef NRADIO
  radio.initialize(FREQUENCY, NODEID, NETWORKID);
  radio.setHighPower(); //uncomment only for RFM69HW! -- GW is RFM69HW
  radio.encrypt(ENCRYPTKEY);
  radio.sleep();
#endif
}

void loop()
{
  if (radio.receiveDone())
  {
    if (radio.ACK_REQUESTED)
    {
      radio.sendACK();
    }
  }
}


The testing code does that:

void setup()
{
  pinMode(LED, OUTPUT);
  Serial.begin(115200);
  radio.initialize(RF69_915MHZ, NODEID, NETWORKID);
  radio.encrypt(KEY);
  radio.sleep(); //sleep right away to save power
  Serial.println("JPB Test Transmitting...\n\n");
  for (int i=0;i<MAX_SEND;i++) {
    retryHist[i]=0;  // initialize retries histogram to 0
  }
}

void loop()
{
  long ackTime;  // time between TX and RX of ACK

  digitalWrite(LED,HIGH);
  Serial.print("Sending[");
  Serial.print(sendSize+1);
  Serial.print("]:");
 
  requestACK = true;    // Pay attention. Everything I say is important :-)
  unsigned short retries = 0; 

  long sendTime = millis();
  unsigned short slots = 1;
  radio.send(GATEWAYID, payload, sendSize+1, requestACK);
  totalPackets++;
  if (requestACK)
  {
    Serial.print(" - wait ");
    unsigned char timeout = 9 + (sendSize+1)/4; //12 + (sendSize+1)/4;  // Actual: 1 char = 10 msec, 88 characters = 33 msec
    Serial.print(timeout);
    while (!waitForAck(timeout) && (retries < RETRY_LIMIT)) {
      retries++;
    }
    ackTime = millis() - sendTime;
    if (retries < RETRY_LIMIT) {
      Serial.print(" On try ");
      Serial.print(retries+1);
      Serial.print(" ACK after ");
    } else {
      Serial.print(" No ACK after ");
    }
  }
  digitalWrite(LED,LOW);
  totalRetries += retries;
  retryHist[sendSize] += ackTime;  // record retry count in histogram
  Serial.print(ackTime);   Serial.print(" msec. Packets: ");
  Serial.print(totalPackets);   Serial.print(" Retries: ");
  Serial.print(totalRetries);
 
  sendSize = (sendSize + 1) % MAX_SEND;
  Serial.println();
  if (!(totalPackets % 50)) {
      for (int i=0;i<MAX_SEND;i++) {
        Serial.print(i+1);
        Serial.print(",");
        Serial.println(retryHist[i]);  // print how many total retries for each packet length
      }
  }
  delay(interPacketDelay);   // low power sleep mode?
}

// wait a few milliseconds for proper ACK, return true if received
static bool waitForAck(unsigned char timeout) {
  long now = millis();
  while (millis() - now <= timeout)
    if (radio.ACKReceived(GATEWAYID))
      return true;
  return false;
}


The RFM69 lib has this config (extract from Felix's Github)

#define  RF_BITRATEMSB_CUSTOM  0x2e
#define  RF_BITRATELSB_CUSTOM  0x66


  const byte CONFIG[][2] =
  {
    /* 0x01 */ { REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY },
    /* 0x02 */ { REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 }, //no shaping
    /* 0x03 */ { REG_BITRATEMSB, RF_BITRATEMSB_CUSTOM },
    /* 0x04 */ { REG_BITRATELSB, RF_BITRATELSB_CUSTOM },
    /* 0x05 */ { REG_FDEVMSB, RF_FDEVMSB_90000 }, //default:90khz, (FDEV + BitRate/2 <= 500Khz)
    /* 0x06 */ { REG_FDEVLSB, RF_FDEVLSB_90000 },

    /* 0x07 */ { REG_FRFMSB, (freqBand==RF69_315MHZ ? RF_FRFMSB_315 : (freqBand==RF69_433MHZ ? RF_FRFMSB_433 : (freqBand==RF69_868MHZ ? RF_FRFMSB_868 : RF_FRFMSB_915))) },
    /* 0x08 */ { REG_FRFMID, (freqBand==RF69_315MHZ ? RF_FRFMID_315 : (freqBand==RF69_433MHZ ? RF_FRFMID_433 : (freqBand==RF69_868MHZ ? RF_FRFMID_868 : RF_FRFMID_915))) },
    /* 0x09 */ { REG_FRFLSB, (freqBand==RF69_315MHZ ? RF_FRFLSB_315 : (freqBand==RF69_433MHZ ? RF_FRFLSB_433 : (freqBand==RF69_868MHZ ? RF_FRFLSB_868 : RF_FRFLSB_915))) },
   
    // looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm
    // +17dBm and +20dBm are possible on RFM69HW
    // +13dBm formula: Pout=-18+OutputPower (with PA0 or PA1**)
    // +17dBm formula: Pout=-14+OutputPower (with PA1 and PA2)**
    // +20dBm formula: Pout=-11+OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet)
    ///* 0x11 */ { REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111},
    ///* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, //over current protection (default is 95mA)
   
    ///* 0x18*/ { REG_LNA,  RF_LNA_ZIN_200 | RF_LNA_CURRENTGAIN }, //as suggested by mav here: http://lowpowerlab.com/forum/index.php/topic,296.msg1571.html
   
    // RXBW defaults are { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5} (RxBw: 10.4khz)
    /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2 }, //(BitRate < 2 * RxBw)
    /* 0x25 */ { REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01 }, //DIO0 is the only IRQ we're using
    /* 0x28 */ { REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN }, // Writing to this bit ensures the FIFO & status flags are reset
    /* 0x29 */ { REG_RSSITHRESH, 220 }, //must be set to dBm = (-Sensitivity / 2) - default is 0xE4=228 so -114dBm
    ///* 0x2d */ { REG_PREAMBLELSB, RF_PREAMBLESIZE_LSB_VALUE } // default 3 preamble bytes 0xAAAAAA
    /* 0x2e */ { REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0 },
    /* 0x2f */ { REG_SYNCVALUE1, 0x2D },      //attempt to make this compatible with sync1 byte of RFM12B lib
    /* 0x30 */ { REG_SYNCVALUE2, networkID }, //NETWORK ID
    /* 0x37 */ { REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_ON | RF_PACKET1_CRCAUTOCLEAR_ON | RF_PACKET1_ADRSFILTERING_NODEBROADCAST },
    /* 0x38 */ { REG_PAYLOADLENGTH, 66 }, //in variable length mode: the max frame size, not used in TX
    /* 0x39 */ { REG_NODEADRS, nodeID }, //address filtering
    /* 0x3a */ { REG_BROADCASTADRS, 0 }, //0 is the broadcast address
    /* 0x3C */ { REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE }, //TX on FIFO not empty
    /* 0x3d */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, //RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent)
    /* 0x6F */ { REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0 }, // run DAGC continuously in RX mode, recommended default for AfcLowBetaOn=0
    {255, 0}
  };



The 2 board (one in RFM69W and the GW in RFM69HW) are 10cm apart (tried even less, 2cm, with exactly the same results).
I've built the code with Arduino IDE, board selected as Arduino UNO
Do you have any idea why I need to wait so long for an ACK ?
Please notice that I'm not resending the data, since I'm receiving it on the GW (In another try, I've added serial debug in the GW to show every packet received, but to eliminate any slow down on the GW to send back the ACK, I've removed all logs)
Title: Re: Long ACK with RF69(H)W
Post by: Felix on June 14, 2014, 08:27:09 PM
Could you please try the Node / Gateway examples and see if you are having the same symptoms: https://github.com/LowPowerLab/RFM69/tree/master/Examples
Title: Re: Long ACK with RF69(H)W
Post by: bobleponge on June 16, 2014, 02:30:56 AM
Yes I have the same issue (unless I set 150ms for the sendWithRetry function's timeout).
Also, there is no need to retry in my case, the first packet is received from the other end.

However, I've checked with the preprogrammed moteino you've sent me, and they do work correctly without such long ACK.
So I've double checked everything, I finally found the culprit. I don't know exactly why, but the RFM69.{h/cpp} files I was using were not the latest from GitHub. It seems like my bitrate was so low anyway that the ACK came longer after.

So the issue is solved, thanks for your support.
Title: Re: [SOLVED] Long ACK with RF69(H)W
Post by: Felix on June 16, 2014, 08:27:24 AM
Right, the 150ms delay was not making a lot of sense. What I mean is that a packet sent by the receiver will arrive a few ms, which led me to believe that your radio was retrying hard to send and only after so long it was able to get through. Glad you found the issue, using the latest code is always a good idea.