UDP Communications between a PC and an Arduino Using Lazarus / Free Pascal

I recently blogged about communicating between a PC and an Arduino using Serial Communications.

While this might be useful once in a while, in reality if I want to talk to an arduino from my PC I would prefer using the network. In fact, using UDP over a network has been exactly how I’ve programmed a ‘production’ arduino.

So in this post, I will convert my last project from using serial (USB) communications to using UDP in the past. It’s really simpler than serial and often more convenient.

If you aren’t familiar with UDP, you might want to Google it. Essentially it is a simple communications protocol that has no error checking. If a packet gets lost, the network does nothing about it (including notify you).

That might sound bad, but it really isn’t for projects like this. If I don’t get a response, I just try again myself.

To make this project work, I had to install an Ethernet shield onto my Uno.

You can get these from Sparkfun for about $45 at the time of writing. I’m sure you can get clones from China for way less as well. If you never messed with this shield, I’d recommend getting the first one from someone like Sparkfun so you know you have what you really want, it probably will work correctly, and you don’t have to wait 3 weeks to receive it.

Hardware Modifications

Once the shield was in place, I ALMOST connected it back up the way it had been for the serial connection. The Ethernet shield uses pin 4 for the on-board SD card reader, so I could no longer use pin 4. So I moved pin 4 to pin 2, and fixed the arduino sketch as well.

Here is the hardware ready to go:


When I designed the original software, it may have been a bit complex, but part of my reason for designing it the way I did was to minimize the locations where I actually touched the hardware – I knew I was going to change serial access to UDP access.

So I simply went thru the arduino sketch and the pascal program and changed the two procedures that read/write from the underlying hardware.

I’ll review those few changes here. Let’s look at the arduino side first.

Arduino Sketch Modifications

UDP is initialized in the setup procedure with these calls:

Ethernet.begin(mac, ip);

The first initiates the ethernet connection and supplies the MAC and IP addresses for the Arduino.

The MAC address is normally on a sticker on the bottom of the Ethernet shield. If you don’t have one, you can just use mine. They generally only need to be unique within your LAN.

Since the PC needs to know where the arduino is, the arduino must have a static IP address.

The 2nd call initiates the UDP protocol and tells it the UDP port on which we will be listening.

The procedure to receive packets was rewritten to:

boolean a2p_i_recvPacket(
    char*                       packet,
    int                         packetMax
    int                         packetSize;

    packetSize = udp.parsePacket();

    if (packetSize == 0)
        return false;

    udp.read(packet, packetMax);
    packet[packetSize] = '';

    return true;

    } // a2p_i_recvPacket

udp.parsePacket returns the size of the packet waiting to be read. If this is 0, there is nothing waiting, so the procedure returns false.

If there is something waiting, the procedure reads that into the packet buffer and terminates it with ” to make it a null terminated string.

This is a test program so I don’t check lengths. Shame on me, though, that is poor programming. I would never do that in a real program!

The procedure to transmit packets was rewritten as:

void a2p_i_xmitPacket(
    char*                                 packet
    ) {

    udp.beginPacket(udp.remoteIP(), udp.remotePort());
    // must terminate packet with <CR><LF>

    } // a2p_i_xmitPacket

udp.beginPacket is used to specify where the packet is going and we are going to use the ‘remote’ IP and Port from whence the last packet came.

udp.write(packet) then transmits the packet. Note that this requires a null terminated string to determine how many bytes to transmit.

The Pascal program is using a recvString procedure which expects strings to be terminated by <CR><LF>, so we must transmit the <CR><LF>at the end of the packet.

Finally udp.endPacket forces the packet to actually be transmitted out onto the network.

Just barely more complicated than the serial versions of these procedures!

Pascal Code Modifications

Now, on to the Pascal side. For UDP access, I will continue to use the Synapse library. In the past I have used the Light Networking Library. The lNet library provides non-blocking network access, but is a bit harder to use for that reason. The Synapse UDP library will easily replace the serial library I had been using.

First, you need to change the uses clause to add the blksock library (this is the Synapse UDP library) AND you MUST remove the synaser library from the uses clause (I didn’t do that to initially and was getting compile errors for some of the constants).

    {$IFDEF UNIX}{$IFDEF UseCThreads}

The Synapse library has the ability to pass it a method to use as a callback to provide status. This is quite useful during debug. To do this I had to add the following declarations:

  TMyEventOBject = class
    procedure myStatus(Sender: TObject; Reason: THookSocketReason; const Value: string);

    mycallback                            : TMyEventObject;

Further I added the actual callback procedure:

procedure TMyEventObject.myStatus(
        Sender                           : TObject;
        Reason                           : THookSocketReason;
const   Value                            : string

    sReason                             : String;


case Reason of
    HR_ResolvingBegin: sReason := 'HR_ResolvingBegin';

if (debug) then
    writeln('  ' + sReason + ': ' + Value );

end; // TMyEventObject.myStatus

The initializeComm procedure now accepts IP/Port of the arduino instead of serial communication information. It then initializes the UDP library:

udp          := TUDPBlockSocket.Create;
udp.OnStatus := @mycallback.myStatus;

    udp.Connect( ipAddr, port);
    writeln('Error connecting to Arduino via UDP.');

In the outer block, instead of closing the serial communications library, now we close the UDP communications library:


The Pascal and Arduino programs are pretty close to a mirror of each other. I just have to fix the same procedures in the Pascal code I did in the Arduino sketch. So I just need to fix the 2 procedures that read/write packets from the hardware.

Receiving the packet is very simple, just use udp.recvString (this is much simpler than the serial code was):

function p2a_i_recvPacket(
    var    packet                        : string
    )                                    : boolean;

    s                                    : string            = '';


    s := UDP.RecvString(1*1000);
    writeln('@p2a_i_recvPacket: recvString error. LastError=', udp.LastError);

packet               := s;
p2a_i_recvPacket     := true;

end; // p2a_i_recvPacket

and transmitting the packet is equally easy:

procedure p2a_i_xmitPacket(
        packet                            : string


    writeln('@p2a_i_xmitPacket: SendString Failed. LastError=', udp.lastError);

end; // p2a_i_xmitPacket

And that is all there is to fixing the code. The nice thing about communicating over the network is now it is possible to use a protocol analyzer such as Wireshark and watch exactly what is going out over the wire. Makes troubleshooting your code much easier.

Here is code for this project:



This entry was posted in c-arduino, c-lazarus and tagged , . Bookmark the permalink.

3 Responses to UDP Communications between a PC and an Arduino Using Lazarus / Free Pascal

  1. Pingback: UDP Communications between a Raspberry Pi and an Arduino Using Lazarus / Free Pascal | Big Dan the Blogging Man

  2. Pingback: TCP Communications between a PC and an Arduino Using Lazarus / Free Pascal | Big Dan the Blogging Man

  3. Pingback: TCP Communications between a Raspberry Pi and an Arduino Using Lazarus / Free Pascal | Big Dan the Blogging Man

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.