Cannot get Teensy 4.1 ethernet connection working

Lateralleap

Well-known member
I have tried two different boards and ethernet kits

The green link LED never lights

I have tried the NativeEthernet UPD example but cannot ping the board

I have tried the code below, still no ping:

Code:
#include <NativeEthernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network.
// gateway and subnet are optional:
byte mac[6];

IPAddress ip(??, ??, ??, ??); // Ethernet address obfuscated

EthernetServer server(80);
boolean alreadyConnected = false; // whether or not the client was connected previously

void teensyMAC(uint8_t *mac) {
  for (uint8_t by = 0; by < 2; by++) mac[by] = (HW_OCOTP_MAC1 >> ((1 - by) * 8)) & 0xFF;
  for (uint8_t by = 0; by < 4; by++) mac[by + 2] = (HW_OCOTP_MAC0 >> ((3 - by) * 8)) & 0xFF;
  Serial.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}

void setup() {
  // Set the MAC address.
  teensyMAC(mac);
  Ethernet.begin(mac, ip);

  // 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
  }

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  // start listening for clients
  server.begin();

  Serial.print("Chat server address:");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // wait for a new client:
  EthernetClient client = server.available();

  // when the client sends the first byte, say hello:
  if (client) {
    while (client.connected()) {

      while (client.available() > 0) {
        char c = client.read();
        Serial.write(c);
      }
    }

    client.stop();
    Serial.println("Client disconnected");
  }
}

When I run this, the MAC address and IP address are printed out with no other errors

Any suggestions?

Thanks
 
Last edited by a moderator:
Just assembled one here and it worked.

Check pin soldering on the T_4.1 PCB cable connection and direction: pjrc.com/store/ethernet_kit.html
ethernet_kit_06.jpg
 
Thanks

I had already done that and tried two separate boards and adaptors

I'm wondering if it's the type of switch it's plugged into so I will try a laptop
 
I have tried the UDP NTP client example below

After the MAC address is printed, I get the error: "Failed to configure Ethernet using DHCP"

So Ethernet.begin is failing

Code:
#include <SPI.h>
#include <NativeEthernet.h>
#include <NativeEthernetUdp.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[6];

unsigned int localPort = 8888;       // local port to listen for UDP packets

const char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server

const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets

// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void teensyMAC(uint8_t *mac) {
  for (uint8_t by = 0; by < 2; by++) mac[by] = (HW_OCOTP_MAC1 >> ((1 - by) * 8)) & 0xFF;
  for (uint8_t by = 0; by < 4; by++) mac[by + 2] = (HW_OCOTP_MAC0 >> ((3 - by) * 8)) & 0xFF;
  Serial.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}

void setup() {
  // You can use Ethernet.init(pin) to configure the CS pin
  //Ethernet.init(10);  // Most Arduino shields
  //Ethernet.init(5);   // MKR ETH shield
  //Ethernet.init(0);   // Teensy 2.0
  //Ethernet.init(20);  // Teensy++ 2.0
  //Ethernet.init(15);  // ESP8266 with Adafruit Featherwing Ethernet
  //Ethernet.init(33);  // ESP32 with Adafruit Featherwing Ethernet

  // 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
  }

  teensyMAC(mac);

    // start Ethernet and UDP
    if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // Check for Ethernet hardware present
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
      Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    } else if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Ethernet cable is not connected.");
    }
    // no point in carrying on, so do nothing forevermore:
    while (true) {
      delay(1);
    }
  }
  Udp.begin(localPort);
}

void loop() {
  sendNTPpacket(timeServer); // send an NTP packet to a time server

  // wait to see if a reply is available
  delay(1000);
  if (Udp.parsePacket()) {
    // We've received a packet, read the data from it
    Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer

    // the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, extract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    Serial.print("Seconds since Jan 1 1900 = ");
    Serial.println(secsSince1900);

    // now convert NTP time into everyday time:
    Serial.print("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;
    // subtract seventy years:
    unsigned long epoch = secsSince1900 - seventyYears;
    // print Unix time:
    Serial.println(epoch);


    // print the hour, minute and second:
    Serial.print("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)
    Serial.print((epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)
    Serial.print(':');
    if (((epoch % 3600) / 60) < 10) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
    Serial.print(':');
    if ((epoch % 60) < 10) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.println(epoch % 60); // print the second
  }
  // wait ten seconds before asking for the time again
  delay(10000);
  Ethernet.maintain();
}

// send an NTP request to the time server at the given address
void sendNTPpacket(const char * address) {
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(address, 123); // NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}
 
Last edited by a moderator:
Code:
#include <SPI.h>
#include <NativeEthernet.h>
#include <NativeEthernetUdp.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[6];

unsigned int localPort = 8888; // local port to listen for UDP packets

const char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server

const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets

// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void teensyMAC(uint8_t* mac) {
	for (uint8_t by = 0; by < 2; by++) mac[by] = (HW_OCOTP_MAC1 >> ((1 - by) * 8)) & 0xFF;
	for (uint8_t by = 0; by < 4; by++) mac[by + 2] = (HW_OCOTP_MAC0 >> ((3 - by) * 8)) & 0xFF;
	Serial.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}

void setup() {
	// You can use Ethernet.init(pin) to configure the CS pin
	//Ethernet.init(10); // Most Arduino shields
	//Ethernet.init(5); // MKR ETH shield
	//Ethernet.init(0); // Teensy 2.0
	//Ethernet.init(20); // Teensy++ 2.0
	//Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet
	//Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet

	// 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
	}

	teensyMAC(mac);

	// start Ethernet and UDP
	if (Ethernet.begin(mac) == 0) {
		Serial.println("Failed to configure Ethernet using DHCP");
		// Check for Ethernet hardware present
		if (Ethernet.hardwareStatus() == EthernetNoHardware) {
			Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. ");
		}
		else if (Ethernet.linkStatus() == LinkOFF) {
			Serial.println("Ethernet cable is not connected.");
		}
		// no point in carrying on, so do nothing forevermore:
		while (true) {
			delay(1);
		}
	}
	Udp.begin(localPort);
}

void loop() {
	sendNTPpacket(timeServer); // send an NTP packet to a time server

	// wait to see if a reply is available
	delay(1000);
	if (Udp.parsePacket()) {
		// We've received a packet, read the data from it
		Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer

		// the timestamp starts at byte 40 of the received packet and is four bytes,
		// or two words, long. First, extract the two words:

		unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
		unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
		// combine the four bytes (two words) into a long integer
		// this is NTP time (seconds since Jan 1 1900):
		unsigned long secsSince1900 = highWord << 16 | lowWord;
		Serial.print("Seconds since Jan 1 1900 = ");
		Serial.println(secsSince1900);

		// now convert NTP time into everyday time:
		Serial.print("Unix time = ");
		// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
		const unsigned long seventyYears = 2208988800UL;
		// subtract seventy years:
		unsigned long epoch = secsSince1900 - seventyYears;
		// print Unix time:
		Serial.println(epoch);


		// print the hour, minute and second:
		Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
		Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
		Serial.print(':');
		if (((epoch % 3600) / 60) < 10) {
			// In the first 10 minutes of each hour, we'll want a leading '0'
			Serial.print('0');
		}
		Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
		Serial.print(':');
		if ((epoch % 60) < 10) {
			// In the first 10 seconds of each minute, we'll want a leading '0'
			Serial.print('0');
		}
		Serial.println(epoch % 60); // print the second
	}
	// wait ten seconds before asking for the time again
	delay(10000);
	Ethernet.maintain();
}

// send an NTP request to the time server at the given address
void sendNTPpacket(const char* address) {
	// set all bytes in the buffer to 0
	memset(packetBuffer, 0, NTP_PACKET_SIZE);
	// Initialize values needed to form NTP request
	// (see URL above for details on the packets)
	packetBuffer[0] = 0b11100011; // LI, Version, Mode
	packetBuffer[1] = 0; // Stratum, or type of clock
	packetBuffer[2] = 6; // Polling Interval
	packetBuffer[3] = 0xEC; // Peer Clock Precision
	// 8 bytes of zero for Root Delay & Root Dispersion
	packetBuffer[12] = 49;
	packetBuffer[13] = 0x4E;
	packetBuffer[14] = 49;
	packetBuffer[15] = 52;

	// all NTP fields have been given values, now
	// you can send a packet requesting a timestamp:
	Udp.beginPacket(address, 123); // NTP requests are to port 123
	Udp.write(packetBuffer, NTP_PACKET_SIZE);
	Udp.endPacket();
}
In future when you post code can you put it between code tags using the # button as I have done above.
It makes it so much easier for others to read and understand.
 
Thanks. Yes, that was my next step. However having decided to update Arduino IDE to resolve another issue, that is not hanging on startup! Fun and games...
 
I decided to try a simple QNEthernet example

HTML:
#include <QNEthernet.h>

using namespace qindesign::network;
//===============================================================================
//  Initialization
//===============================================================================
void setup() {
  Ethernet.begin();
  Serial.begin(115200);
}
//===============================================================================
//  Main
//===============================================================================
void loop() {
  bool link = Ethernet.linkState();
  Serial.print("Link State: ");
  if (link==true){
    Serial.println("ON");
  }else {
    Serial.println("OFF");  
}
  delay(1000);
}

When I run this, it reports "Link state On"

However green LED is still not on, the network switch it is connected to also doesn't think there is a device attached to the relevant port

Any ideas?
 
Running that here (with added FILE name print) shows:
Code:
C:\T_Drive\tCode\ethernet\SimpleQNE\SimpleQNE.ino Feb 26 2023 13:35:24
Link State: OFF
Link State: OFF
Link State: ON
Link State: ON
Link State: ON
Link State: ON
...

I do see an active green LED with the MagJack that looks to be the CETUS unit shown in p#2 - so it is the current PJRC kit.

This is with a recent PJRC T_4.1 and IDE 2.0 builder using TD 1.58 beta 3
Code:
...
"-tools=C:\\Users\\Tim\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-tools\\0.58.3/" -board=TEENSY41
"C:\\Users\\Tim\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-tools\\0.58.3/stdout_redirect" "R:\\temp\\arduino_build_SimpleQNE.ino/SimpleQNE.ino.sym" "C:\\Users\\Tim\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\11.3.1-beta2/arm/bin/arm-none-eabi-objdump" -t -C "R:\\temp\\arduino_build_SimpleQNE.ino/SimpleQNE.ino.elf"
"C:\\Users\\Tim\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-tools\\0.58.3/teensy_size" "R:\\temp\\arduino_build_SimpleQNE.ino/SimpleQNE.ino.elf"
teensy_size: Memory Usage on Teensy 4.1:
teensy_size:   FLASH: code:81784, data:14232, headers:8428   free for files:8022020
teensy_size:    RAM1: variables:45088, code:79144, padding:19160   free for local variables:380896
teensy_size:    RAM2: variables:51776  free for malloc/new:472512
"C:\\Users\\Tim\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-tools\\0.58.3/stdout_redirect" "R:\\temp\\arduino_build_SimpleQNE.ino/SimpleQNE.ino.lst" "C:\\Users\\Tim\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\11.3.1-beta2/arm/bin/arm-none-eabi-objdump" -d -S -C "R:\\temp\\arduino_build_SimpleQNE.ino/SimpleQNE.ino.elf"
Using library QNEthernet at version 0.18.0 in folder: C:\T_Drive\tCode\libraries\QNEthernet 
Using library Entropy in folder: C:\Users\Tim\AppData\Local\Arduino15\packages\teensy\hardware\avr\0.58.3\libraries\Entropy (legacy)
...
 
Thanks Defragster

When I run it I get Link State: On but if I remove the ethernet cable, it still says the same!!!

Just tried another board and ethernet adaptor. Same result

I am using Teensydino 1.57.2 and IDE 2.03

So maybe I should try 1.58 beta 3
 
I have installed 1.58 beta 3 and no change

I have plugged the enthernet cable (still plugged into the same switch port) into my laptop and it works fine

I am not supplying separate power to the board, just the USB power, should that be OK?

I am at a loss to know what to do next....
 
Not clear what is different/wrong there?

Left it 'ON' here then it went OFF after some time.

Pulled ethernet and then repowered and it came up 'OFF' - no Green LED

Plugging Cable went 'ON' and GREEN LED ... flashing and seems good ....

Unplug ethernet and 'OFF' ... replug and 'ON' with GREEN LED ... twice
 
The benefit of sleeping on problems

I woke this morning thinking, I wonder if there are multiple versions of the Teensy 4.1...

I thought there was only one and that you just had to buy the ethernet adaptor.

I then noticed the missing chip on my boards

So sorry to have wasted your time but thanks for your help and what you have sent me will help when I get the right boards :)
 
I feel SO foolish...

I looked at your photo to confirm the cable orientation was correct but did not spot the additional chip

When the supplier specified "no ethernet", I assumed they meant "no ethernet adaptor" since the price difference was a few pounds, so I just ordered the ethernet kit separately

The fact that you have to solder the ethernet header for both versions just reinforced the confusion!

Finally, the devices return seemingly unique/ valid MAC addresses so all seemed good

It's a pity there is no way (I assume?) for the ethernet libraries to detect the presence of the ethernet chip and complain if it's missing?

Anyway, older and wiser :)
 
Hopefully the NOT-NE is available as needed!

Stuff happens - Ordered a pair of the PJRC MagJack kits - pushed them around for months and now need one and don't know where they have been hidden. Did find one of the current kits and assembled that allowed for this test.

Okay - just found them - in 'Teensy' the box under my desk ... by my foot. The original ones with the UDI Magjack - been here a while. One plugged onto prior T_4.1 code and it works.
 
And yes, it would be nice if the lowest level could/would detect no PHY chip on board.

That wasn't a concern when PJRC did the initial work.

The NE version only came about because of supply issues requiring the choice of NO T_4.1 shipping while waiting, or shipping some as NE.
 
The earliest ethernet test code did use the 2 MDIO signals to check for the PHY.

https://github.com/PaulStoffregen/t...18cbed3d269ec5043a/teensy41_ethernet.ino#L216

It didn't actually do much, other than just print the info, with the expected ID number for DP83825I and also LAN8720A which was used with Teensy 3.5 & 3.6 but never turned a product. (but Teensy 3.5 / 3.6 need different ethernet clock config where the PHY creates the 50 MHz reference clock)

You can also see some commented out test code at line #109 which blinks the green LED. :)
 
Just for the sake of completeness, here's the earlier test code for LAN8720A with Teensy 3.6. It also checks if the PHY is present (but just prints the info, doesn't actually use it) at line 107.

https://github.com/PaulStoffregen/k66_ethernet/blob/master/k66_ethernet.ino

Only about 80 ethernet shields were ever made (by PJRC) for Teensy 3.6, all of them hand soldered. Details on the hardware and PCB are still available with OSH Park.

https://oshpark.com/shared_projects/Y2JckjhM

The LAN8720A is pretty badly impacted by chip shortages. I do have a couple dozen LAN8720A chips somewhere in a box...
 
Many thanks Paul for the information

Now that these ethernetless variants are out in the wild, it would be useful if the various ethernet libraries built in that PHY test code
 
Back
Top