This website uses cookies to ensure you get the best experience.

Industrial 7-Segment Display Control System over Embedded Linux & TCP/IP

Publication Date: 10 September 2026

Watch System in Action:

In this industrial automation setup, we showcase real-time remote control of a 4-digit industrial 7-segment display panel using a C host engine, Lua scripting, and TCP/IP socket communication running on the RDF-GW2 Embedded Linux Gateway. The system features seamless hot-reloading (live code updates) and a high-speed shared memory IPC architecture.

System Architecture & Software Layers

The field display control system is designed with a layered software architecture to ensure high performance, modularity, and rapid live development:

  • RDF-GW2 (Embedded Linux Gateway): Located at the heart of the system, this Linux-based gateway device executes low-level hardware drivers and high-level application services simultaneously.
  • C Driver Core (Segment Driver): Directly controls shift-register ICs and digital pin matrices at the hardware layer, enabling high-frequency scanning of 7-segment characters and decimal points.
  • Shared Memory (/dev/shm IPC): Utilizes the Linux RAM-based `/dev/shm` filesystem for zero-latency data exchange between the C driver engine and the Lua application layer.
  • Seamless Lua Engine & Hot-Reloading: The `script.lua` file is monitored by the C engine via `mtime` tracking. Code modifications deployed via SFTP are instantly loaded into the live environment without service downtime.
  • TCP Socket Server & Python Client: A non-blocking TCP server listening on Port 5000 allows remote PCs, PLCs, or SCADA systems (via a Python client) to send dynamic character strings over the network to update the panel in real time.

Key Features & Operating Principles

Live Hot-Reloading

Lua code updated from VS Code is immediately detected and reloaded by the C host program without dropping active TCP socket connections or requiring a system reboot.

Remote TCP Socket Control

Text payloads like `"12.34"` or `"A.B.C.D."` sent from Python or any TCP client are automatically parsed and displayed on the 4-digit panel with sub-second latency.

Decimal Point (DP) Support

Thanks to smart string-parsing logic, dot `.` characters do not occupy an extra digit slot; instead, they automatically activate the decimal LED segment (`Bit 7 / 0x80`) of the corresponding digit.

High-Speed Shared Memory (IPC)

Leveraging Linux `/dev/shm` (Shared Memory) eliminates disk I/O overhead, allowing the Lua script and C driver to communicate through system RAM within microseconds.

Implementation Code Examples

Below are the practical implementation scripts powering the IPC write interface, non-blocking TCP server, and client communication:

1. Direct IPC Memory Writing (Basic Lua Example)

This initial script demonstrates writing character payloads directly to the RAM-backed /dev/shm/ nodes monitored by the C driver core:

-- script.lua
print("--- 7-Segment Control ---")

local function io_write(display_node, payload)
    local path = "/dev/shm/" .. display_node .. "_out"
    local file = io.open(path, "w")
    if file then
        file:write(tostring(payload))
        file:close()
    else
        print("Error: Could not write to target shared memory " .. path)
    end
end

local display1 = "display1"
local display2 = "display2"
local display3 = "display3"
local display4 = "display4"

io_write(display1, "1")
io_write(display2, " ")
io_write(display3, " ")
io_write(display4, " ")
--os.execute("sleep 1")

2. Non-Blocking TCP Display Server (Advanced Lua Service)

This production script runs on Port 5000. On each loop step, it polls for incoming socket clients, handles decimal point placement automatically, and updates shared memory:

-- /root/script.lua
local socket = require("socket")

print("--- Starting Non-Blocking TCP Display Server (Port 5000) ---")

-- Bind TCP server once on load
local server = assert(socket.bind("*", 5000))
server:settimeout(0) -- Non-blocking check

local function io_write(display_node, payload)
    local path = "/dev/shm/" .. display_node .. "_out"
    local file = io.open(path, "w")
    if file then
        file:write(tostring(payload))
        file:close()
    else
        print("Error: Could not write to " .. path)
    end
end

local function update_displays(text)
    local displays = {"display1", "display2", "display3", "display4"}
    local char_idx = 1
    local text_len = #text

    for d = 1, 4 do
        if char_idx <= text_len then
            local char = text:sub(char_idx, char_idx)
            local payload = char

            if char_idx + 1 <= text_len and text:sub(char_idx + 1, char_idx + 1) == "." then
                payload = payload .. "."
                char_idx = char_idx + 2
            else
                char_idx = char_idx + 1
            end

            io_write(displays[d], payload)
        else
            io_write(displays[d], " ")
        end
    end
end

-- This function will be called by C on every loop tick
function step()
    local client = server:accept()
    if client then
        client:settimeout(0.5)
        local line, err = client:receive()
        if not err and line then
            print("Received command: " .. line)
            update_displays(line)
            client:send("OK\n")
        end
        client:close()
    end
end

3. Remote Python Socket Client

A lightweight Python script that connects to the RDF-GW2 Gateway over TCP and sends commands (e.g., python send_display.py "12.34"):

import socket
import sys

GATEWAY_IP = "192.168.1.50"
GATEWAY_PORT = 5000

def send_to_display(text: str):
    """
    Sends a string payload over TCP to the 7-segment Gateway.
    Examples:
      - "1234"   -> Displays 1, 2, 3, 4
      - "1.234"  -> Displays 1. on segment 1, 2, 3, 4 on rest
      - "A B C"  -> Displays A, space, B, space
    """
    try:
        # Create TCP/IP socket
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client:
            client.settimeout(2.0)
            client.connect((GATEWAY_IP, GATEWAY_PORT))
            
            # Send message terminated with a newline
            message = text + "\n"
            client.sendall(message.encode('utf-8'))
            
            # Wait for acknowledgement from Gateway
            response = client.recv(1024).decode('utf-8')
            print(f"Gateway Response: {response.strip()}")

    except Exception as e:
        print(f"Error communicating with Gateway ({GATEWAY_IP}): {e}")

if __name__ == "__main__":
    if len(sys.argv) > 1:
        # Pass command line argument if provided: python send_display.py "12.34"
        display_text = sys.argv[1]
    else:
        # Default test string
        display_text = "0050"

    print(f"Sending '{display_text}' to 7-Segment Gateway ({GATEWAY_IP})...")
    send_to_display(display_text)

Unlike traditional displays with rigid firmware, this flexible Linux architecture and remote TCP connectivity make it easy to deploy as a dynamic status indicator, counter, or telemetry panel in demanding industrial environments.



Project Summary
Industry: Industrial Automation & Field Indicators
Communication: TCP/IP Socket (Port 5000) & Shared Memory (/dev/shm)
Languages: Embedded C, LuaScript, Python 3
Features: Live Hot-Reloading, Non-Blocking Polling
Hardware: RDF-GW2 Linux Gateway, 4-Digit 7-Segment Panel