class ApplicationWindow(QMainWindow): def __init__(self): #Initialization stuff QMainWindow.__init__(self) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setWindowTitle("Turtle Window") #Name of the specific window self.setStyleSheet(""" QMainWindow { background-color:#437919; } QMenuBar { background-color:#313131; color: rgb(255,255,255); border: 1px solid #000; } QMenuBar::item { background-color: rgb(49,49,49); color: rgb(255,255,255); } QMenuBar::item::selected { background-color: rgb(30,30,30); } QMenu { background-color: rgb(49,49,49); color: rgb(255,255,255); border: 1px solid #000; } QMenu::item::selected { background-color: rgb(30,30,30); } QStatusBar { background-color:#313131; color: rgb(255,255,255); border: 1px solid #000; } """) #Serial Setup self.serialObject = serial.Serial() self.serialObject.baudrate = 9600 self.serialObject.parity = serial.PARITY_NONE self.serialObject.stopbits = serial.STOPBITS_ONE self.serialObject.bytesize = serial.EIGHTBITS self.serialObject.timeout = None self.serialObject.setWriteTimeout(0.01) #Variables self.liveUpdate = False self.datapulls = 0 self.dataSamples = [] self.dataXaccelSamples = [] self.dataZgyroSamples = [] self.dataTickSamples = [] self.dataTickSamplesCount = 0 self.laps = [] self.speeds = [] #Data stuff self.com_monitor = None self.com_data_puller = None self.com_data_Xaccel_q = None self.com_data_Zgyro_q = None self.com_data_Tick_q = None self.com_data_Lap_q = None self.com_terminal_q = None self.liveFeed = LiveDataFeed() self.dataTimerUpdateRate = 10 self.plotUpdater = QTimer(self) self.plotUpdater.timeout.connect(self.UpdateData) self.dataToPlot = "Live" self.dataBeingPlot = "Live" #Menues #File menu self.file_menu = QMenu('&File', self) self.file_menu.addAction('&Quit', self.fileQuit, QtCore.Qt.CTRL + QtCore.Qt.Key_Q) self.menuBar().addMenu(self.file_menu) #Help menu self.help_menu = QMenu('&Help', self) self.menuBar().addSeparator() self.menuBar().addMenu(self.help_menu) self.help_menu.addAction('&About', self.about) #Serial Menu self.serial_menu = QMenu('&Serial', self) self.menuBar().addSeparator() self.menuBar().addMenu(self.serial_menu) serialConnectAction = self.serial_menu.addAction('Connect') serialConnectAction.setShortcut(QtCore.Qt.Key_C) serialConnectAction.triggered.connect(self.serialConnect) serialConnectAction.setIcon(QIcon('SerialConnect.png')) serialReconnectAction = self.serial_menu.addAction('Reconnect') serialReconnectAction.setShortcut(QtCore.Qt.Key_R) serialReconnectAction.triggered.connect(self.serialReconnect) serialReconnectAction.setIcon(QIcon('SerialReconnect.png')) serialDisconnectAction = self.serial_menu.addAction('Disconnect') serialDisconnectAction.triggered.connect(self.serialDisconnect) serialDisconnectAction.setIcon(QIcon('SerialDisconnect.png')) #GUI #Stats self.labelLapTime = QLabel('LapTime', self) self.labelLapTime.setStyleSheet("background-color:#FFFFFF") self.labelLapTime.setAlignment(Qt.AlignLeft) self.labelLapTicks = QLabel('LapTicks', self) self.labelLapTicks.setStyleSheet("background-color:#FFFFFF") self.labelLapTicks.setAlignment(Qt.AlignLeft) self.labelSpeed = QLabel('Speed', self) self.labelSpeed.setStyleSheet("background-color:#FFFFFF") self.labelSpeed.setAlignment(Qt.AlignLeft) self.labelSpeedAvg = QLabel('Speed avg.', self) self.labelSpeedAvg.setStyleSheet("background-color:#FFFFFF") self.labelSpeedAvg.setAlignment(Qt.AlignLeft) self.listDataSets = QListWidget(self) self.listDataSets.setMaximumWidth(200) self.listDataSets.addItem('Live') self.listDataSets.itemClicked.connect(self.chooseDataSet) self.ButtonLiveSave = QPushButton('Save') self.ButtonLiveSave.setStyleSheet("background-color:#00FF00") self.ButtonLiveSave.clicked.connect(self.SaveData) statbox = QVBoxLayout() statbox.addWidget(self.listDataSets) statbox.addWidget(self.labelLapTime) statbox.addWidget(self.labelLapTicks) statbox.addWidget(self.labelSpeed) statbox.addWidget(self.labelSpeedAvg) statbox.addWidget(self.ButtonLiveSave) #Start/Stop interface self.buttonStart = QPushButton('Start', self) self.buttonStart.setStyleSheet("background-color:#00FF00") self.buttonStart.clicked.connect(self.buttonStartPressed) buttonStop = QPushButton('Stop', self) buttonStop.setStyleSheet("background-color:#FF6666") buttonStop.clicked.connect(self.CarStop) self.buttonData = QPushButton('Datacollection', self) self.buttonData.setStyleSheet("background-color:#a2adff") self.buttonData.setCheckable(True) self.buttonData.clicked[bool].connect(self.buttonDataToggle) self.lineEditSpeed = QLineEdit('35') self.lineEditSpeed.setStyleSheet("background-color:#FFFFFF") self.lineEditSpeed.returnPressed.connect(self.buttonStartPressed) self.lineEditSpeed.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) #Terminal self.labelTerminal = QLabel('>>Terminal Ready<br />', self) self.labelTerminal.setAlignment(Qt.AlignLeft | Qt.AlignTop) self.labelTerminal.setWordWrap(True) self.labelTerminal.setStyleSheet( "background-color:#000000; color:#FFFFFF") self.labelTerminal.setTextFormat(Qt.RichText) self.scrollAreaTerminal = QScrollArea() self.scrollAreaTerminal.setWidget(self.labelTerminal) self.scrollAreaTerminal.setWidgetResizable(True) self.scrollAreaTerminal.verticalScrollBar().rangeChanged.connect( self.terminalScrollToBottom) self.lineEditTerminal = QLineEdit() self.lineEditTerminal.setStyleSheet("background-color:#FFFFFF") self.lineEditTerminal.returnPressed.connect(self.terminalLineEditEnter) self.lineEditTerminal.setToolTip('Use , to seperate bytes') self.comboboxTerminalType = QComboBox(self) self.comboboxTerminalType.addItem("HEX") self.comboboxTerminalType.addItem("DEC") #Layout self.main_widget = QWidget(self) turtlePicLabel = QLabel(self) turtlePic = QPixmap("Turtle.jpg") turtlePicLabel.setPixmap(turtlePic) hbox = QHBoxLayout() vbox = QVBoxLayout() vbox.setAlignment(Qt.AlignRight) vbox.addWidget(turtlePicLabel) vbox.addWidget(self.lineEditSpeed) vbox.addWidget(self.buttonStart) vbox.addWidget(buttonStop) vbox.addWidget(self.buttonData) vbox.addStretch(1) v2box = QVBoxLayout() self.figure = plt.figure() self.canvas = FigureCanvas(self.figure) self.canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.canvas.updateGeometry() self.canvas.draw() self.Toolbar = NavigationToolbar(self.canvas, self, coordinates=True) drawingBox = QVBoxLayout() drawingBox.addWidget(self.canvas) drawingBox.addWidget(self.Toolbar) hbox.addLayout(drawingBox) hbox.addLayout(statbox) hbox.addLayout(vbox) hbox2 = QHBoxLayout() hbox2.addWidget(self.lineEditTerminal) hbox2.addWidget(self.comboboxTerminalType) v2box.addLayout(hbox) v2box.addWidget(self.scrollAreaTerminal) v2box.addLayout(hbox2) self.main_widget.setLayout(v2box) self.main_widget.setFocus() self.setCentralWidget(self.main_widget) def chooseDataSet(self, item): if (item.text() == 'Live'): self.dataToPlot = "Live" else: self.dataToPlot = item.text().lstrip('Lap: ') def updateLaptime(self): self.labelLapTime.setText("LapTime: " + str(self.laps[len(self.laps) - 1][0])) ticks = self.laps[len(self.laps) - 1][1] distance = ((ticks / 12) * 2.5 * math.pi) / 100 self.labelLapTicks.setText("LapTicks: " + str(ticks) + "/" + "%.2f" % distance + "m") def listDataSetsUpdate(self): self.listDataSets.addItem("Lap: " + str((len(self.dataSamples) - 1))) def read_serial_data(self): qdata = list(get_all_from_queue(self.com_data_Xaccel_q)) if (len(qdata) > 0): print("Received Xaccel data") for dataSet in qdata: self.dataXaccelSamples.append(dataSet) qdata = list(get_all_from_queue(self.com_data_Zgyro_q)) if (len(qdata) > 0): #print("Received Zgyro data") for dataSet in qdata: self.dataZgyroSamples.append(dataSet) qdata = list(get_all_from_queue(self.com_data_Tick_q)) if (len(qdata) > 0): #print("Received ticks data") for dataSet in qdata: self.dataTickSamples.append(dataSet) qdata = list(get_all_from_queue(self.com_data_Lap_q)) if (len(qdata) > 0): try: indexEnd = self.dataTickSamples.index('e') self.dataSamples.append((self.dataTickSamples[0:indexEnd])) del (self.dataTickSamples[0:indexEnd + 1]) self.laps.append(qdata[0]) self.updateLaptime() self.listDataSetsUpdate() except ValueError: print('Lap has updated, but no "e" in datasamples') def SaveData(self): self.dataSamples.append((self.dataTickSamples)) self.listDataSetsUpdate() def UpdateData(self): self.read_serial_data() if (self.dataToPlot == "Live"): self.dataBeingPlot = self.dataToPlot self.plot(self.dataTickSamples) elif ((self.dataToPlot != None) and (self.dataToPlot != self.dataBeingPlot)): self.dataBeingPlot = self.dataToPlot self.plot(self.dataSamples[int(self.dataToPlot)]) else: print('No data yet') ''' if(len(self.dataTickSamples) > self.dataTickSamplesCount and len(self.dataTickSamples) >=2): self.dataTickSamplesCount = len(self.dataTickSamples) sampleLast = self.dataTickSamples[len(self.dataTickSamples)-1] sampleSecondLast = self.dataTickSamples[len(self.dataTickSamples)-2] ticks = sampleLast[0] - sampleSecondLast[0] time = sampleLast[1] - sampleSecondLast[1] distance = ((ticks/12)*math.pi*2.5)/100 speed = distance/time self.speeds.append(speed) self.labelSpeed.setText("Speed: " + "%.2f" %speed) if(len(self.speeds)>0): speedAvg = np.mean(self.speeds) self.labelSpeedAvg.setText("Speed: " + "%.2f" %speedAvg) ''' def plot(self, data): if (len(data) >= 2): ax = self.figure.add_subplot(111) ax.hold(False) x_list = [y for [x, y] in data] y_list = [x for [x, y] in data] ax.plot(x_list, y_list, 'r') ax.set_title('Gyro over time') ax.set_ylabel('Z-Gyro') ax.set_xlabel('Time in ms') #ax.set_xlim([0, 5]) #ax.set_ylim([0, 65535]) #ax.autoscale(True) self.figure.tight_layout() self.canvas.draw() else: print('Not enough data yet') def terminalLineEditEnter(self): if self.serialObject.isOpen() == True: input_text = self.lineEditTerminal.text() input_type = 'None' input_bytes = input_text.split(',') if self.comboboxTerminalType.currentText() == "HEX": input_type = "HEX" for byte in range(0, len(input_bytes)): input_bytes[byte] = int(input_bytes[byte], 16) print('It was hex') elif self.comboboxTerminalType.currentText() == "DEC": input_type = "DEC" for byte in range(0, len(input_bytes)): input_bytes[byte] = int(input_bytes[byte]) print('It was ascii') self.terminalAppend(">><font color=#FFFF00>" + input_type + "(" + input_text + ")" + "</font> <br />") command = bytearray(input_bytes) self.serialObject.write(command) else: self.terminalAppend(">><font color=#FF0000>" + "Serial port not open!" + "</font> <br />") self.lineEditTerminal.setText("") def terminalScrollToBottom(self, min, max): self.scrollAreaTerminal.verticalScrollBar().setValue(max) def terminalAppend(self, textToAppend): text = self.labelTerminal.text() text += textToAppend self.labelTerminal.setText(text) def buttonDataToggle(self, state): if (state): self.com_data_puller.start() print('Es ist true') else: self.com_data_puller.stop() print('Es ist false') def buttonStartPressed(self): text = self.lineEditSpeed.text() self.lineEditSpeed.setText("") try: value = int(text) except ValueError: return if (value <= 100 and value >= 0): self.CarStart(value) def CarStart(self, speed): if self.serialObject.isOpen(): command = bytearray([ord('\x55'), ord('\x10'), speed]) self.serialObject.write(command) self.terminalAppend(">><font color=#00FF00>" + "Starting the car with " + str(speed) + "% speed!" + "</font> <br />") def CarStop(self): if self.serialObject.isOpen(): command = bytearray([ord('\x55'), ord('\x11'), 0]) self.serialObject.write(command) self.terminalAppend(">><font color=#FF0000>" + "Stopping the car!" + "</font> <br />") def serialConnect(self): if self.serialObject.isOpen(): self.statusBar().showMessage( "Serial communication is already running on " + self.serialObject.port + "!", 3000) else: portSelected, ok = SerialConnectDialog.getPort(self) if (ok == True): try: self.serialObject.port = portSelected self.serialObject.open() self.statusBar().showMessage( "Opened serial communication on " + portSelected + "!", 3000) self.startDaemons() except serial.SerialException: self.statusBar().showMessage( "Could not open serial connection on " + portSelected + "!", 3000) else: self.statusBar().showMessage("Serial connection cancelled!", 3000) def startDaemons(self): self.plotUpdater.start(self.dataTimerUpdateRate) self.com_data_Xaccel_q = queue.Queue() self.com_data_Zgyro_q = queue.Queue() self.com_data_Tick_q = queue.Queue() self.com_terminal_q = queue.Queue() self.com_data_Lap_q = queue.Queue() self.com_monitor = ComMonitorThread(self.com_data_Xaccel_q, self.com_data_Zgyro_q, self.com_data_Tick_q, self.com_data_Lap_q, self.com_terminal_q, self.serialObject) self.com_monitor.daemon = True self.com_monitor.start() self.com_data_puller = ComDataPullerThread(self.serialObject, 25) def serialReconnect(self): if self.serialObject.isOpen(): self.statusBar().showMessage( "Serial communication is already running on " + self.serialObject.port + "!", 3000) else: try: self.serialObject.open() self.statusBar().showMessage( "Opened serial communication on " + self.serialObject.port + "!", 3000) self.startDaemons() except serial.SerialException: self.statusBar().showMessage( "Could not open serial connection on " + self.serialObject.port + "!", 3000) def serialDisconnect(self): if self.serialObject.isOpen(): #self.com_monitor.join() self.com_monitor = None self.com_data_puller.stop() self.com_data_puller = None self.serialObject.close() self.statusBar().showMessage( "Closed serial communication on " + self.serialObject.port + "!", 3000) else: self.statusBar().showMessage("No serial port to be closed!", 3000) def fileQuit(self): self.close() def closeEvent(self, ce): self.fileQuit() def about(self): QMessageBox.about( self, "About", """This is the turtle interface used for monitoring and modifying the behaviour of the Turtle Car""" )
class PlottingDataMonitor(QMainWindow): def __init__(self, parent=None): super(PlottingDataMonitor, self).__init__(parent) self.monitor_active = False self.logger_active = False self.com_monitor = None self.com_data_q = None self.com_error_q = None self.livefeed = LiveDataFeed() self.temperature_samples = [] self.timer = QTimer() self.create_menu() self.create_main_frame() self.create_status_bar() def make_data_box(self, name): label = QLabel(name) qle = QLineEdit() qle.setEnabled(False) qle.setFrame(False) return (label, qle) def create_plot(self): plot = Qwt.QwtPlot(self) plot.setCanvasBackground(Qt.black) #plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10000, 1000) plot.setAxisTitle(Qwt.QwtPlot.xBottom, 'Time') plot.setAxisScaleDraw(Qwt.QwtPlot.xBottom, DateTimeScaleDraw()) plot.setAxisLabelRotation(Qwt.QwtPlot.xBottom, -45.0 ) plot.setAxisLabelAlignment(Qwt.QwtPlot.xBottom, QtCore.Qt.AlignLeft | QtCore.Qt.AlignBottom ) plot.setAxisTitle(Qwt.QwtPlot.yLeft, 'CDC Counts') plot.setAxisAutoScale(Qwt.QwtPlot.yLeft) #plot.setAxisScale(Qwt.QwtPlot.yLeft, 0, 8000000, 1000000) #plot.replot() curve = Qwt.QwtPlotCurve('') curve.setRenderHint(Qwt.QwtPlotItem.RenderAntialiased) pen = QPen(QColor('limegreen')) pen.setWidth(2) curve.setPen(pen) curve.attach(plot) return plot, curve def create_status_bar(self): self.status_text = QLabel('Monitor idle') self.statusBar().addWidget(self.status_text, 1) def create_main_frame(self): # Edit Box # self.editbox = QTextEdit() self.editbox.setReadOnly(True) editbox_layout = QVBoxLayout() editbox_layout.addWidget(self.editbox) editbox_layout.addStretch(1) editbox_groupbox = QGroupBox('CDC Counts') editbox_groupbox.setLayout(editbox_layout) # Port name # portname_l, self.portname = self.make_data_box('COM Port:') portname_layout = QHBoxLayout() portname_layout.addWidget(portname_l) portname_layout.addWidget(self.portname, 0) portname_layout.addStretch(1) portname_groupbox = QGroupBox('COM Port') portname_groupbox.setLayout(portname_layout) # Period Box # periodBox_l, self.periodBox = self.make_data_box('Period:') meanBox_l, self.meanBox = self.make_data_box('Mean:') deviationBox_l, self.deviationBox = self.make_data_box('Deviation:') countBox_l, self.countBox = self.make_data_box('Counts:') self.resetButton = QPushButton(QIcon('lucia.png'), 'Reset') self.resetButton.setGeometry(10, 10, 100, 30) self.resetButton.clicked.connect(self.periodReset) self.stopButton = QPushButton(QIcon('lucia.png'), 'Stop') self.stopButton.setGeometry(10,10,100,30) self.stopButton.clicked.connect(self.periodStop) periodBox_layout = QHBoxLayout() periodBox_layout.addWidget(periodBox_l) periodBox_layout.addWidget(self.periodBox, 0) #periodBox_layout.addWidget(meanBox_l) #periodBox_layout.addWidget(self.meanBox, 0) periodBox_layout.addWidget(deviationBox_l) periodBox_layout.addWidget(self.deviationBox, 0) periodBox_layout.addWidget(countBox_l) periodBox_layout.addWidget(self.countBox, 0) periodBox_layout.addWidget(self.resetButton) periodBox_layout.addWidget(self.stopButton) self.stop = 1 periodBox_layout.addStretch(1) periodBox_groupbox = QGroupBox('Period Calculation') self.periodBox.setText('0') #self.meanBox.setText('M0') self.deviationBox.setText('0') self.countBox.setText('0') periodBox_groupbox.setLayout(periodBox_layout) # Add The Plot # self.plot, self.curve = self.create_plot() plot_layout = QVBoxLayout() plot_layout.addWidget(self.plot) plot_groupbox = QGroupBox('Capacitive to Digital Sensor Graph') plot_groupbox.setLayout(plot_layout) # Add The Zoomer # self.zoomer = Qwt.QwtPlotZoomer( Qwt.QwtPlot.xBottom, Qwt.QwtPlot.yLeft, Qwt.QwtPicker.DragSelection, Qwt.QwtPicker.AlwaysOff, self.plot.canvas()) self.zoomer.setRubberBandPen(QPen(Qt.red)) #self.zoomer.setZoomBase(True) # Main frame and layout # self.main_frame = QWidget() main_layout = QVBoxLayout() main_layout.addWidget(portname_groupbox) main_layout.addWidget(plot_groupbox) main_layout.addWidget(periodBox_groupbox) main_layout.addWidget(editbox_groupbox) main_layout.addStretch(1) self.main_frame.setLayout(main_layout) self.setCentralWidget(self.main_frame) self.set_actions_enable_state() def periodReset(self): print('Reset') self.periodAvg = [] self.periodCount = 0 self.stop = 0 self.startTime=time.clock() self.r = Tk() self.r.withdraw() self.r.clipboard_clear() def periodStop(self): print('Stop') self.stop = 1 try: for elem in self.periodAvg[2:len(self.periodAvg)]: self.r.clipboard_append(str(elem)) self.r.clipboard_append('\n') self.r.destroy() except: print('There is nothing in the clipboard') #win32clipboard.OpenClipboard() #win32clipboard.EmptyClipboard() #win32clipboard.SetClipboardText(str(self.periodAvg[1:len(self.periodAvg)])) #win32clipboard.CloseClipboard() def create_menu(self): # The File Menu # self.file_menu = self.menuBar().addMenu("&File") selectport_action = self.create_action("Select COM &Port...", shortcut="Ctrl+P", slot=self.on_select_port, tip="Select a COM port") self.startMon_action = self.create_action("&Start monitor", shortcut="Ctrl+M", slot=self.on_startMon, tip="Start the data monitor") self.stopMon_action = self.create_action("&Stop monitor", shortcut="Ctrl+T", slot=self.on_stopMon, tip="Stop the data monitor") self.startLog_action = self.create_action("&Start logger", shortcut="Ctrl+L", slot=self.on_startLog, tip="Start the data logger") self.stopLog_action = self.create_action("&Stop logger", shortcut="Ctrl+T", slot=self.on_stopLog, tip="Stop the data logger") self.openFile = QAction(QIcon('open.png'), 'Open Graph', self) self.openFile.setShortcut('Ctrl+O') self.openFile.setStatusTip('Open Graph File') self.openFile.triggered.connect(self.on_Open) exit_action = self.create_action("E&xit", slot=self.close, shortcut="Ctrl+X", tip="Exit the application") self.startMon_action.setEnabled(False) self.stopMon_action.setEnabled(False) self.startLog_action.setEnabled(False) self.stopLog_action.setEnabled(False) self.add_actions(self.file_menu, ( selectport_action, self.openFile, self.startMon_action, self.stopMon_action, self.startLog_action, self.stopLog_action, None, exit_action)) self.help_menu = self.menuBar().addMenu("&Help") about_action = self.create_action("&About", shortcut='F1', slot=self.on_about, tip='About the monitor') self.add_actions(self.help_menu, (about_action,)) def selected(self, _): self.showInfo() def meanstdv(self, x): """ Calculate mean and standard deviation of data x[]: mean = {\sum_i x_i \over n} std = sqrt(\sum_i (x_i - mean)^2 \over n-1) """ from math import sqrt n, mean, std = len(x), 0, 0 for a in x: mean = mean + a mean = mean / float(n) for a in x: std = std + (a - mean)**2 std = sqrt(std / float(n-1)) return mean, std def on_Open(self): cdc_data = [] index = [] fname = QFileDialog.getOpenFileName(self, 'Open file', 'QDir::currentPath()') if fname.isEmpty() == False: f = open(fname, 'r') cdc_data = f.readlines() f.close() cdc_data.pop(0) #Pop the first and the last to get rid of bad data cdc_data.pop(-1) cdc_data_float = map(float, cdc_data) index = [i for i in range(len(cdc_data))] # Draw the Graph # self.curve.setData(index, cdc_data_float) #self.curve.setData(index[0:3600], cdc_data_float[0:3600]) #Set up the axis scales self.plot.setAxisAutoScale(Qwt.QwtPlot.xBottom) self.plot.setAxisAutoScale(Qwt.QwtPlot.yLeft) self.zoomer.setZoomBase(True) #self.plot.replot() def set_actions_enable_state(self): if self.portname.text() == '': startMon_enable = stopMon_enable = False startLog_enable = stopLog_enable = False else: startMon_enable = not self.monitor_active stopMon_enable = self.monitor_active startLog_enable = not self.logger_active stopLog_enable = self.logger_active self.startLog_action.setEnabled(startLog_enable) self.startMon_action.setEnabled(startMon_enable) self.stopLog_action.setEnabled(stopLog_enable) self.stopMon_action.setEnabled(stopMon_enable) def on_about(self): msg = __doc__ QMessageBox.about(self, "About cdcLogger", msg.strip()) def on_select_port(self): ports = list(enumerate_serial_ports()) if len(ports) == 0: QMessageBox.critical(self, 'No ports', 'No serial ports found') return item, ok = QInputDialog.getItem(self, 'Select a port', 'Serial port:', ports, 0, False) if ok and not item.isEmpty(): self.portname.setText(item) self.set_actions_enable_state() def on_stopMon(self): if self.com_monitor is not None: self.com_monitor.join(10) self.com_monitor = None self.monitor_active = False self.timer.stop() self.set_actions_enable_state() self.status_text.setText('Monitor idle') def on_startMon(self): if self.com_monitor is not None or self.portname.text() == '': return # First define a couple of variables that will be used to calculate the period #self.startTime = 1.1 self.mark = 'False' self.periodAvg = [] self.periodCount = 0 self.data_q = Queue.Queue() self.error_q = Queue.Queue() self.com_monitor = ComMonitorThread( self.data_q, self.error_q, full_port_name(str(self.portname.text())), 57600) self.com_monitor.start() com_error = get_item_from_queue(self.error_q) if com_error is not None: QMessageBox.critical(self, 'ComMonitorThread error', com_error) self.com_monitor = None self.monitor_active = True self.set_actions_enable_state() self.timer = QTimer() self.connect(self.timer, SIGNAL('timeout()'), self.on_timer) self.timer.start(.005) self.status_text.setText('Monitor running') def on_startLog(self): self.log() self.logger_active = True self.set_actions_enable_state() def on_stopLog(self): self.logger_active = False self.set_actions_enable_state() def on_timer(self): """ Executed periodically when the monitor update timer is fired. """ self.read_serial_data() self.update_monitor() def log(self): self.log_state = True self.reading_num = 0 self.today = str(datetime.date.today()) self.logname = '%s.csv' % self.today self.file = open(self.logname, "wb") self.file_cvs = csv.writer(self.file) def save_data(self,reading): self.file_cvs.writerow ([reading]) def save_data_stamps(self,reading_num,reading,timestamp,utimestamp): self.file_cvs.writerow ([reading_num,reading,timestamp,utimestamp]) def update_monitor(self): """ Updates the state of the monitor window with new data. The livefeed is used to find out whether new data was received since the last update. If not, nothing is updated. """ if self.livefeed.has_new_data: data = self.livefeed.read_data() # time.time() is a timestamp for the graph X axis ticks # This may be a good place to add period calculation # self.temperature_samples.append((time.time(), data['temperature'])) if len(self.temperature_samples) > 765: self.temperature_samples.pop(0) xdata = [s[0] for s in self.temperature_samples] ydata = [s[1] for s in self.temperature_samples] if (len(self.temperature_samples) > 2 and self.stop == 0): if data['temperature'] > self.temperature_samples[-2][1]: self.mark = 1 elif (data['temperature'] < self.temperature_samples[-2][1]) and (self.mark == 1): endTime = time.clock() period = (endTime - self.startTime) self.periodAvg.append(period) if (len(self.periodAvg) <= 3): self.periodBox.setText('0') self.deviationBox.setText('0') self.countBox.setText('Waiting') if (len(self.periodAvg) > 3): self.Average, self.Deviation = self.meanstdv(self.periodAvg[2:len(self.periodAvg)]) self.periodBox.setText(str(self.Average)) self.deviationBox.setText(str(self.Deviation)) self.countBox.setText(str(len(self.periodAvg)-2)) self.startTime = endTime self.periodCount += 1 self.mark = 0 #avg = sum(ydata) / float(len(ydata)) self.plot.setAxisAutoScale(Qwt.QwtPlot.yLeft) self.plot.setAxisScale(Qwt.QwtPlot.xBottom, xdata[0], max(20, xdata[-1])) self.curve.setData(xdata, ydata) self.plot.replot() #self.plot.setAxisAutoScale(Qwt.QwtPlot.xBottom) #self.zoomer.setZoomBase(True) #self.thermo.setValue(avg) def read_serial_data(self): """ Called periodically by the update timer to read data from the serial port. """ qdata = list(get_all_from_queue(self.data_q)) if len(qdata) > 0: # At this point qdata object is a list type count = 0 # Updates the text box with the incoming values # Clears the text box every 4096 values so that # Memory does not fill up with scrolling text for elem in list(qdata): self.editbox.append(qdata[count][0]) if self.editbox.document().blockCount() == 4096: self.editbox.clear() data = dict(timestamp=qdata[count][1],temperature=int(qdata[count][0])) self.livefeed.add_data(data) if self.logger_active: self.reading_num = self.reading_num + 1 #Uncomment for stamps # #utimestamp = time.time() #A unix style timestamp for the log #self.save_data_stamps(self.reading_num,int(qdata[count][0]),qdata[count][1],utimestamp) if self.today != str(datetime.date.today()): self.file.close() self.log(); self.reading_num = self.reading_num + 1 self.save_data(int(qdata[count][0])) count=count+1 #data = dict(timestamp=qdata[-1][1], # temperature=int(qdata[-1][0])) #self.livefeed.add_data(data) def add_actions(self, target, actions): '''The following two methods are utilities for simpler creation and assignment of actions ''' for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def create_action( self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action def closeEvent(self, event): self.editbox.append("closing PyQtTest")
class PlottingDataMonitor(QMainWindow): def __init__(self, parent=None): super(PlottingDataMonitor, self).__init__(parent) self.setWindowTitle('ADXL345 Realtime Monitor') self.resize(800, 600) self.port = "" self.baudrate = 9600 self.monitor_active = False # on/off monitor state self.com_monitor = None # monitor reception thread self.com_data_q = None self.com_error_q = None self.livefeed = LiveDataFeed() self.timer = QTimer() self.g_samples = [[], [], []] self.curve = [None]*3 self.gcurveOn = [1]*3 # by default all curve are plotted self.csvdata = [] self.create_menu() self.create_main_frame() self.create_status_bar() # Activate start-stop button connections self.connect(self.button_Connect, SIGNAL("clicked()"), self.OnStart) self.connect(self.button_Disconnect, SIGNAL("clicked()"), self.OnStop) #---------------------------------------------------------- def create_com_box(self): """ Purpose: create the serial com groupbox Return: return a layout of the serial com """ self.com_box = QGroupBox("COM Configuration") com_layout = QGridLayout() self.radio115200 = QRadioButton("115200") self.radio115200.setChecked(1) self.radio19200 = QRadioButton("19200") self.radio9600 = QRadioButton("9600") self.Com_ComboBox = QComboBox() com_layout.addWidget(self.Com_ComboBox,0,0,1,3) com_layout.addWidget(self.radio115200,1,0) com_layout.addWidget(self.radio19200,1,1) com_layout.addWidget(self.radio9600,1,2) self.fill_ports_combobox() self.button_Connect = QPushButton("Start") self.button_Disconnect = QPushButton("Stop") self.button_Disconnect.setEnabled(False) com_layout.addWidget(self.button_Connect,0,3) com_layout.addWidget(self.button_Disconnect,1,3) return com_layout #--------------------------------------------------------------------- def create_plot(self): """ Purpose: create the pyqwt plot Return: return a list containing the plot and the list of the curves """ plot = Qwt.QwtPlot(self) plot.setCanvasBackground(Qt.black) plot.setAxisTitle(Qwt.QwtPlot.xBottom, 'Time') plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10, 1) plot.setAxisTitle(Qwt.QwtPlot.yLeft, 'Acceleration') plot.setAxisScale(Qwt.QwtPlot.yLeft, YMIN, YMAX, (YMAX-YMIN)/10) plot.replot() curve = [None]*3 pen = [QPen(QColor('limegreen')), QPen(QColor('red')) ,QPen(QColor('yellow')) ] for i in range(3): curve[i] = Qwt.QwtPlotCurve('') curve[i].setRenderHint(Qwt.QwtPlotItem.RenderAntialiased) pen[i].setWidth(2) curve[i].setPen(pen[i]) curve[i].attach(plot) return plot, curve #--------------------------------------------------- def create_knob(self): """ Purpose: create a knob Return: return a the knob widget """ knob = Qwt.QwtKnob(self) knob.setRange(0, 180, 0, 1) knob.setScaleMaxMajor(10) knob.setKnobWidth(50) knob.setValue(180) return knob #--------------------------------------------------- def create_status_bar(self): self.status_text = QLabel('Monitor idle') self.statusBar().addWidget(self.status_text, 1) #--------------------------------------------------- def create_checkbox(self, label, color, connect_fn, connect_param): """ Purpose: create a personalized checkbox Input: the label, color, activated function and the transmitted parameter Return: return a checkbox widget """ checkBox = QCheckBox(label) checkBox.setChecked(1) checkBox.setFont( QFont("Arial", pointSize=12, weight=QFont.Bold ) ) green = QPalette() green.setColor(QPalette.Foreground, color) checkBox.setPalette(green) self.connect(checkBox, SIGNAL("clicked()"), partial(connect_fn,connect_param)) return checkBox #--------------------------------------------------- def create_main_frame(self): """ Purpose: create the main frame Qt widget """ # Serial communication combo box portname_layout = self.create_com_box() self.com_box.setLayout(portname_layout) # Update speed knob self.updatespeed_knob = self.create_knob() self.connect(self.updatespeed_knob, SIGNAL('valueChanged(double)'), self.on_knob_change) self.knob_l = QLabel('Update speed = %s (Hz)' % self.updatespeed_knob.value()) self.knob_l.setAlignment(Qt.AlignTop | Qt.AlignHCenter) # Create the plot and curves self.plot, self.curve = self.create_plot() # Create the configuration horizontal panel self.max_spin = QSpinBox() self.max_spin.setMaximum(10000) self.max_spin.setValue(10000) spins_hbox = QHBoxLayout() spins_hbox.addWidget(QLabel('Save every')) spins_hbox.addWidget(self.max_spin) spins_hbox.addWidget( QLabel('Lines')) #spins_hbox.addStretch(1) self.gCheckBox = [ self.create_checkbox("Acceleration(x)", Qt.green, self.activate_curve, 0), self.create_checkbox("Acceleration(y)", Qt.red, self.activate_curve, 1), self.create_checkbox("Acceleration(z)", Qt.yellow, self.activate_curve, 2) ] self.button_clear = QPushButton("Clear screen") self.connect(self.button_clear, SIGNAL("clicked()"), self.clear_screen) # Place the horizontal panel widget plot_layout = QGridLayout() plot_layout.addWidget(self.plot,0,0,8,7) plot_layout.addWidget(self.gCheckBox[0],0,8) plot_layout.addWidget(self.gCheckBox[1],1,8) plot_layout.addWidget(self.gCheckBox[2],2,8) plot_layout.addWidget(self.button_clear,3,8) plot_layout.addLayout(spins_hbox,4,8) plot_layout.addWidget(self.updatespeed_knob,5,8) plot_layout.addWidget(self.knob_l,6,8) plot_groupbox = QGroupBox('Acceleration') plot_groupbox.setLayout(plot_layout) # Place the main frame and layout self.main_frame = QWidget() main_layout = QVBoxLayout() main_layout.addWidget(self.com_box) main_layout.addWidget(plot_groupbox) main_layout.addStretch(1) self.main_frame.setLayout(main_layout) self.setCentralWidget(self.main_frame) #---------------------------------------------------------------------- def clear_screen(self): self.g_samples = [[], [], []] self.plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10) for i in range(3): self.curve[i].setData([], []) self.plot.replot() #----------------------------- def activate_curve(self, axe): if self.gCheckBox[axe].isChecked(): self.gcurveOn[axe] = 1 else: self.gcurveOn[axe] = 0 #--------------------------------------- def create_menu(self): self.file_menu = self.menuBar().addMenu("&File") selectport_action = self.create_action("Select COM &Port...", shortcut="Ctrl+P", slot=self.on_select_port, tip="Select a COM port") self.start_action = self.create_action("&Start monitor", shortcut="Ctrl+M", slot=self.OnStart, tip="Start the data monitor") self.stop_action = self.create_action("&Stop monitor", shortcut="Ctrl+T", slot=self.OnStop, tip="Stop the data monitor") exit_action = self.create_action("E&xit", slot=self.close, shortcut="Ctrl+X", tip="Exit the application") self.start_action.setEnabled(False) self.stop_action.setEnabled(False) self.add_actions(self.file_menu, ( selectport_action, self.start_action, self.stop_action, None, exit_action)) self.help_menu = self.menuBar().addMenu("&Help") about_action = self.create_action("&About", shortcut='F1', slot=self.on_about, tip='About the monitor') self.add_actions(self.help_menu, (about_action,)) #---------------------------------------------------------------------- def set_actions_enable_state(self): if self.portname.text() == '': start_enable = stop_enable = False else: start_enable = not self.monitor_active stop_enable = self.monitor_active self.start_action.setEnabled(start_enable) self.stop_action.setEnabled(stop_enable) #----------------------------------------------- def on_about(self): msg = __doc__ QMessageBox.about(self, "About the demo", msg.strip()) #----------------------------------------------- def on_select_port(self): ports = enumerate_serial_ports() if len(ports) == 0: QMessageBox.critical(self, 'No ports', 'No serial ports found') return item, ok = QInputDialog.getItem(self, 'Select a port', 'Serial port:', ports, 0, False) if ok and not item.isEmpty(): self.portname.setText(item) self.set_actions_enable_state() #----------------------------------------------- def fill_ports_combobox(self): """ Purpose: rescan the serial port com and update the combobox """ vNbCombo = "" self.Com_ComboBox.clear() self.AvailablePorts = enumerate_serial_ports() for value in self.AvailablePorts: self.Com_ComboBox.addItem(value) vNbCombo += value + " - " vNbCombo = vNbCombo[:-3] debug(("--> Les ports series disponibles sont: %s " % (vNbCombo))) #---------------------------------------------------------------------- def OnStart(self): """ Start the monitor: com_monitor thread and the update timer """ if self.radio115200.isChecked(): self.baudrate = 115200 print "--> baudrate is 115200 bps" if self.radio19200.isChecked(): self.baudrate = 19200 print "--> baudrate is 19200 bps" if self.radio9600.isChecked(): self.baudrate = 9600 print "--> baudrate is 9600 bps" vNbCombo = self.Com_ComboBox.currentIndex() self.port = self.AvailablePorts[vNbCombo] self.button_Connect.setEnabled(False) self.button_Disconnect.setEnabled(True) self.Com_ComboBox.setEnabled(False) self.data_q = Queue.Queue() self.error_q = Queue.Queue() self.com_monitor = ComMonitorThread( self.data_q, self.error_q, self.port, self.baudrate) self.com_monitor.start() com_error = get_item_from_queue(self.error_q) if com_error is not None: QMessageBox.critical(self, 'ComMonitorThread error', com_error) self.com_monitor = None self.monitor_active = True self.connect(self.timer, SIGNAL('timeout()'), self.on_timer) update_freq = self.updatespeed_knob.value() if update_freq > 0: self.timer.start(1000.0 / update_freq) self.status_text.setText('Monitor running') debug('--> Monitor running') #------------------------------------------------------------ def OnStop(self): """ Stop the monitor """ if self.com_monitor is not None: self.com_monitor.join(1000) self.com_monitor = None self.monitor_active = False self.button_Connect.setEnabled(True) self.button_Disconnect.setEnabled(False) self.Com_ComboBox.setEnabled(True) self.timer.stop() self.status_text.setText('Monitor idle') debug('--> Monitor idle') #----------------------------------------------- def on_timer(self): """ Executed periodically when the monitor update timer is fired. """ self.read_serial_data() self.update_monitor() #----------------------------------------------- def on_knob_change(self): """ When the knob is rotated, it sets the update interval of the timer. """ update_freq = self.updatespeed_knob.value() self.knob_l.setText('Update speed = %s (Hz)' % self.updatespeed_knob.value()) if self.timer.isActive(): update_freq = max(0.01, update_freq) self.timer.setInterval(1000.0 / update_freq) #----------------------------------------------- def update_monitor(self): """ Updates the state of the monitor window with new data. The livefeed is used to find out whether new data was received since the last update. If not, nothing is updated. """ if self.livefeed.has_new_data: data = self.livefeed.read_data() self.csvdata.append([data['timestamp'], data['gx'], data['gy'], data['gz']] ) if len(self.csvdata) > self.max_spin.value(): f = open(time.strftime("%H%M%S")+".csv", 'wt') try: writer = csv.writer(f) for i in range(self.max_spin.value()): writer.writerow( self.csvdata[i] ) print 'transfer data to csv after 10000 samples' finally: f.close() self.csvdata = [] self.g_samples[0].append( (data['timestamp'], data['gx'])) if len(self.g_samples[0]) > 1000: self.g_samples[0].pop(0) self.g_samples[1].append( (data['timestamp'], data['gy'])) if len(self.g_samples[1]) > 1000: self.g_samples[1].pop(0) self.g_samples[2].append( (data['timestamp'], data['gz'])) if len(self.g_samples[2]) > 1000: self.g_samples[2].pop(0) tdata = [s[0] for s in self.g_samples[2]] for i in range(3): data[i] = [s[1] for s in self.g_samples[i]] if self.gcurveOn[i]: self.curve[i].setData(tdata, data[i]) """ debug("xdata", data[0]) debug("ydata", data[1]) debug("tdata", data[2]) """ #self.plot.setAxisScale(Qwt.QwtPlot.xBottom, tdata[0], max(10, tdata[-1]) ) self.plot.replot() #----------------------------------------------- def read_serial_data(self): """ Called periodically by the update timer to read data from the serial port. """ qdata = list(get_all_from_queue(self.data_q)) # get just the most recent data, others are lost #print "qdata" , qdata if len(qdata) > 0: data = dict(timestamp=qdata[-1][1], gx=qdata[-1][0][0], gy=qdata[-1][0][1], gz=qdata[-1][0][2] ) self.livefeed.add_data(data) #----------------------------------------------- # The following two methods are utilities for simpler creation # and assignment of actions # def add_actions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) #----------------------------------------------- def create_action( self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action
class ProdGui(QMainWindow): def __init__(self, parent = None): super(ProdGui, self).__init__(parent) # counters self.face_count = 0 self.device_count = 1 self.current_device_no = 1 # Create the queues for data transfer from serial self.q_Data = None self.q_Error = None # Create (serial) event monitor flag self.event_monitor = False self.com_monitor = None # Create a data class self.livefeed = LiveDataFeed() self.value_samples = [] # Create a Timer Class self.timer = QTimer() #Init the UI self.create_main_frame() self.create_menu() #text file we will be saving in # ACC | GSM | GSM_SNR | RTC | SD | NRF_SPI | STN | V_BAT | GPS | GPS_ANT | NRF-ACC | NRF_SD | NRF_OTA self.failed_checks = {"acc":0,"gsm":0,"gsm_snr":0,"rtc":0,"sd":0,"nrf_spi":0,"stn":0,"v_bat":0, "gps":0,"gps_ant":0,"nrf_acc":0,"nrf_sd":0,"nrf_ota":0} self.setWindowTitle("Carnot Production") #advanced stuff self.advanced_set = False self.timer_counter = 0 self.small_string_flag = 0 def create_main_frame(self): self.createFaces() self.create_next_button() self.create_status_bar() self.leftGroupBox.setEnabled(False) self.middleGroupBox.setEnabled(False) self.rightGroupBox.setEnabled(False) self.basicGroupBox.setEnabled(False) self.leftGroupBox.hide() self.middleGroupBox.hide() self.rightGroupBox.hide() self.basic.pixelLabel.setPixmap(QPixmap("images/logo.png")) self.left.pixelLabel.setPixmap(QPixmap("images/logo.png")) self.basic.saveToText.clicked.connect(self.on_save_txt) self.basic.submitButton.clicked.connect(self.on_submit) self.basic.device_text.append(str(self.current_device_no)) self.basic.nextButton.clicked.connect(self.on_flash_button) # self.left.device_id.append(str(self.current_device_no)) self.main_frame = QWidget() face_widget = QWidget() face_layout = QHBoxLayout() face_layout.addWidget(self.leftGroupBox); face_layout.addWidget(self.middleGroupBox); face_layout.addWidget(self.rightGroupBox); face_layout.addWidget(self.basicGroupBox) face_widget.setLayout(face_layout) main_layout = QVBoxLayout() main_layout.addWidget(face_widget) main_layout.addWidget(self.next_button) self.main_frame.setLayout(main_layout) self.setCentralWidget(self.main_frame) def on_flash_button(self): print("\n\nFlashing NRF\n") os.system("flashNRF.cmd") os.system('testing_main1.cmd') time.sleep(5) def create_menu(self): self.menu = self.menuBar().addMenu("&File") self.start_qc = self.create_action("Start &QC", shortcut = "Ctrl+Q", slot = self.on_start, tip = "Start the QC process") self.advanced = self.create_action("&Advanced", shortcut = "Ctrl+C", slot = self.on_advanced, tip = "Super Saiyan") self.menu.addAction(self.start_qc) self.menu.addAction(self.advanced) def createFaces(self): self.leftGroupBox = QGroupBox("Step 1") self.left = LeftWidget() layout1 = QVBoxLayout() layout1.addWidget(self.left) self.leftGroupBox.setLayout(layout1) self.leftGroupBox.setMaximumSize(400, 450) self.middleGroupBox = QGroupBox("Step 2") self.middle = MiddleWidget() layout2 = QVBoxLayout() layout2.addWidget(self.middle) self.middleGroupBox.setLayout(layout2) self.middleGroupBox.setMaximumSize(450, 450) self.rightGroupBox = QGroupBox("Step 3") self.right = RightWidget() layout3 = QVBoxLayout() layout3.addWidget(self.right) self.rightGroupBox.setLayout(layout3) self.rightGroupBox.setMaximumSize(400, 450) # adding the next device button the right widget self.right.nextButton.clicked.connect(self.new_device) self.basicGroupBox = QGroupBox("Carnot") self.basic = BasicWidget() layout4 = QVBoxLayout() layout4.addWidget(self.basic) self.basicGroupBox.setLayout(layout4) self.basicGroupBox.setMinimumSize(400, 550) self.basicGroupBox.setMaximumSize(400, 1000) #self.basic.nextButton.clicked.connect(self.new_device()) def create_next_button(self): self.next_button = QPushButton("Next") #self.next_button.clicked.connect(self.__next_face) self.next_button.clicked.connect(self.new_device) self.next_button.setEnabled(False) def create_status_bar(self): self.status_text = QLabel("Idle (No QC?)") #self.statusBar().addWidget(self.status_text) def create_action( self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.triggered.connect(slot) if checkable: action.setCheckable(True) return action def new_device(self): #inclease device number self.basic.device_text.clear() self.basic.device_text.append(str(int(self.current_device_no) + 1)) self.current_device_no = int(self.current_device_no) + 1 #disable the buttons self.basic.saveToText.setEnabled(False) self.basic.submitButton.setEnabled(False) self.basic.nextButton.setEnabled(False) self.basic.pixelLabel.setPixmap(QPixmap("images/logo.png")) #refresh_face #self.update_faces() ''' self.leftGroupBox.setEnabled(False) self.middleGroupBox.setEnabled(False) self.rightGroupBox.setEnabled(False) self.leftGroupBox.setEnabled(True) self.next_button.setEnabled(True) print("device count:", self.device_count, '\n') self.left.update(self.on_serial_ports(),"Checked", qr_code(self.device_count)) ''' def __next_face(self): if self.face_count == 0: self.middleGroupBox.setEnabled(True) self.face_count += 1 self.update_faces() elif self.face_count == 1: self.rightGroupBox.setEnabled(True) self.face_count = 0 self.next_button.setEnabled(False) self.device_count += 1 def on_serial_ports(self): ''' get a list of ports available. ''' port_list = serial_ports() if len(port_list) == 0: QMessageBox.critical(self, "Check Connection", "Device Not Connected") return port = port_list return port def on_timer(self): """Executed periodically when qc update timer is launched""" self.read_serial_data() def on_advanced(self): self.leftGroupBox.show() self.middleGroupBox.show() self.advanced_set = True if self.basicGroupBox.isEnabled(): self.leftGroupBox.setEnabled(True) self.middleGroupBox.setEnabled(True) else: self.leftGroupBox.setEnabled(False) self.middleGroupBox.setEnabled(False) def on_start(self): ''' Start session -> on_serial_ports, then com_monitor thread ''' # this will call the flashing cmd scripts print("\n\nFlashing NRF\n") os.system("flashNRF.cmd") os.system("testing_main1.cmd") # so on start we will flash the device #then we sleep for 5 seconds so that the system is ready time.sleep(5) self.basicGroupBox.setEnabled(True) self.next_button.setEnabled(True) # self.basic.pixelLabel.setPixmap(QPixmap("images/cross-1.png")) self.basic.pixelLabel.setEnabled(True) if self.advanced_set: self.leftGroupBox.setEnabled(True) self.middleGroupBox.setEnabled(True) if self.com_monitor is not None and self.left.com_set() == "": return self.q_Data = queue.Queue() self.q_Error = queue.Queue() self.com_monitor = ComMonitorThread( self.q_Data, self.q_Error, self.on_serial_ports(), 9600) self.com_monitor.start() com_error = get_item_from_queue(self.q_Error) if com_error is not None: QMessageBox.critical(self, 'ComMonitorThread error', com_error) self.com_monitor = None self.event_monitor = True self.timer = QTimer() # self.connect(self.timer, SIGNAL('timeout()'), self.on_timer) self.timer.timeout.connect(self.on_timer) self.timer.start(500.0) #self.status_text.setText("Bad Batch") def read_serial_data(self): """Called periodically to see if serial buffer data available""" ''' each qdata has a list which with-in has a list with single character plus time stamp. ''' #[STAT]: ACC | GSM | GSM_SNR | RTC | SD | NRF_SPI | STN | GPS | GPS_ANT | NRF-ACC #[INFO]: STM_FW | STM_ID | STN_FW | GSM_Ver | CCID | NRF_ID_low | NRF_ID_high b = [] self.timer_counter += 1 #every 1 sec if self.timer_counter > 2: self.timer_counter = 0 qdata = list(get_all_from_queue(self.q_Data)) print(qdata) if len(qdata) > 0 and b'S' in qdata[0][0]: qdata = qdata[1:] #skip the first S if len(qdata) > 70: self.left.update(self.on_serial_ports(),"Checked", qr_code(self.device_count)) for i_a in qdata: if b'\r' in i_a: break b.append(i_a[0]) #TODO: there is a glich in the code, if we do advanced while running the QC, # we only get a portion of the UART string if len(b) > 120: if b[1] == b'A': #in b we dont need the last 3 values \r \n and b'S' #and in the bedinning we dont need b'TAT' data = [] # print(b) for i in range(0,len(b)): data.append(b[i].decode("utf-8")) #find position of "I" for STAT string ending #find position of "S" or "\r" for INFT string ending # print(data) if "I" in data: data_stat = data[4:(data.index("I")-1)] data_info = data[data.index("I")+5:] print(data_stat) print(data_info) data_stat = "".join(data_stat) data_info = "".join(data_info) data_stat = data_stat.split(",") data_info = data_info.split(",") # now we have our data in the above variables '''ACC | GSM | GSM_SNR | RTC | SD | NRF_SPI | STN | V_BAT | GPS | GPS_ANT | NRF-ACC | NRF_SD | NRF_OTA STM_FW | STM_ID | STN_FW | GSM_Ver | CCID | NRF_ID_low | NRF_ID_high ''' print(data_stat) print(data_info) self.livefeed.add_status(data_stat) self.livefeed.add_info(data_info) self.update_faces() else: self.small_string_flag += 1 if self.small_string_flag > 10: QMessageBox.information(self, "Check Connections", "Receiving less data, maybe NRF SPI has failed") self.small_string_flag = 5 else: pass self.current_device_no = self.basic.device_text.toPlainText() if self.current_device_no != "": self.basic.qr.clear() self.basic.qr.append(qr_code(self.current_device_no)) #the following is for data from Teensy '''data = qdata[0] data = data[0].decode("utf-8") data_stat = "".join(data[5:34]) data_info = ''.join(data[41:]) data_stat = data_stat.split(",") data_info = data_info.split(",") print(data_stat) print(data_info) self.livefeed.add_status(data_stat) self.livefeed.add_info(data_info) self.update_faces()''' def update_faces(self): '''ACC | GSM | GSM_SNR | RTC | SD | NRF_SPI | STN | V_BAT | GPS | GPS_ANT | NRF-ACC | NRF_SD | NRF_OTA STM_FW | STM_ID | STN_FW | GSM_Ver | CCID | NRF_ID_low | NRF_ID_high | NRF_Version ''' if self.livefeed.has_new_status: data_status = self.livefeed.read_status() #update battery voltage self.basic.text1.clear() self.basic.text1.append(data_status[7]) #read info data_info = self.livefeed.read_info() if self.check_stm_status(data_status,data_info): print("All stats good") else: print("Error\n") if self.livefeed.has_new_info: data_info = self.livefeed.read_info() else: pass '''if self.livefeed.has_new_status: data_status = self.livefeed.read_status() if self.check_stm_status(data_status): self.middle.update_middle_status(data_status[-1]) else: print("Error\n") # self.middle.update_middle(data[0], data[1], data[2], data[3:]) if self.livefeed.has_new_info: data_info = self.livefeed.read_info() #format stm_id, nrf_id, stm_ver, nrf_ver if self.check_stm_status(data_status): self.middle.update_middle(data_info[1], data_info[-1], data_info[0], data_info[2]) else: print("Error\n") else: pass''' def check_stm_status(self,data,info): '''ACC | GSM | GSM_SNR | RTC | SD | NRF_SPI | STN | V_BAT | GPS | GPS_ANT | NRF-ACC | NRF_SD | NRF_OTA STM_FW | STM_ID | STN_FW | GSM_Ver | CCID | NRF_ID_low | NRF_ID_high | NRF_version ''' #this is used for teensy debugging #[STAT]: //ACC | GSM | GSM_SNR | RTC | SD | NRF_SPI | STN | V_BAT | GPS | GPS_ANT | NRF-ACC | NRF_SD | NRF_OTA #self.middle.update_status_flags(data[6], data[1], data[0], data[3], data[5],data[2], # data[4], data[7], data[8], data[9]) if self.advanced_set: print(info[8]) if 'S' not in info[8]: self.middle.update_middle(*info) self.middle.update_status_flags(data[6], data[1], data[0], data[3], data[5], data[2], data[4], data[8], data[9], data[10], data[11], data[12]) else: print("Bad info string received\n") #print(data) if '0' in data: print(data) number_fails = data.count('0') fail = "" failed_devices = [] if data[0] == '0': failed_devices.append("ACC") if data[1] == '0': failed_devices.append("GSM") if data[2] == '0': failed_devices.append("GSM-SNR") if data[3] == '0': failed_devices.append("RTC") if data[4] == '0': failed_devices.append("SD") if data[5] == '0': failed_devices.append("NRF-SPI") if data[6] == '0': failed_devices.append("STN") if data[7] == '0': failed_devices.append("GPS") if data[8] == '0': failed_devices.append("GPS-ANT") if data[9] == '0': failed_devices.append("NRF-ACC") print(failed_devices) fail = " ".join(failed_devices) print(fail) QMessageBox.critical(self, "Device Modules Failed", "%s module(s) failed"% fail) self.basic.pixelLabel.setPixmap(QPixmap("images/cross-1.png")) #TODO: Disable this popup from comming again and again return 0 elif int(data[2]) < 12: QMessageBox.critical(self, "GSM Antenna", "Please reconnect it") else: #TODO: Enable all the buttons self.basic.pixelLabel.setPixmap(QPixmap("images/tick-black.png")) self.basic.submitButton.setEnabled(True) self.basic.saveToText.setEnabled(True) self.basic.nextButton.setEnabled(True) return 1 def on_submit(self): self.basic.pixelLabel.setPixmap(QPixmap("images/wait_1.jpg")) time.sleep(1) data_status = self.livefeed.read_status() data_info = self.livefeed.read_info() user_input_voltage = self.basic.text2.toPlainText() if user_input_voltage != "": user_input_voltage = float(user_input_voltage) else: QMessageBox.information(self, "Please enter value", "Measure the voltage value.") return if data_info[4] == "": print("no ccid") data_info[4] = "123456789" if data_info[3] == "": print("No gsm version") data_info[3] = 255 if data_info[2] == "": print("no STN version") data_info[2] = "255" ''' stms_i = stnFlag nrfs_st= string of nrf_sd+unplug+gps+acc nrfs_i = gps gsmv = gsm version gpsv = we dont currently have gps version ''' stm_status_bk = str(data_status[0]+data_status[1]+data_status[3]+data_status[4]+data_status[5]+data_status[6]+ data_status[7]+data_status[8]+data_status[9]) data_to_backend = {"lb":int(self.current_device_no), "pc":str(qr_code(int(self.current_device_no))), "flg":1, "stm":str(data_info[1]), "stmv": int(data_info[0]), "nrf":str(data_info[5] + data_info[6]), "nrfv":int(data_info[-1]), "simcc":str(data_info[4]), "stms_st":stm_status_bk, "stms_i":int(data_status[6]), "nrfs_st": "1111","nrfs_i": int(data_status[8]), "gsmv": data_info[3] ,"pwr": data_status[7],"hbn":int(data_info[-1]), "stnv":str(data_info[2]),"gpsv":"123456789A", "vltDevice":int(user_input_voltage)} print(data_to_backend) r = requests.post('http://carnot-staging.herokuapp.com/devices/log/', data = json.dumps(data_to_backend), headers = {"ApiKey":"JXn8e6C29jhZ065i8wyQktY33YD3s9zy"}) #print(r.content) y = r.content.decode("utf-8") # now we have a string if "true" in y: QMessageBox.information(self, "Server", "Data saved to backed") self.new_device() else: QMessageBox.critical(self, "Server", "Check internet connection") def on_save_txt(self): data_status = self.livefeed.read_status() data_info = self.livefeed.read_info() self.local_file = open("carnot_device.csv","a+") self.local_file.write("%d, " % int(self.current_device_no)) self.local_file.write("%s, " % (qr_code(int(self.current_device_no)))) for i in data_info: self.local_file.write("%s, " % i) for i in data_status: print(i) self.local_file.write("%s, " % (data_status)) self.local_file.write("\r\n") self.local_file.close()
class PlottingDataMonitor(QMainWindow): def __init__(self, parent=None): super(PlottingDataMonitor, self).__init__(parent) self.monitor_active = False self.com_monitor = None self.livefeed = LiveDataFeed() self.temperature_samples = [] self.timer = QTimer() # menu # self.file_menu = self.menuBar().addMenu("&File") selectport_action = QAction('Select TTY &Port...', self) selectport_action.triggered.connect(self.on_select_port) self.file_menu.addAction(selectport_action) self.start_action = QAction('&Start monitor') self.start_action.triggered.connect(self.on_start) self.start_action.setEnabled(False) self.file_menu.addAction(self.start_action) self.stop_action = QAction('&Stop monitor') self.stop_action.triggered.connect(self.on_stop) # main widget # # port portname_label = QLabel('tty port:') self.portname = QLineEdit() self.portname.setEnabled(False) self.portname.setFrame(False) portname_layout = QHBoxLayout() portname_layout.addWidget(portname_label) portname_layout.addWidget(self.portname, 0) portname_layout.addStretch(1) portname_groupbox = QGroupBox('Port') portname_groupbox.setLayout(portname_layout) # plot widget self.plot = qwt.QwtPlot(self) self.plot.setCanvasBackground(Qt.black) self.plot.setAxisTitle(qwt.QwtPlot.xBottom, 'Time') self.plot.setAxisScale(qwt.QwtPlot.xBottom, 0, 10, 1) self.plot.setAxisTitle(qwt.QwtPlot.yLeft, 'Temperature') self.plot.setAxisScale(qwt.QwtPlot.yLeft, 0, 250, 40) self.plot.replot() # curve widget self.curve = qwt.QwtPlotCurve('') self.curve.setRenderHint(qwt.QwtPlotItem.RenderAntialiased) pen = QPen(QColor('limegreen')) pen.setWidth(2) self.curve.setPen(pen) self.curve.attach(self.plot) # dial # self.dial = QDial() self.dial.setNotchesVisible(True) self.dial.setRange(0, 20) self.dial.setValue(10) self.dial.valueChanged.connect(self.on_dial_change) self.dial_label = QLabel('Update speed = %s (Hz)' % self.dial.value()) self.dial_label.setAlignment(Qt.AlignTop | Qt.AlignHCenter) dial_layout = QVBoxLayout() dial_layout.addWidget(self.dial) dial_layout.addWidget(self.dial_label) # plot layout plot_layout = QVBoxLayout() plot_layout.addWidget(self.plot) plot_layout.addLayout(dial_layout) plot_groupbox = QGroupBox('Temperature') plot_groupbox.setLayout(plot_layout) # main self.main_frame = QWidget() main_layout = QVBoxLayout() main_layout.addWidget(portname_groupbox) main_layout.addWidget(plot_groupbox) main_layout.addStretch(1) self.main_frame.setLayout(main_layout) self.setCentralWidget(self.main_frame) # status # self.status_text = QLabel('Monitor idle') self.statusBar().addWidget(self.status_text, 1) def set_actions_enable_state(self): if self.portname.text() == '': start_enable = stop_enable = False else: start_enable = not self.monitor_active stop_enable = self.monitor_active self.start_action.setEnabled(start_enable) self.stop_action.setEnabled(stop_enable) def read_serial_data(self): '''Called periodically be the update timer to read data from the serial port. ''' qdata = list(get_all_from_queue(self.data_q)) if len(qdata) > 0: # print(len(qdata)) data = dict(timestamp=qdata[-1][1], temperature=ord(qdata[-1][0])) # print(data) self.livefeed.add_data(data) else: print('no data') def update_monitor(self): '''Updates the state of the monitor window with new data. The livefeed is used to dind out whether new data was received since last update. If not, nothing is updated. ''' if self.livefeed.has_new_data: data = self.livefeed.read_data() # print(data) self.temperature_samples.append( (data['timestamp'], data['temperature'])) if len(self.temperature_samples) > 100: self.temperature_samples.pop(0) xdata = [s[0] for s in self.temperature_samples] ydata = [s[1] for s in self.temperature_samples] avg = sum(ydata) / float(len(ydata)) self.plot.setAxisScale(qwt.QwtPlot.xBottom, xdata[0], max(20, xdata[-1])) self.curve.setData(xdata, ydata) self.plot.replot() # slots def on_select_port(self): text, ok = QInputDialog.getText(self, 'Port Name', 'Enter tty:') if ok: self.portname.setText(str(text)) self.set_actions_enable_state() def on_start(self): '''Start the monitor: com_monitor thread and the update timer''' if self.com_monitor is not None or self.portname.text() == '': return self.data_q = Queue() self.error_q = Queue() self.com_monitor = ComMonitorThread(self.data_q, self.error_q, self.portname.text(), 38400) self.com_monitor.start() com_error = None try: com_error = self.error_q.get(True, 0.01) except Empty: pass if com_error is not None: QMessageBox.critical(self, 'ComMonitorThread error', com_error) self.com_monitor = None self.monitor_active = True self.set_actions_enable_state() self.timer = QTimer() self.timer.timeout.connect(self.on_timer) update_freq = self.dial.value() if update_freq > 0: self.timer.start(1000 / update_freq) self.status_text.setText('Monitor running') def on_stop(self): '''Stop the monitor''' if self.com_monitor is not None: self.com_monitor.join(0.01) self.com_monitor = None self.monitor_actibe = False self.timer.stop() self.set_actions_enable_state() self.status_text.setText('Monitor idle') def on_timer(self): '''Executed periodically when the monitor update timer is fired.''' self.read_serial_data() self.update_monitor() def on_dial_change(self): '''When the dial is rotated, it sets the update interval of the timer''' update_freq = self.dial.value() self.dial_label.setText('Update speed = %s (Hz)' % self.dial.value()) if self.timer.isActive(): update_freq = max(0.01, update_freq) self.timer.setInterval(1000 / update_freq)
class PlottingDataMonitor(QMainWindow): def __init__(self, parent=None): super(PlottingDataMonitor, self).__init__(parent) self.monitor_active = False self.com_monitor = None self.com_data_q = None self.com_error_q = None self.livefeed = LiveDataFeed() self.temperature_samples = [] self.timer = QTimer() self.create_menu() self.create_main_frame() self.create_status_bar() # self.showFullScreen() def make_data_box(self, name): label = QLabel(name) qle = QLineEdit() qle.setEnabled(False) qle.setFrame(False) return (label, qle) def create_plot(self): plot = Qwt.QwtPlot(self) plot.setCanvasBackground(Qt.black) plot.setAxisTitle(Qwt.QwtPlot.xBottom, "Time") plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10, 1) plot.setAxisTitle(Qwt.QwtPlot.yLeft, "val") plot.setAxisScale(Qwt.QwtPlot.yLeft, 0, 30000, 40) plot.setAxisAutoScale(Qwt.QwtPlot.yLeft) plot.replot() curve = Qwt.QwtPlotCurve("") # curve.setRenderHint(Qwt.QwtPlotItem.RenderAntialiased) pen = QPen(QColor("limegreen")) pen.setWidth(2) curve.setPen(pen) curve.attach(plot) return plot, curve def create_status_bar(self): self.status_text = QLabel("Monitor idle") self.statusBar().addWidget(self.status_text, 1) def create_main_frame(self): # Port name # portname_l, self.portname = self.make_data_box("Serial port:") portname_layout = QHBoxLayout() portname_layout.addWidget(portname_l) portname_layout.addWidget(self.portname, 0) portname_layout.addStretch(1) portname_groupbox = QGroupBox("Serial Port") portname_groupbox.setLayout(portname_layout) # Plot and thermo # self.plot, self.curve = self.create_plot() # self.thermo = self.create_thermo() plot_layout = QVBoxLayout() plot_layout.addWidget(self.plot) plot_groupbox = QGroupBox("Value") plot_groupbox.setLayout(plot_layout) # Main frame and layout # self.main_frame = QWidget() main_layout = QVBoxLayout() main_layout.addWidget(portname_groupbox) main_layout.addWidget(plot_groupbox) main_layout.addStretch(1) self.main_frame.setLayout(main_layout) self.setCentralWidget(self.main_frame) self.set_actions_enable_state() def create_menu(self): self.file_menu = self.menuBar().addMenu("&File") selectport_action = self.create_action( "Select serial &Port...", shortcut="Ctrl+P", slot=self.on_select_port, tip="Select a serial port" ) self.start_action = self.create_action( "&Start monitor", shortcut="Ctrl+M", slot=self.on_start, tip="Start the data monitor" ) self.stop_action = self.create_action( "&Stop monitor", shortcut="Ctrl+T", slot=self.on_stop, tip="Stop the data monitor" ) exit_action = self.create_action("E&xit", slot=self.close, shortcut="Ctrl+X", tip="Exit the application") self.start_action.setEnabled(False) self.stop_action.setEnabled(False) self.add_actions(self.file_menu, (selectport_action, self.start_action, self.stop_action, None, exit_action)) self.help_menu = self.menuBar().addMenu("&Help") about_action = self.create_action("&About", shortcut="F1", slot=self.on_about, tip="About the monitor") self.add_actions(self.help_menu, (about_action,)) def set_actions_enable_state(self): if self.portname.text() == "": start_enable = stop_enable = False else: start_enable = not self.monitor_active stop_enable = self.monitor_active self.start_action.setEnabled(start_enable) self.stop_action.setEnabled(stop_enable) def on_about(self): msg = __doc__ QMessageBox.about(self, "About the demo", msg.strip()) def on_select_port(self): ports = list(enumerate_serial_ports()) if len(ports) == 0: QMessageBox.critical(self, "No ports", "No serial ports found") return item, ok = QInputDialog.getItem(self, "Select a port", "Serial port:", ports, 0, False) if ok and not item.isEmpty(): self.portname.setText(item) self.set_actions_enable_state() def on_stop(self): """ Stop the monitor """ if self.com_monitor is not None: self.com_monitor.join(0.01) self.com_monitor = None self.monitor_active = False self.timer.stop() self.set_actions_enable_state() self.status_text.setText("Monitor idle") def on_start(self): """ Start the monitor: com_monitor thread and the update timer """ if self.com_monitor is not None or self.portname.text() == "": return self.data_q = Queue.Queue() self.error_q = Queue.Queue() self.com_monitor = ComMonitorThread(self.data_q, self.error_q, full_port_name(str(self.portname.text())), 9600) self.com_monitor.start() com_error = get_item_from_queue(self.error_q) if com_error is not None: QMessageBox.critical(self, "ComMonitorThread error", com_error) self.com_monitor = None self.monitor_active = True self.set_actions_enable_state() self.timer = QTimer() self.connect(self.timer, SIGNAL("timeout()"), self.on_timer) update_freq = 20 self.timer.start(1000.0 / update_freq) self.status_text.setText("Monitor running") def on_timer(self): """ Executed periodically when the monitor update timer is fired. """ self.read_serial_data() self.update_monitor() def update_monitor(self): """ Updates the state of the monitor window with new data. The livefeed is used to find out whether new data was received since the last update. If not, nothing is updated. """ if self.livefeed.has_new_data: data = self.livefeed.read_data() self.temperature_samples.append((data["timestamp"], data["temperature"])) if len(self.temperature_samples) > 100: self.temperature_samples.pop(0) xdata = [s[0] for s in self.temperature_samples] ydata = [s[1] for s in self.temperature_samples] # self.plot.setAxisScale(Qwt.QwtPlot.xBottom, xdata[0], max(10, xdata[-1])) self.plot.setAxisScale(Qwt.QwtPlot.xBottom, xdata[0], xdata[0] + 5) self.curve.setData(xdata, ydata) self.plot.replot() def read_serial_data(self): """ Called periodically by the update timer to read data from the serial port. """ qdata = list(get_all_from_queue(self.data_q)) if len(qdata) > 0: # print qdata data = dict(timestamp=qdata[-1][1], temperature=int(qdata[-1][0])) self.livefeed.add_data(data) # The following two methods are utilities for simpler creation # and assignment of actions # def add_actions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def create_action(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action
class PlottingDataMonitor(QMainWindow): def __init__(self, parent=None): super(PlottingDataMonitor, self).__init__(parent) self.setWindowTitle('ADXL345 Realtime Monitor') self.resize(800, 600) self.port = "" self.baudrate = 9600 self.monitor_active = False # on/off monitor state self.com_monitor = None # monitor reception thread self.com_data_q = None self.com_error_q = None self.livefeed = LiveDataFeed() self.timer = QTimer() self.g_samples = [[], [], []] self.curve = [None]*3 self.gcurveOn = [1]*3 # by default all curve are plotted self.csvdata = [] self.create_menu() self.create_main_frame() self.create_status_bar() # Activate start-stop button connections self.connect(self.button_Connect, SIGNAL("clicked()"), self.OnStart) self.connect(self.button_Disconnect, SIGNAL("clicked()"), self.OnStop) #---------------------------------------------------------- def create_com_box(self): """ Purpose: create the serial com groupbox Return: return a layout of the serial com """ self.com_box = QGroupBox("COM Configuration") com_layout = QGridLayout() self.radio9600 = QRadioButton("9600") self.radio9600.setChecked(1) self.radio19200 = QRadioButton("19200") self.Com_ComboBox = QComboBox() com_layout.addWidget(self.Com_ComboBox,0,0,1,2) com_layout.addWidget(self.radio9600,1,0) com_layout.addWidget(self.radio19200,1,1) self.fill_ports_combobox() self.button_Connect = QPushButton("Start") self.button_Disconnect = QPushButton("Stop") self.button_Disconnect.setEnabled(False) com_layout.addWidget(self.button_Connect,0,2) com_layout.addWidget(self.button_Disconnect,1,2) return com_layout #--------------------------------------------------------------------- def create_plot(self): """ Purpose: create the pyqwt plot Return: return a list containing the plot and the list of the curves """ plot = Qwt.QwtPlot(self) plot.setCanvasBackground(Qt.black) plot.setAxisTitle(Qwt.QwtPlot.xBottom, 'Time') plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10, 1) plot.setAxisTitle(Qwt.QwtPlot.yLeft, 'Acceleration') plot.setAxisScale(Qwt.QwtPlot.yLeft, YMIN, YMAX, (YMAX-YMIN)/10) plot.replot() curve = [None]*3 pen = [QPen(QColor('limegreen')), QPen(QColor('red')) ,QPen(QColor('yellow')) ] for i in range(3): curve[i] = Qwt.QwtPlotCurve('') curve[i].setRenderHint(Qwt.QwtPlotItem.RenderAntialiased) pen[i].setWidth(2) curve[i].setPen(pen[i]) curve[i].attach(plot) return plot, curve #--------------------------------------------------- def create_knob(self): """ Purpose: create a knob Return: return a the knob widget """ knob = Qwt.QwtKnob(self) knob.setRange(0, 180, 0, 1) knob.setScaleMaxMajor(10) knob.setKnobWidth(50) knob.setValue(10) return knob #--------------------------------------------------- def create_status_bar(self): self.status_text = QLabel('Monitor idle') self.statusBar().addWidget(self.status_text, 1) #--------------------------------------------------- def create_checkbox(self, label, color, connect_fn, connect_param): """ Purpose: create a personalized checkbox Input: the label, color, activated function and the transmitted parameter Return: return a checkbox widget """ checkBox = QCheckBox(label) checkBox.setChecked(1) checkBox.setFont( QFont("Arial", pointSize=12, weight=QFont.Bold ) ) green = QPalette() green.setColor(QPalette.Foreground, color) checkBox.setPalette(green) self.connect(checkBox, SIGNAL("clicked()"), partial(connect_fn,connect_param)) return checkBox #--------------------------------------------------- def create_main_frame(self): """ Purpose: create the main frame Qt widget """ # Serial communication combo box portname_layout = self.create_com_box() self.com_box.setLayout(portname_layout) # Update speed knob self.updatespeed_knob = self.create_knob() self.connect(self.updatespeed_knob, SIGNAL('valueChanged(double)'), self.on_knob_change) self.knob_l = QLabel('Update speed = %s (Hz)' % self.updatespeed_knob.value()) self.knob_l.setAlignment(Qt.AlignTop | Qt.AlignHCenter) # Create the plot and curves self.plot, self.curve = self.create_plot() # Create the configuration horizontal panel self.max_spin = QSpinBox() self.max_spin.setMaximum(1000) self.max_spin.setValue(1000) spins_hbox = QHBoxLayout() spins_hbox.addWidget(QLabel('Save every')) spins_hbox.addWidget(self.max_spin) spins_hbox.addWidget( QLabel('Lines')) #spins_hbox.addStretch(1) self.gCheckBox = [ self.create_checkbox("Acceleration(x)", Qt.green, self.activate_curve, 0), self.create_checkbox("Acceleration(y)", Qt.red, self.activate_curve, 1), self.create_checkbox("Acceleration(z)", Qt.yellow, self.activate_curve, 2) ] self.button_clear = QPushButton("Clear screen") self.connect(self.button_clear, SIGNAL("clicked()"), self.clear_screen) # Place the horizontal panel widget plot_layout = QGridLayout() plot_layout.addWidget(self.plot,0,0,8,7) plot_layout.addWidget(self.gCheckBox[0],0,8) plot_layout.addWidget(self.gCheckBox[1],1,8) plot_layout.addWidget(self.gCheckBox[2],2,8) plot_layout.addWidget(self.button_clear,3,8) plot_layout.addLayout(spins_hbox,4,8) plot_layout.addWidget(self.updatespeed_knob,5,8) plot_layout.addWidget(self.knob_l,6,8) plot_groupbox = QGroupBox('Acceleration') plot_groupbox.setLayout(plot_layout) # Place the main frame and layout self.main_frame = QWidget() main_layout = QVBoxLayout() main_layout.addWidget(self.com_box) main_layout.addWidget(plot_groupbox) main_layout.addStretch(1) self.main_frame.setLayout(main_layout) self.setCentralWidget(self.main_frame) #---------------------------------------------------------------------- def clear_screen(self): g_samples[0] = [] #----------------------------- def activate_curve(self, axe): if self.gCheckBox[axe].isChecked(): self.gcurveOn[axe] = 1 else: self.gcurveOn[axe] = 0 #--------------------------------------- def create_menu(self): self.file_menu = self.menuBar().addMenu("&File") selectport_action = self.create_action("Select COM &Port...", shortcut="Ctrl+P", slot=self.on_select_port, tip="Select a COM port") self.start_action = self.create_action("&Start monitor", shortcut="Ctrl+M", slot=self.OnStart, tip="Start the data monitor") self.stop_action = self.create_action("&Stop monitor", shortcut="Ctrl+T", slot=self.OnStop, tip="Stop the data monitor") exit_action = self.create_action("E&xit", slot=self.close, shortcut="Ctrl+X", tip="Exit the application") self.start_action.setEnabled(False) self.stop_action.setEnabled(False) self.add_actions(self.file_menu, ( selectport_action, self.start_action, self.stop_action, None, exit_action)) self.help_menu = self.menuBar().addMenu("&Help") about_action = self.create_action("&About", shortcut='F1', slot=self.on_about, tip='About the monitor') self.add_actions(self.help_menu, (about_action,)) #---------------------------------------------------------------------- def set_actions_enable_state(self): if self.portname.text() == '': start_enable = stop_enable = False else: start_enable = not self.monitor_active stop_enable = self.monitor_active self.start_action.setEnabled(start_enable) self.stop_action.setEnabled(stop_enable) #----------------------------------------------- def on_about(self): msg = __doc__ QMessageBox.about(self, "About the demo", msg.strip()) #----------------------------------------------- def on_select_port(self): ports = enumerate_serial_ports() if len(ports) == 0: QMessageBox.critical(self, 'No ports', 'No serial ports found') return item, ok = QInputDialog.getItem(self, 'Select a port', 'Serial port:', ports, 0, False) if ok and not item.isEmpty(): self.portname.setText(item) self.set_actions_enable_state() #----------------------------------------------- def fill_ports_combobox(self): """ Purpose: rescan the serial port com and update the combobox """ vNbCombo = "" self.Com_ComboBox.clear() self.AvailablePorts = enumerate_serial_ports() for value in self.AvailablePorts: self.Com_ComboBox.addItem(value) vNbCombo += value + " - " vNbCombo = vNbCombo[:-3] debug(("--> Les ports series disponibles sont: %s " % (vNbCombo))) #---------------------------------------------------------------------- def OnStart(self): """ Start the monitor: com_monitor thread and the update timer """ if self.radio19200.isChecked(): self.baudrate = 19200 print "--> baudrate is 19200 bps" if self.radio9600.isChecked(): self.baudrate = 9600 print "--> baudrate is 9600 bps" vNbCombo = self.Com_ComboBox.currentIndex() self.port = self.AvailablePorts[vNbCombo] self.button_Connect.setEnabled(False) self.button_Disconnect.setEnabled(True) self.Com_ComboBox.setEnabled(False) self.data_q = Queue.Queue() self.error_q = Queue.Queue() self.com_monitor = ComMonitorThread( self.data_q, self.error_q, self.port, self.baudrate) self.com_monitor.start() com_error = get_item_from_queue(self.error_q) if com_error is not None: QMessageBox.critical(self, 'ComMonitorThread error', com_error) self.com_monitor = None self.monitor_active = True self.connect(self.timer, SIGNAL('timeout()'), self.on_timer) update_freq = self.updatespeed_knob.value() if update_freq > 0: self.timer.start(1000.0 / update_freq) self.status_text.setText('Monitor running') debug('--> Monitor running') #------------------------------------------------------------ def OnStop(self): """ Stop the monitor """ if self.com_monitor is not None: self.com_monitor.join(1000) self.com_monitor = None self.monitor_active = False self.button_Connect.setEnabled(True) self.button_Disconnect.setEnabled(False) self.Com_ComboBox.setEnabled(True) self.timer.stop() self.status_text.setText('Monitor idle') debug('--> Monitor idle') #----------------------------------------------- def on_timer(self): """ Executed periodically when the monitor update timer is fired. """ self.read_serial_data() self.update_monitor() #----------------------------------------------- def on_knob_change(self): """ When the knob is rotated, it sets the update interval of the timer. """ update_freq = self.updatespeed_knob.value() self.knob_l.setText('Update speed = %s (Hz)' % self.updatespeed_knob.value()) if self.timer.isActive(): update_freq = max(0.01, update_freq) self.timer.setInterval(1000.0 / update_freq) #----------------------------------------------- def update_monitor(self): """ Updates the state of the monitor window with new data. The livefeed is used to find out whether new data was received since the last update. If not, nothing is updated. """ if self.livefeed.has_new_data: data = self.livefeed.read_data() self.csvdata.append([data['timestamp'], data['gx'], data['gy'], data['gz']] ) if len(self.csvdata) > self.max_spin.value(): f = open(time.strftime("%H%M%S")+".csv", 'wt') try: writer = csv.writer(f) for i in range(self.max_spin.value()): writer.writerow( self.csvdata[i] ) print 'transfert data to csv after 1000 samples' finally: f.close() self.csvdata = [] self.g_samples[0].append( (data['timestamp'], data['gx'])) if len(self.g_samples[0]) > 100: self.g_samples[0].pop(0) self.g_samples[1].append( (data['timestamp'], data['gy'])) if len(self.g_samples[1]) > 100: self.g_samples[1].pop(0) self.g_samples[2].append( (data['timestamp'], data['gz'])) if len(self.g_samples[2]) > 100: self.g_samples[2].pop(0) tdata = [s[0] for s in self.g_samples[2]] for i in range(3): data[i] = [s[1] for s in self.g_samples[i]] if self.gcurveOn[i]: self.curve[i].setData(tdata, data[i]) """ debug("xdata", data[0]) debug("ydata", data[1]) debug("tdata", data[2]) """ self.plot.setAxisScale(Qwt.QwtPlot.xBottom, tdata[0], max(5, tdata[-1]) ) self.plot.replot() #----------------------------------------------- def read_serial_data(self): """ Called periodically by the update timer to read data from the serial port. """ qdata = list(get_all_from_queue(self.data_q)) # get just the most recent data, others are lost #print "qdata" , qdata if len(qdata) > 0: data = dict(timestamp=qdata[-1][1], gx=qdata[-1][0][0], gy=qdata[-1][0][1], gz=qdata[-1][0][2] ) self.livefeed.add_data(data) #----------------------------------------------- # The following two methods are utilities for simpler creation # and assignment of actions # def add_actions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) #----------------------------------------------- def create_action( self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action
class nanoScat_PD(QtGui.QMainWindow): ui = None stepperCOMPort = None ATrtAddr = 255 currentAngle = 0 prevMove = ([0, 0], [0, 0]) line0, line1, line_sig, line_ref, line_ref_norm, line5, line6, line7 = None, None, None, None, None, None, None, None lines = [ line0, line1, line_sig, line_ref, line_ref_norm, line5, line6, line7 ] steppingTimer = None calibrTimer = None measTimer = None stepperStateTimer = None FWCalibrationCounter = 0 FWCalibrationCounterList = [] angleSensorSerial = None com_monitor = None angleUpdateTimer = None angleUpdateThread = None lastDirection = 1 tmpData = None num = 10 calibrData = np.array([]) measData = np.array([]) intStepCounter = 0 moveFlag = 0 extLaserStrob = None extDataBuffer = None oscillo = None oscReadTimerTimer = None lastFiltChTime = None lastDivChange = time.time() oscilloLastMaster = None oscilloLastIndex = [-1, -1] #et = ET1255() def __init__(self, parent=None): QtGui.QMainWindow.__init__(self, parent) self.ui = uic.loadUi("mainwindow.ui") self.ui.closeEvent = self.closeEvent self.steppingTimer = QtCore.QTimer() self.calibrTimer = QtCore.QTimer() self.calibrHomeTimer = QtCore.QTimer() self.calibrFWTimer = QtCore.QTimer() self.measTimer = QtCore.QTimer() self.angleUpdateTimer = QtCore.QTimer() self.stepperStateTimer = QtCore.QTimer() self.oscReadTimer = QtCore.QTimer() self.config = configparser.ConfigParser() self.config.read('settings.ini') print(sys.argv[0], self.config.sections()) self.globalSettingsDict = self.config[ 'GLOBAL'] #.read('globalSettings.ini') self.updateSettingsTable() self.uiConnect() self.initUi() self.fileDialog = QFileDialog(self) #self.initET1255() self.tmpData = [] #[[0,0,0]] self.calibrData = np.array([]) #[0,0,0]) #self.SMD = SMD004() #self.extLaserStrob = laserStrob(0.1) self.oscillo = HAMEG() self.oscilloLastMaster = 'HAMEG' #self.startLaserStrob(0.02) def updateSettingsTable(self): if 'GLOBAL' in self.config.sections(): section = self.config['GLOBAL'] self.ui.globalConfig.setVerticalHeaderLabels(list(section)) for row, key in enumerate(section): print(row, key) for column, val in enumerate(section[key].split(',')): print(column, val) newitem = QTableWidgetItem(val) self.ui.globalConfig.setItem(row, column, newitem) if 'FILTERS' in self.config.sections(): section = self.config['FILTERS'] self.ui.filtersTab.setVerticalHeaderLabels(list(section)) for row, key in enumerate(section): print(row, key) for column, val in enumerate(section[key].split(',')): print(column, val) newitem = QTableWidgetItem(val) self.ui.filtersTab.setItem(row, column, newitem) #for column, key in enumerate(section): # newitem = QTableWidgetItem(item) # for row, item in enumerate(self.data[key]): # newitem = QTableWidgetItem(item) # self.setItem(row, column, newitem) def saveConfig(self): if 'GLOBAL' in self.config.sections(): section = self.config['GLOBAL'] rows = self.ui.globalConfig.rowCount() columns = self.ui.globalConfig.columnCount() for row in range(rows): key = self.ui.globalConfig.verticalHeaderItem(row).text() val = [] for column in range(columns): try: val.append( self.ui.globalConfig.item(row, column).text()) except: break section[key] = ','.join(val) print(key, val) if 'FILTERS' in self.config.sections(): section = self.config['FILTERS'] rows = self.ui.filtersTab.rowCount() columns = self.ui.filtersTab.columnCount() for row in range(rows): key = self.ui.filtersTab.verticalHeaderItem(row).text() val = [] for column in range(columns): try: val.append(self.ui.filtersTab.item(row, column).text()) except: break section[key] = ','.join(val) print(key, val) with open('settings.ini', 'w') as configfile: self.config.write(configfile) ''' for row,key in enumerate(section): print(row,key) for column,val in enumerate(section[key].split(',')): print(column,val) newitem = QTableWidgetItem(val) self.ui.globalConfig.setItem(row,column,newitem) if 'FILTERS' in self.config.sections(): section = self.config['FILTERS'] self.ui.globalConfig.setVerticalHeaderLabels(list(section)) for row,key in enumerate(section): print(row,key) newitem = QTableWidgetItem(key) self.ui.filtersTab.setItem(row,0,newitem) for column,val in enumerate(section[key].split(',')): print(column,val) newitem = QTableWidgetItem(val) self.ui.filtersTab.setItem(row,column+1,newitem) ''' def initUi(self): self.pw = pg.PlotWidget( name='Plot1' ) ## giving the plots names allows us to link their axes together self.ui.l.addWidget(self.pw) self.pw2 = pg.PlotWidget(name='Plot2') self.ui.l.addWidget(self.pw2) self.osc_pw = pg.PlotWidget(name='Plot3') self.ui.oscilloPlot.addWidget(self.osc_pw) #self.osc_pw.setXRange(0, 360) #self.osc_pw.showAxis('bottom', False) self.osc_pw.showGrid(x=True, y=True) self.pw.showGrid(x=True, y=True) self.pw2.showGrid(x=True, y=True) #self.osc_pw.showAxis('bottom', False) self.osc_pw.setYRange(0, 256) self.osc_pw.setMinimumWidth(300) self.osc_pw.setMinimumHeight(200) self.ui.show() ## Create an empty plot curve to be filled later, set its pen colors = [ 'red', "green", 'blue', 'cyan', 'magenta', 'yellow', 'purple', 'olive' ] #for i in range(0,self.ui.channelsSettings.rowCount()): # self.lines[i] = self.pw.plot() # self.lines[i].setPen(QtGui.QColor(colors[i])) self.line0 = self.pw2.plot() print(self.line0) self.line0.setPen(QtGui.QColor('cyan')) self.line1 = self.pw.plot() self.line1.setPen(QtGui.QColor("orange")) self.line5 = self.pw.plot() self.line5.setPen(QtGui.QColor("red")) self.line_sig = self.osc_pw.plot() self.line_sig.setPen(QtGui.QColor("orange")) self.line_ref = self.osc_pw.plot() self.line_ref.setPen(QtGui.QColor("cyan")) self.line_ref_norm = self.osc_pw.plot() self.line_ref_norm.setPen(QtGui.QColor("red")) self.pw.setLabel('left', 'Signal', units='arb. un.') self.pw.setLabel('bottom', 'Angle', units='deg.') self.pw.setXRange(0, 360) self.pw.setYRange(0, 1e10) self.pw2.setMaximumHeight(300) def setStepperParam(self): pass def getCorrectedAngle(self): angle = self.ui.steppingAngle.value() #calibr = float(self.config['STEPPER1']['calibrationCoefficient']) #self.ui.steppingCalibr.value() #tmp_angle = int(angle*calibr)/calibr #self.ui.steppingAngle.setValue(tmp_angle) #return int(tmp_angle*calibr), tmp_angle return angle, angle def steps2angle(self, steps, motor=1): calibr = float( self.config['STEPPER' + str(motor)] ['calibrationCoefficient']) #self.ui.steppingCalibr.value() return steps / calibr def prepInternCounter(self, direction): if direction != self.lastDirection: #self.SMD.eClearSteps()#SMD_ClearStep(self.ATrtAddr) self.lastDirection = direction def relCCWMove(self): val = self.ui.relAngleIncrement.value() self.com_monitor.serial_port.write(b"REL=" + str(val).encode('utf-8') + b"\n") #r = self.com_monitor.serial_port.readline() #print(r) def relCWMove(self): val = self.ui.relAngleIncrement.value() self.com_monitor.serial_port.write(b"REL=" + str(-val).encode('utf-8') + b"\n") #r = self.com_monitor.serial_port.readline() #print(r) def CCWMoveToStop(self): print("CCWMoveToStop") self.com_monitor.serial_port.write(b"CCW\n") #r = self.com_monitor.serial_port.readline() #print(r) def CWMoveToStop(self): print("CWMoveToStop") self.com_monitor.serial_port.write(b"CW\n") #r = self.com_monitor.serial_port.readline() #print(r) def CCWHome(self): print("CCWHome") self.com_monitor.serial_port.write(b"HOME=CCW\n") #r = self.com_monitor.serial_port.readline() #print(r) def CWHome(self): print("CWHome") self.com_monitor.serial_port.write(b"HOME=CW\n") #r = self.com_monitor.serial_port.readline() #print(r) def getCurrentFilter(self): row = self.ui.filtersTab.currentRow() try: name = self.ui.filtersTab.item(row, 0).text() except: name = 'none' try: val = self.ui.filtersTab.item(row, 1).text() except: val = 'none' # return (None, None) return name, val, row def prevFilter(self): row = self.ui.filtersTab.currentRow() if row > 0: print(b"FW=" + str(row - 1).encode('utf-8') + b"\n") self.com_monitor.serial_port.write(b"FW=" + str(row - 1).encode('utf-8') + b"\n") #r = self.com_monitor.serial_port.readline() #print(r) self.ui.filtersTab.setCurrentCell(row - 1, 0) self.lastFiltChTime = datetime.now() #self.ui.oscilloVdiv2.setCurrentIndex(10) #self.oscillo.vdiv2(10) #ch2_v = self.oscillo.get_vdiv2() #print(ch2_v) return 1 else: return 0 def nextFilter(self): row = self.ui.filtersTab.currentRow() if row < 5: print(b"FW=" + str(row + 1).encode('utf-8') + b"\n") self.com_monitor.serial_port.write(b"FW=" + str(row + 1).encode('utf-8') + b"\n") #r = self.com_monitor.serial_port.readline() #print(r) self.lastFiltChTime = datetime.now() #self.ui.oscilloVdiv2.setCurrentIndex(3) #self.oscillo.vdiv2(3) #ch2_v = self.oscillo.get_vdiv2() #print(ch2_v) return 1 else: return 0 def stepperStop(self): self.com_monitor.serial_port.write(b"STOP\n") #r = self.com_monitor.serial_port.readline() #print(r) def stepperLock(self, state): if state: self.com_monitor.serial_port.write(b"ON\n") else: self.com_monitor.serial_port.write(b"OFF\n") #r = self.com_monitor.serial_port.readline() #print(r) def setStepperSpeed(self): speed = self.ui.stepperSpeed.value() self.com_monitor.serial_port.write(b"SPEED=" + str(speed).encode('utf-8') + b"\n") #r = self.com_monitor.serial_port.readline() #print(r) def updateAngle(self, new_angle=0, angle_counter=0, mode='None'): if self.sender().objectName() == "resetAngle": mode = "reset" if mode == "reset": self.currentAngle = 0 self.com_monitor.serial_port.write(b"ANGLE=" + str(0).encode('utf-8') + b"\n") elif mode == "set": self.currentAngle = new_angle # in deg val = new_angle / float(self.config['GLOBAL']['anglecalibr']) self.com_monitor.serial_port.write(b"ANGLE=" + str(val).encode('utf-8') + b"\n") #r = self.com_monitor.serial_port.readline() #print(r) else: try: self.currentAngle = new_angle * float( self.config['GLOBAL']['anglecalibr']) except: pass self.ui.currentAngle.setText(str(self.currentAngle)) self.ui.currentAngleCounter.setText(str(angle_counter)) return self.currentAngle def setCustomAngle(self): dlg = QtGui.QInputDialog(self) dlg.setInputMode(QtGui.QInputDialog.DoubleInput) dlg.setLabelText("Angle:") dlg.setDoubleDecimals(6) dlg.setDoubleRange(-999999, 999999) ok = dlg.exec_() angle = dlg.doubleValue() if ok: self.updateAngle(angle, mode='set') def moveToAngle(self): dlg = QtGui.QInputDialog(self) dlg.setInputMode(QtGui.QInputDialog.DoubleInput) dlg.setLabelText("Angle:") dlg.setDoubleDecimals(6) dlg.setDoubleRange(-999999, 999999) ok = dlg.exec_() angle = dlg.doubleValue() if ok: self.com_monitor.serial_port.write(b"ABS=" + str(angle).encode('utf-8') + b"\n") #r = self.com_monitor.serial_port.readline() print(r) def startMeasurement(self, state): if state: if self.isStepperConnected(): self.steppingTimer.start() self.ui.startMeasurement.setText("Stop") self.getCurrentFilter(self) else: self.ui.startMeasurement.setChecked(False) self.ui.startMeasurement.setText("Start") else: self.steppingTimer.stop() self.ui.startMeasurement.setText("Start") self.num = 0 self.calibrData = [] def stepperOn(self): pass def getStepperState(self): state = [i.value for i in getState(self.ATrtAddr, 1)] #if sum(state) == 0: # state [0] = 1 return state def startCalibr(self, state): if state: self.calibrTimer.start(self.ui.plotPeriod.value()) direction = -1 if self.ui.measurementDirCW.isChecked() else 1 self.line0.setData(x=[], y=[]) self.line1.setData(x=[], y=[]) self.line2.setData(x=[], y=[]) self.line3.setData(x=[], y=[]) self.line5.setData(x=[], y=[]) else: self.calibrTimer.stop() self.calibrData = np.array([]) def onCalibrTimer(self): r = [] #chanels=[0,1,2] ##################################################################################### #r=et.getDataProcN(2,100,chanels,True) name, tmp_filt, index = self.getCurrentFilter() print('Filter:', name, tmp_filt, index) r = self.oscilloGetData() y0 = r[1] y1 = r[0] / float(tmp_filt) if len(self.calibrData) > 0: self.calibrData = np.vstack((self.calibrData, [y0, y1])) else: self.calibrData = np.array([y0, y1]) data = self.calibrData self.line0.setData(x=np.arange(len(data)), y=data[:, 0]) self.line1.setData(x=np.arange(len(data)), y=data[:, 1]) self.updateAngle(len(data)) app.processEvents() def startContMeas(self, state): if state: self.angleUpdateTimer.stop() with open(self.ui.saveToPath.text(), 'a') as f: f.write("\n#$Filter:" + self.getCurrentFilter()[0] + "\n") for row in range(6): name = self.ui.filtersTab.item(row, 0).text() val = self.ui.filtersTab.item(row, 1).text() f.write("#$\t" + str(row) + "\t" + name + "\t" + val + '\n') f.write("#$POWER:" + self.config['GLOBAL']['power'].replace('\n', '\t') + '\n') f.write( "#$WAVELENGTH:" + self.config['GLOBAL']['wavelength'].replace('\n', '\t') + '\n') f.write("#$OBJECT:" + self.config['GLOBAL']['object'].replace('\n', '\t') + '\n') f.write( "angle\tangle_counter\tref\tsignal\tsignal_std\tfilter\tTime\tfreq\tduty_cycle\n" ) self.measTimer.start(self.ui.plotPeriod.value()) direction = -1 if self.ui.measurementDirCW.isChecked() else 1 if direction == 1: self.CWMoveToStop() else: self.CCWMoveToStop() self.line0.setData(x=[], y=[]) self.line1.setData(x=[], y=[]) else: self.stepperStop() #et.ET_stopStrobData() #try: # self.SMD.eStop() #except: # print('Err') self.measTimer.stop() #self.openAngleSensorPort(True) self.angleUpdateTimer.start() self.calibrData = np.array([]) #data = np.loadtxt(self.ui.saveToPath.text(),comments='#') #self.line2.setData(x=data[:,4], y=data[:,1]) #self.line3.setData(x=data[:,-1], y=data[:,2]) def onContMeasTimer(self): r = [] #chanels=[0,1,2] ############################################################################ r = self.oscilloGetData() y0 = r[1] y1 = r[0] y1_std = r[2] name, tmp_filt, index = self.getCurrentFilter() print('Filter:', name, float(tmp_filt), index) info = self.getNanoScatInfo(['angle', 'FW', 'angle_counter']) angle = float(self.ui.currentAngle.text()) angle_counter = float( self.ui.currentAngleCounter.text()) #info['angle'] filt = info['FW'] freq = float(self.ui.oscilloFreq.text()) duty_cycle = float(self.ui.duty_cycle.text()) #try: #self.currentAngle = angle#et.getAngle() #except: # pass print("angle", angle) #self.ui.currentAngle.setText(str(self.currentAngle)) x = angle x_c = angle_counter with open(self.ui.saveToPath.text(), 'a') as f: f.write( str(x) + "\t" + str(x_c) + "\t" + str(y0) + "\t" + str(y1) + "\t" + str(y1_std) + '\t' + str(filt) + "\t" + str(time.time()) + "\t" + str(freq) + "\t" + str(duty_cycle) + "\n") #print(self.measData) if len(self.measData) > 0: self.measData = np.vstack( (self.measData, [x, y0, y1 / float(tmp_filt), x_c])) else: self.measData = np.array([x, y0, y1 / float(tmp_filt), x_c]) data = self.measData #print(data) self.line0.setData(x=data[:, 0], y=data[:, 1]) self.line1.setData(x=data[:, 0], y=data[:, 2]) self.line5.setData(x=data[:, 3], y=data[:, 2]) #self.updateAngle(x) app.processEvents() def saveToBtn(self): filename = self.fileDialog.getSaveFileName(self) print(filename) self.ui.saveToPath.setText(filename) def openAngleSensorPort(self, state): if state: print(">>>>>>open") #port = '/dev/ttyUSB'+str(self.ui.angleSensorPort.value()) self.data_q = queue.Queue() self.error_q = queue.Queue() self.port = list(list_ports.grep("0403:0000"))[0][0] self.com_monitor = ComMonitorThread(self.data_q, self.error_q, self.port, 9600) self.com_monitor.start() #self.angleSensorSerial = serial.Serial(port,baudrate=9600,timeout=0.1)#.port = port print(self.port) time.sleep(2) #self.angleSensorSerial.port = port #self.angleSensorSerial.baudrate = 19200 #self.angleSensorSerial.timeout = 4 #self.angleSensorSerial.open() #self.angleSensorSerial.setDTR(True) #self.angleSensorSerial.write(b'') #self.angleSensorSerial.flush() #self.angleSensorSerial.flushInput() #self.angleSensorSerial.flushOutput() #a=self.angleSensorSerial.read(5) print("0>>", self.data_q) #self.angleSensorSerial.write(b"STATE?\n") #a=self.angleSensorSerial.readline() #print("1>>",a) self.angleUpdateTimer.start(self.ui.plotPeriod.value()) else: self.angleUpdateTimer.stop() self.com_monitor.stop() def getNanoScatInfo(self, keys=['angle']): if not self.com_monitor.serial_port.isOpen(): self.openAngleSensorPort(True) return None else: outDict = {} #self.angleSensorSerial.flush() #self.angleSensorSerial.flushInput() #self.angleSensorSerial.flushOutput() self.com_monitor.serial_port.write(b"STATE?\n") #line = self.angleSensorSerial.readline().decode("utf-8") prev_data = [] while not self.com_monitor.data_q.empty(): prev_data.append(self.com_monitor.data_q.get()) data = '' for i in prev_data: data += i[0].decode() line = data.split('\n') if len(line) < 2: line = line[0] elif len(line) >= 2: line = line[-2] print(">>", line) self.ui.statusBar.showMessage(line) if 'angle' in keys: try: outDict['angle'] = float( line.split('A:')[-1].split('\t')[0]) outDict['angle_counter'] = float( line.split('c:')[-1].split('\t')[0]) self.updateAngle(outDict['angle'], angle_counter=outDict['angle_counter']) except ValueError: outDict['angle'] = None if 'zero' in keys: try: outDict['zero'] = int(line.split('Z:')[-1].split('\t')[0]) except ValueError: outDict['zero'] = None if 'FW' in keys: try: outDict['FW'] = int(line.split('FW:')[-1].split('\t')[0]) except ValueError: outDict['FW'] = None if 'freqMode' in keys: try: outDict['freqMode'] = [ float(i) for i in ( line.split('\tFM:')[-1].split('\t')[0]).split('x') ] except ValueError: outDict['freqMode'] = [None, None] return outDict def onAngleUpdateTimer(self): info = self.getNanoScatInfo(['angle', 'FW', 'angle_counter']) angle = info['angle'] angle_counter = info['angle_counter'] filt = info['FW'] try: #self.currentAngle = angle#et.getAngle() self.ui.filtersTab.setCurrentCell(filt, 0) except: pass print("angle", angle) self.updateAngle(angle, angle_counter=angle_counter) #self.ui.currentAngle.setText(str(self.currentAngle)) def checkStepperState(self): pass #def setADCAmplif(self, value): #et.ET_SetAmplif(value) def cleanPlot(self): self.calibrData = np.array([]) self.measData = np.array([]) self.line0.setData(x=[], y=[]) self.line1.setData(x=[], y=[]) self.line5.setData(x=[], y=[]) def closeEvent(self, event): print("event") reply = QtGui.QMessageBox.question(self, 'Message', "Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: self.com_monitor.stop() self.oscillo.disconnect() self.oscillo.close() event.accept() #self.stopLaserStrob() #self.stopDataBuffering() else: event.ignore() def oscilloConnect(self, state): if state: self.oscillo.connect() r = self.oscillo.init() print(r) r = self.oscillo.vers() print(r) ch1_v = self.oscillo.get_vdiv1() if self.ui.CH1_AC_DC.isChecked(): ch1_v -= 64 print(ch1_v) self.ui.oscilloVdiv1.setCurrentIndex(ch1_v) yp1 = self.oscillo.get_ypos1() print(yp1) self.ui.oscilloYpos1.setValue(yp1) ch2_v = self.oscillo.get_vdiv2() if self.ui.CH2_AC_DC.isChecked(): ch1_v -= 64 print(ch2_v) self.ui.oscilloVdiv2.setCurrentIndex(ch2_v) yp2 = self.oscillo.get_ypos2() self.oscilloLastIndex = [ch1_v, ch2_v] print(yp2) self.ui.oscilloYpos2.setValue(yp2) td = self.oscillo.get_tdiv() print(td) self.ui.oscilloTdiv.setCurrentIndex(td) self.oscReadTimer.start(400) else: self.oscReadTimer.stop() self.oscillo.disconnect() self.oscillo.close() def oscilloGetData(self): div = (0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20) div_t = self.ui.oscilloTdiv.currentText() print(div_t) tdiv_val, t_order = div_t.split(' ') scales = {'ns': 1e-9, 'mks': 1e-3, 'ms': 1e-3, 's': 1} tdiv_val = float(tdiv_val) * scales[t_order] res1 = self.oscillo.rdwf1() sig = np.array([int(i) for i in res1[50:]]) self.line_sig.setData(x=np.arange(len(sig)), y=sig) index1 = self.ui.oscilloVdiv1.currentIndex() res2 = self.oscillo.rdwf2() ref = np.array([int(i) for i in res2[50:]]) self.line_ref.setData(x=np.arange(len(ref)), y=ref) index2 = self.ui.oscilloVdiv2.currentIndex() Vpp1, STD, HIGH, LOW, ref_norm, f, duty_cycle = peak2peak( ref, sig, ref_mode='triangle') self.line_ref_norm.setData(x=np.arange(len(ref_norm)), y=ref_norm) frequency = 1 / (0.1 / 2048 * 10 / f) self.ui.oscilloFreq.setText(str(frequency)) self.ui.duty_cycle.setText(str(duty_cycle)) val1 = self.oscillo.dig2Volts( Vpp1, div[index1]) #(Vpp1)/256*(div[index1]*8)*1.333333 STD1 = self.oscillo.dig2Volts( STD, div[index1]) #(STD)/256*(div[index1]*8)*1.333333 self.ui.CH1Val.setText(str(val1)) self.ui.CH1Val_std.setText(str(STD1)) ref = medfilt(ref, 5) Vpp2 = ref.max() - ref.min() print("Vpp1:", Vpp1, "Vpp2:", Vpp2) val2 = self.oscillo.dig2Volts( Vpp2, div[index2]) #(Vpp2)/256*(div[index2]*8)*1.333333 self.ui.CH2Val.setText(str(val2)) if LOW > HIGH: tmp = HIGH HIGH = LOW LOW = tmp if self.ui.oscilloAuto.isChecked() and (time.time() - self.lastDivChange) > 1: self.lastDivChange = time.time() ac_dc1 = self.ui.CH1_AC_DC.isChecked() if LOW < 20: index1 = self.ui.oscilloVdiv1.currentIndex() if self.oscilloLastMaster == 'HAMEG': #if self.oscilloLastIndex[0] == index1+1: # self.oscilloLastMaster = 'FM' if index1 < 12: self.oscilloLastIndex[0] = index1 self.oscillo.vdiv1(index1 + 1, ac_dc1) self.ui.oscilloVdiv1.setCurrentIndex(index1 + 1) #self.oscilloAutoSet() #self.oscillo.tdiv(17) #self.ui.oscilloTdiv.setCurrentIndex(17) #else: # self.oscilloLastMaster = 'FM' else: #self.nextFilter() #self.oscilloAutoSet() #self.oscillo.tdiv(17) #self.ui.oscilloTdiv.setCurrentIndex(17) self.oscilloLastIndex == 'HAMEG' elif HIGH > 230: index1 = self.ui.oscilloVdiv1.currentIndex() if self.oscilloLastMaster == 'HAMEG': #if self.oscilloLastIndex[0] == index1+1: # self.oscilloLastMaster = 'FM' if index1 > 1: self.oscilloLastIndex[0] = index1 self.oscillo.vdiv1(index1 - 1, ac_dc1) self.ui.oscilloVdiv1.setCurrentIndex(index1 - 1) #self.oscilloAutoSet() #self.oscillo.tdiv(17) #self.ui.oscilloTdiv.setCurrentIndex(17) #else: # self.oscilloLastMaster = 'FM' else: #self.nextFilter() #self.oscilloAutoSet() #self.oscillo.tdiv(17) #self.ui.oscilloTdiv.setCurrentIndex(17) self.oscilloLastIndex == 'HAMEG' elif abs(Vpp1) < 10: index1 = self.ui.oscilloVdiv1.currentIndex() if self.oscilloLastMaster == 'HAMEG': #if self.oscilloLastIndex[0] == index1-1: # self.oscilloLastMaster = 'FM' if index1 > 1: self.oscilloLastIndex[0] = index1 self.ui.oscilloVdiv1.setCurrentIndex(index1 - 1) self.oscillo.vdiv1(index1 - 1, ac_dc1) #self.oscilloAutoSet() #self.oscillo.tdiv(17) #self.ui.oscilloTdiv.setCurrentIndex(17) #else: # self.oscilloLastMaster = 'FM' else: #self.prevFilter() #self.oscilloAutoSet() #self.oscillo.tdiv(17) #self.ui.oscilloTdiv.setCurrentIndex(17) self.oscilloLastIndex == 'HAMEG' print(Vpp1, self.oscilloLastMaster) return [val1, val2, STD1] def onOscReadTimer(self): start = time.time() self.oscReadTimer.stop() res = self.oscilloGetData() self.oscReadTimer.start(400) end = time.time() print("oscillo_dt:\t", end - start) print(res) def oscilloAutoSet(self): r = self.oscillo.autoset() print(r) ch1_v = self.oscillo.get_vdiv1() print(ch1_v) self.ui.oscilloVdiv1.setCurrentIndex(ch1_v) yp1 = self.oscillo.get_ypos1() print(yp1) self.ui.oscilloYpos1.setValue(yp1) ch2_v = self.oscillo.get_vdiv2() print(ch2_v) self.ui.oscilloVdiv2.setCurrentIndex(ch2_v) yp2 = self.oscillo.get_ypos2() print(yp2) self.ui.oscilloYpos2.setValue(yp2) td = self.oscillo.get_tdiv() print(td) self.ui.oscilloTdiv.setCurrentIndex(td) def oscilloSet(self): v1 = self.ui.oscilloVdiv1.currentIndex() ac_dc1 = self.ui.CH1_AC_DC.isChecked() r = self.oscillo.vdiv1(v1, ac_dc1) print(r) ac_dc2 = self.ui.CH2_AC_DC.isChecked() v2 = self.ui.oscilloVdiv2.currentIndex() r = self.oscillo.vdiv2(v2, ac_dc2) print(r) td = self.ui.oscilloTdiv.currentIndex() r = self.oscillo.tdiv(td) print(r) y1 = self.ui.oscilloYpos1.value() r = self.oscillo.ypos1(y1) print(r) y2 = self.ui.oscilloYpos2.value() r = self.oscillo.ypos2(y2) print(r) def uiConnect(self): #self.ui.btnExit.clicked.connect(self.closeAll) #self.ui.actionExit.triggered.connect(self.closeAll) #self.ui.measurementDirCW.clicked.connect(lambda state: (self.ui.measurementDirCCW.setChecked(False), self.ui.measurementDirCW.setEnabled(False),self.ui.measurementDirCCW.setEnabled(True))) #self.ui.measurementDirCCW.clicked.connect(lambda state: (self.ui.measurementDirCW.setChecked(False), self.ui.measurementDirCCW.setEnabled(False),self.ui.measurementDirCW.setEnabled(True))) self.ui.startCalibr.toggled[bool].connect(self.startCalibr) self.ui.startMeasurement.toggled[bool].connect(self.startContMeas) self.ui.oscilloConnect.toggled[bool].connect(self.oscilloConnect) self.ui.oscilloAutoSet.clicked.connect(self.oscilloAutoSet) self.ui.oscilloSet.clicked.connect(self.oscilloSet) #self.ui.ADCAmplif.valueChanged[int].connect(self.setADCAmplif) #self.ui.laserFreq.valueChanged[int].connect(self.setLaserFreq) #self.ui.pauseMeasurements.toggled[bool].connect(self.pauseMeasurements) #self.ui.openCOMPort_btn.toggled[bool].connect(self.Open_CloseStepperCOMPort) self.ui.openAngleSensorPort.toggled[bool].connect( self.openAngleSensorPort) self.ui.setCustomAngle.clicked.connect(self.setCustomAngle) self.ui.moveToAngle.clicked.connect(self.moveToAngle) #self.ui.editStepperSettings.clicked.connect(self.setStepperParam) self.ui.relCWMove.clicked.connect(self.relCWMove) self.ui.relCCWMove.clicked.connect(self.relCCWMove) self.ui.cleanPlot.clicked.connect(self.cleanPlot) self.ui.CCWMoveToStop.clicked.connect(self.CCWMoveToStop) self.ui.CWMoveToStop.clicked.connect(self.CWMoveToStop) self.ui.CCWHome.clicked.connect(self.CCWHome) self.ui.CWHome.clicked.connect(self.CWHome) self.ui.setStepperSpeed.clicked.connect(self.setStepperSpeed) self.ui.stepperSpeed.valueChanged[int].connect( self.ui.stepperSpeedValue.setValue) self.ui.stepperSpeedValue.valueChanged[int].connect( self.ui.stepperSpeed.setValue) self.ui.nextFilter.clicked.connect(self.nextFilter) self.ui.prevFilter.clicked.connect(self.prevFilter) self.ui.stepperStop.clicked.connect(self.stepperStop) self.ui.stepperLock.toggled[bool].connect(self.stepperLock) self.ui.saveToBtn.clicked.connect(self.saveToBtn) #self.ui.resetAngle.clicked.connect(self.updateAngle) #self.ui.setCustomAngle.toggled[bool].connect(self.setCustomAngle) #self.ui.calibrFW.clicked.connect(self.calibrFW) #self.ui.startMeasurement.clicked.connect(self.startMeasurement) #self.steppingTimer.timeout.connect(self.stepMeasurement) self.calibrTimer.timeout.connect(self.onCalibrTimer) self.measTimer.timeout.connect(self.onContMeasTimer) self.angleUpdateTimer.timeout.connect(self.onAngleUpdateTimer) #self.calibrHomeTimer.timeout.connect(self.onCalibrHomeTimer) self.oscReadTimer.timeout.connect(self.onOscReadTimer) #self.calibrFWTimer.timeout.connect(self.onCalibrFWTimer) #self.stepperStateTimer.timeout.connect(self.checkStepperState) #self.laserStrobTimer.timeout.connect(self.laserStrob) self.ui.saveConfig.clicked.connect(self.saveConfig) self.ui.actionClose.triggered.connect(self.close)
class mainWindow(QtGui.QMainWindow): def __init__(self, parent=None): QtGui.QMainWindow.__init__(self, parent) uifile = os.path.join( os.path.abspath(os.path.dirname(__file__)), 'ui_data', 'main.ui') uic.loadUi(uifile, self) self.adsrw = adsrWidget() self.adsrList = adsrList() self.adsrw.adsr = self.adsrList self.adsrWidgetContainer.addWidget(self.adsrw) self.current_adsr = None self.monitor_adsr = True self.players = [] self.invert_control = False self.trigger_shadow = False self.sounds = [] self.plotw = PlotWindow() self.plotw.plot.setAxisScale(Qwt.QwtPlot.yLeft, 0, 1024, 1024 / 8) self.plotw.plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 20, 20. / 10) self.plotWindowContainer.addWidget(self.plotw) for curve in 'Entrada d/dT Umbral Salida'.split(): self.plotw.add_curve(curve) self._idx = 0 self.plotw.show() self.timer = QtCore.QTimer() self.open_port() self.load_config() def load_config(self): config.load() adsrconf = config.get('adsr') if adsrconf: for k, v in adsrconf.iteritems(): setattr(self.adsrList, k, v) self.adsrw.adsr = self.adsrList sounds = config.get('sounds') if sounds: for snd in sounds['files']: self.add_sound(str(snd)) globs = config.get('globals') if globs: self.invert_control = globs['invert_control'] self.trigger_shadow = globs['trigger_shadow'] if self.invert_control: self.invert.setCheckState(QtCore.Qt.Checked) if self.trigger_shadow: self.invert_slope.setCheckState(QtCore.Qt.Checked) self.sldVolumen.setValue(globs['default_volume']) for x in xrange(globs['sensor_count']): self.add_sensor() def closeEvent(self, event): self.save_config() event.accept() def save_config(self): adsrconf = config.get('adsr') for param in adsr_params.keys(): adsrconf[param] = getattr(self.adsrList, param) sounds = config.get('sounds') sounds['files'] = self.sounds[:] globs = config.get('globals') globs['invert_control'] = self.invert_control globs['trigger_shadow'] = self.trigger_shadow globs['default_volume'] = self.sldVolumen.value() globs['sensor_count'] = len(self.players) config.save() def add_sensor(self): play = SensorPlayer(gui=False) self.players.append(play) self.adsrList.append(play.adsr) play.invert_control = self.invert_control play.trigger_on_light = not self.trigger_shadow self.sensorList.addItem('Sensor %i' % len(self.adsrList)) @QtCore.pyqtSlot() def on_sensorAdd_clicked(self): self.add_sensor() @QtCore.pyqtSlot() def on_sensorDelete_clicked(self): idx = self.sensorList.count() if idx == 0: return item = self.sensorList.takeItem(idx - 1) del item self.adsrList.pop() p = self.players.pop() #FIXME: matar el vlc hijo p.stop() @QtCore.pyqtSlot(bool) def on_plotWindowGroup_clicked(self, checked): #FIXME: desconectar el grafico y borrar datos if checked: self.monitor_adsr = True else: self.monitor_adsr = False self.connect_adsr() @QtCore.pyqtSlot(int) def on_invert_stateChanged(self, state): if state: self.invert_control = True else: self.invert_control = False for player in self.players: player.invert_control = self.invert_control @QtCore.pyqtSlot(int) def on_invert_slope_stateChanged(self, state): if state: self.trigger_shadow = True else: self.trigger_shadow = False for player in self.players: player.trigger_on_light = not self.trigger_shadow @QtCore.pyqtSlot(int) def on_sldVolumen_valueChanged(self, value): for player in self.players: player.default_volume = value def add_sound(self, filename): self.sounds.append(filename) self.soundList.addItem(filename) @QtCore.pyqtSlot() def on_soundAdd_clicked(self): fn = QtGui.QFileDialog.getOpenFileName() if fn: fn = str(fn) self.add_sound(fn) @QtCore.pyqtSlot() def on_soundDelete_clicked(self): idx = self.soundList.currentRow() if idx == -1: return item = self.soundList.takeItem(idx) del item del self.sounds[idx] @QtCore.pyqtSlot(bool) def on_Start_clicked(self, checked): if checked: for idx in xrange(min(len(self.players), len(self.sounds))): player = self.players[idx] player.playlist.clear() player.default_volume = self.sldVolumen.value() player.playlist.append(self.sounds[idx]) player.start() else: for player in self.players: player.stop() @QtCore.pyqtSlot(int) def on_sensorList_currentRowChanged(self, row): self.connect_adsr(self.adsrList[row]) def connect_adsr(self, adsr=None): if self.monitor_adsr: self.plotw.clear() self._idx = 0 if adsr is not None and adsr is not self.current_adsr: if self.current_adsr: self.current_adsr.internal_state_changed.disconnect( self.adsr_internal_cb) self.current_adsr = adsr self.current_adsr.internal_state_changed.connect( self.adsr_internal_cb) else: if self.current_adsr: self.current_adsr.internal_state_changed.connect( self.adsr_internal_cb) else: if self.current_adsr: self.current_adsr.internal_state_changed.disconnect( self.adsr_internal_cb) def adsr_internal_cb(self, *args, **kwargs): salida, trig, entrada, dx = args idx = self._idx + .1 self._idx = idx self.plotw.add_datapoint(idx, entrada, abs(dx), self.adsrList.umbral, salida) def open_port(self): self.data_q = Queue.Queue() self.error_q = Queue.Queue() self.com_monitor = ComMonitorThread(self.data_q, self.error_q, '/dev/ttyACM0', 115200) self.com_monitor.start() com_error = get_item_from_queue(self.error_q) if com_error is not None: QtGui.QMessageBox.critical(self, 'ComMonitorThread error', com_error) self.com_monitor = None self.monitor_active = True self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.on_timer) self.timer.start(1000.0 / 10) def on_timer(self, *args): data = list(get_all_from_queue(self.data_q)) # (timestamp, [x0, x1, x2, etc]) if (len(data) == 0): return for row in data: for idx in xrange(min(len(row[1]), len(self.players))): self.players[idx].adsr(row[1][idx])
def main(): time.sleep(10) Irma3Dflag = False tpmsflag = False counter = 0 gpsflag = False weigthflag = False inflag = False lasttiempo = 0 global saveflag saveflag = False logging.basicConfig( filename='home/pi/report.log', level=logging.DEBUG, format='%(levelname)s:(%(threadName)-10s) %(asctime)s %(message)s') config.read("/home/pi/config.ini") for section in config.sections(): if (config.has_option(section, 'sensorname')): if ((config.get(section, 'sensorname') == 'tpms') and (config.getboolean(section, 'connected'))): tpmsflag = True baudrate = config.getint(section, 'baudrate') print baudrate port = config.get(section, 'port') data_q = Queue.Queue() error_q = Queue.Queue() sensor_name = config.get(section, 'sensorname') com_monitor = ComMonitorThread(data_q, error_q, port, baudrate, tpmsflag) logging.info('Iniciando puerto Serial') com_monitor.start() com_error = get_item_from_queue(error_q) if com_error is not None: logging.critical('ComMonitorThread error') print com_error com_monitor = None if ((config.get(section, 'sensorname') == 'weight') and (config.getboolean(section, 'connected'))): weigthflag = True baudrate = config.getint(section, 'baudrate') print baudrate port = config.get(section, 'port') data_w = Queue.Queue() error_w = Queue.Queue() sensor_name = config.get(section, 'sensorname') com_monitor = weigthMonitor(data_w, error_w, port, baudrate, weigthflag) logging.info('Iniciando puerto Serial') com_monitor.start() com_error = get_item_from_queue(error_w) if com_error is not None: logging.critical('weigthThread error') print com_error com_monitor = None if ((config.get(section, 'sensorname') == 'hanover') and (config.getboolean(section, 'connected'))): hanover = True baudrate = config.getint(section, 'baudrate') port = config.get(section, 'port') data_z = Queue.Queue() error_z = Queue.Queue() sensor_name = config.get(section, 'sensorname') hanover_monitor = HanoverSignController( data_z, error_z, port, baudrate, hanover) logging.info('Iniciando Hanover Service') usb_monitor.start() usb_error = get_item_from_queue(error_z) if usb_error is not None: logging.critical('Hanover Thread error') print usb_error usb_monitor = None if ((config.get(section, 'sensorname') == 'Irma3D') and (config.getboolean(section, 'connected'))): Irma3Dflag = True baudrate = config.getint(section, 'baudrate') port = config.get(section, 'port') data_u = Queue.Queue() error_u = Queue.Queue() sensor_name = config.get(section, 'sensorname') usb_monitor = UsbMonitorThread(data_u, error_u, port, baudrate, Irma3Dflag) logging.info('Iniciando puerto USB Serial') usb_monitor.start() usb_error = get_item_from_queue(error_u) if usb_error is not None: logging.critical('USBMonitorThread error') print usb_error usb_monitor = None while True: if (config.getboolean('reportmethod', 'time')): tiempo = config.getint('reportmethod', 'reportime') if (inflag): GPIO.cleanup() inflag = False counter = 0 if (tiempo != lasttiempo): try: schedule.every(tiempo).minutes.do(saving_flag2) except Exception as e: print(e) print("siguiente ejecucion en: " + str(tiempo)) lasttiempo = tiempo try: schedule.run_pending() except Exception as e: print(e) time.sleep(1) elif (config.getboolean('reportmethod', 'input')): try: for section in config.sections(): if (config.has_option(section, 'sensorname')): if ((config.get(section, 'sensorname') == 'report') and (config.getboolean(section, 'connected'))): puerto = config.getint(section, 'port') #print(puerto) except Exception as e: print(e) if (counter == 0): try: GPIO.setmode(GPIO.BOARD) GPIO.setup(puerto, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.add_event_detect(puerto, GPIO.RISING, callback=saving_flag, bouncetime=300) inflag = True counter = counter + 1 except Exception as e: print(e) if (gpsflag): out_msg = configuration.read_serial_data(data_g, config) if out_msg is not None: data_o.put(out_msg) if (Irma3Dflag): if (saveflag): read_usb_data(data_u, Irma3Dflag) if (weigthflag): if (saveflag): read_weight_data(data_w, weigthflag) if (tpmsflag): if (saveflag): read_serial_data(data_q, tpmsflag) saveflag = False
class CAN_Sniffer(QtGui.QMainWindow): def __init__(self, parent=None): super(CAN_Sniffer, self).__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.monitor_active = False self.com_monitor = None self.com_data_q = None self.com_error_q = None self.data = "" # self.livefeed = LiveDataFeed() # self.temperature_samples = [] self.timer = QtCore.QTimer() self.ui.serialPortSelectPb.clicked.connect(self.on_select_port) self.ui.serialConnectPb.clicked.connect(self.on_start) self.ui.serialDisconnectPb.clicked.connect(self.on_stop) self.ui.serialConnectPb.setEnabled(False) self.ui.serialDisconnectPb.hide() # @QtCore.pyqtSlot(int) # def on_inputSpinBox1_valueChanged(self, value): # self.ui.outputWidget.setText(str(value + self.ui.inputSpinBox2.value())) # @QtCore.pyqtSlot(int) # def on_inputSpinBox2_valueChanged(self, value): # self.ui.outputWidget.setText(str(value + self.ui.inputSpinBox1.value())) self.ui.dataTable.setColumnWidth(0,50) self.ui.dataTable.setColumnWidth(1,50) # for i in range(2,10): # self.ui.dataTable.setColumnWidth(i,25) # self.update_data(512, [2,3,4,5,6,7,8,9]) # self.update_data(654, [1,1,1,1,1,1,1,1]) # self.update_data(543, [6,8,4,8,2,6,5,8]) # self.update_data(456, [4,5,7,9,23,7,9,3]) # self.update_data(512, [5,8,2,78,9,2,78,8]) # self.update_data(512, [3,78,9,23,78,8,3]) # self.update_data(512, [3,78,10,23,78]) def on_select_port(self): ports = list(enumerate_serial_ports()) if len(ports) == 0: QMessageBox.critical(self, 'No ports', 'No serial ports found') return item, ok = QtGui.QInputDialog.getItem(self, 'Select a port', 'Serial port:', ports, 0, False) if ok and not item.isEmpty(): self.ui.serialConnectPb.setEnabled(True) self.ui.serialPortLbl.setText(item) # self.set_actions_enable_state() def on_stop(self): """ Stop the monitor """ if self.com_monitor is not None: self.com_monitor.join(0.01) self.com_monitor = None self.monitor_active = False self.timer.stop() # self.set_actions_enable_state() self.ui.statusbar.showMessage('Monitor idle') self.ui.serialConnectPb.show() self.ui.serialDisconnectPb.hide() def on_start(self): """ Start the monitor: com_monitor thread and the update timer """ if self.com_monitor is not None or self.ui.serialPortLbl.text() == '': return self.data_q = Queue.Queue() self.error_q = Queue.Queue() self.com_monitor = ComMonitorThread( self.data_q, self.error_q, full_port_name(str(self.ui.serialPortLbl.text())), 38400) self.com_monitor.start() com_error = get_item_from_queue(self.error_q) if com_error is not None: QMessageBox.critical(self, 'ComMonitorThread error', com_error) self.com_monitor = None self.monitor_active = True # self.set_actions_enable_state() # self.timer = QtCore.QTimer() self.timer.timeout.connect(self.on_timer) # self.connect(self.timer, SIGNAL('timeout()'), self.on_timer) update_freq = 100 if update_freq > 0: self.timer.start(1000.0 / update_freq) self.ui.statusbar.showMessage('Monitor running') self.ui.serialConnectPb.hide() self.ui.serialDisconnectPb.show() def on_timer(self): """ Executed periodically when the monitor update timer is fired. """ self.read_serial_data() # self.update_monitor() def read_serial_data(self): """ Called periodically by the update timer to read data from the serial port. """ qdata = list(get_all_from_queue(self.data_q)) if len(qdata) > 0: data = self.data+''.join(qdata) while data.find("Id: ")!=-1: msgStart = data.find("Id: ") msgEnd = data.find("\n",msgStart) if msgEnd == -1: break packet = data[msgStart:msgEnd-1] # print "msg: [%s]" % packet msgId = int(packet[4:8],16) # print "msgId: %d [%x]" % (msgId, msgId) msgData = map(lambda x: int(x,16) ,packet[16:].split(" ")) # print "data: ", msgData self.update_data(msgId, msgData) data = data[msgEnd:] self.data = data def update_data(self, msgId, msgData): rowCount = self.ui.dataTable.rowCount() print rowCount msgIdExists = False for i in range(rowCount): if self.ui.dataTable.item(i, 0).text() == "%04X" % msgId: msgIdExists = True count = int(self.ui.dataTable.item(i, 1).text()) self.ui.dataTable.item(i, 1).setText(str(count+1)) for j in range(8): try: txt = "%02X" % msgData[j] except IndexError: txt = "" if self.ui.dataTable.item(i, 2+j).text() != txt: self.ui.dataTable.item(i, 2+j).setText(txt) self.ui.dataTable.item(i, 2+j).setBackground(QtGui.QColor('red')) else: self.ui.dataTable.item(i, 2+j).setBackground(QtGui.QColor('white')) if not msgIdExists: self.ui.dataTable.insertRow(rowCount) print "msgId: %d [%x]" % (msgId, msgId) item = QtGui.QTableWidgetItem("%04X" % msgId) self.ui.dataTable.setItem(rowCount,0,item) item = QtGui.QTableWidgetItem("1") self.ui.dataTable.setItem(rowCount,1,item) for i in range(8): try: item = QtGui.QTableWidgetItem("%02X" % msgData[i]) except IndexError: item = QtGui.QTableWidgetItem("") self.ui.dataTable.setItem(rowCount,2+i,item)
class nS_SMFW(): data_q = None error_q = None com_monitor = None port = None def __init__(self, parent=None): self.data_q = queue.Queue() self.error_q = queue.Queue() def open(self): self.port = list(list_ports.grep("0403:0000"))[0][ 0] #'/dev/ttyUSB'+str(self.ui.angleSensorPort.value()) self.com_monitor = ComMonitorThread(self.data_q, self.error_q, self.port, 9600) self.com_monitor.daemon = True self.com_monitor.start() def close(self): self.com_monitor.stop() def getData(self): prev_data = [] while not self.data_q.empty(): prev_data.append(self.data_q.get()) return prev_data def insertToSerialFlow(function_to_decorate): out = None def wrapper(*args, **kw): self = args[0] print('Readout locked') self.com_monitor.lock_readout() try: #self.getData() out = function_to_decorate(*args, **kw) except serial.SerialException as e: self.error_q.put(e) self.com_monitor.release_readout() print('Readout released') return out return wrapper @insertToSerialFlow def setFilter(self, filterIndex): #try: self.com_monitor.serial_port.write(b"FW:" + str(filterIndex).encode('utf-8') + b"\n") r = self.com_monitor.read() print(r, '@@@') return r #except AttributeError: #return None @insertToSerialFlow def getNanoScatInfo(self, keys=['angle']): outDict = {} self.com_monitor.serial_port.write(b"STATE?\n") data = self.getData() #if data[-1][0].decode() #print(data) line = '' for i in data: tmp = i[0].decode() #if not '>' in tmp and not '<' in tmp: line += tmp line = re.sub('>.*?<', '', line) print(">", line) line = line.split('\t\r\n') #print(">>",line) if len(line) < 2: return None else: line = line[-2] print(">>>", line) if 'angle' in keys: try: outDict['angle'] = float(line.split('A:')[-1].split('\t')[0]) #self.updateAngle(outDict['angle']) except ValueError: outDict['angle'] = None if 'zero' in keys: try: outDict['zero'] = int(line.split('Z:')[-1].split('\t')[0]) except ValueError: outDict['zero'] = None if 'FW' in keys: try: outDict['FW'] = int(line.split('FW:')[-1].split('\t')[0]) except ValueError: outDict['FW'] = None if 'freqMode' in keys: try: outDict['freqMode'] = [ float(i) for i in ( line.split('\tFM:')[-1].split('\t')[0]).split('x') ] except ValueError: outDict['freqMode'] = [None, None] return outDict @insertToSerialFlow def setStepperSpeed(self, speed): #speed = self.ui.stepperSpeed.value() self.com_monitor.serial_port.write(b"SPEED:" + str(speed).encode('utf-8') + b"\n") r = self.com_monitor.read() print(r)
class PlottingDataMonitor(QMainWindow): def __init__(self, parent=None): super(PlottingDataMonitor, self).__init__(parent) self.monitor_active = False self.com_monitor = None self.com_data_q = None self.com_error_q = None self.livefeed = LiveDataFeed() self.temperature_samples = [] self.timer = QTimer() self.create_menu() self.create_main_frame() self.create_status_bar() def make_data_box(self, name): label = QLabel(name) qle = QLineEdit() qle.setEnabled(False) qle.setFrame(False) return (label, qle) def create_plot(self): plot = Qwt.QwtPlot(self) plot.setCanvasBackground(Qt.black) plot.setAxisTitle(Qwt.QwtPlot.xBottom, 'Time') plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 10, 1) plot.setAxisTitle(Qwt.QwtPlot.yLeft, 'Temperature') plot.setAxisScale(Qwt.QwtPlot.yLeft, 0, 250, 40) plot.replot() curve = Qwt.QwtPlotCurve('') curve.setRenderHint(Qwt.QwtPlotItem.RenderAntialiased) pen = QPen(QColor('limegreen')) pen.setWidth(2) curve.setPen(pen) curve.attach(plot) return plot, curve def create_thermo(self): thermo = Qwt.QwtThermo(self) thermo.setPipeWidth(6) thermo.setRange(0, 120) thermo.setAlarmLevel(80) thermo.setAlarmEnabled(True) thermo.setFillColor(Qt.green) thermo.setAlarmColor(Qt.red) thermo.setOrientation(Qt.Horizontal, Qwt.QwtThermo.BottomScale) return thermo def create_knob(self): knob = Qwt.QwtKnob(self) knob.setRange(0, 20, 0, 1) knob.setScaleMaxMajor(10) knob.setKnobWidth(50) knob.setValue(10) return knob def create_status_bar(self): self.status_text = QLabel('Monitor idle') self.statusBar().addWidget(self.status_text, 1) def create_main_frame(self): # Port name # portname_l, self.portname = self.make_data_box('COM Port:') portname_layout = QHBoxLayout() portname_layout.addWidget(portname_l) portname_layout.addWidget(self.portname, 0) portname_layout.addStretch(1) portname_groupbox = QGroupBox('COM Port') portname_groupbox.setLayout(portname_layout) # Plot and thermo # self.plot, self.curve = self.create_plot() self.thermo = self.create_thermo() thermo_l = QLabel('Average') thermo_layout = QHBoxLayout() thermo_layout.addWidget(thermo_l) thermo_layout.addWidget(self.thermo) thermo_layout.setSpacing(5) self.updatespeed_knob = self.create_knob() self.connect(self.updatespeed_knob, SIGNAL('valueChanged(double)'), self.on_knob_change) self.knob_l = QLabel('Update speed = %s (Hz)' % self.updatespeed_knob.value()) self.knob_l.setAlignment(Qt.AlignTop | Qt.AlignHCenter) knob_layout = QVBoxLayout() knob_layout.addWidget(self.updatespeed_knob) knob_layout.addWidget(self.knob_l) plot_layout = QVBoxLayout() plot_layout.addWidget(self.plot) plot_layout.addLayout(thermo_layout) plot_layout.addLayout(knob_layout) plot_groupbox = QGroupBox('Temperature') plot_groupbox.setLayout(plot_layout) # Main frame and layout # self.main_frame = QWidget() main_layout = QVBoxLayout() main_layout.addWidget(portname_groupbox) main_layout.addWidget(plot_groupbox) main_layout.addStretch(1) self.main_frame.setLayout(main_layout) self.setCentralWidget(self.main_frame) self.set_actions_enable_state() def create_menu(self): self.file_menu = self.menuBar().addMenu("&File") selectport_action = self.create_action("Select COM &Port...", shortcut="Ctrl+P", slot=self.on_select_port, tip="Select a COM port") self.start_action = self.create_action("&Start monitor", shortcut="Ctrl+M", slot=self.on_start, tip="Start the data monitor") self.stop_action = self.create_action("&Stop monitor", shortcut="Ctrl+T", slot=self.on_stop, tip="Stop the data monitor") exit_action = self.create_action("E&xit", slot=self.close, shortcut="Ctrl+X", tip="Exit the application") self.start_action.setEnabled(False) self.stop_action.setEnabled(False) self.add_actions(self.file_menu, ( selectport_action, self.start_action, self.stop_action, None, exit_action)) self.help_menu = self.menuBar().addMenu("&Help") about_action = self.create_action("&About", shortcut='F1', slot=self.on_about, tip='About the monitor') self.add_actions(self.help_menu, (about_action,)) def set_actions_enable_state(self): if self.portname.text() == '': start_enable = stop_enable = False else: start_enable = not self.monitor_active stop_enable = self.monitor_active self.start_action.setEnabled(start_enable) self.stop_action.setEnabled(stop_enable) def on_about(self): msg = __doc__ QMessageBox.about(self, "About the demo", msg.strip()) def on_select_port(self): ports = list(enumerate_serial_ports()) if len(ports) == 0: QMessageBox.critical(self, 'No ports', 'No serial ports found') return item, ok = QInputDialog.getItem(self, 'Select a port', 'Serial port:', ports, 0, False) if ok and not item.isEmpty(): self.portname.setText(item) self.set_actions_enable_state() def on_stop(self): """ Stop the monitor """ if self.com_monitor is not None: self.com_monitor.join(0.01) self.com_monitor = None self.monitor_active = False self.timer.stop() self.set_actions_enable_state() self.status_text.setText('Monitor idle') def on_start(self): """ Start the monitor: com_monitor thread and the update timer """ if self.com_monitor is not None or self.portname.text() == '': return self.data_q = queue.Queue() self.error_q = queue.Queue() self.com_monitor = ComMonitorThread( self.data_q, self.error_q, full_port_name(str(self.portname.text())), 38400) self.com_monitor.start() com_error = get_item_from_queue(self.error_q) if com_error is not None: QMessageBox.critical(self, 'ComMonitorThread error', com_error) self.com_monitor = None self.monitor_active = True self.set_actions_enable_state() self.timer = QTimer() self.connect(self.timer, SIGNAL('timeout()'), self.on_timer) update_freq = self.updatespeed_knob.value() if update_freq > 0: self.timer.start(1000.0 / update_freq) self.status_text.setText('Monitor running') def on_timer(self): """ Executed periodically when the monitor update timer is fired. """ self.read_serial_data() self.update_monitor() def on_knob_change(self): """ When the knob is rotated, it sets the update interval of the timer. """ update_freq = self.updatespeed_knob.value() self.knob_l.setText('Update speed = %s (Hz)' % self.updatespeed_knob.value()) if self.timer.isActive(): update_freq = max(0.01, update_freq) self.timer.setInterval(1000.0 / update_freq) def update_monitor(self): """ Updates the state of the monitor window with new data. The livefeed is used to find out whether new data was received since the last update. If not, nothing is updated. """ if self.livefeed.has_new_data: data = self.livefeed.read_data() self.temperature_samples.append( (data['timestamp'], data['temperature'])) if len(self.temperature_samples) > 100: self.temperature_samples.pop(0) xdata = [s[0] for s in self.temperature_samples] ydata = [s[1] for s in self.temperature_samples] avg = sum(ydata) / float(len(ydata)) self.plot.setAxisScale(Qwt.QwtPlot.xBottom, xdata[0], max(20, xdata[-1])) self.curve.setData(xdata, ydata) self.plot.replot() self.thermo.setValue(avg) def read_serial_data(self): """ Called periodically by the update timer to read data from the serial port. """ qdata = list(get_all_from_queue(self.data_q)) if len(qdata) > 0: data = dict(timestamp=qdata[-1][1], temperature=ord(qdata[-1][0])) self.livefeed.add_data(data) # The following two methods are utilities for simpler creation # and assignment of actions # def add_actions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def create_action( self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action
class DataMonitor(QMainWindow): def __init__(self, parent=None): super(DataMonitor, self).__init__(parent) self.timer = QTimer() self.com_monitor = None self.main_frame = QWidget() main_layout = QVBoxLayout() self.main_frame.setLayout(main_layout) self.setCentralWidget(self.main_frame) hl = QHBoxLayout() sb = QPushButton('Iniciar') sb.setCheckable(True) self.sb = sb hl.addWidget(sb) self.connect(sb, SIGNAL('toggled(bool)'), self.onoff) self.portname = QLineEdit(DEFAULT_PORT) hl.addWidget(self.portname) main_layout.addLayout(hl) self.modules = QListWidget() self.modules.itemChanged.connect(self.mod_onoff) main_layout.addWidget(self.modules) self.fill_plugins() def fill_plugins(self): for p in plugins.all: it = QListWidgetItem(p.name) it.setCheckState(Qt.Unchecked) it.ob = p() self.modules.addItem(it) def onoff(self, checked): if checked: self.sb.setChecked(self.on_start()) else: self.on_stop() def mod_onoff(self,item): if item.checkState(): item.ob.start() else: item.ob.stop() def on_timer(self,*args): data = list(get_all_from_queue(self.data_q)) if (len(data)==0): return for idx in xrange(self.modules.count()): plug = self.modules.item(idx) if plug.checkState(): plug.ob.new_data(data) def on_stop(self): """ Stop the monitor """ if self.com_monitor is not None: self.com_monitor.join(0.01) self.com_monitor = None self.monitor_active = False self.timer.stop() def on_start(self): """ Start the monitor: com_monitor thread and the update timer """ if self.com_monitor is not None or self.portname.text() == '': return False self.data_q = Queue.Queue() self.error_q = Queue.Queue() self.com_monitor = ComMonitorThread( self.data_q, self.error_q, full_port_name(str(self.portname.text())), 115200) self.com_monitor.start() # self.com_monitor.invert = True com_error = get_item_from_queue(self.error_q) if com_error is not None: QMessageBox.critical(self, 'ComMonitorThread error', com_error) self.com_monitor = None self.monitor_active = True self.timer = QTimer() self.connect(self.timer, SIGNAL('timeout()'), self.on_timer) update_freq = 10 if update_freq > 0: self.timer.start(1000.0 / update_freq) return True def closeEvent(self, event): for idx in xrange(self.modules.count()): plug = self.modules.item(idx) plug.ob.destroy() event.accept()