Teensy 4.0/4.1 to Raspberry Pi wired communication over 1-2 meters

Status
Not open for further replies.

jackson

Member
The project I am working on has a pi and teensy communicating where the teensy controls a bunch of stepper motors and recieves sensor input, and that data is sent to a pi to be diplayed for the user on a large touch screen. The display allows inputs to be sent to control motor positions and speeds (basically an HMI).

What is the best way to communicate between the two? I figured i2c is out because of the cable distance, so would Serial, CAN, or USB be appropriate? The two will likely be connected by USB anyway to do OTA updates. I'd like to use the 4.0 since it's a tad smaller and things are going to be tight in my control box, but if I have to use a 4.1 it isn't too much of a problem. Thanks!
 
USB can do 2 meters. It's the way needing the least amount of extra hardware, just a good quality 2 meter cable. USB provides power, but for 2 meters make sure the cable has #24 or larger wires for the power. Cheap cables have tiny #28 or #30 wires which cause too much voltage loss if going a long distance.

Serial using RS422 / RS485 can go a long distance, but you need the transceiver hardware on both ends.

CAN bus also needs transceivers, and you'll need a CAN add-on board since Raspberry Pi doesn't have CAN built in.

Ethernet is the other good way to work over long distance. There you'd need Teensy 4.1 and the ethernet kit, and of course an ethernet cable. Ethernet has the nice advantage that it's magnetically coupled, so you don't have to worry about ground loops or ground difference if the 2 aren't powered from a common source.
 
Thanks for the help. Ethernet seems like it may be the way to go.

Does the ethernet kit just break the pins out to be used with an RJ45 connector? Because of the physical requirements, most of my connectors are industrial m12 style plugs. Is it possible to wire striaght to the board if I'm not using a standard ethernet plug or does the ethernet kit have some other functionality needed to facilitate data transfer?
 
Does the ethernet kit just break the pins out to be used with an RJ45 connector?

The connector is a "magjack", which means is more than just a plain RJ45. It has the ethernet magnetic coupling parts built in.

The kit does more or less just break out the pins, but to a magjack. It also has 1 capacitor. Scroll down to the bottom of that page for the schematic and datasheet on the magjack.
 
Hello! I have a similar project I am working on. I have two motors, and each motor has an encoder sending data to my Teensy 4.1. The hardware is also ready to go; I soldered the magjack Ethernet setup. Now I am trying to send the data from my Teensy encoder to my Raspberry Pi 4B. Could you direct me to the correct software for this? Do I need to configure my Pi in order to receive this data? I read somewhere about the <Ethernet.h> library vs the <NativeEthernet.h> library. Do you mind explaining the difference? Thank you!
 
Hello! I have a similar project I am working on. I have two motors, and each motor has an encoder sending data to my Teensy 4.1. The hardware is also ready to go; I soldered the magjack Ethernet setup. Now I am trying to send the data from my Teensy encoder to my Raspberry Pi 4B. Could you direct me to the correct software for this? Do I need to configure my Pi in order to receive this data? I read somewhere about the <Ethernet.h> library vs the <NativeEthernet.h> library. Do you mind explaining the difference? Thank you!

NativeEthernet was created to take advantage of the ethernet controller built inside the iMXRT chip. This should be more efficient and faster than an external controller, which is what the WIZNET is. The WIZNET controller uses the Ethernet.h. With the Teensy 4.1, NativeEthernet is the preferred library.

Start with this example: https://github.com/vjmuzik/NativeEt...UDPSendReceiveString/UDPSendReceiveString.ino

Then write your UDP receiver on the pi.

I've used python with this code to receive binary UDP packets on port 5555 on windows. Should work on the RPi, or may need some slight tweaks.

Code:
import socket
import sys
import hexdump

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind( ( '192.168.1.77', 5555) )  # (host, port) because AF_INET
print("Listening...")

while True:
    packet=sock.recv(2048)
    length = len(packet)
    print('Received', length, "| ", end='')
  
    if (length > 2 ):
        x = 0
        while x < length:
            char = format(packet[x],'02x')
            if ( x > (2 + packet[3]) ):
                print ('     ', end='')
            else:
                print ('0x',char,' ', sep='', end='')
            x = x + 1
        print('')
        print(' | ', end='')
        print(packet)
    else:
        print(packet)

192.168.1.77' is the IP of my windows PC. Be sure to open up port 5555 on the Windows firewall of the packets will get blocked.
 
Last edited:
Thanks TeensyWolf!

I tried running the python code on my pi, but I don't have the hexdump module and I'm not sure how to open up the 5555 port (or what that means exactly). Do you mind clarifying?

Also, how do I find the IP of my Raspberry Pi? Is it the same or different than the IP address in the UDPSendReceiveString code for the Teensy?

Thanks!
Hannah
 
Ports are usually blocked by computer firewalls, by default. At least, they should be. This is to protect the computer from bad actors trying to send data into ports.

On Raspbian terminal, type this to open the firewall for port 5555.

Code:
sudo ufw allow 5555

This should open for UDP as well as TCP packets. If you have something listening (python), then the UDP packets should get thru.

You can find your Raspberry Pi's IP address by typing this into terminal

Code:
ifconfig

It will return something like this

Code:
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.20.10  netmask 255.255.255.0  broadcast 192.168.20.255
        inet6 fe80::7d88:cb48:b2d5:ed31  prefixlen 64  scopeid 0x20<link>
        ether b8:27:eb:6a:5c:ff  txqueuelen 1000  (Ethernet)
        RX packets 3383323  bytes 746246998 (711.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 507067  bytes 66524730 (63.4 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

In this case 192.168.20.10 is my eth0 (wired ethernet) IP address

You will also get more if you have WiFi hardware running, it will show as wlan0, wlan1, etc.

Let me look at that Python code, get something that will compile & run on Raspian. Standby.
 
The Python code I had was printing binary packets.

If you are sending ASCII strings, you can use this, found over here: https://www.raspberrypi.org/forums/viewtopic.php?t=184241

Code:
import socket

UDP_IP = "192.168.20.10" # IP address of the Raspberry Pi
UDP_PORT = 5555 # UDP Port teensy is sending data to

sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))

while True:
  data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
  print("received message:", data)

Binary data will still print, but it will start with b'\x
 
On the example "UDPSendReceiveString" at this link: https://github.com/vjmuzik/NativeEt...UDPSendReceiveString/UDPSendReceiveString.ino

Do I change the localPort to match the UDP_PORT on the Pi? So I should set both to 5555, even though it comes in the Native Ethernet code as 8888?

I'm getting the following error on my Pi interface:

sock.bind((UDP_IP, UDP_PORT))
OSError: [Errno 99] Cannot assign requested address


Thanks,
Hannah

Your error is likely because your UDP_IP is wrong, this needs to be the eth0 IP of the Raspberry Pi. Do a ifconfig on pi terminal to get the IP address of the eth0. Post here if you are unsure.

The UDPSendReceiveString.ino example requires you to send a UDP packet to the Teensy first, then it mirrors it back on the incoming IP address.

Each UDP device will have an LOCAL port for incoming packets, the device will listen on this port. So NativeEthernet uses 8888, so the Pi should send stuff to this port. I don't have an example for any Python code to do this for you at moment. Everything I've been talking about is Teensy sending UDP packet and Pi receiving it and displaying it. Try to get that working first.

You can hard-code the Raspberry pi's IP address by adding this at/after line 25 (change it to the raspberry pi's address) in example UDPSendReceiveString.ino

Code:
  IPAddress destinationIP(192, 168, 20, 10);

Then change your loop code to just spit out a UDP packet to the raspberry pi, port 5555 once every second:

Code:
void loop() {  
  Udp.beginPacket(destinationIP, 5555);
  Udp.write(ReplyBuffer);
  Udp.endPacket();
  delay(1000);
}

Are you direct cable connected pi to teensy? If so, you will have to configure the IP address on the pi manually - see https://www.raspberrypi.org/documentation/configuration/tcpip/
 
THANK YOU TeensyWolf! After some time sifting through this, I got it figured out and it makes sense now :)

I have the Pi receiving UDP messages from the Teensy. Did you happen to find any Python code for sending UDP messages back to the Teensy from the Pi?

Thank you again for your help!
 
Status
Not open for further replies.
Back
Top