UDP server for Raspberry Pi in C that control GPIO (led pins)

Share your projects
Post Reply
User avatar
david
Site Admin
Posts: 366
Joined: Sat May 21, 2016 7:50 pm

UDP server for Raspberry Pi in C that control GPIO (led pins)

Post by david »

Join our telegram group if you wana chat or have specific questions:
https://t.me/+h2K5CX5jEZA0MWJk


This program is a UDP server running on a Raspberry Pi 3 that listens for commands to turn an LED on or off via GPIO pin 29 (which corresponds to physical pin 40 on the Raspberry Pi).

How It Works

The Raspberry Pi runs this program as a UDP server.
It waits for UDP messages on 192.168.1.70:54321.
When it receives a message, it:
Checks if the command is "ledon" or "ledoff".
Controls GPIO pin 29 to turn the LED on or off.
The program runs continuously, waiting for new commands.




Code: Select all


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <wiringPi.h>

#define SERVER_IP "192.168.1.70"
#define PORT 54321
#define BUFFER_SIZE 1024

void setup_gpio() {
    wiringPiSetup(); // Initialize WiringPi library
    pinMode(29, OUTPUT); // Set GPIO pin 2 (which is physical pin 28) as an output
}

int main() {
    int sockfd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);
    char buffer[BUFFER_SIZE];

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&server_addr, 0, sizeof(server_addr));
    memset(&client_addr, 0, sizeof(client_addr));

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

    if (bind(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Bind failed");
        exit(EXIT_FAILURE);
    }

    setup_gpio();

    printf("UDP Server is up and listening on %s:%d\n", SERVER_IP, PORT);

    while (1) {
        int n = recvfrom(sockfd, buffer, BUFFER_SIZE, MSG_WAITALL, (struct sockaddr *)&client_addr, &client_len);
        if (n < 0) {
            perror("Receive failed");
            continue;
        }

        buffer[n] = '\0'; // Null-terminate the received data
        printf("Received command: %s\n", buffer);

        if (strstr(buffer, "ledon") != NULL) {
            digitalWrite(29, HIGH); // Turn LED ON
            printf("LED turned ON\n");
        } else if (strstr(buffer, "ledoff") != NULL) {
            digitalWrite(29, LOW); // Turn LED OFF
            printf("LED turned OFF\n");
        } else {
            printf("Unknown command: %s\n", buffer);
        }
    }

    close(sockfd);
    return 0;
}


Breakdown of the Code
1. Includes Required Libraries

Code: Select all

#include <stdio.h>       // Standard I/O operations
#include <stdlib.h>      // Standard library for memory allocation, process control, etc.
#include <string.h>      // String manipulation functions
#include <unistd.h>      // POSIX API (e.g., close())
#include <arpa/inet.h>   // Networking functions (for UDP communication)
#include <wiringPi.h>    // Raspberry Pi GPIO control
These libraries are required for:

Networking (UDP communication)
GPIO control (wiringPi)
Basic I/O operations


2. Define Constants

Code: Select all

#define SERVER_IP "192.168.1.70" // Server's IP Address
#define PORT 54321               // Port number for UDP communication
#define BUFFER_SIZE 1024         // Buffer size for receiving messages
  • The server listens for incoming UDP messages on IP 192.168.1.70 and port 54321.
    The buffer size is 1024 bytes.

3. GPIO Setup Function

Code: Select all

void setup_gpio() {
    wiringPiSetup();      // Initialize WiringPi library
    pinMode(29, OUTPUT);  // Set GPIO pin 29 as an output
}
  • This function initializes the WiringPi library, which is used for controlling the Raspberry Pi’s GPIO pins.
    It sets GPIO pin 29 as an output (to control the LED).

4. Create and Bind a UDP Socket

Code: Select all

int sockfd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
char buffer[BUFFER_SIZE];

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    perror("Socket creation failed");
    exit(EXIT_FAILURE);
}

Code: Select all

[list=][b]socket(AF_INET, SOCK_DGRAM, 0) creates a UDP socket (instead of a TCP socket).
If the socket creation fails, it prints an error and exits.[/b][/list]

memset(&server_addr, 0, sizeof(server_addr));
memset(&client_addr, 0, sizeof(client_addr));

server_addr.sin_family = AF_INET; // IPv4
server_addr.sin_port = htons(PORT); // Set port (network byte order)
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); // Bind to given IP address
The server address structure is set up:

IPv4 (AF_INET)
Port 54321
IP 192.168.1.70

Code: Select all

if (bind(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
    perror("Bind failed");
    exit(EXIT_FAILURE);
}

  • The socket is bound to the IP and port.
    If binding fails, an error is printed and the program exits.


5. Start the UDP Server

Code: Select all

setup_gpio(); // Initialize GPIO settings
printf("UDP Server is up and listening on %s:%d\n", SERVER_IP, PORT);
  • Calls setup_gpio() to prepare the Raspberry Pi’s GPIO for LED control.
    Displays a message indicating the server is running.
6. Listen for UDP Messages

Code: Select all

while (1) {
    int n = recvfrom(sockfd, buffer, BUFFER_SIZE, MSG_WAITALL, 
                     (struct sockaddr *)&client_addr, &client_len);
    if (n < 0) {
        perror("Receive failed");
        continue;
    }
  • The server waits for a UDP packet using recvfrom().
    If a message is received, it is stored in buffer.
    If an error occurs, it prints an error and continues listening.

Code: Select all

buffer[n] = '\0'; // Null-terminate the received data
printf("Received command: %s\n", buffer);
  • The received message is null-terminated to ensure it is a valid string.
    The command is printed for debugging purposes.
7. Process Commands

Code: Select all

if (strstr(buffer, "ledon") != NULL) {
    digitalWrite(29, HIGH); // Turn LED ON
    printf("LED turned ON\n");
} else if (strstr(buffer, "ledoff") != NULL) {
    digitalWrite(29, LOW); // Turn LED OFF
    printf("LED turned OFF\n");
} else {
    printf("Unknown command: %s\n", buffer);
}
  • The program checks if the received message contains:

    "ledon" → Turns ON the LED using digitalWrite(29, HIGH).
    "ledoff" → Turns OFF the LED using digitalWrite(29, LOW).
    Otherwise, it prints "Unknown command".
8. Close the Socket (Cleanup)

Code: Select all

close(sockfd);
return 0;


User avatar
david
Site Admin
Posts: 366
Joined: Sat May 21, 2016 7:50 pm

Re: UDP server for Raspberry Pi in C that control GPIO (led pins)

Post by david »

How to Use:

1. Compile and Run on Raspberry Pi

Code: Select all

gcc -o led_server led_server.c -lwiringPi
sudo ./led_server
-lwiringPi links the WiringPi library for GPIO control.
Run with sudo to access GPIO.

2. Send UDP Commands

From another computer on the same network, send commands using netcat:

Code: Select all

echo "ledon" | nc -u 192.168.1.70 54321
echo "ledoff" | nc -u 192.168.1.70 54321

Or use Python with GUI

Image

How It Works
  • Enter the Raspberry Pi's IP and Port.
    Click "Turn LED ON" to send "ledon" via UDP.
    Click "Turn LED OFF" to send "ledoff" via UDP.
    Status messages show whether the command was sent successfully or if there's an error.

Code: Select all

sudo apt install python3-tk  # For Linux

Code: Select all

import tkinter as tk
import socket

# Function to send UDP command
def send_command(command):
    ip = ip_entry.get().strip()
    port = port_entry.get().strip()

    if not ip or not port:
        status_label.config(text="Enter IP and Port!", fg="red")
        return

    try:
        port = int(port)  # Convert port to integer
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.sendto(command.encode(), (ip, port))
        sock.close()
        status_label.config(text=f"Sent: {command}", fg="green")
    except ValueError:
        status_label.config(text="Invalid port number!", fg="red")
    except Exception as e:
        status_label.config(text=f"Error: {e}", fg="red")

# Create the GUI window
root = tk.Tk()
root.title("UDP LED Controller")
root.geometry("300x200")
root.resizable(False, False)

# IP and Port Input
tk.Label(root, text="IP Address:").pack()
ip_entry = tk.Entry(root)
ip_entry.pack()
ip_entry.insert(0, "192.168.1.70")  # Default IP

tk.Label(root, text="Port:").pack()
port_entry = tk.Entry(root)
port_entry.pack()
port_entry.insert(0, "54321")  # Default Port

# Buttons
ledon_button = tk.Button(root, text="Turn LED ON", command=lambda: send_command("ledon"), bg="green", fg="white")
ledon_button.pack(pady=5)

ledoff_button = tk.Button(root, text="Turn LED OFF", command=lambda: send_command("ledoff"), bg="red", fg="white")
ledoff_button.pack(pady=5)

# Status Label
status_label = tk.Label(root, text="", fg="black")
status_label.pack()

# Run the GUI
root.mainloop()


Post Reply