嵌入式设备做信号处理,通过串口实时将采集数据传递出来。
PC端调试工具通过串口接收采集数据,并实时显示,方便分析
python丰富的基础组件可以让嵌入式工程师快速搭建自己的调试工具,本例的串口采集实验libusb,图像界面使用pyQT。
代码如下:
#!/usr/bin/env python3
import random
import sys
from PyQt5.QtCore import (QAbstractListModel, QAbstractTableModel,
QModelIndex, QSize, QTimer, QVariant, Qt, pyqtSignal)
from PyQt5.QtWidgets import (QApplication, QDialog, QHBoxLayout,
QListView, QSpinBox, QStyledItemDelegate, QStyleOptionViewItem, QWidget, QVBoxLayout)
from PyQt5.QtGui import QColor, QPainter, QPixmap, QFont
import usbhelper as uh
class BarGraphModel(QAbstractListModel):
dataChanged = pyqtSignal(QModelIndex, QModelIndex)
def __init__(self):
super(BarGraphModel, self).__init__()
self.__data = []
self.__colors = {}
self.minValue = 0
self.maxValue = 0
def rowCount(self, index=QModelIndex()):
return len(self.__data)
def insertRows(self, row, count):
extra = row + count
if extra >= len(self.__data):
self.beginInsertRows(QModelIndex(), row, count)
self.__data.extend([0] * (extra - len(self.__data)))
self.endInsertRows()
return True
return False
def flags(self, index):
return QAbstractListModel.flags(self, index) | Qt.ItemIsEditable
def setData(self, index, value, role=Qt.DisplayRole):
row = index.row()
if not index.isValid() or 0 > row >= len(self.__data):
return False
changed = False
if role == Qt.DisplayRole:
value = value
self.__data[row] = value
if self.minValue > value:
self.minValue = value
if self.maxValue < value:
self.maxValue = value
changed = True
elif role == Qt.UserRole:
self.__colors[row] = value
changed = True
if changed:
self.dataChanged[QModelIndex, QModelIndex].emit(index, index)
return changed
def data(self, index, role=Qt.DisplayRole):
row = index.row()
if not index.isValid() or 0 > row >= len(self.__data):
return QVariant()
if role == Qt.DisplayRole:
return self.__data[row]
if role == Qt.UserRole:
# print('UserRole')
return QVariant(self.__colors.get(row, QColor(Qt.red))) # for BarGraphView paintEvent
if role == Qt.DecorationRole:
color = QColor(self.__colors.get(row, QColor(Qt.red)))
pixmap = QPixmap(20, 20)
pixmap.fill(color)
# print('DecorationRole', index.model().data(index, Qt.UserRole))
return QVariant(pixmap)
return QVariant()
class BarGraphView(QWidget):
WIDTH = 30
def __init__(self, parent=None):
super(BarGraphView, self).__init__(parent)
self.model = None
def setModel(self, model):
self.model = model
self.model.dataChanged[QModelIndex, QModelIndex].connect(self.update)
# self.connect(self.model, SIGNAL("modelReset()"), self.update)
self.model.modelReset.connect(self.update)
def sizeHint(self):
return self.minimumSizeHint()
def minimumSizeHint(self):
if self.model is None:
return QSize(BarGraphView.WIDTH * 10, 100)
return QSize(BarGraphView.WIDTH * self.model.rowCount(), 300)
def paintEvent(self, event):
if self.model is None:
return
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
span = self.model.maxValue - self.model.minValue
painter.setWindow(0, 0, BarGraphView.WIDTH * self.model.rowCount(), span + 30)
for row in range(self.model.rowCount()):
x = row * BarGraphView.WIDTH
index = self.model.index(row)
color = QColor(self.model.data(index, Qt.UserRole))
y = self.model.data(index)
painter.fillRect(x, span - y, BarGraphView.WIDTH, y, color)
class BarGraphView1(QWidget):
WIDTH = 30
span = 20
def __init__(self, parent=None):
super(BarGraphView1, self).__init__(parent)
self.model = None
def setModel(self, model):
self.model = model
self.model.dataChanged[QModelIndex, QModelIndex].connect(self.update)
# self.connect(self.model, SIGNAL("modelReset()"), self.update)
self.model.modelReset.connect(self.update)
def sizeHint(self):
return self.minimumSizeHint()
def minimumSizeHint(self):
if self.model is None:
return QSize(BarGraphView1.WIDTH * 10, BarGraphView1.span)
return QSize(BarGraphView1.WIDTH * self.model.rowCount(), BarGraphView1.span)
def paintEvent(self, event):
if self.model is None:
return
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.setWindow(0, 0, BarGraphView.WIDTH * self.model.rowCount(), BarGraphView1.span)
for row in range(self.model.rowCount()):
x = row * BarGraphView.WIDTH
if row < 10:
x += 8
index = self.model.index(row)
color = QColor(self.model.data(index, Qt.UserRole))
y = self.model.data(index)
# painter.fillRect(x, span - y, BarGraphView.WIDTH, y, color)
font = QFont()
font.setPointSize(15)
painter.setFont(font)
painter.drawText(x, 15, str(row))
# print(x, span, str(row))
class MainForm(QDialog):
def __init__(self, parent=None):
super(MainForm, self).__init__(parent)
self.__end = False
self.model = BarGraphModel()
self.barGraphView = BarGraphView()
self.barGraphView.setModel(self.model)
layout = QVBoxLayout()
self.barGraphView1 = BarGraphView1()
self.barGraphView1.setModel(self.model)
layout.addWidget(self.barGraphView)
layout.addWidget(self.barGraphView1, 1)
self.setLayout(layout)
self.setWindowTitle("Bar Grapher")
QTimer.singleShot(0, self.load)
def load(self):
count = 30
if self.model.rowCount() < count:
self.model.insertRows(0, count)
print("row sum ", self.model.rowCount())
for row in range(count):
color = QColor(random.randint(0, 255), random.randint(0, 255),
random.randint(0, 255))
index = self.model.index(row)
self.model.setData(index, 0)
self.model.setData(index, QVariant(color), Qt.UserRole)
state, x, y, press, x_gain, y_gain, vx, vy, chx, chy, xl, xr, yl, yr, data = uh.get_point()
if state and press:
for row in range(count):
index = self.model.index(row)
if chx > row + 5 or chx < row - 5:
self.model.setData(index, 0)
continue
value = uh.get_int16(data, 32 + 2 * (row + 5 - chx))
self.model.setData(index, value)
if not self.__end:
QTimer.singleShot(0, self.load)
def quit(self):
self.__end = True
if __name__ == '__main__':
uh.start_read()
app = QApplication(sys.argv)
form = MainForm()
form.resize(600, 400)
form.show()
app.exec_()
form.quit()
uh.stop()
运行界面如下: