协议

问题

目前需要通过烧录多个程序,通过多套代码来驱动控制板。

我们更希望的是下位机一个文件就可以,然后调试代码也是一套就行

思考

单一功能的下位机程序,只能接收有限的指令,不能通过指令来区分到底是让谁干活,或者说只能让固定的部件干活。

要解决这个问题,只需要上位机和下位机沟通好,到底怎么干活就行。沟通的话术就是我们俗称的协议。

大家按照统一的协议规定,去干具体的活就行。

协议制定分析

功能 原始协议 现有协议
LED 0x01(开),0x02(关),0x03(切换) 0x01 + 0x01(开),0x02(关),0x03(切换)
蜂鸣器 0x01(开),0x02(关),0x03(切换) 0x02 + 0x01(开),0x02(关),0x03(切换)
电机 0xb8 0x0b(pwm值) 0x03 + 0xb8 0x0b(pwm值)
OLED 0x69 0x74 0x63 0x61 0x73 0x74(显示的内容) 0x04 + 0x69 0x74 0x63 0x61 0x73 0x74(显示的内容)

Note

通过一个唯一的标记值取标定指令,后续根据实际操作来控制

控制代码实现

基本代码实现

import serial


def test_led():
    # 字节数据
    data = bytearray([0x01, 0x02])
    ser.write(data)


def test_buzzer():
    # 字节数据
    data = bytearray([0x02, 0x02])
    ser.write(data)


def test_motor():
    # 字节数据 pwm 3000
    data = bytearray([0x03, 0xb8, 0x0b])
    ser.write(data)


def test_oled():
    # 字节数据 itcast
    data = bytearray([0x04, 0x69, 0x74, 0x63, 0x61, 0x73, 0x74])
    ser.write(data)


if __name__ == '__main__':
    ser = serial.Serial(port='/dev/ttyUSB0', baudrate=115200)

    test_led()
    test_buzzer()
    test_motor()
    test_oled()

异常

程序在运行过程中,发生了未知的事件,影响到了程序的正常运行。

异常是一种事件 异常会影响到程序正常运行。

格式如下:

try:
    代码
except:
    出现异常后的逻辑

a = 10
b = 0
c = a/b
print(c)

Warning

执行以上代码就会出现错误。

出现了ZeroDivisionError异常

出现异常会造成程序停止

GUI实现

布局拆分

整个窗体可以分为一个水平布局,包含两个部分。

第一个部分,又可以分为一个垂直布局,包含连个部分

第二个部分,又可以分为一个垂直布局,包含连个部分

按照这种方式依次类推,就可以更细化的布局。

布局的原则就是由外向内。

分组控件

Qt中QGroupBox是一个分组控件,可以帮助我们将一个布局包括在一起。

QGroupBox包含了title和内部的布局两个部分.

group = QGroupBox('我是title')
layout = QVBoxLayout(group)

完整代码实现

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys

import serial
import struct


class MyWindow(QWidget):

    def __init__(self):
        super(MyWindow, self).__init__()

        self.__init_ui()

        count = 0
        while count < 10:
            count += 1
            try:
                self.ser = serial.Serial(port='/dev/ttyUSB0', baudrate=115200)
                # 如果出错了,后面的代码就不执行了
                # 能到达这个位置说明,链接成功
                break
            except Exception as e:
                print(e)

    def __init_ui(self):
        self.setWindowTitle('下位机控制')

        layout = QHBoxLayout()
        self.setLayout(layout)

        first_layout = QVBoxLayout()
        second_layout = QVBoxLayout()

        layout.addLayout(first_layout)
        layout.addLayout(second_layout)

        self.__init_first(first_layout)
        self.__init_second(second_layout)

    def __init_first(self, layout):
        led_group = QGroupBox('LED控制')
        layout.addWidget(led_group)
        led_layout = QVBoxLayout(led_group)
        self.__init_led_layout(led_layout)

        buzzer_group = QGroupBox('蜂鸣器控制')
        layout.addWidget(buzzer_group)
        buzzer_layout = QVBoxLayout(buzzer_group)
        self.__init_buzzer_layout(buzzer_layout)

    def __init_led_layout(self, layout):
        btn_open = QPushButton('打开LED')
        btn_close = QPushButton('关闭LED')
        btn_toggle = QPushButton('开关LED')

        layout.addWidget(btn_open)
        layout.addWidget(btn_close)
        layout.addWidget(btn_toggle)

        btn_open.clicked.connect(self.led_open)
        btn_close.clicked.connect(self.led_close)
        btn_toggle.clicked.connect(self.led_toggle)

    def __init_buzzer_layout(self, layout):
        btn_open = QPushButton('打开蜂鸣器')
        btn_close = QPushButton('关闭蜂鸣器')
        btn_toggle = QPushButton('开关蜂鸣器')

        layout.addWidget(btn_open)
        layout.addWidget(btn_close)
        layout.addWidget(btn_toggle)

        btn_open.clicked.connect(self.buzzer_open)
        btn_close.clicked.connect(self.buzzer_close)
        btn_toggle.clicked.connect(self.buzzer_toggle)

    def __init_second(self, layout):
        motor_group = QGroupBox('电机控制')
        layout.addWidget(motor_group)
        motor_layout = QVBoxLayout(motor_group)
        self.__init_motor_layout(motor_layout)

        oled_group = QGroupBox('OLED控制')
        layout.addWidget(oled_group)
        oled_layout = QVBoxLayout(oled_group)
        self.__init_oled_layout(oled_layout)

    def __init_motor_layout(self, layout):
        self.__le_motor = QLineEdit()
        btn = QPushButton("发送")

        layout.addWidget(self.__le_motor)
        layout.addWidget(btn)

        btn.clicked.connect(self.motor_spin)

    def __init_oled_layout(self, layout):
        self.__le_oled = QLineEdit()
        btn = QPushButton("发送")

        layout.addWidget(self.__le_oled)
        layout.addWidget(btn)

        btn.clicked.connect(self.oled_show)

    def led_open(self):
        # 字节数据
        data = bytearray([0x01, 0x01])
        self.ser.write(data)

    def led_close(self):
        # 字节数据
        data = bytearray([0x01, 0x02])
        self.ser.write(data)

    def led_toggle(self):
        # 字节数据
        data = bytearray([0x01, 0x03])
        self.ser.write(data)

    def buzzer_open(self):
        # 字节数据
        data = bytearray([0x02, 0x01])
        self.ser.write(data)

    def buzzer_close(self):
        # 字节数据
        data = bytearray([0x02, 0x02])
        self.ser.write(data)

    def buzzer_toggle(self):
        # 字节数据
        data = bytearray([0x02, 0x03])
        self.ser.write(data)

    def motor_spin(self):
        text = self.__le_motor.text()
        pwm = int(text)
        pack = struct.pack('h', pwm)
        data = bytearray([0x03, pack[0], pack[1]])
        self.ser.write(data)

    def oled_show(self):
        text = self.__le_oled.text()
        data = bytearray([0x04])
        data.extend(text.encode())
        self.ser.write(data)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = MyWindow()
    window.show()

    sys.exit(app.exec_())