Weird protocol version mismatch
-
-
OK, did some more troubleshooting.
- Confirmed that using a Moteino has exactly the same result with the previous code
- I added the basic send/receive debugging in the RFM69_new.cpp on both the Arduino side and the Raspberry Pi side:
LOCAL uint8_t RFM69_receive(uint8_t *buf, const uint8_t maxBufSize) { const uint8_t payloadLen = min(RFM69.currentPacket.payloadLen, maxBufSize); const uint8_t sender = RFM69.currentPacket.header.sender; const rfm69_sequenceNumber_t sequenceNumber = RFM69.currentPacket.header.sequenceNumber; const uint8_t controlFlags = RFM69.currentPacket.header.controlFlags; const rfm69_RSSI_t RSSI = RFM69.currentPacket.RSSI; DEBUG_OUTPUT(PSTR("LEN=%" PRIu8 ",DST=%" PRIu8 ",VER=%" PRIu8 ",SND=%" PRIu8 ",FLG=%" PRIu8 ",SEQ=%" PRIu8 "\n"), (int)RFM69.currentPacket.header.packetLen, (int)RFM69.currentPacket.header.recipient, (int)RFM69.currentPacket.header.version, (int)RFM69.currentPacket.header.sender, (int)RFM69.currentPacket.header.controlFlags, (int)RFM69.currentPacket.header.sequenceNumber); if (buf != NULL) { (void)memcpy((void *)buf, (void *)&RFM69.currentPacket.payload, payloadLen); } // clear data flag RFM69.dataReceived = false; if (RFM69_getACKRequested(controlFlags) && !RFM69_getACKReceived(controlFlags)) { #if defined(MY_GATEWAY_FEATURE) && (F_CPU>16*1000000ul) // delay for fast GW and slow nodes delay(50); #endif RFM69_sendACK(sender, sequenceNumber, RSSI); } return payloadLen; }and
LOCAL bool RFM69_sendFrame(rfm69_packet_t *packet, const bool increaseSequenceCounter) { // ensure we are in RX for correct RSSI sampling, dirty hack to enforce rx restart :) RFM69.radioMode = RFM69_RADIO_MODE_STDBY; (void)RFM69_setRadioMode(RFM69_RADIO_MODE_RX); delay(1); // timing for correct RSSI sampling const uint32_t CSMA_START_MS = hwMillis(); while (!RFM69_channelFree() && ((hwMillis() - CSMA_START_MS) < MY_RFM69_CSMA_TIMEOUT_MS)) { doYield(); } // set radio to standby to load fifo (void)RFM69_setRadioMode(RFM69_RADIO_MODE_STDBY); if (increaseSequenceCounter) { // increase sequence counter, overflow is ok RFM69.txSequenceNumber++; } // clear FIFO and flags RFM69_clearFIFO(); // assign sequence number packet->header.sequenceNumber = RFM69.txSequenceNumber; DEBUG_OUTPUT(PSTR("LEN=%" PRIu8 ",DST=%" PRIu8 ",VER=%" PRIu8 ",SND=%" PRIu8 ",FLG=%" PRIu8 ",SEQ=%" PRIu8 "\n"), (int)packet->header.packetLen, (int)packet->header.recipient, (int)packet->header.version, (int)packet->header.sender, (int)packet->header.controlFlags, (int)packet->header.sequenceNumber); // write packet const uint8_t finalLen = packet->payloadLen + RFM69_HEADER_LEN; // including length byte (void)RFM69_burstWriteReg(RFM69_REG_FIFO, packet->data, finalLen); // send message (void)RFM69_setRadioMode(RFM69_RADIO_MODE_TX); // irq upon txsent const uint32_t txStartMS = hwMillis(); while (!RFM69_irq && (hwMillis() - txStartMS < MY_RFM69_TX_TIMEOUT_MS)) { doYield(); }; return RFM69_irq; }On the Arduino (Moteino) side I removed the MY_DEBUG_VERBOSE_RFM69 define to reduce the debug output and changed node ID to 99:
__ __ ____ | \/ |_ _/ ___| ___ _ __ ___ ___ _ __ ___ | |\/| | | | \___ \ / _ \ `_ \/ __|/ _ \| `__/ __| | | | | |_| |___| | __/ | | \__ \ _ | | \__ \ |_| |_|\__, |____/ \___|_| |_|___/\___/|_| |___/ |___/ 2.3.2 16 MCO:BGN:INIT NODE,CP=RPNNA---,FQ=16,REL=255,VER=2.3.2 26 TSM:INIT 28 TSF:WUR:MS=0 29 TSM:INIT:TSP OK 31 TSM:INIT:STATID=99 33 TSF:SID:OK,ID=99 35 TSM:FPAR 537 LEN=12,DST=255,VER=1,SND=99,FLG=32,SEQ=1 544 ?TSF:MSG:SEND,99-99-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK: 2551 !TSM:FPAR:NO REPLY 2553 TSM:FPAR 3055 LEN=12,DST=255,VER=1,SND=99,FLG=32,SEQ=2 3062 ?TSF:MSG:SEND,99-99-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK: 5069 !TSM:FPAR:NO REPLY 5071 TSM:FPAR 5112 LEN=12,DST=255,VER=1,SND=99,FLG=32,SEQ=3 5120 ?TSF:MSG:SEND,99-99-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK: 7128 !TSM:FPAR:NO REPLY 7130 TSM:FPAR 7171 LEN=12,DST=255,VER=1,SND=99,FLG=32,SEQ=4 7178 ?TSF:MSG:SEND,99-99-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK: 9186 !TSM:FPAR:FAIL 9187 TSM:FAIL:CNT=1 9189 TSM:FAIL:DIS 9191 TSF:TDI:TSLThe mysgw output for those exact messages:
May 24 19:52:54 DEBUG THA:DATA:AVAIL May 24 19:52:54 DEBUG LEN=12,DST=255,VER=99,SND=32,FLG=1,SEQ=99 May 24 19:52:54 DEBUG THA:RCV:MSG=63FF020307FF00 May 24 19:52:54 DEBUG !THA:RCV:PVER=3 May 24 19:52:57 DEBUG THA:DATA:AVAIL May 24 19:52:57 DEBUG LEN=12,DST=255,VER=99,SND=32,FLG=2,SEQ=99 May 24 19:52:57 DEBUG THA:RCV:MSG=63FF020307FF00 May 24 19:52:57 DEBUG !THA:RCV:PVER=3 May 24 19:52:59 DEBUG THA:DATA:AVAIL May 24 19:52:59 DEBUG LEN=12,DST=255,VER=99,SND=32,FLG=3,SEQ=99 May 24 19:52:59 DEBUG THA:RCV:MSG=63FF020307FF00 May 24 19:52:59 DEBUG !THA:RCV:PVER=3 May 24 19:53:01 DEBUG THA:DATA:AVAIL May 24 19:53:01 DEBUG LEN=12,DST=255,VER=99,SND=32,FLG=4,SEQ=99 May 24 19:53:01 DEBUG THA:RCV:MSG=63FF020307FF00 May 24 19:53:01 DEBUG !THA:RCV:PVER=3So there is some kind of misalignment in the message header. Is there some setting that modifies the header, like maybe a meshing flag or mode? I quickly lost my way digging in the lower level transport abstractions. I'm also convinced that there is some setting that I'm not using correctly. More than happy to try whatever anyone can come up.
BTW I did a completely clean install of the MySensors github files on the Pi and modified only the RFM69_new.cpp file after that. -
Success!! At least progress. After stuffing around with more debug output on the gateway side it seems to me that the linux specific code in the RFM69_interruptHandling function is not quite correct. In fact disabling it and using the standard non-linux code works fine. At least in terms of the parent registration (small steps here). If I change that function as follows:
LOCAL void RFM69_interruptHandling(void) { const uint8_t regIrqFlags2 = RFM69_readReg(RFM69_REG_IRQFLAGS2); if (RFM69.radioMode == RFM69_RADIO_MODE_RX && (regIrqFlags2 & RFM69_IRQFLAGS2_PAYLOADREADY)) { (void)RFM69_setRadioMode(RFM69_RADIO_MODE_STDBY); // use the fifo level irq as indicator if header bytes received if (regIrqFlags2 & RFM69_IRQFLAGS2_FIFOLEVEL) { RFM69_prepareSPITransaction(); RFM69_csn(LOW); //#if defined(__linux__) // char data[RFM69_MAX_PACKET_LEN + 1]; // max packet len + 1 byte for the command // data[0] = RFM69_REG_FIFO & RFM69_READ_REGISTER; // RFM69_SPI.transfern(data, RFM69_HEADER_LEN+1); //3); // RFM69.currentPacket.header.packetLen = data[1]; // RFM69.currentPacket.header.recipient = data[2]; // // if (RFM69.currentPacket.header.packetLen > RFM69_MAX_PACKET_LEN) { // RFM69.currentPacket.header.packetLen = RFM69_MAX_PACKET_LEN; // } // // data[0] = RFM69_REG_FIFO & RFM69_READ_REGISTER; // //SPI.transfern(data, RFM69.currentPacket.header.packetLen - 1); //TODO: Wrong packetLen? // RFM69_SPI.transfern(data, RFM69.currentPacket.header.packetLen); // // //(void)memcpy((void *)&RFM69.currentPacket.data[2], (void *)&data[1], RFM69.currentPacket.header.packetLen - 2); //TODO: Wrong packetLen? // (void)memcpy((void *)&RFM69.currentPacket.data[2], (void *)&data[1], // RFM69.currentPacket.header.packetLen - 1); // // if (RFM69.currentPacket.header.version >= RFM69_MIN_PACKET_HEADER_VERSION) { // RFM69.currentPacket.payloadLen = min(RFM69.currentPacket.header.packetLen - (RFM69_HEADER_LEN - 1), // RFM69_MAX_PACKET_LEN); // RFM69.ackReceived = RFM69_getACKReceived(RFM69.currentPacket.header.controlFlags); // RFM69.dataReceived = !RFM69.ackReceived; // } //#else (void)RFM69_SPI.transfer(RFM69_REG_FIFO & RFM69_READ_REGISTER); // set reading pointer uint8_t *current = (uint8_t *)&RFM69.currentPacket; bool headerRead = false; // first read header uint8_t readingLength = RFM69_HEADER_LEN; while (readingLength--) { *current++ = RFM69_SPI.transfer((uint8_t)RFM69_NOP); if (!readingLength && !headerRead) { // header read headerRead = true; if (RFM69.currentPacket.header.version >= RFM69_MIN_PACKET_HEADER_VERSION) { // read payload readingLength = min(RFM69.currentPacket.header.packetLen - (RFM69_HEADER_LEN - 1), RFM69_MAX_PACKET_LEN); // save payload length RFM69.currentPacket.payloadLen = readingLength; RFM69.ackReceived = RFM69_getACKReceived(RFM69.currentPacket.header.controlFlags); RFM69.dataReceived = !RFM69.ackReceived; } } } //#endif RFM69_csn(HIGH); RFM69_concludeSPITransaction(); } RFM69.currentPacket.RSSI = RFM69_readRSSI(); // radio remains in stdby until packet read } else { // back to RX (void)RFM69_setRadioMode(RFM69_RADIO_MODE_RX); } }At least the FPAR stage succeeds on the Moteino side:
__ __ ____ | \/ |_ _/ ___| ___ _ __ ___ ___ _ __ ___ | |\/| | | | \___ \ / _ \ `_ \/ __|/ _ \| `__/ __| | | | | |_| |___| | __/ | | \__ \ _ | | \__ \ |_| |_|\__, |____/ \___|_| |_|___/\___/|_| |___/ |___/ 2.3.2 16 MCO:BGN:INIT NODE,CP=RPNNA---,FQ=16,REL=255,VER=2.3.2 26 TSM:INIT 28 TSF:WUR:MS=0 29 TSM:INIT:TSP OK 31 TSM:INIT:STATID=99 33 TSF:SID:OK,ID=99 35 TSM:FPAR 537 SND: LEN=12,DST=255,VER=1,SND=99,FLG=32,SEQ=1 544 ?TSF:MSG:SEND,99-99-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK: 1434 RECV: LEN=13,DST=99,VER=1,SND=0,FLG=128,SEQ=18 1939 SND: LEN=7,DST=0,VER=1,SND=99,FLG=96,SEQ=2 1945 TSF:MSG:READ,0-0-99,s=255,c=3,t=8,pt=1,l=1,sg=0:0 1950 TSF:MSG:FPAR OK,ID=0,D=1 2552 TSM:FPAR:OK 2553 TSM:ID 2554 TSM:ID:OK 2556 TSM:UPL 3058 SND: LEN=13,DST=0,VER=1,SND=99,FLG=160,SEQ=3 3766 SND: LEN=13,DST=0,VER=1,SND=99,FLG=160,SEQ=3 4471 SND: LEN=13,DST=0,VER=1,SND=99,FLG=160,SEQ=3 5179 SND: LEN=13,DST=0,VER=1,SND=99,FLG=160,SEQ=3 5888 SND: LEN=13,DST=0,VER=1,SND=99,FLG=160,SEQ=3 6095 !TSF:MSG:SEND,99-99-0-0,s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=NACK:1 6882 RECV: LEN=13,DST=99,VER=1,SND=0,FLG=128,SEQ=20 7388 SND: LEN=7,DST=0,VER=1,SND=99,FLG=96,SEQ=4 7394 TSF:MSG:READ,0-0-99,s=255,c=3,t=25,pt=1,l=1,sg=0:1 7399 TSF:MSG:PONG RECV,HP=1 7402 TSM:UPL:OKDon't know whether this is all correct, but at least it says TSM:FPAR:OK which shows the original problem is now solved.
Reading the code I imagine that the linux specific part of the RFM69_interruptHandling function was to make SPI communication more efficient with multi-byte transfers. I would like to help maybe fix this if there truly is an error in the code. Off to the application level debugging.
Again, I truly appreciate the amount of work that has gone into developing this framework and documentation. -
I think the appropriate words of wisdom are that the Raspberry Pi as gateway, directly interfacing to the RFM69 radio via GPIO, is not well supported yet. In fact, now that I've looked at it in more detail, there really is no use case where this is a desirable configuration. Any Arduino embedded controller can function as the gateway for connection to a home automation controller. Much cheaper, lower power and less complicated. I got my Home Assistant setup working with a Moteino gateway over serial with minimal effort.
-
Darn, I was actually looking into the RFM69-directly-on-PI use case. Seems desirable enough to me?
-
Darn, I was actually looking into the RFM69-directly-on-PI use case. Seems desirable enough to me?
@alowhum Yes I thought the same initially. I really wanted to use the Adafruit bonnet because it also has a little display and some buttons and I thought that would be pretty cool. But my use case is to connect my own sensors to a Home Automation controller. It runs on a Pi but the software installation is very much standardized (you download the complete image including OS and dockerized HA) so you can't really add much custom code such as native radio drivers requiring GPIO and interrupt access without it becoming a very custom configuration that then becomes harder to maintain over time.
Turns out the the standard HA release has a standard configuration for a serial sensor gateway that MySensors supports. so instead of trying to get the bonnet to work it's far, far easier to simply connect a Moteino or whatever running the serial gateway code on the MCU, taking care of the radio specific timing and stuff. Downside is that there's now a loose Moteino board sitting next to the Pi that needs some kind of case. Upside is that I can update the HA image without worrying about re-installing radio drivers, etc.
Mind you, if someone is interested in making this work then I'd be happy to help with testing and troubleshooting. -
Ah, thanks for the clarification. In my use case this wouldn't be a problem. Phew!
-
I will, but it won't be for a while.