Dateien nach "/" hochladen

init
This commit is contained in:
Johannes Guter 2024-10-07 19:55:43 +02:00
commit 7c73e07a09
3 changed files with 704 additions and 0 deletions

189
Arduino_Code.ino Normal file
View File

@ -0,0 +1,189 @@
//Code für den Arduino, später nur den Pin 11 entfernen, da der für das selbstständige Triggern ohne Messrad benutzt wird
#include <EEPROM.h>
volatile unsigned int counter = 0;
unsigned long lastSignalMillis1 = 0;
unsigned long lastSignalMillis2 = 0;
unsigned long time200 = 0;
bool signalActive1 = false;
bool signalActive2 = false;
int trigger = 10;
int vortrigger = 8;
int belichtung = 3;
bool pwmAktiv = false;
bool light_reset = false;
volatile float pwmFrequency = 15000; // PWM-Frequenz in Hz
volatile float dutyCycle = 70; // Duty Cycle in Prozent
long tast = (16000000L / pwmFrequency) * (dutyCycle / 100);
void setup() {
Serial.begin(9600);
// Falls vorhanden, werden die letzten gespeicherten Werte aus dem EEPROM gelesen
EEPROM.get(0, trigger);
EEPROM.get(4, vortrigger);
EEPROM.get(8, belichtung);
EEPROM.get(12, pwmFrequency);
EEPROM.get(16, dutyCycle);
//EEPROM.get(20, pwmAktiv);
//Falls nicht vorhanden, werden vordefinierte Werte verwendet und in den EEPROM geschrieben
if ((trigger == 0 || trigger == -1) || (vortrigger == 0 || vortrigger == -1) || (belichtung == 0 || belichtung == -1) || (pwmFrequency == 0 || pwmFrequency == -1) || (dutyCycle == 0 || dutyCycle == -1))
{
trigger = 10;
vortrigger = 8;
belichtung = 3;
pwmFrequency = 15000;
dutyCycle = 10;
pwmAktiv = false;
EEPROM.put(0, trigger);
EEPROM.put(4, vortrigger);
EEPROM.put(8, belichtung);
EEPROM.put(12, pwmFrequency);
EEPROM.put(16, dutyCycle);
//EEPROM.put(20, pwmAktiv);
}
updateTast(); //Tastverhältnis für die PWM Einstellung aktuallisieren
pinMode(2, INPUT); // Eingangspin
pinMode(13, OUTPUT); // Hauptausgang zum Triggern der Kameras
pinMode(12, OUTPUT); //Zweiter Hauptausgang zum Triggern der Kameras (Aufgrund von reduzierter Belastbarkeit des Stromteilers benötigt)
pinMode(9, OUTPUT); // PWM-Ausgang für Beleuchtung
pinMode(11, OUTPUT); // PWM-Ausgang für das selbstständige Triggern
// Timer 1 Konfiguration fast PWM an Pin 9
TCCR1A = 0;
TCCR1B = 0;
TCCR1A |= (1 << COM1A1) | (1 << WGM11);
TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1 << CS10);
ICR1 = (16000000L / pwmFrequency) - 1;
//Pin 2 (Eingang Messrad) erzeugt einen Interrupt um Impulse sicher zu erfassen
attachInterrupt(digitalPinToInterrupt(2), countSignal, RISING);
}
void loop() {
int cycleTime = 4000; // Mikrosekunden 3703 = 27 Hz (nur für selbstständiges Triggern benötigt)
int onTime = cycleTime * 0.5; // 50% Duty Cycle
int offTime = cycleTime - onTime;
digitalWrite(11, HIGH);
delayMicroseconds(onTime);
digitalWrite(11, LOW);
delayMicroseconds(offTime);
if (counter >= vortrigger) { //Beleuchtung X Impulse vor dem Kameratrigger einschalten
if (!signalActive2) {
signalActive2 = true;
OCR1A = tast;
}
lastSignalMillis2 = millis();
}
if (counter >= trigger) { //Kameras triggern
time200 = millis();
if (!signalActive1) {
signalActive1 = true;
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
}
lastSignalMillis1 = millis();
counter -= trigger;
}
if (signalActive2 && (millis() - time200 >= belichtung) && counter < vortrigger && pwmAktiv==false) { //Beleuchtung ausschalten, wenn Belichtungszeit (beginnend ab Trigger) vorbei ist und der Counter wieder zurückgesetzt wurde
signalActive2 = false;
OCR1A = 0;
}
if (signalActive1 && (millis() - lastSignalMillis1 >= 1)) {
signalActive1 = false;
digitalWrite(13, LOW);
digitalWrite(12, LOW);
}
if (pwmAktiv == true) //Beleuchtung dauerhaft an wenn das über GUI angefordert wurde. (Noch to do: Diese Abfrage aus dem loop herausziehen und den Aufruf in recieveData packen)
{
OCR1A = tast;
}
if (light_reset == true) {
OCR1A = 0;
light_reset = false;
}
if (Serial.available() > 0) {
receiveData();
}
}
void countSignal() {
counter++;
}
void updateTast() {
tast = (16000000L / pwmFrequency) * (dutyCycle / 100);
ICR1 = (16000000L / pwmFrequency) - 1;
}
//Funktion zum Erhalten von Daten über den RPi
void receiveData() {
String data = Serial.readStringUntil('\n');
if (data.startsWith("SET")) {
String command = data.substring(4);
if (command.startsWith("trigger")) {
trigger = command.substring(8).toInt();
EEPROM.put(0, trigger);
} else if (command.startsWith("vortrigger")) {
int tempVortrigger = command.substring(11).toInt();
vortrigger = trigger - tempVortrigger;
EEPROM.put(4, vortrigger);
} else if (command.startsWith("belichtung")) {
belichtung = command.substring(11).toInt();
EEPROM.put(8, belichtung);
} else if (command.startsWith("pwmFrequency")) {
pwmFrequency = command.substring(13).toInt();
EEPROM.put(12, pwmFrequency);
updateTast();
} else if (command.startsWith("dutyCycle")) {
int dutyCycleInt = command.substring(10).toInt();
dutyCycle = dutyCycleInt / 1.0;
EEPROM.put(16, dutyCycle);
updateTast();
} else if (command.startsWith("pwm_aktiv")) {
pwmAktiv = command.substring(10).toInt();
EEPROM.put(20, pwmAktiv);
if (pwmAktiv == 0) {
light_reset = 1;
}
}
} else if (data.startsWith("GET")) {
sendData();
}
}
//Funktion zum Senden von Daten an den RPi
void sendData() {
String data = "trigger:" + String(trigger) + ";";
data += "vortrigger:" + String(trigger-vortrigger) + ";";
data += "belichtung:" + String(belichtung) + ";";
data += "pwmFrequency:" + String(pwmFrequency) + ";";
data += "dutyCycle:" + String(int(dutyCycle)) + ";";
data += "pwm_aktiv:" + String(pwmAktiv) + ";";
Serial.println(data);
}

353
Hauptprogramm.py Normal file
View File

@ -0,0 +1,353 @@
#Hauptprogramm; Nimmt kontinuierlich Bilder auf wenn externer Trigger ausgelöst wird und speichert diese bei Bedarf
import cv2
import av
import time
import subprocess
import multiprocessing
from multiprocessing import shared_memory
import sys
import signal
import RPi.GPIO as GPIO
import numpy as np
import psutil
import os
#Region of Interest definieren:
roi_start = 0 #min: 0
roi_end = 800 #max: 720
roi_breite = roi_end - roi_start
#Warnungen von av deaktivieren (Ansonsten kommt dauerhaft eine Warnung über ein mögliches falsches Pixelformat, ist aber iO)
av.logging.set_level(av.logging.ERROR)
#GPIO Pin für Speicherimpuls einstellen
ausloeser = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(ausloeser, GPIO.IN, pull_up_down = GPIO.PUD_UP)
#Kameraeinstellungen; Soll später aus einer Textdatei ausgelesen werden, die über ein GUI eingestellt wird (Fast fertig)
camera_ids = [0, 2, 4, 6]
triggermodus_on = "v4l2-ctl -d %d -c exposure_dynamic_framerate=1"
triggermodus_off = "v4l2-ctl -d %d -c exposure_dynamic_framerate=0"
belichtung = "v4l2-ctl -d %d -c exposure_time_absolute=1"
auto_exposure = "v4l2-ctl -d %d -c auto_exposure=1"
brightness = "v4l2-ctl -d %d -c brightness=64"
contrast = "v4l2-ctl -d %d -c contrast=64"
#Funktion um die Kameraeinstellungen an das Terminal zu senden
def run_cmd(cmd):
try:
subprocess.run(cmd, shell=True, check=True)
except subprocess.CalledProcessError as e:
print("Fehler", e)
#Ctrl+C zum Programmabbruch definieren
def signal_handler(sig, frame):
print('Abbruch')
sys.exit(0)
#Evtl. noch Kameras schließen, Python Prozesse beenden, Bildspeicher komplett leeren, usw..)
signal.signal(signal.SIGINT, signal_handler)
#Klasse definieren, um Bilder von den Kameras aufzunehmen
class CameraModule():
def run(self, camera_id, camera_values, shm_np_block, shm_camera_id_block, shm_k_block):
shm_np_array = np.ndarray(shm_shape, dtype='uint8', buffer=shm_np_block.buf)
shm_camera_id_array = np.frombuffer(shm_camera_id_block.buf, dtype='int32')
shm_k_array = np.frombuffer(shm_k_block.buf, dtype='int32')
shm_cam_id = np.frombuffer(camera_values.buf, dtype='int32')
ring_counter = 0
#Cv2-Stream öffnen (Ohne den Cv2 Warmup werden die Kameras komischerweise nicht korrekt gestartet, hab da vieles probiert..)
cap = cv2.VideoCapture(f"/dev/video{camera_id}", cv2.CAP_V4L2)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 800)
for _ in range(50): #50 Bilder aufnehmen um Kamera zu stabilisieren
ret, frame = cap.read()
cap.release()
cv2.destroyAllWindows()
time.sleep(5)
#av-Kameraeinstellungen
options = {
'video_size': '1280x800',
'framerate': '60',
'input_format': 'mjpeg'
}
input_stream = av.open('/dev/video{}'.format(camera_id), format='video4linux2', options=options)
time.sleep(1)
video_stream = next(s for s in input_stream.streams if s.type == 'video')
framerate = video_stream.average_rate
print(f"Kamera {camera_id} Framerate: {framerate}") #Zur Kontrolle
#50 Bilder aufnehmen; Dient dazu, die Kamera zu stabilisieren (Weißabgleich usw.)
for _ in range(50):
frame = next(input_stream.decode(video_stream))
time.sleep(0.1)
#Triggermodus der Kamera auf externen Trigger umstellen
run_cmd(triggermodus_on % camera_id)
k = 1
frame = None
ring_counter = 0
#Buffer der Kameras (~5 Bilder) füllen und Trigger synchronisieren; Wird später auch noch automatisiert durch Verbindung mit dem Arduino
print("Trigger auslösen bis Freigabe kommt")
for _ in range(50):
frame = next(input_stream.decode(video_stream))
print("Freigabe erteilt")
time.sleep(5)
print("Bereit")
#Kontinuierlich Bilder aufnehmen und in die image_queue schreiben
while True:
slot = (camera_id // 2 + ring_counter * 4) % 200
frame = next(input_stream.decode(video_stream))
numpy_frame = frame.to_ndarray(format='bgr24')[roi_start:roi_end, :]
freigabe = shm_k_array[slot]
if freigabe == 0:
shm_np_array[slot] = numpy_frame
shm_camera_id_array[slot] = camera_id
shm_k_array[slot] = k
shm_cam_id[camera_id//2] = k
k += 1
ring_counter = (ring_counter + 1)
else:
print("Speicher wird überschrieben")
print(shm_k_array[slot])
print(slot)
print(camera_id)
#Noch eine Fehlererkennung einbauen, falls Frame nicht ausgelesen werden kann?
#Kameraworker definieren
def camera_worker(camera_id, camera_values, shm_np_block, shm_camera_id_block, shm_k_block, cpu_core):
p = psutil.Process(os.getpid())
p.cpu_affinity([cpu_core]) #Jede Instanz wird auf einem seperaten CPU Kern ausgeführt
camera_module = CameraModule()
camera_module.run(camera_id, camera_values, shm_np_block, shm_camera_id_block, shm_k_block)
#Klasse definieren, um GPIO/Speicherimpuls zu überwachen
class SaveHandler():
def __init__(self, camera_values, trigger_liste):
self.camera_values = camera_values
self.trigger_liste = trigger_liste
GPIO.add_event_detect(ausloeser, GPIO.FALLING, callback=self.ausloeser_callback, bouncetime=200)
def ausloeser_callback(self, channel):
shm_cam_id = np.frombuffer(camera_values.buf, dtype='int32')
while True:
if not GPIO.input(channel):
cam_value = shm_cam_id
self.trigger_liste.append(cam_value)
print("Trigger empfangen")
time.sleep(1) #Ist nur Testweise drin, damit nicht zu oft getriggert wird durch betätigen eines Tasters
def handler_worker(camera_values, trigger_liste):
handler = SaveHandler(camera_values, trigger_liste)
handler.ausloeser_callback(ausloeser)
#Klasse definieren, um Bilder von der image_queue zu holen und an den Saver zu senden, falls gewünscht
class SaveImageProcess():
def __init__(self, shm_np_block, shm_camera_id_block, shm_k_block, trigger_liste, shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t):
self.trigger_liste = trigger_liste
self.shm_np_block = shm_np_block
self.shm_camera_id_block = shm_camera_id_block
self.shm_k_block = shm_k_block
self.shm_save_frame = shm_save_frame
self.shm_save_k = shm_save_k
self.shm_save_camera_id = shm_save_camera_id
self.shm_save_ts = shm_save_ts
self.shm_save_t = shm_save_t
def run(self, shm_np_block, shm_camera_id_block, shm_k_block, trigger_liste, shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t):
shm_np_array = np.ndarray(shm_shape, dtype='uint8', buffer=shm_np_block.buf)
shm_camera_id_array = np.frombuffer(shm_camera_id_block.buf, dtype='int32')
shm_k_array = np.frombuffer(shm_k_block.buf, dtype='int32')
shm_save_frame_array = np.ndarray(save_shape, dtype='uint8', buffer=shm_save_frame.buf)
shm_save_k_array = np.frombuffer(shm_save_k.buf, dtype='int32')
shm_save_camera_id_array = np.frombuffer(shm_save_camera_id.buf, dtype='int32')
shm_save_ts_array = np.frombuffer(shm_save_ts.buf, dtype='int32')
shm_save_t_array = np.frombuffer(shm_save_t.buf, dtype='int32')
ring_counter = 0
save_counter = 0
j = 0
l = 0
print("SaveImageProcess gestartet")
while True:
non_zero_indices = [index for index, value in enumerate(shm_k_array[:]) if value != 0]
if len(non_zero_indices) > 20:
print(non_zero_indices)
for index in non_zero_indices:
camera_id = shm_camera_id_array[index]
k = shm_k_array[index]
shm_k_array[index] = 0
trigger_test = np.array(trigger_liste)
for i in range(j, trigger_test.shape[0]):
if k >= (trigger_test[i][camera_id//2]-5+1) and k <= (trigger_test[i][camera_id//2]+5+1):
shm_save_frame_array[save_counter] = shm_np_array[index]
shm_save_camera_id_array[save_counter] = camera_id
shm_save_k_array[save_counter] = k
shm_save_ts_array[save_counter] = trigger_test[i][camera_id//2]
shm_save_t_array[save_counter] = i
save_counter = (save_counter + 1) % 200
if k > (trigger_test[i][camera_id//2]+200):
j += 1
def save_worker(shm_np_block, shm_camera_id_block, shm_k_block, trigger_liste, shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t):
save_worker = SaveImageProcess(shm_np_block, shm_camera_id_block, shm_k_block, trigger_liste, shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t)
save_worker.run(shm_np_block, shm_camera_id_block, shm_k_block, trigger_liste, shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t)
#Klasse um die Bilder zu speichern (Ist aufgeteilt, da das Speichern der Bilder deutlich der Aufnahme der Bilder hinterherhängt und ohne diesen Frames verworfen werden)
class Saver():
def __init__(self, shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t):
self.shm_save_frame = shm_save_frame
self.shm_save_k = shm_save_k
self.shm_save_camera_id = shm_save_camera_id
self.shm_save_ts = shm_save_ts
self.shm_save_t = shm_save_t
def run(self, shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t):
shm_save_frame_array = np.ndarray(save_shape, dtype='uint8', buffer=shm_save_frame.buf)
shm_save_k_array = np.frombuffer(shm_save_k.buf, dtype='int32')
shm_save_camera_id_array = np.frombuffer(shm_save_camera_id.buf, dtype='int32')
shm_save_ts_array = np.frombuffer(shm_save_ts.buf, dtype='int32')
shm_save_t_array = np.frombuffer(shm_save_t.buf, dtype='int32')
ring_counter = 0
while True:
if shm_save_k_array[ring_counter] != 0:
filename = "/mnt/ramdisk/Cam{}_T{}_TS{}_B{}.jpg".format(shm_save_camera_id_array[ring_counter], shm_save_t_array[ring_counter], shm_save_ts_array[ring_counter], shm_save_k_array[ring_counter])
cv2.imwrite(filename, shm_save_frame_array[ring_counter])
shm_save_k_array[ring_counter] = 0
ring_counter = (ring_counter + 1) % 200
def saver_worker(shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t):
saver = Saver(shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t)
saver.run(shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t)
if __name__ == "__main__":
#Einstellungen der Shared Memory Blöcke
shm_shape = (200, roi_breite, 1280, 3)
save_shape = (200, roi_breite, 1280, 3)
cv_shape = (1, 4, 1, 1)
shm_np_block = shared_memory.SharedMemory(create=True, size=shm_shape[0]*shm_shape[1]*shm_shape[2]*shm_shape[3]*np.dtype('uint8').itemsize)
shm_camera_id_block = shared_memory.SharedMemory(create=True, size=200 * np.dtype('int32').itemsize)
shm_k_block = shared_memory.SharedMemory(create=True, size=200 * np.dtype('int32').itemsize)
shm_save_frame = shared_memory.SharedMemory(create=True, size=save_shape[0]*save_shape[1]*save_shape[2]*save_shape[3]*np.dtype('uint8').itemsize)
shm_save_k = shared_memory.SharedMemory(create=True, size=200 * np.dtype('int32').itemsize)
shm_save_camera_id = shared_memory.SharedMemory(create=True, size=200 * np.dtype('int32').itemsize)
shm_save_ts = shared_memory.SharedMemory(create=True, size=200 * np.dtype('int32').itemsize)
shm_save_t = shared_memory.SharedMemory(create=True, size=200 * np.dtype('int32').itemsize)
camera_values = shared_memory.SharedMemory(create=True, size= 4*np.dtype('int32').itemsize)
#Kameraeinstellungen vornehmen/Wird später durch GUI ersetzt
print("Kameras einstellen")
for i in [0, 2, 4, 6]:
run_cmd(triggermodus_off % i)
time.sleep(0.5)
run_cmd(auto_exposure % i)
time.sleep(0.5)
run_cmd(belichtung % i)
time.sleep(0.5)
run_cmd(brightness % i)
time.sleep(0.5)
run_cmd(contrast % i)
time.sleep(0.5)
print("Kamera %d eingestellt" % i)
#Trigger_liste als Multiprocessing-Liste erstellen
manager = multiprocessing.Manager()
trigger_liste = manager.list()
processes = []
i = 0
cpu_cores = [0, 1, 2, 3]
for camera_id in camera_ids:
process = multiprocessing.Process(target=camera_worker, args=(camera_id, camera_values, shm_np_block, shm_camera_id_block, shm_k_block, cpu_cores[i]))
i += 1
process.start()
processes.append(process)
handler = SaveHandler(camera_values, trigger_liste)
save_process = multiprocessing.Process(target=save_worker, args=(shm_np_block, shm_camera_id_block, shm_k_block, trigger_liste, shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t))
processes.append(save_process)
save_process.start()
saver2 = Saver(shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t)
saver2.run(shm_save_frame, shm_save_k, shm_save_camera_id, shm_save_ts, shm_save_t)
process.join()
save_process.join()
saver2.join()

162
Steuerung_Arduino.py Normal file
View File

@ -0,0 +1,162 @@
#Erstellt die grafische Oberfläche und ermöglicht die serielle Kommunikation mit dem Arduino, um die Einstellungen für die Beleuchtung und Triggerhandhabung vorzunehmen
import tkinter as tk
from tkinter import messagebox
import serial
import os
class Entry:
def __init__(self, root):
self.root = root
root.title("Steuerung Arduino")
root.protocol("WM_DELETE_WINDOW", self.on_closing)
self.settings_file = "/home/pi/Arduino/einstellungen.txt"
settings_path = os.path.dirname(self.settings_file)
if not os.path.exists(settings_path):
os.makedirs(settings_path)
self.load_settings() #Einstellungen beim Start des Programms laden
try:
self.ser = serial.Serial("/dev/ttyUSB0", 9600, timeout = 2) #Serielle Verbindung zum Arduino aufbauen mit 2 Sekunden Timeout
except serial.SerialException as e:
messagebox.showerror("Fehler in der Kommunikation mit dem Arduino", e)
return
self.create_widgets()
root.geometry("400x500")
#Widgets für die GUI erstellen (Checkboxen, Eingabefelder, Beschriftungen)
def create_widgets(self):
self.entries = []
names = ["trigger", "vortrigger", "belichtung", "pwmFrequency", "dutyCycle"]
description = ["Impulse zum Auslösen des Kameratriggers", "Start der Beleuchtung vor dem Kameratrigger", "Belichtungsdauer", "Frequenz PWM", "Duty Cycle PWM"]
units = ["Imp", "Imp", "ms", "Hz", "%"]
extra = ["[250 Hz - 60 kHz]", "[0 - 100 %]"]
i = 0
for name in names:
frame = tk.Frame(self.root)
frame.pack(fill=tk.X, pady=5)
tk.Label(frame, text = description[i]).pack()
entry_frame = tk.Frame(frame)
entry_frame.pack(side=tk.TOP)
entry = tk.Entry(entry_frame, width = 7)
entry.pack(side=tk.LEFT)
unit = tk.Label(entry_frame, text=units[i]).pack(side=tk.LEFT)
entry.insert(0, self.settings.get(name, ''))
self.entries.append((name, entry))
i += 1
self.pwm_aktiv = tk.IntVar(value = self.settings.get("pwm_aktiv", 0))
tk.Checkbutton(self.root, text = "Beleuchtung einschalten", variable=self.pwm_aktiv).pack(pady=5)
tk.Button(self.root, text = "Einstellungen an Arduino senden", command = self.send_arduino_settings).pack(pady=5)
tk.Button(self.root, text = "Einstellungen aus Arduino laden", command = self.load_arduino_settings).pack(pady=5)
tk.Button(self.root, text='Einstellungen speichern', command=self.save_settings).pack(pady=5)
tk.Button(self.root, text='Einstellungen laden', command=self.load_settings).pack(pady=5)
#Funktion um die Einstellungen in der Textdatei zu speichern
def save_settings(self):
settings = [f"{name}:{entry.get()}\n" for name, entry in self.entries]
with open(self.settings_file, "w") as f:
f.writelines(settings)
#Funktion um Einstellungen aus Textdatei zu lesen
def load_settings(self):
if os.path.exists(self.settings_file):
with open(self.settings_file, "r") as f:
self.settings = {line.split(':')[0]: line.split(':')[1].strip() for line in f}
else:
self.settings = {}
#Einstellungen über serielle Verbindung vom Arduino laden
def load_arduino_settings(self):
if not self.ser.is_open:
messagebox.showerror("Fehler", "Keine Verbindung zum Arduino")
return
try:
self.ser.write(b'GET\n')
data = self.ser.readline().decode('utf-8').strip()
except serial.SerialException as e:
messagebox.showerror("Fehler in der Kommunikation mit dem Arduino", e)
return
settings = data.split(';')
for setting, (name, entry) in zip(settings, self.entries):
try:
value = setting.split(':')[1]
except IndexError:
messagebox.showerror("Fehler", "Unerwartete Daten vom Arduino erhalten, Kommunikation überprüfen")
return
if name == "pwm_aktiv":
self.pwm_aktiv.set(int(value))
if "." in value:
float_value = float(value)
if float_value.is_integer():
value = int(float_value)
entry.delete(0, tk.END) #Feld leeren
entry.insert(0, value) #Am Anfang des Feldes wird Value eingegeben
self.settings[name] = value #Werte in settings speichern
#Einstellungen über serielle Verbindung an Arduino senden
def send_arduino_settings(self):
if not self.ser.is_open:
messagebox.showerror("Fehler", "Keine Verbindung zum Arduino")
return
try:
for name, entry in self.entries:
value = entry.get()
if not value.isdigit() and name != "pwm_aktiv":
messagebox.showerror("Fehler", f"Ungültiger Wert für {name}")
return
if name == "pwmFrequency" and not (250 <= float(value) <= 60000):
messagebox.showerror("Fehler", f"Ungültiger Wert für PWM Frequenz. Der Wert muss zwischen 250 und 60000 liegen")
return
if name == "dutyCycle" and not (0 <= int(value) <= 100):
messagebox.showerror("Fehler", f"Ungültiger Wert für Duty Cycle. Der Wert muss zwischen 0 und 100 liegen")
return
command = f"SET {name} {value}"
self.ser.write((command + "\n").encode("utf-8"))
command = f"SET pwm_aktiv {self.pwm_aktiv.get()}"
self.ser.write((command + "\n").encode("utf-8"))
except serial.SerialException as e:
messagebox.showerror("Fehler in der Kommunikation mit dem Arduino", e)
return
def on_closing(self):
if self.ser.is_open:
self.ser.close()
self.root.destroy()
if __name__ == "__main__":
root = tk.Tk()
app = Entry(root)
root.mainloop()