Sending Packets From Teensy Over Ethernet

marsTAK

New member
I am currently trying to set up communication between my Laptop (Ubuntu 20.04) and a Teensy board over the Ethernet Protocol. To test, I am trying to send simple strings back and forth between the two devices. I'm using the Arduino IDE on the teensy end and C++ on the device end. So far, I've been able to send data from my laptop and read it on the teensy, but I haven't been able to send data from the teensy back to the laptop. I'm not sure how to proceed. I've tried to change the Broadcast IP by changing the subnet mask and setting the same IP for my laptop for the ethernet connection, however that hasn't worked. I'm using the QNEthernet Library for the teensy; most of my code is stitched together by looking at examples online. Any help would be greatly appreciated!

C++ CODE
C++:
#include <iostream>
#include <string>

#include <arpa/inet.h> // htons, inet_addr
#include <netinet/in.h> // sockaddr_in
#include <sys/types.h> // uint16_t
#include <sys/socket.h> // socket, sendto
#include <unistd.h> // close

int main(int argc, char const *argv[])
{
    std::string hostname{"10.0.0.7"};
    uint16_t port = 4333;

    int sock = ::socket(AF_INET, SOCK_DGRAM, 0);

    sockaddr_in destination;
    destination.sin_family = AF_INET;
    destination.sin_port = htons(port);
    destination.sin_addr.s_addr = inet_addr(hostname.c_str());

    std::string msg = "Jane Doe";
    int n_bytes = ::sendto(sock, msg.c_str(), msg.length(), 0, reinterpret_cast<sockaddr*>(&destination), sizeof(destination));
    std::cout << n_bytes << " bytes sent" << std::endl;
 
   char buffer[1024];
    sockaddr_in senderAddr;
    socklen_t senderAddrLen = sizeof(senderAddr);

    size_t recvBytes = 0;
    // do {
        recvBytes = ::recvfrom(sock, buffer, sizeof(buffer), 0, reinterpret_cast<sockaddr*>(&senderAddr), &senderAddrLen);
        std::cout << recvBytes << std::endl;
    // } while(recvBytes==0);

    // ssize_t recvBytes = ::recvfrom(sock, buffer, sizeof(buffer), 0, reinterpret_cast<sockaddr*>(&senderAddr), &senderAddrLen);
    if (recvBytes > 0) {
        std::cout<<"YEP"<<std::endl;
        buffer[recvBytes] = '\0'; // Null-terminate the received data
        std::cout << "Received: " << buffer << std::endl;
    } else if (recvBytes == 0) {
        std::cerr << "Connection closed by peer\n";
    } else {
        std::cerr << "Error receiving data\n";
    }

    ::close(sock);


    return 0;
}

TEENSY CODE
Code:
#include <QNEthernet.h>

using namespace qindesign::network;

// --------------------------------------------------------------------------
//  Configuration
// --------------------------------------------------------------------------

constexpr uint16_t kPort = 4333;  // Chat port

// --------------------------------------------------------------------------
//  Program State
// --------------------------------------------------------------------------

// UDP port.
EthernetUDP udp;
bool read_packet = false;

// --------------------------------------------------------------------------
//  Main Program
// --------------------------------------------------------------------------

// Forward declarations (not really needed in the Arduino environment)
// static void printPrompt();
void receivePacket();
static void sendPacket();

// Program setup.
void setup() {

  Serial.begin(115200);
  while (!Serial && millis() < 4000) {
    // Wait for Serial
  }
  printf("Starting...\r\n");

  uint8_t mac[6];
  Ethernet.macAddress(mac);  // This is informative; it retrieves, not sets
  printf("MAC = %02x:%02x:%02x:%02x:%02x:%02x\r\n",
         mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

  Ethernet.onLinkState([](bool state) {
    printf("[Ethernet] Link %s\r\n", state ? "ON" : "OFF");
  });

  IPAddress ip(10, 0, 0, 7);
  IPAddress sn{255,255,255,0};  // Subnet Mask
  IPAddress gw{10,0,0,6};       // Default Gateway

  if (!Ethernet.begin(ip, sn, gw)) {
    printf("Failed to start Ethernet\r\n");
    return;
  }

  // if (!Ethernet.waitForLocalIP(kDHCPTimeout)) {
  //   printf("Failed to get IP address from DHCP\r\n");
  //   return;
  // }
  printf("Obtaining the IP, Subnet and Gateway\r\n");
  ip = Ethernet.localIP();
  printf("    Local IP     = %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.subnetMask();
  printf("    Subnet mask  = %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.broadcastIP();
  printf("    Broadcast IP = %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.gatewayIP();
  printf("    Gateway      = %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.dnsServerIP();
  printf("    DNS          = %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3]);

  // Start UDP listening on the port
  udp.begin(kPort);

  // printPrompt();
}

void loop() {
  receivePacket();
  sendPacket();
}

// Tries to read a line from the console and returns whether
// a complete line was read. This is CR/CRLF/LF EOL-aware.
static bool readLine(String &line) {
  static bool inCR = false;  // Keeps track of CR state

  while (Serial.available() > 0) {
    int c;
    switch (c = Serial.read()) {
      case '\r':
        inCR = true;
        return true;

      case '\n':
        if (inCR) {
          // Ignore the LF
          inCR = false;
          break;
        }
        return true;

      default:
        if (c < 0) {
          return false;
        }
        inCR = false;
        line.append(static_cast<char>(c));
    }
  }

  return false;
};


// Control character names.
static const String kCtrlNames[]{
  "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
  "BS",  "HT",  "LF",  "VT",  "FF",  "CR",  "SO",  "SI",
  "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
  "CAN", "EM",  "SUB", "ESC", "FS",  "GS",  "RS",  "US",
};

// Receives and prints chat packets.
void receivePacket() {
  int size = udp.parsePacket();
  if (size < 0) {
    return;
  };

  // Get the packet data and remote address
  const uint8_t *data = udp.data();
  IPAddress ip = udp.remoteIP();

  printf("[%u.%u.%u.%u][%d] ", ip[0], ip[1], ip[2], ip[3], size);

  // Print each character
  for (int i = 0; i < size; i++) {
    uint8_t b = data[i];
    if (b < 0x20) {
      printf("<%s>", kCtrlNames[b].c_str());
    } else if (b < 0x7f) {
      putchar(data[i]);
    } else {
      printf("<%02xh>", data[i]);
    }
  }
  printf("\r\n");
  read_packet = true;
  printf("Set read_packet to true\n");
}

static void sendPacket() {
  static String line;
  line = "Dane Joe";

  IPAddress ip = Ethernet.broadcastIP();
  // printf("    Broadcast IP     = %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3]);
  // printf(Ethernet.broadcastIP());
 
  // Read from the console and send lines
  // if (readLine(line)) {
    // printf("Attempting to send.");
  if (read_packet) {
    printf("Attempting to send.\n");
    if (!udp.send(Ethernet.broadcastIP(), kPort,
                  reinterpret_cast<const uint8_t *>(line.c_str()),
                  line.length())) {
      printf("[Error sending]\r\n");
    }
    line = "";
  }
  read_packet = false;
}

The Serial Monitor readout terminates at "Attempting to send". It does not give the subsequent "Error sending" message; which means it might be broadcasting the message, or not.
(I have very little background in Networking, happy to learn more!)
 
Back
Top