|
本帖最后由 中国罗宾鸟 于 2018-8-15 11:23 编辑
本次主要更新以下内容:
1、增加菜单功能,通过菜单对测试过程进行操作;
2、增加测试与学习记录查看功能;
3、增加关于设备信息显示功能;
4、增加长按3秒以上恢复默认设置(学习记录恢复到一对一直连)功能,主要防止因误操作而修改了学习记录(设置参数);
扩展或升级方向:
1、将按键由当前的1个扩展为2个,操作更方便;
2、使用带WIFI或蓝牙功能的板子,可增加无线通讯功能,通过手机端直接对设置文件进行编辑,并可查看测试与学习记录;
3、将当前的学习和测试记录由1个扩展为更多。
正确的操作步骤:
1、将测试参考线缆接入检测口;
2、屏幕菜单上单击按键移动光标到“Studay“项,再双击按键,开始学习(扫描)并记录当前线缆的通断状态,学习完成之后将自动进入学习记录查看界面;
3、待界面中图标闪烁(通常只闪烁3次)停止后再单击按键翻页查看学习记录,确认学习结果与当前线缆一致。当到达末页后继续单击按键将会自动回到首页开始;
4、待界面中图标闪烁(通常只闪烁3次)停止后再双击按键退出当前界面,回到菜单界面;
5、更换线缆为待测线缆;
6、单击按键移动光标到”TEST“项,再双击按键,开始对当前线缆进行测试,若结果与学习记录一致,则在屏幕显示“PASS’文字,3秒后返回菜单界面,若不一致,则会自动进入测试记录查看界面;
7、测试记录提查阅与退出方式与学习记录一致。同时测试记录给出了问题线号与问题原因("Open circuit!":开路、"Short circuit!":短路、"Wrong order!":线序错误);
8、移动光标到”VIEW“菜单,双击按键进入,通过单击和双击操作,可在些分别进入、查看和退出测试记录与学习记录。
备注:
1、若参考线缆为1对1 直接连接的线缆,则可以通过长按按键3秒以上,直接设置,无需再进行学习操作;
2、在接入待测线缆后,请勿进行学习操作,否则无法检测出问题;
3、在记录查看过程中,若上方图标在闪烁过程中,则此时操作按键将会无反应(闪烁语句中使用的是sleep_ms());
4、由于每个人的手速不一样,按键单击、双击间隔时间可自行调整。
当前代码已全部调整完成,可正常使用。部分功能可以继续优化。
本准备在启动时增加启动LOGO的,但由于对OLED图片显示功能还没搞懂,所以暂放下。
主菜单
记录查看菜单
测试记录显示界面
学习记录显示界面
关于信息界面
屏幕显示界面
- # -*- coding:UTF-8 -*-
- '''
- MIT License
- Copyright (c) 2018 Robin Chen
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- '''
- '''
- ******************************************************************************
- * 文 件:GUI.py
- * 概 述:当前模块主要用于OLED(SSD1306)屏画面显示。
- * 版 本:V0.10
- * 作 者:Robin Chen
- * 日 期:2018年7月26日
- * 历 史: 日期 编辑 版本 记录
- 2018年7月26日 Robin Chen V0.10 创建文件
- `
- ******************************************************************************'''
- from machine import Pin, I2C
- from ssd1306 import SSD1306_I2C
- from time import sleep_ms
- i2c = I2C(scl= Pin("C2"), sda= Pin("C3"))
- oled = SSD1306_I2C(128, 64, i2c)
- oled.text("Hellow MicroPython!", 0, 30)
- oled.show()
- sleep_ms(1000)
- oled.fill(0)
- oled.show()
- '''*************************************************************************
- * 功 能:图示显示
- * 说 明:报告(包括问题报告与学习报告)界面图示显示。
- * 输入参数:
- x: 横坐标
- y: 纵坐标
- l: 显示图形的二进制制编码,通常用16进制形式表示。
- * 输出参数:None
- * 返 回 值:True
- **************************************************************************'''
- def dhView(x, y, l):
- l = int(l) # 将字符串型16进制数转换为整型16进制数
- # ll = list(bin(1 << 8 | l)[3:])[::-1]
- ll = bin(1 << 8 | l)[3:]
- #print('ll = ',ll)
- oled.framebuf.fill_rect(x, y, 108, 8, 0)
- for i in range(8):
- if ll[i] == '1':
- oled.framebuf.fill_rect((x + 14 * i), y, 8, 8, 1)
- else:
- oled.framebuf.rect((x + 14 * i), y, 8, 8, 1)
- oled.show()
- '''*************************************************************************
- * 功 能:报告显示
- * 说 明:根据提供的参数,判断当前当部属于哪种类型,并返回错误提示。
- * 输入参数:
- l1: 源线号,整型值,1~8
- l2: 待测线路显示位,二进制处理,16进制表示。
- x: 图形区域的起始位置x坐标
- y: 图形区域的起始位置y坐标
- cont: 位置图示闪烁次数,为 -1 时一直闪烁,为 0 时不闪烁。
- * 输出参数:None
- * 返 回 值:True
- **************************************************************************'''
- def oledFlash(l1, l2, x=20, y=0, cont = 1):
- n = 128 >> (int(l1) - 1)
- oled.framebuf.fill_rect(0, 0, 128, 35, 0)
- oled.text("S:", 0, y)
- oled.text("T:", 0, (y+14))
- oled.framebuf.hline(0, (y + 26), 128, 1)
- while cont:
- dhView(x, y, 0x00)
- dhView(x, (y + 14), 0x00)
- sleep_ms(500)
- dhView(x, y, n)
- dhView(x, (y + 14), l2)
- sleep_ms(500)
- cont -= 1
- '''*************************************************************************
- * 名 称:问题信息显示
- * 说 明:显示错误信息(线路号和故障原因(开路、短路、错序))
- * 输入参数:
- znum:总页数
- nonum:当前页码
- err:错误内容
- _line:线号
- * 输出参数:None
- * 返 回 值:True
- **************************************************************************'''
- def viewReportText(strTitle, strR1, strR2):
- oled.framebuf.fill_rect(0, 35, 128, 29, 0)
- oled.text(strTitle, 0, 35)
- oled.text(strR1, 10, 45)
- oled.text(strR2, 10, 56)
- oled.show()
- '''*************************************************************************
- * 名 称:菜单显示与处理
- * 说 明:在屏幕上显示菜单,并根据按键的操作来显示不同的菜单界面。
- * 输入参数:
- _lmenu:菜单内容,tule格式,0位为菜单标题。
- _gb: 光标所在行号,默认为None(不显示)。
- * 输出参数:None
- * 返 回 值:True
- **************************************************************************'''
- def oledView(_lmenu, _gb = None):
- oled.fill(0)
- oled.text(_lmenu[0], ((128 - (len(_lmenu[0])*8)) // 2), 5)
- oled.framebuf.hline(0, 20, 128, 1)
- for i in range(len(_lmenu))[1:]:
- oled.text(_lmenu[i], ((128 - (len(_lmenu[i])*8)) // 2), (i*10+15))
- if _gb != None:
- if _gb == 0:
- _gb += 1
- oled.text(">", (((128 - (len(_lmenu[_gb])*8)) // 2) - 16), (_gb * 10 + 15))
- oled.text("<", (((128 - (len(_lmenu[_gb]) * 8)) // 2) + (len(_lmenu[_gb]) * 8) + 8), (_gb * 10 + 15))
- oled.show()
- '''*************************************************************************
- * 名 称:报告显示与翻页效果
- * 说 明:在报告页面按下翻页按钮后,报告将向后轮循翻页,同时适用检测报告与学习报告
- * 输入参数:
- _drReport:报告内容,包含线号、报告内容、报告说明。格式为:((linenumber,0x00, "note"), (linenumber,0x00, "note"),...)
- _gb: 报告页码,整型,值为 1~ max
- ty:报告类型,字符串型,通常为 'ERR' 或 'STU'
- * 输出参数:None
- * 返 回 值:None
- **************************************************************************'''
- def repView(_drReport, _gb, ty = 'ERR'):
- l1 = _drReport[_gb][0]
- l2 = _drReport[_gb][1]
- strTitle = ty + ' ' + str(len(_drReport)) + '-' + str(_gb + 1) + ' >>'
- strR1 = 'Line ' + str(_drReport[_gb][0])
- strR2 = _drReport[_gb][2]
- viewReportText(strTitle, strR1, strR2)
- oledFlash(l1, l2, cont=3)
- return True
复制代码
测试主模块
- # -*- coding:UTF-8 -*-
- '''
- MIT License
- Copyright (c) 2018 Robin Chen
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- '''
- '''
- ******************************************************************************
- * 文 件:wiretest.py
- * 概 述:当前模块主要用于线路检测,并返回检测结果。
- * 版 本:V0.10
- * 作 者:Robin Chen
- * 日 期:2018年7月26日
- * 历 史: 日期 编辑 版本 记录
- 2018年7月26日 Robin Chen V0.10 创建文件
- `
- ******************************************************************************'''
- from time import sleep_ms
- class WIRETEST:
- def __init__(self, _lIN, _lOUT):
- self.lin = _lIN
- self.lout = _lOUT
- # 接收端初始化,注意,如果实际电路中使用了外部下拉或芯片内部无内部下拉,请取消此处的下拉声明。
- for i in self.lin:
- i.init(i.IN, i.PULL_DOWN)
- # 发送端初始化
- for o in self.lout:
- o.init(o.OUT)
- o.value(0)
- '''*************************************************************************
- * 功 能:线路扫描
- * 说 明:给线路一端加高电平,检测另一端是高电平还是低电平。
- * 输入参数:
- _filName: 文件名
- * 输出参数:None
- * 返 回 值:
- * lScan : 扫描结果,16进制形式的 tule。
- **************************************************************************'''
- def doScan(self, _filName = None):
- lScan2 = ()
- bLab = 0
- while True:
- lScan = ()
- for o in self.lout:
- o.value(1)
- iValue = 0
- for i in self.lin:
- iValue = (iValue << 1) | i.value()
- lScan += (hex(iValue),)
- o.value(0)
- sleep_ms(10)
- # 重复扫描连续5次结果一致算通过,否则重新计数,直到满足条件为止。
- if lScan == lScan2:
- bLab += 1
- else:
- bLab = 0
- if bLab > 5:
- if _filName == None:
- return lScan
- else:
- # 将扫描记录写入指定的文件
- sep = ','
- f = open(_filName, 'w')
- f.write(sep.join(lScan))
- f.close()
- break
- lScan2 = lScan
- return True
- '''*************************************************************************
- * 功 能:检测线路状态
- * 说 明:
- * 输入参数:None
- * 输出参数:None
- * 返 回 值:True
- **************************************************************************'''
- def doTest(self):
- tuResult=() # 错误信息元组格式
- lmemory = self.getLog("LineSequence.stu")
- #print('文件中提取得到的线序:', lmemory)
- lLineSeq = self.doScan()
- #print("待测线缆扫描结果(线序):", lLineSeq)
- if lmemory == lLineSeq:
- return True, tuResult
- else:
- for j in range(len(lLineSeq)):
- if lLineSeq[j] != lmemory[j]:
- if lLineSeq[j] == '0x0': # 开(断)路
- strErr = "Open circuit!"
- elif lLineSeq[j] != '0x0' and not (lLineSeq[j] in lmemory): # 短路
- strErr = "Short circuit!"
- elif lLineSeq[j] != '0x0' and (lLineSeq[j] in lmemory): # 错序
- strErr = "Wrong order!"
- tuResult = tuResult + ((j+1, lLineSeq[j], strErr),) # 结果中有问题的序号+内容组成的字典
- return False, tuResult
- '''*************************************************************************
- * 功 能:获取学习记录文件内容
- * 说 明:
- * 输入参数:
- _filName: 记录文件名
- * 输出参数:None
- * 返 回 值:
- temp:记录内容,元组。
- **************************************************************************'''
- def getLog(self, _filName):
- f = open(_filName, 'r')
- temp = f.readline()
- f.close()
- temp = tuple(temp.split(','))
- return temp
- '''*************************************************************************
- * 功 能:恢复默认设置
- * 说 明:将当前设置文件恢复到初始状态(1对1直连)
- * 输入参数:
- _filName: 记录文件名
- * 输出参数:None
- * 返 回 值:None
- **************************************************************************'''
- def setDefault(self, _filName):
- temp = ('0x80', '0x40', '0x20', '0x10', '0x8', '0x4', '0x2', '0x1')
- sep = ','
- f = open(_filName, 'w')
- f.write(sep.join(temp))
- f.close()
- return True
复制代码
测试调度与菜单操作模块
- # -*- coding:UTF-8 -*-
- '''
- MIT License
- Copyright (c) 2018 Robin Chen
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- '''
- '''******************************************************************************
- * 文 件:testline.py
- * 概 述:当前模块主要用于测试调用调用相关模块或程序完成相应动作。
- * 版 本:V0.10
- * 作 者:Robin Chen
- * 日 期:2018年7月26日
- * 历 史: 日期 编辑 版本 记录
- 2018年7月26日 Robin Chen V0.10 创建文件
- ******************************************************************************'''
- from wiretest import WIRETEST
- from GUI import *
- from machine import Pin
- from pyb import Timer
- from time import sleep_ms
- from keyboard import KEYBOARD
- lin = (Pin('C1'), Pin('C0'), Pin('C13'), Pin('C5'), Pin('C4'), Pin('A6'), Pin('A5'), Pin('A4'))
- lout = (Pin('A13'), Pin('A14'), Pin('A15'), Pin('B4'), Pin('B1'), Pin('B0'), Pin('B12'), Pin('B9'))
- wt = WIRETEST(lin, lout)
- # 按键引脚
- p = Pin('B3')
- # 定时器,按键时钟使用
- s = Timer(1)
- # 经过处理的测试记录
- tuTest = ()
- # 经过处理的学习记录
- tuStu = ()
- bLab = 0 # 按键点击状态标志字
- guangbiao = 1 # 光标位置计数
- # 菜单的字典格式
- diMenu = {'WCSD': ('WCSD MENU', 'TEST', 'STUDAY', 'VIEW', 'ABOUT'), 'VIEW': ('VIEW MENU', 'TEST LOG', 'STUDAY LOG', 'BACK'), 'ABOUT': ('ABOUT', '', 'Wire Connecting', 'State Detector', 'V 1.00')}
- # 主菜单与子菜单标题元组
- lMenu = ('WCSD', 'VIEW', 'ABOUT')
- # 主菜单标题
- menu = diMenu['WCSD']
- # 学习函数
- def stu():
- doView("Studaying...", 10, 30)
- wt.doScan("LineSequence.stu")
- doReportGo('STULOG')
- return True
- # 测试函数
- def test():
- global tuTest
- tuTest = ()
- doView('Test Start....', 10, 30)
- bTets, tuTest = wt.doTest()
- if not bTets:
- sleep_ms(3000)
- return False
- else:
- doView("PASS!!!.", 10, 30)
- sleep_ms(3000)
- return True
- # 长按按键事件
- def evn_long():
- global bLab
- bLab = 3
- # 在指定位置显示文字
- def doView(text, x, y):
- oled.fill(0)
- oled.text(text, x, y)
- oled.show()
- # 连续点击事件
- def evn_con(con):
- global bLab
- if con == 1:
- bLab = 1
- elif con == 2:
- bLab = 2
- '''
- *************************************************************************
- * 名 称:报告显示与查阅
- * 说 明:
- * 输入参数:
- sta:报告阅读状态标志字,通常为 TESTLOG:测试报告 STULOG: 学习报告(记录)
- * 输出参数:None
- * 返 回 值:None
- **************************************************************************'''
- def doReportGo(sta):
- global bLab, tuStu
- mjs = 0
- bLab = 0
- if sta == 'TESTLOG':
- if tuTest == ():
- doView("No have Log!", 10, 30)
- sleep_ms(3000)
- else:
- repView(tuTest, mjs % len(tuTest), ty='ERR')
- elif sta == 'STULOG':
- tuStu = ()
- tempStu = wt.getLog("LineSequence.stu")
- for i in range(len(tempStu)):
- tuStu = tuStu + ((i + 1, tempStu[i], ''),)
- if tuStu == ():
- doView("No have Log!", 10, 30)
- sleep_ms(3000)
- else:
- repView(tuStu, mjs % len(tuStu), ty='STU')
- while True:
- if bLab == 1:
- mjs += 1
- if sta == 'TESTLOG':
- repView(tuTest, mjs % len(tuTest), ty='ERR')
- elif sta == 'STULOG':
- repView(tuStu, mjs % len(tuStu), ty='STU')
- bLab = 0
- elif bLab == 2:
- bLab = 0
- break
- sw = KEYBOARD(p, s, 0, evn_long, evn_con, "UP")
- oledView(menu, 1)
- menuLab = 'MENU'
- tuStu = wt.getLog("LineSequence.stu")
- while True:
- if bLab == 1: # 检测到按钮当前单击
- if menu[0] != 'ABOUT':
- # 光标循环处理
- guangbiao = (guangbiao + 1)%len(menu)
- if guangbiao == 0:
- guangbiao = 1
- oledView(menu, guangbiao)
- bLab = 0
- #oledMenu(menunum, guangbiao)
- elif bLab == 2:
- if menu[guangbiao] in lMenu: # 如果当前菜单项下有子菜单
- menu = diMenu[menu[guangbiao]]
- if menu[0] == "ABOUT":
- oledView(menu)
- else:
- guangbiao = 1
- oledView(menu, guangbiao)
- else:
- if menu[guangbiao] == 'TEST': # 测试问题线路
- test()
- menuLab = 'TESTLOG'
- if tuTest:
- doReportGo(menuLab)
- menuLab = 'MENU'
- elif menu[guangbiao] == 'STUDAY': # 学习、记忆标准线路
- stu()
- menuLab = 'STULOG'
- if tuStu:
- doReportGo(menuLab)
- menuLab = 'MENU'
- elif menu[guangbiao] == 'TEST LOG': # 查看测试报告
- # 此处由代码演示按钮翻页效果
- menuLab = 'TESTLOG'
- if tuTest:
- doReportGo(menuLab)
- else:
- doView("No have Log!", 10, 30)
- sleep_ms(3000)
- menuLab = 'MENU'
- elif menu[guangbiao] == 'STUDAY LOG': # 查看学习记录
- menuLab = 'STULOG'
- if tuStu:
- doReportGo(menuLab)
- else:
- doView("Studaying...", 10, 30)
- menuLab = 'MENU'
- elif menu[guangbiao] == 'BACK': # 返回上一层菜单
- menu = diMenu[lMenu[0]]
- guangbiao = 3
- else:
- menu = diMenu[lMenu[0]]
- oledView(menu, guangbiao)
- bLab = 0
- # 为防止误操作将已学习的记录覆盖或损坏,在此增加长按3秒恢复默认设置(即一对一直连模式)
- elif bLab == 3:
- print("开始恢复默认设置!")
- wt.setDefault("LineSequence.stu")
- print("当前设置已恢复默认设置!")
- doView("Default Seted!...", 10, 30)
- sleep_ms(1500)
- bLab = 0
复制代码
|
|