From 82af33082c4c917b099f1212f7175bbfe73db1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Sandstr=C3=B6m?= Date: Fri, 18 Aug 2023 12:49:16 +0200 Subject: [PATCH] Decode of statusword added --- tools/ecmcMotionMainPyQtGraph.py | 58 ++++--------- tools/ecmcParseAxisStatusWord.py | 140 +++++++++++++++++++++++++++++++ tools/ecmcPvDataItem.py | 38 ++++++++- 3 files changed, 195 insertions(+), 41 deletions(-) create mode 100644 tools/ecmcParseAxisStatusWord.py diff --git a/tools/ecmcMotionMainPyQtGraph.py b/tools/ecmcMotionMainPyQtGraph.py index 4b5d656..2ecc900 100644 --- a/tools/ecmcMotionMainPyQtGraph.py +++ b/tools/ecmcMotionMainPyQtGraph.py @@ -13,19 +13,16 @@ #************************************************************************* import sys -import os import epics from PyQt5.QtWidgets import * from PyQt5 import QtWidgets from PyQt5.QtCore import * from PyQt5.QtGui import * import numpy as np -import time from ecmcOneMotorGUI import * - import pyqtgraph as pg -import threading from ecmcPvDataItem import * +from ecmcParseAxisStatusWord import * # Allow buffering of 10s data, need to add setting for this xMaxTime = 10 @@ -85,7 +82,7 @@ class ecmcMtnMainGui(QtWidgets.QDialog): def __init__(self,prefix="IOC_TEST:",mtnPluginId=0): super(ecmcMtnMainGui, self).__init__() self.pvItems = {} - + self.parseAxisStaWd = ecmcParseAxisStatusWord() self.plottedLineAnalog = {} self.plottedLineBinary = {} @@ -212,6 +209,8 @@ class ecmcMtnMainGui(QtWidgets.QDialog): self.pvItems['Mde-RB'].regExtSigCallback(self.sig_cb_Mde_RB) self.pvItems['AxCmd-RB'].regExtSigCallback(self.sig_cb_AxCmd_RB) self.pvItems['EnaCmd-RB'].regExtSigCallback(self.sig_cb_EnaCmd_RB) + self.pvItems['Stat-Arr'].regExtSigCallback(self.sig_cb_Stat_Arr) + # Example calls to ecmcPvDataItem: #self.testPV.regExtSigCallback(self.testSigCallback) #self.testPV.regExtPvMonCallback(self.testPVMonCallback) @@ -435,8 +434,7 @@ class ecmcMtnMainGui(QtWidgets.QDialog): if value is None: return print('Axis Id Value: ' + str(value)) - - + id = self.cmbBxSelectAxis.findText(str(int(value))) if id >= 0: self.cmbBxSelectAxis.setCurrentIndex(id) @@ -461,6 +459,14 @@ class ecmcMtnMainGui(QtWidgets.QDialog): self.enableBtn.setStyleSheet("background-color: red") return + def sig_cb_Stat_Arr(self,value): + + bindata = self.parseAxisStaWd.convert(value) + #bindata=self.pvItems['Stat-Arr'].binaryRepr(value) + print('Binary data: ' + str(bindata.shape)) + print(bindata) + + # State chenge for Analog checkboxes def checkBoxStateChangedAnalog(self, int): # refresh plots @@ -652,6 +658,10 @@ class ecmcMtnMainGui(QtWidgets.QDialog): self.plotBinary() self.MtnYDataValid = False self.RawYDataValid = False + + def convertStatusWordToBits(self,statwd): + print('test') + def plotAnalog(self, autozoom=False): @@ -679,9 +689,6 @@ class ecmcMtnMainGui(QtWidgets.QDialog): x_len=len(self.x) y_len=len(y) - #print('x_len: ' + str(x_len)) - #print('y_len: ' + str(y_len)) - if self.checkBoxListAnalog[pv].isChecked(): if self.plottedLineAnalog[pv] is None: plotpen=pg.mkPen(self.plotColor[pv],width=2) @@ -697,30 +704,6 @@ class ecmcMtnMainGui(QtWidgets.QDialog): self.plotItemAnalog.removeItem(self.plottedLineAnalog[pv]) self.plottedLineAnalog[pv] = None - #else: - # print("Data null for pv: " + pv) - - #if autozoom: - # ymin = np.min(self.data['PosAct-Arr']) - # ymax = np.max(self.data['PosAct-Arr']) - # # ensure different values - # if ymin == ymax: - # ymin=ymin-1 - # ymax=ymax+1 - # range = ymax - ymin - # ymax += range * 0.1 - # ymin -= range * 0.1 - # xmin = minimum_x - # xmax = 0 - # if xmin == xmax: - # xmin = xmin - 1 - # xmax = xmax + 1 - # range = xmax - xmin - # xmax += range * 0.02 - # xmin -= range * 0.02 - # #self.plotItemAnalog.setYRange(ymin, ymax, padding=0) - # self.plotItemAnalog.setXRange(xmin, xmax, padding=0) - self.allowSave = True self.saveBtn.setEnabled(True) @@ -742,11 +725,8 @@ class ecmcMtnMainGui(QtWidgets.QDialog): print('X is None') continue - x_len=len(self.x) - + x_len=len(self.x) y_len=len(y) - #print('x_len: ' +str(x_len)) - #print('y_len: ' +str(y_len)) if self.checkBoxListBinary[pv].isChecked(): if self.plottedLineBinary[pv] is None: @@ -765,8 +745,6 @@ class ecmcMtnMainGui(QtWidgets.QDialog): if self.plottedLineBinary[pv] is not None: self.plotItemBinary.removeItem(self.plottedLineBinary[pv]) self.plottedLineBinary[pv] = None - #else: - # print("Data null for pv: " + pv) if autozoom: ymin = -0.1 diff --git a/tools/ecmcParseAxisStatusWord.py b/tools/ecmcParseAxisStatusWord.py new file mode 100644 index 0000000..9562576 --- /dev/null +++ b/tools/ecmcParseAxisStatusWord.py @@ -0,0 +1,140 @@ + + +import numpy as np + +# unsigned char enable : 1; +# unsigned char enabled : 1; +# unsigned char execute : 1; +# unsigned char busy : 1; +# unsigned char attarget : 1; +# unsigned char moving : 1; +# unsigned char limitfwd : 1; +# unsigned char limitbwd : 1; +# unsigned char homeswitch : 1; +# unsigned char homed : 1; +# unsigned char inrealtime : 1; +# unsigned char trajsource : 1; +# unsigned char encsource : 1; +# unsigned char plccmdallowed : 1; +# unsigned char softlimfwdena : 1; +# unsigned char softlimbwdena : 1; +# unsigned char instartup : 1; +# unsigned char sumilockfwd : 1; +# unsigned char sumilockbwd : 1; +# unsigned char axisType : 1; +# unsigned char seqstate : 4; +# unsigned char lastilock : 8; + +names = ['enable', + 'enabled', + 'execute', + 'busy', + 'attarget', + 'moving', + 'limitfwd', + 'limitbwd', + 'homeswitch', + 'homed', + 'inrealtime', + 'trajsource', + 'encsource', + 'plccmdallowed', + 'softlimfwdena', + 'softlimbwdena', + 'instartup', + 'sumilockfwd', + 'sumilockbwd', + 'axisType', + 'seqstate', + 'lastilock'] + +class ecmcParseAxisStatusWord(): + + def convert(self,statuswdArray): + arraylength = len(statuswdArray) + data=np.empty([22,arraylength]) + #seqdata=np.empty(arraylength) + #ilockdata=np.empty(arraylength) + i = 0 + for statwd in statuswdArray: + data[0:20:,i] = self.binaryRepr20(statwd) + data[20,i] = self.getSeqState(statwd) + data[21,i] = self.getIlockData(statwd) + i += 1 + return data + + def getSeqState(self,data): + localdata = data.astype(int) + return np.bitwise_and(localdata,0b11110000000000000000000) >> 20 + + def getIlockData(self,data): + localdata = data.astype(int) + return np.bitwise_and(localdata,0b1111111100000000000000000000000) >> 24 + + def binaryRepr32(self,data): + localdata = data.astype(int) + return( + np.dstack(( + np.bitwise_and(localdata, 0b10000000000000000000000000000000) >> 31, + np.bitwise_and(localdata, 0b1000000000000000000000000000000) >> 30, + np.bitwise_and(localdata, 0b100000000000000000000000000000) >> 29, + np.bitwise_and(localdata, 0b10000000000000000000000000000) >> 28, + np.bitwise_and(localdata, 0b1000000000000000000000000000) >> 27, + np.bitwise_and(localdata, 0b100000000000000000000000000) >> 26, + np.bitwise_and(localdata, 0b10000000000000000000000000) >> 25, + np.bitwise_and(localdata, 0b1000000000000000000000000) >> 24, + np.bitwise_and(localdata, 0b100000000000000000000000) >> 23, + np.bitwise_and(localdata, 0b10000000000000000000000) >> 22, + np.bitwise_and(localdata, 0b1000000000000000000000) >> 21, + np.bitwise_and(localdata, 0b100000000000000000000) >> 20, + np.bitwise_and(localdata, 0b10000000000000000000) >> 19, + np.bitwise_and(localdata, 0b1000000000000000000) >> 18, + np.bitwise_and(localdata, 0b100000000000000000) >> 17, + np.bitwise_and(localdata, 0b10000000000000000) >> 16, + np.bitwise_and(localdata, 0b1000000000000000) >> 15, + np.bitwise_and(localdata, 0b100000000000000) >> 14, + np.bitwise_and(localdata, 0b10000000000000) >> 13, + np.bitwise_and(localdata, 0b1000000000000) >> 12, + np.bitwise_and(localdata, 0b100000000000) >> 11, + np.bitwise_and(localdata, 0b10000000000) >> 10, + np.bitwise_and(localdata, 0b1000000000) >> 9, + np.bitwise_and(localdata, 0b100000000) >> 8, + np.bitwise_and(localdata, 0b10000000) >> 7, + np.bitwise_and(localdata, 0b1000000) >> 6, + np.bitwise_and(localdata, 0b100000) >> 5, + np.bitwise_and(localdata, 0b10000) >> 4, + np.bitwise_and(localdata, 0b1000) >> 3, + np.bitwise_and(localdata, 0b100) >> 2, + np.bitwise_and(localdata, 0b10) >> 1, + np.bitwise_and(localdata, 0b1) + )).flatten() > 0).astype(int) + + def binaryRepr20(self,data): + localdata = data.astype(int) + return( + np.dstack(( + np.bitwise_and(localdata, 0b10000000000000000000) >> 19, + np.bitwise_and(localdata, 0b1000000000000000000) >> 18, + np.bitwise_and(localdata, 0b100000000000000000) >> 17, + np.bitwise_and(localdata, 0b10000000000000000) >> 16, + np.bitwise_and(localdata, 0b1000000000000000) >> 15, + np.bitwise_and(localdata, 0b100000000000000) >> 14, + np.bitwise_and(localdata, 0b10000000000000) >> 13, + np.bitwise_and(localdata, 0b1000000000000) >> 12, + np.bitwise_and(localdata, 0b100000000000) >> 11, + np.bitwise_and(localdata, 0b10000000000) >> 10, + np.bitwise_and(localdata, 0b1000000000) >> 9, + np.bitwise_and(localdata, 0b100000000) >> 8, + np.bitwise_and(localdata, 0b10000000) >> 7, + np.bitwise_and(localdata, 0b1000000) >> 6, + np.bitwise_and(localdata, 0b100000) >> 5, + np.bitwise_and(localdata, 0b10000) >> 4, + np.bitwise_and(localdata, 0b1000) >> 3, + np.bitwise_and(localdata, 0b100) >> 2, + np.bitwise_and(localdata, 0b10) >> 1, + np.bitwise_and(localdata, 0b1) + )).flatten() > 0) + + def getNames(self): + return names + diff --git a/tools/ecmcPvDataItem.py b/tools/ecmcPvDataItem.py index 1e55fd5..cfd6f62 100644 --- a/tools/ecmcPvDataItem.py +++ b/tools/ecmcPvDataItem.py @@ -97,4 +97,40 @@ class ecmcPvDataItem(): self.pv.put(value) self.data = value - \ No newline at end of file + def binaryRepr(self,data): + localdata = data.astype(int) + return( + np.dstack(( + np.bitwise_and(localdata, 0b10000000000000000000000000000000) >> 31, + np.bitwise_and(localdata, 0b1000000000000000000000000000000) >> 30, + np.bitwise_and(localdata, 0b100000000000000000000000000000) >> 29, + np.bitwise_and(localdata, 0b10000000000000000000000000000) >> 28, + np.bitwise_and(localdata, 0b1000000000000000000000000000) >> 27, + np.bitwise_and(localdata, 0b100000000000000000000000000) >> 26, + np.bitwise_and(localdata, 0b10000000000000000000000000) >> 25, + np.bitwise_and(localdata, 0b1000000000000000000000000) >> 24, + np.bitwise_and(localdata, 0b100000000000000000000000) >> 23, + np.bitwise_and(localdata, 0b10000000000000000000000) >> 22, + np.bitwise_and(localdata, 0b1000000000000000000000) >> 21, + np.bitwise_and(localdata, 0b100000000000000000000) >> 20, + np.bitwise_and(localdata, 0b10000000000000000000) >> 19, + np.bitwise_and(localdata, 0b1000000000000000000) >> 18, + np.bitwise_and(localdata, 0b100000000000000000) >> 17, + np.bitwise_and(localdata, 0b10000000000000000) >> 16, + np.bitwise_and(localdata, 0b1000000000000000) >> 15, + np.bitwise_and(localdata, 0b100000000000000) >> 14, + np.bitwise_and(localdata, 0b10000000000000) >> 13, + np.bitwise_and(localdata, 0b1000000000000) >> 12, + np.bitwise_and(localdata, 0b100000000000) >> 11, + np.bitwise_and(localdata, 0b10000000000) >> 10, + np.bitwise_and(localdata, 0b1000000000) >> 9, + np.bitwise_and(localdata, 0b100000000) >> 8, + np.bitwise_and(localdata, 0b10000000) >> 7, + np.bitwise_and(localdata, 0b1000000) >> 6, + np.bitwise_and(localdata, 0b100000) >> 5, + np.bitwise_and(localdata, 0b10000) >> 4, + np.bitwise_and(localdata, 0b1000) >> 3, + np.bitwise_and(localdata, 0b100) >> 2, + np.bitwise_and(localdata, 0b10) >> 1, + np.bitwise_and(localdata, 0b1) + )).flatten() > 0) \ No newline at end of file