Gömülü Linux ve TCP/IP Üzerinden Endüstriyel 7-Segment Ekran Kontrol Sistemi
Sistemin Çalışmasını İzleyin:
Bu endüstriyel otomasyon uygulamasında, RDF-GW2 Embedded Linux Ağ Geçidi üzerinde çalışan C çekirdeği, Lua betik motoru ve TCP/IP soket haberleşmesi kullanarak 4 haneli endüstriyel 7-segment ekran panelinin gerçek zamanlı ve uzaktan kontrolünü gerçekleştiriyoruz. Sistem, kesintisiz hot-reloading (canlı kod güncelleme) ve yüksek hızlı shared memory (paylaşımlı bellek) altyapısı sunar.
Sistem Mimarisi ve Yazılım Katmanları
Saha paneli kontrol sistemi, yüksek performans, modülerlik ve canlı kod geliştirme kolaylığı sağlayacak şekilde katmanlı bir yazılım mimarisiyle tasarlanmıştır:
- RDF-GW2 (Embedded Linux Gateway): Sistem merkezinde yer alan Linux tabanlı ağ geçidi cihazı, tüm donanım sürücülerini ve yüksek seviyeli uygulama servislerini çalıştırır.
- C Sürücü Çekirdeği (Segment Driver): Donanım seviyesindeki shift-register entegrelerini ve dijital pin matrisini doğrudan yönlendirerek 7-segment karakterlerin (ve ondalık noktaların) yüksek hızda taranmasını sağlar.
- Paylaşımlı Bellek (/dev/shm IPC): C sürücü motoru ile Lua uygulama katmanı arasındaki veri transferini sıfır gecikmeyle yürütmek için Linux RAM tabanlı `/dev/shm` dosya sistemini kullanır.
- Kesintisiz Lua Motoru & Hot-Reloading: `script.lua` dosyası C motoru tarafından `mtime` takibi ile izlenir. Kod üzerinde yapılan değişiklikler servis kesintisi yaşanmadan anında canlı sisteme aktarılır.
- TCP Soket Sunucusu & Python İstemci: Port 5000 üzerinden dinleme yapan non-blocking TCP sunucusu sayesinde uzaktaki PC, PLC veya SCADA sistemleri (Python istemcisi) ağ üzerinden ekrana anlık karakter dizileri gönderebilir.
Öne Çıkan Özellikler ve Çalışma Mantığı
Canlı Kod Güncelleme (Hot-Reloading)
VS Code üzerinden SFTP ile cihaza aktarılan yeni Lua kodları, C host programı tarafından anında algılanıp yeniden yüklenir; TCP soket bağlantısı kopmadan veya sistem yeniden başlatılmadan çalışma devam eder.
Ağ Üzerinden TCP Soket Kontrolü
Python veya herhangi bir TCP istemcisi üzerinden gönderilen `"12.34"`, `"A.B.C.D."` gibi metin verileri otomatik ayrıştırılarak 4 haneli ekran panelinde anında görüntülenir.
Ondalık Nokta (Decimal Point) Desteği
Ayrıştırma mantığı sayesinde gelen dizideki nokta `.` karakterleri bağımsız bir hane kaplamaz, ilişkili olduğu sayısal hanenin ondalık LED segmentini (`Bit 7 / 0x80`) otomatik aktif eder.
Yüksek Hızlı Paylaşımlı Bellek (IPC)
Linux `/dev/shm` (Shared Memory) yapısı sayesinde disk I/O yükü oluşmaz; Lua betiği ve C sürücüsü RAM üzerinden mikrosaniyeler içinde haberleşir.
Uygulama Kod Örnekleri
Aşağıda IPC bellek yazma arayüzü, non-blocking TCP sunucu yapısı ve istemci haberleşmesini sağlayan örnek kod blokları yer almaktadır:
1. Doğrudan IPC Bellek Yazımı (Temel Lua Örneği)
Bu başlangıç betiği, karakter verilerini C sürücü çekirdeği tarafından izlenen RAM tabanlı /dev/shm/ düğümlerine doğrudan yazar:
-- 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 Ekran Sunucusu (Gelişmiş Lua Servisi)
Port 5000 üzerinde çalışan bu servis, her döngüde istemci bağlantılarını kontrol eder, ondalık nokta konumlarını otomatik işler ve paylaşımlı belleği günceller:
-- /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. Uzaktan TCP Python İstemcisi
RDF-GW2 Gateway cihazına TCP üzerinden bağlanıp komut gönderen hafif Python betiği (örneğin: 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)
Geleneksel sabit yazılımlı gösterge panellerinin aksine, esnek Linux mimarisi ve uzaktan TCP haberleşmesi sayesinde bu çözüm endüstriyel sahalarda dinamik durum göstergesi, sayaç ve telemetri paneli olarak kolayca entegre edilebilir.