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:
- From 1 to 14 bytes msg I need to wait 150ms to get back an ACK
- From 15 to 30 bytes msg I need to wait 199ms to get back an ACK
- From 31 to 46 bytes msg I need to wait 246ms to get back an ACK
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)
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
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.
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.