1

I'm trying to build a serial over radio transmitter module using two Feather M0 boards with RFM69HCW chips on board. As a test I'm trying to run a slip IP over serial session. This seems to work consistantly for UDP sessions (in my case ICMP ping requests) but fails for TCP sessions (in my case a simple HTTP request).

Here is the code:

#include <RFM69.h>
#include <RFM69_ATC.h>
#include <SPI.h>
#include <string>
// a simple off the shelf CRC8 implementation
#include <crc.h>

// defined for one of the two boards // #define B

#ifdef B #define NODEID 1 #define RECEIVER 2 #endif #ifndef B #define NODEID 2 #define RECEIVER 1 #endif

#define MAX_BYTES 56

#define NETWORKID 100 #define FREQUENCY RF69_433MHZ #define IS_RFM69HW_HCW

RFM69_ATC radio(8, 3, true);

char buf[512];

void setup() { // initialize random using receiver address // this guarantees that both nodes have different initial random values randomSeed(RECEIVER);

Serial.begin(115200);

radio.initialize(FREQUENCY, NODEID, NETWORKID); radio.setPowerLevel(0); radio.setFrequency(446000000); }

int8_t receiver_last_id = -1;

bool read_packet(bool override = false) { if (radio.receiveDone() || override) { int cnt = radio.DATALEN - 2; int crc = radio.DATA[0]; int8_t packet_id = radio.DATA[1];

memcpy(buf, radio.DATA + 2, cnt);

uint8_t crc_data = crc8(0, (uint8_t*)buf, cnt);

if (radio.ACKRequested())
{
  if (crc == crc_data)
  {
    radio.sendACK();

    // sometimes duplicates seem to occure
    // in case this happens just ignore the packet
    if (packet_id != receiver_last_id)
    {
      Serial.write(buf, cnt);
      receiver_last_id = packet_id;
      return true;
    }
    return false;
  }
  else
  {
    radio.ACK_REQUESTED = 0;
    return false;
  }
}

return false;

} return false; }

int8_t sender_packet_id = 0;

bool send_packet() { int serial_cnt = Serial.available();

if (serial_cnt > 0 && radio.canSend()) { // packet structure: // 1. byte: CRC8 of DATA // 2. byte: ID of packet (to prevent duplicates) // variable length: DATA

int payload_size = min(MAX_BYTES, serial_cnt);
int total_size = payload_size + 2;

Serial.readBytes((char *)buf + 2, payload_size);
buf[0] = crc8(0, (uint8_t*)(buf + 2), payload_size);
buf[1] = sender_packet_id++;

while (!radio.sendWithRetry(RECEIVER, buf, total_size, 1, 5U))
{
  // radio.receiveDone() switches the
  // radio into receive mode
  if (radio.receiveDone())
  {
    // if receive is done instantly
    // process the packet and move on
    read_packet(true);
    continue;
  }

  // wait random time in case
  // a collision happened
  delay(random(5, 30));

  read_packet();

  // wait for radio to be ready to send
  while (!radio.canSend()) ;
}

return true;

}

return false; }

void loop() { read_packet();

send_packet(); }

I also have a network capture of both sides.

Here is the capture for the Client: https://ufile.io/v945jl8i

Here is the capture for the Server: https://ufile.io/yn36rjw4

I've figured out that it happens somewhere in the while (!radio.sendWithRetry(RECEIVER, buf, total_size, 1, 5U)) loop but I can't figure out what exactly goes wrong and how I can fix it.

Any help would be greatly appreciated!

Edit: I'm running a simple python HTTP server (python 3 -m http.server 8080). And as client i'm using curl (curl <server address>:8080)

Here are the Commands I use for starting slip:

modprobe slip
slattach -vL -s 115200 -p slip /dev/ttyACM0
ifconfig sl0 192.168.2.1 pointtopoint 192.168.2.2 up

I switched the two IP addresses for the other side.

Also interestingly it sometimes seems to randomly work for one or two requests, so i'm guessing some kind of race condition.

I also made sure that i'm connecting to the correct serial ports.

PS: i'm kind of new to C++ so any recommendations on best practices are also appreciated

Lukas
  • 11
  • 2

0 Answers0