#!/usr/bin/python3 """ author Benoit Dubois copyright FEMTO ENGINEERING license GPL v3.0+ brief Basic GUI to deal with "servo2toX" 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 from struct import pack import argparse import configparser import tkinter as tk from tkinter import messagebox import serial import select APPLICATION = "stm_client" CONFIG_DIR = os.path.join(os.path.expanduser("~"), ".config/", APPLICATION) PARAMETERS = ( {'mnemo': "kp", 'default': 0, 'min': -32768, 'max': 32768, 'format': None}, {'mnemo': "ki", 'default': 0, 'min': -32768, 'max': 32768, 'format': None}, {'mnemo': "sp", 'default': 0, 'min': 0, 'max': 4095, 'format': None}, {'mnemo': "osp", 'default': 0, 'min': -40000, 'max': 40000, 'format': None}, {'mnemo': "imax", 'default': 80000, 'min': 0, 'max': 800000, 'format': None}, {'mnemo': "omax", 'default': 40000, 'min': 0, 'max': 40000, 'format': None}, {'mnemo': "oscale", 'default': 8, 'min': 0, 'max': 20, 'format': None}, {'mnemo': "fs", 'default': 1, 'min': 1, 'max': 1000, 'format': None} ) #============================================================================== class ClientStmGui(tk.Frame): """Basic GUI to deal with "double PID" servo STM32 board. """ def __init__(self, master=None): super().__init__(master) self.cctrl = tk.IntVar() self._build_ui() def __str__(self): print("toto") def _build_ui(self): lbl = (dict(), dict()) self.sbox = (dict(), dict()) self.box_val = (dict(), dict()) self.btn = (dict(), dict()) for ctrl in range(2): for param in PARAMETERS: lbl[ctrl][param['mnemo']] = tk.Label(text=param['mnemo']) self.box_val[ctrl][param['mnemo']] = tk.IntVar() self.sbox[ctrl][param['mnemo']] = tk.Spinbox(from_=param['min'], to=param['max'], textvariable=self.box_val[ctrl][param['mnemo']], format=param['format']) self.btn[ctrl][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 ctrl in range(2): for idx, param in enumerate(PARAMETERS): lbl[ctrl][param['mnemo']].grid(row=idx+len(PARAMETERS)+1, column=ctrl*3+0) self.sbox[ctrl][param['mnemo']].grid(row=idx+len(PARAMETERS)+1, column=ctrl*3+1) self.btn[ctrl][param['mnemo']].grid(row=idx+len(PARAMETERS)+1, column=ctrl*3+2) # Global look self.config(bd=3, relief='groove') #============================================================================== class ClientStm(object): def __init__(self, port, config_file, ui_type='2to1', master=None): """ :param ui_type: handle behavior of client with respect to final application (value: '2to1', '2to2' or '2to2s'). """ self.stm = serial.Serial(port=port, baudrate=9600, timeout=1, xonxoff=False, rtscts=False, dsrdtr=True) self.ui = ClientStmGui(master) self.ui_type = ui_type self.config_file = config_file self.config_to_device() self.config_to_ui(0) self.config_to_ui(1) self.ui.mainloop() @property def ui_type(self): return self._ui_type @ui_type.setter def ui_type(self, ui_type): self._ui_type = ui_type for ctrl in range(2): for param in PARAMETERS: self.ui.btn[ctrl][param['mnemo']].configure( command=lambda x=ctrl, y=param['mnemo']: self.btn_clicked(x, y)) if ui_type == '2to2': pass elif ui_type == '2to2s': # Sync spinbox 'fs' self.ui.sbox[0]['fs'].configure(command=lambda: self.ui.box_val[1]['fs'].set(self.ui.box_val[0]['fs'].get())) self.ui.sbox[1]['fs'].configure(command=lambda: self.ui.box_val[0]['fs'].set(self.ui.box_val[1]['fs'].get())) else: # -> ui_type = '2to1' pass def btn_clicked(self, ctrl, mnemo): try: value = self.ui.box_val[ctrl][mnemo].get() except Exception as ex: print("Value error: {}".format(ex)) return self.send_cmd(mnemo, ctrl, value) self.save_setting("servo"+str(ctrl), mnemo, value) def config_to_device(self): """Get value of parameters from configuration file and set them to device. """ for ctrl in range(2): config = self.get_servo_config(ctrl) for param in PARAMETERS: mnemo = param['mnemo'] value = config[param['mnemo']] self.send_cmd(mnemo, ctrl, value) def config_to_ui(self, cctrl): """Get value of parameters of the controller from configuration file and set them to UI. """ config = self.get_servo_config(cctrl) for param in PARAMETERS: self.ui.box_val[cctrl][param['mnemo']].set(config[param['mnemo']]) def send_cmd(self, mnemo, ctrl, value): msg = "{} {} {}".format(mnemo, ctrl, value) self.send_data(msg) def send_data(self, msg): header = pack('