#!/usr/bin/python3 """ author Benoit Dubois copyright FEMTO ENGINEERING license GPL v3.0+ brief Basic GUI to deal with "PWM controller" of STM32 board. Need to connect USB cable to CN5 to open a serial link with board (usually /dev/ttyACM0). """ # Ctrl-c closes the application import signal signal.signal(signal.SIGINT, signal.SIG_DFL) import os import sys import struct import argparse import configparser import tkinter as tk from tkinter import messagebox import serial APPLICATION = "pwm_client" BASE_CONFIG_DIR = os.path.expanduser("~") + "/.config/" + APPLICATION PARAMETERS = ( {'mnemo': "value", 'default': 0, 'min': -100, 'max': 100, 'format': None}, ) #============================================================================== class ClientStmGui(tk.Frame): """Basic GUI to deal with "PWM handler" on STM32 board. """ def __init__(self, master=None): """ master: the parent window of the tk.Frame """ super().__init__(master) self.cctrl = tk.IntVar() self._build_ui() def _build_ui(self): lbl = (dict(), dict()) self.sbox = (dict(), dict()) self.box_val = (dict(), dict()) self.btn = (dict(), dict()) for pwmh in range(2): for param in PARAMETERS: lbl[pwmh][param['mnemo']] = tk.Label(text=param['mnemo']) self.box_val[pwmh][param['mnemo']] = tk.IntVar() self.sbox[pwmh][param['mnemo']] = tk.Spinbox(from_=param['min'], to=param['max'], textvariable=self.box_val[pwmh][param['mnemo']], format=param['format']) self.btn[pwmh][param['mnemo']] = tk.Button(text="Set") # Layout tk.Label(text='Controller 1').grid(row=0, column=1) tk.Label(text='Controller 2').grid(row=0, column=4) for pwmh in range(2): for idx, param in enumerate(PARAMETERS): lbl[pwmh][param['mnemo']].grid(row=idx+len(PARAMETERS)+1, column=pwmh*3+0) self.sbox[pwmh][param['mnemo']].grid(row=idx+len(PARAMETERS)+1, column=pwmh*3+1) self.btn[pwmh][param['mnemo']].grid(row=idx+len(PARAMETERS)+1, column=pwmh*3+2) # Global look self.config(bd=3, relief='groove') #============================================================================== class ClientPwm(object): def __init__(self, port, config_file, master=None): """ port: serial port device file (e.g. /dev/ttyACMx) config_file: a configuration file used to initialise the client master: the parent window (see ClientStmGui()) """ self.stm = serial.Serial(port=port, baudrate=9600, timeout=1, xonxoff=False, rtscts=False, dsrdtr=True) self.stm.reset_input_buffer() self.stm.reset_output_buffer() self.ui = ClientStmGui(master) for pwmh in range(2): for param in PARAMETERS: self.ui.btn[pwmh][param['mnemo']].configure( command=lambda x=pwmh, y=param['mnemo']: self.btn_clicked(x, y)) self.config_file = config_file self.config_to_device() self.config_to_ui() self.ui.mainloop() def btn_clicked(self, pwmh, mnemo): """Action when button is clicked """ try: value = self.ui.box_val[pwmh][mnemo].get() except Exception as ex: print("Value error: {}".format(ex)) return self.send_cmd(mnemo, pwmh, value) print("Send to STM:", mnemo, pwmh, value) retval = self.get_data() print("STM returns:", retval) self.save_setting('pwm_handler'+str(pwmh), mnemo, value) def config_to_device(self): """Get value of parameters from configuration file and set them to device. """ for pwmh in range(2): config = self.get_pwmh_config(pwmh) for param in PARAMETERS: mnemo = param['mnemo'] value = config[param['mnemo']] self.send_cmd(mnemo, pwmh, value) def config_to_ui(self): """Get value of parameters of the controller from configuration file and set them to UI. """ for pwmh in range(2): config = self.get_pwmh_config(pwmh) for param in PARAMETERS: self.ui.box_val[pwmh][param['mnemo']]. \ set(config[param['mnemo']]) def send_cmd(self, mnemo, pwmh, value): """High level data sending process """ msg = "{} {} {}".format(mnemo, pwmh, value) header = struct.pack('