Teensy 4.1 Ethernet Trouble Shooting

Edward

Well-known member
Hi All,

I'm having trouble getting a successful ping from my teensy 4.1 project using Ethernet. All I really need at this stage is to get a ping through to confirm the hardware is working.

For code, I've used the example chat server, just changing #20 to #include <NativeEthernet.h>

For the hardware
ethernet.jpg

What I'm getting is a successful compile/program, Serial reports the Ip address, green light on the ethernet is lit/blinks, but I can't get a ping. I can ping another device using the same cable and port.

Any thoughts on what I'm doing wrong?

thanks
Ed
 
My five cents:
a) assuming you use DHCP in MCU FW, and you get an IP address - this sounds to me as: ETH is working, it can talk to DHCP server (and get IP address assigned).
b) but if you use a STATIC IP address in MCU, and Serial prints IP address - it does not mean anything (at least not for sure if ETH is working).
Is the IP address (for STATIC) the same as you computer is on the network?
If you are on different networks - a ping cannot work (without a gateway to bridge networks)
If you use DHCP (and you get IP address assigned as in your network) - you should be fine even without ping working:
Using DHCP and getting a "reasonable" IP address - ETH works, for sure.
c) other thought:
ping is a "specific" protocol, not sure if using <NativeEthernet.h> would enable and handle this protocol needed for ping.
ping is ICMP protocol, potentially not enabled neither handled by <NativeEthernet.h> (or without ETH handling code).

I use QNEthernet, AysncWebServer, here the ping works fine.
Assuming, potentially "just" using NativeEthernet, there is not any ICMP protocol handler running (and therefore ping does not work).

Even ping does not work - the ETH connection you want to handle might work, ETH is potentially still able to receive and send (esp. if DHCP works).
Just think about that ping is a specific protocol and when not handled - no ping, but other stuff might be fine.
 
Note: AsyncWebServer runs cooperatively and has similar behaviour and performance as polling/single-threading.

Deeper: it runs whenever QNEthernet’s `Ethernet.loop()` is run, and that happens internally in a few places when making API calls, in yield() calls, and after every iteration of the main program’s loop().
 
Thanks all.
I swapped to QNEthernet. The link was up immediately but the IP took a few minutes to get assigned.
 
Are you saying it took a few minutes to get an IP address from DHCP? If so, would you mind pasting a small example that demonstrates what you’re doing? DHCP doesn’t normally take that long. (Slow DHCP server, maybe?)
 
This is the code. It's basically just the setup code from the raw frame monitor. I confess once I'd got my ping that was enough to validate the hardware, so I've already passed the hardware on.
Code:
#include <QNEthernet.h>

using namespace qindesign::network;

// Main program setup.
void setup() {
  Serial.begin(115200);
  Serial.printf("Starting...\r\n");

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

  // Add listeners before starting Ethernet

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

  Ethernet.onAddressChanged([]() {
    IPAddress ip = Ethernet.localIP();
    bool hasIP = (ip != INADDR_NONE);
    if (hasIP) {
      IPAddress subnet = Ethernet.subnetMask();
      IPAddress broadcast = Ethernet.broadcastIP();
      IPAddress gw = Ethernet.gatewayIP();
      IPAddress dns = Ethernet.dnsServerIP();

      Serial.printf("[Ethernet] Address changed:\r\n"
             "    Local IP     = %u.%u.%u.%u\r\n"
             "    Subnet       = %u.%u.%u.%u\r\n"
             "    Broadcast IP = %u.%u.%u.%u\r\n"
             "    Gateway      = %u.%u.%u.%u\r\n"
             "    DNS          = %u.%u.%u.%u\r\n",
             ip[0], ip[1], ip[2], ip[3],
             subnet[0], subnet[1], subnet[2], subnet[3],
             broadcast[0], broadcast[1], broadcast[2], broadcast[3],
             gw[0], gw[1], gw[2], gw[3],
             dns[0], dns[1], dns[2], dns[3]);
    } else {
      Serial.printf("[Ethernet] Address changed: No IP address\r\n");
    }
  });

  // Initialize Ethernet, in this case with DHCP
  Serial.printf("Starting Ethernet with DHCP...\r\n");
  if (!Ethernet.begin()) {
    Serial.printf("Failed to start Ethernet\r\n");
    return;
  }
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}
 
Hmm. The code looks fine. Either the DHCP server is slow to respond or the network has high packet loss or something.
 
Interestingly that appears to happen with my system (Windows 11) when I run that code:

10:46:37.938 -> Starting...
10:46:37.938 -> MAC = 04:e9:e5:0f:69:fc
10:46:37.938 -> Starting Ethernet with DHCP...
10:46:37.938 -> [Ethernet] Link ON
10:50:35.432 -> [Ethernet] Address changed:
10:50:35.432 -> Local IP = 169.254.253.105
10:50:35.432 -> Subnet = 255.255.0.0
10:50:35.432 -> Broadcast IP = 169.254.255.255
10:50:35.432 -> Gateway = 0.0.0.0
10:50:35.432 -> DNS = 0.0.0.0

It takes 4 minutes to respond or am I reading that wrong....
 
That’s a self-assigned IP. What you’re seeing is a timeout; the system gives itself an IP after trying to contact a DHCP server for a while. Either your DHCP server isn’t responding or the Teensy isn’t plugged into a network that has a DHCP server. A DHCP-assigned address often takes about 5-10 seconds to arrive.

I think this also explains @Edward’s minutes-long delay. It’s a timeout; there’s no DHCP response.
 
Last edited:
Hi Shawn,

I do have the same issue on my side, maybe because I am using a corporative computer with loads of protection and stuff.
Is there a way to lower this timeout value to less than a minute ? Or should I contact my IT department to expose this ?

Thanks in advance,
Pedro
 
Code:
#include <QNEthernet.h> // Most optimized Ethernet library for Teensy 4.1 Seems to have resolved memory leak in other libraries
#include <ArduinoModbus.h> // Dependency ArduinoRS485\RS485.cpp must have line 209 edited to use Serial5 and associated pins.
#include <EEPROM.h> // Enable access to EEPROM on Teensy board

using namespace qindesign::network;
EthernetServer EthServer(5005);
ModbusTCPServer modbusTCPServer;

void updateOutput(); // Updates all output pins to high/low based on Modbus coil values

// Global variables
IPAddress ip{ 192, 168, 1, 1 }; // Default IP address
IPAddress subnet{ 255, 255, 240, 0 }; // Default Subnet mask
IPAddress gw{ 192, 168, 47, 254}; // Gateway

void setup() {

  pinMode(13, OUTPUT);

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


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


  Ethernet.onAddressChanged([]() {
    IPAddress ip = Ethernet.localIP();
    bool hasIP = (ip != INADDR_NONE);
    if (hasIP) {
      IPAddress subnet = Ethernet.subnetMask();
      Serial.printf("Local IP: %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3], subnet[0], subnet[1], subnet[2], subnet[3]);
    } else {
      Serial.printf("Address changed: No IP address\r\n");
    }
  });
      
  // start the Modbus TCP server
  if (!modbusTCPServer.begin()) {
    Serial.println("Failed to start Modbus TCP Server!");
    //while (1);
  }

  modbusTCPServer.configureCoils(0, 20);

  if (!Ethernet.begin()) {
    Serial.print("ERROR3: Failed to start Ethernet\r\n");
    return;
  }
  EthServer.begin();
  Serial.println("Setup has finished.");

}

void loop() {


  EthernetClient client = EthServer.available();
  //Serial.print("Client=");
  if (client) {
    Serial.print("Client Connected\n");
    modbusTCPServer.accept(client);
    if (client.available()>0) { // Updated to Shawn's suggestion
      Serial.print("Client Connected Inside\n");
      if (modbusTCPServer.poll()) { // poll() returns true when a request is present
        modbusTCPServer.holdingRegisterRead(44);
        updateOutput();
        Serial.print("Client Update Output\n");
      }
    }
  }


}

void updateOutput() {
  boolean state=modbusTCPServer.coilRead(0);
  digitalWrite(13, state);
}


This is my code, the issue is that it takes like 5/6 minutes for the teensy to give the IP Address:

Code:
00:00:01 Setup has finished.
00:00:02 Link ON
00:05:21 Local IP: 169.254.239.162
00:06:08 Client Connected
00:06:08 Client Connected Inside
00:06:08 Client Update Output

That is the output of my code.

Need additional information ?
 
Even when I try to manually configure the ip address it does not work, and only by using Ethernet.onAddressChanged I was able to stabilish a connection to the teensy otherwise is impossible.
 
Ethernet.begin() tries to get an IP address via DHCP. Since it doesn’t look like you have a DHCP server on your network, the locally-assigned 169.* address is assigned after some timeout. I’ll suggest using a static IP instead with Ethernet.begin(ip, subnet, gw).

onAddressChanged() simply prints the status when there’s a change.
 
Code:
#include <QNEthernet.h> // Most optimized Ethernet library for Teensy 4.1 Seems to have resolved memory leak in other libraries
#include <ArduinoModbus.h> // Dependency ArduinoRS485\RS485.cpp must have line 209 edited to use Serial5 and associated pins.
#include <EEPROM.h> // Enable access to EEPROM on Teensy board

using namespace qindesign::network;
EthernetServer EthServer(5005);
ModbusTCPServer modbusTCPServer;

void updateOutput(); // Updates all output pins to high/low based on Modbus coil values

// Global variables
IPAddress ip{ 192, 168, 1, 1 }; // Default IP address
IPAddress subnet{ 255, 255, 240, 0 }; // Default Subnet mask
IPAddress gw{ 192, 168, 47, 254}; // Gateway

void setup() {

  pinMode(13, OUTPUT);

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


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


  Ethernet.onAddressChanged([]() {
    IPAddress ip = Ethernet.localIP();
    bool hasIP = (ip != INADDR_NONE);
    if (hasIP) {
      IPAddress subnet = Ethernet.subnetMask();
      Serial.printf("Local IP: %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3], subnet[0], subnet[1], subnet[2], subnet[3]);
    } else {
      Serial.printf("Address changed: No IP address\r\n");
    }
  });
      
  // start the Modbus TCP server
  if (!modbusTCPServer.begin()) {
    Serial.println("Failed to start Modbus TCP Server!");
    //while (1);
  }

  modbusTCPServer.configureCoils(0, 20);

  Ethernet.begin(ip, subnet, gw);
  EthServer.begin();
  Serial.println("Setup has finished.");

}

void loop() {


  EthernetClient client = EthServer.available();
  //Serial.print("Client=");
  if (client) {
    Serial.print("Client Connected\n");
    modbusTCPServer.accept(client);
    if (client.available()>0) { // Updated to Shawn's suggestion
      Serial.print("Client Connected Inside\n");
      if (modbusTCPServer.poll()) { // poll() returns true when a request is present
        modbusTCPServer.holdingRegisterRead(44);
        updateOutput();
        Serial.print("Client Update Output\n");
      }
    }
  }


}

void updateOutput() {
  boolean state=modbusTCPServer.coilRead(0);
  digitalWrite(13, state);
}

The output console:
Code:
Local IP: 192.168.1.1
Setup has finished.
Link ON


Although says it is connected to 192.168.1.1, on the QModMaster tool I am not able to connect.

After a while the console outputs "Local IP: 169.254.239.162" and then for this particular ip. I can connect using QModMaster.

Thanks in advance,
 
Uhmmm, I apologize but just forget the last part of the comment:
"After a while the console outputs "Local IP: 169.254.239.162" and then for this particular ip. I can connect using QModMaster."

It is not able to connect to anything when the code is like this:
Code:
#include <QNEthernet.h> // Most optimized Ethernet library for Teensy 4.1 Seems to have resolved memory leak in other libraries
#include <ArduinoModbus.h> // Dependency ArduinoRS485\RS485.cpp must have line 209 edited to use Serial5 and associated pins.
#include <EEPROM.h> // Enable access to EEPROM on Teensy board

using namespace qindesign::network;
EthernetServer EthServer(5005);
ModbusTCPServer modbusTCPServer;

void updateOutput(); // Updates all output pins to high/low based on Modbus coil values

// Global variables
IPAddress ip{ 192, 168, 1, 1 }; // Default IP address
IPAddress subnet{ 255, 255, 240, 0 }; // Default Subnet mask
IPAddress gw{ 192, 168, 47, 254}; // Gateway

void setup() {

  pinMode(13, OUTPUT);

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


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


  Ethernet.onAddressChanged([]() {
    IPAddress ip = Ethernet.localIP();
    bool hasIP = (ip != INADDR_NONE);
    if (hasIP) {
      IPAddress subnet = Ethernet.subnetMask();
      Serial.printf("Local IP: %u.%u.%u.%u\r\n", ip[0], ip[1], ip[2], ip[3], subnet[0], subnet[1], subnet[2], subnet[3]);
    } else {
      Serial.printf("Address changed: No IP address\r\n");
    }
  });
      
  // start the Modbus TCP server
  if (!modbusTCPServer.begin()) {
    Serial.println("Failed to start Modbus TCP Server!");
    //while (1);
  }

  modbusTCPServer.configureCoils(0, 20);

  Ethernet.begin(ip, subnet, gw);
  EthServer.begin();
  Serial.println("Setup has finished.");

}

void loop() {


  EthernetClient client = EthServer.available();
  //Serial.print("Client=");
  if (client) {
    Serial.print("Client Connected\n");
    modbusTCPServer.accept(client);
    if (client.available()>0) { // Updated to Shawn's suggestion
      Serial.print("Client Connected Inside\n");
      if (modbusTCPServer.poll()) { // poll() returns true when a request is present
        modbusTCPServer.holdingRegisterRead(44);
        updateOutput();
        Serial.print("Client Update Output\n");
      }
    }
  }


}

void updateOutput() {
  boolean state=modbusTCPServer.coilRead(0);
  digitalWrite(13, state);
}

And the console output is just:

Code:
00:00:00 Local IP: 192.168.1.1
00:00:00 Setup has finished.
00:00:02 Link ON


Any suggestion ?
Thank you
 
So it does or doesn’t print the IP change to 169.*? (I asked for all the output, but you’re only showing three lines.)
 
I’m guessing here, but what happens if you initialize Modbus after initializing Ethernet instead of before?
 
Hi Shawn,

Meanwhile I was able to configure the ethernet connection properly. My mistake was on the IP address, subnet and gateway.

Thanks for the support, I really appreciate it.
best regards,
Pedro
 
Back
Top