总结Python连接CS2000的详细步骤


Posted in Python onJune 23, 2021

前言

记录CS2000设备使用串口连接以及相关控制。

CS2000是一台分光辐射亮度计,也就是可以测量光源的亮度。详细的规格网址参考CS2000/CS-2000A ,所有信息以柯尼卡美能达官网的参数以及使用手册为主。

使用目的及环境

当前的使用目的是使用PC端控制CS2000,测量屏幕的亮度数据。

PC端使用Python,在Win10环境下开发;

需要额外安装的模块:pySerial;

设备连接方法

这台设备是支持USB1.1 Full-Speed和RS-232C的。其配套的软件CS-S10是使用的USB1.1接口,如果安装了软件,也就相当于安装了对应驱动。当然,我这里则是使用了配置串行通讯端口COM Port(Cluster Communication Port)。

CS2000支持的通讯设定如下:

总结Python连接CS2000的详细步骤

这里选用波特率115200,数据长度8 bits, 无校验,1 bit停止位的设定;至于Hardware(RTS/CTS),即Require To Send和Clear To Send信号,这里先不做考虑。

程序主体流程

1.获取电脑COM列表;

2.连接并打开CS2000的设备端口;

3.设备初始化(设定控制模式,关闭测试按键操作,设定同步模式等);

4.单次测量并获取测量值;

5.关闭串口;

接下来就开始结合手册进行操作。

获取端口

需要引入serial.tools.list_ports模块:

def port_list():
    """
    获取电脑端口列表
    :return: 端口列表
    """
    pl = serial.tools.list_ports.comports()
    # print(pl)
    print("Port List:")
    for item in pl:
        print("{}\t\t:\t{}".format(item.usb_description(), item.manufacturer))

获取端口列表后,可以打印端口的描述和制造商,用于区分多个端口。

连接端口

需要引入serial模块:

def connect_com(port, baudrate=115200, timeout=0):
    """
    配置串口参数并进行连接;
    :param port: 端口号,“COM1”
    :param baudrate: 波特率,115200
    :param timeout: 超时时间,0
    :return: 连接好的串口,ser
    """
    # noinspection PyBroadException
    try:
        ser = serial.Serial(port, baudrate, timeout=timeout)
        print("Port\t\t:\t{}".format(ser.name))
        print("Baudrate\t:\t{}".format(ser.baudrate))
        print("Status\t\t:\t{} Connect Successful!".format(port))
        return ser
    except Exception:
        print("Status\t\t:\t\t\tConnect COM Failed!")

定义的函数,返回打开串口之后的对象。

发送格式

分隔符

使用PC发送命令到测量设备的时候,需要使用如下分隔符:

CR, LF对应的ASCII的0x0D0x0A;也就是在命令结束后要加分隔符进行分割;

数据字符格式

发送的数据中,数字发送,必须要跟数字的字符一样。比如发送十进制数据886,就需要发送对应的字符886。如果需要输入的字符长度少,需要用空格补齐。

超时

PC通信的超时设定至少要10s。这里可以理解为设备测量亮度是需要积分时间的,比如说测试比较暗的画面,需要长时间的积分,因此测量的返回数据需要对应延迟很长时间,因此超时设定为至少10s。

实际使用的情况中,比较暗的画面可能需要超过7s的测量时间。

初始化

初始化包含以下以几个环节,包括设置远端模式(SCMS),关闭测量按键(MSWE),设定同步模式(SCMS)等;这里仔细参考手册,很容易就能理解,下面就直接贴出代码。

def remote_mode(ser):
    """
    对cs2000进行远程控制设置
    :param ser: cs2000的串口
    :return: None
    """
    data = b'RMTS,1\n'
    tx_data(ser, data)
    if rx_data(ser)[0] == "OK00":
        print("Status\t\t:\tRemote Mode Setting OK!")
    else:
        print("Status\t\t:\tRemote Mode Setting ERROR!")


def meas_key_off(ser):
    """
    关闭cs2000设备上的measure按键控制
    :param ser: cs2000的串口
    :return: None
    """
    data = b'MSWE,0\n'
    tx_data(ser, data)
    if rx_data(ser)[0] == "OK00":
        # print("Status\t\t:\tMeasure Key Disable OK!")
        pass
    else:
        print("Status\t\t:\tMeasure Key Disable ERROR!")


def sync_mode_set(ser, freq):
    """
    同步模式设定
    :param ser: cs2000的串口
    :param freq: 频率,单位Hz
    :return: None
    """
    mode = b'1,'
    freq = freq.encode()
    data = b'SCMS,' + mode + freq + b'00\n'
    tx_data(ser, data)
    if rx_data(ser)[0] == "OK00":
        print("Status\t\t:\tSync Mode is {}, freq is {}Hz!".format(mode, freq))
        pass
    else:
        print("Status\t\t:\tMeasure Key Disable ERROR!")


def sync_mode_read(ser):
    """
    同步模式读取
    :param ser: cs2000的串口
    :return: None
    """
    sync_mode_dict = {"0": "No sync",
                      "1": "Internal sync",
                      "2": "External sync"}
    data = b'SCMR\n'
    tx_data(ser, data)
    rdata = rx_data(ser)
    if rdata[0] == "OK00":
        print("Status\t\t:\tSync Mode is {}. ".format(sync_mode_dict[rdata[1]]))
        if rdata[1] == "1":
            print("Status\t\t:\tSync frequency is {}Hz. ".format(rdata[2][:-2]))
        pass
    else:
        print("Status\t\t:\tSync Mode read ERROR!")


def dev_init(ser):
    """
    cs2000设备进行初始化,包含设置为远程控制,关闭测量按键,设置同步模式,查询同步模式数据
    :param ser: cs2000的串口
    :return: None
    """
    remote_mode(ser)
    meas_key_off(ser)
    sync_mode_set(ser, SYNC_FREQ)
    sync_mode_read(ser)

注意:这里每次发送命令之后,设备均会返回数据。如若返回的是OK00,则说明命令发送和接收都没有出现问题,如果返回的指令有ERxx等字样,需要根据手册中的错误代码列表查询错误原因,并进行改正。

测量数据

测量数据需要先发送测量指令,等待返回测量时间,等待测量结束;

再发送测量数据读取指令。

def measure(ser):
    """
    向cs2000发出测量的命令
    :param ser: cs2000的串口
    :return: None
    """
    data = b'MEAS,1\n'
    tx_data(ser, data)
    rdata = rx_data(ser)
    if rdata[0] == "OK00":
        # print("Status\t\t:\tMeasure time is {}s".format(rdata[1]))
        pass
    else:
        print("Status\t\t:\tMeasure CMD ERROR Code {}".format(rdata[0]))

    rdata_1 = rx_data(ser)
    if rdata_1[0] == "OK00":
        # print("Status\t\t:\tMeasurement completed!")
        pass
    else:
        print("Status\t\t:\tMeasure Wait ERROR Code {}".format(rdata_1[0]))


def lv_read(ser):
    """
    向cs2000发出测量的命令
    :param ser: cs2000的串口
    :return: 亮度值lv
    """
    data = b'MEDR,2,0,101\n'
    tx_data(ser, data)
    rdata = rx_data(ser)
    if rdata[0] == "OK00":
        # print("Status\t\t:\tLuminance is {} cd/m²".format(rdata[1]))
        return rdata[1]
    else:
        print("Status\t\t:\tLuminance Read ERROR Code {}".format(rdata[0]))
        return None


def get_lv(ser):
    """
    获取亮度值
    :param ser: cs2000的串口
    :return: 亮度值,单位cd/m²
    """
    measure(ser)
    return lv_read(ser)


def xylv_read(ser):
    """
    向cs2000发出测量的命令
    :param ser: cs2000的串口
    :return: 色坐标,X,Y,亮度,LV
    """
    data = b'MEDR,2,0,2\n'
    tx_data(ser, data)
    rdata = rx_data(ser)
    if rdata[0] == "OK00":
        print("Status\t\t:\tX,Y,LV are {} {} {}".format(rdata[1], rdata[2], rdata[3]))
        return rdata[1:]
    else:
        print("Status\t\t:\tMeasure ERROR!")
        return None


def get_xylv(ser):
    """
    获取色坐标X,Y和亮度LV。
    :param ser: cs2000的串口
    :return: 色坐标,X,Y,亮度,LV
    """
    measure(ser)
    return xylv_read(ser)

其中,返回数据的格式需要根据发送的指令进行解析,对应在Datasheet中也有介绍。

串口收发数据的函数

对于串口收发数据,也封装了一层函数,方便调用:

def tx_data(ser, data):
    # noinspection PyBroadException
    try:
        ser.write(data)
        # print("Status\t\t:\tSend OK!")
    except Exception:
        print("Status\t\t:\tSend ERROR!")


def rx_data(ser):
    # noinspection PyBroadException
    try:
        rdata = ser.readline().decode("utf-8").replace("\n", "").split(",")
        # print("Status\t\t:\tReceived {}".format(rdata))
        return rdata
    except Exception:
        print("Status\t\t:\tReceive ERROR!")

串口关闭

串口使用之后一定要进行合理的关闭,防止多个程序运行,出现连接问题。

def serial_close(ser):
    """
    关闭串口连接
    :return: None
    """
    # noinspection PyBroadException
    try:
        ser.close()
        print("Port {} has been closed!".format(ser.name))
    except Exception:
        print("----serial_close failed!")

主函数

所有的参数传递,都是将产生的串口对象作为参数传递。

if __name__ == '__main__':

    port_list()

    cs2000 = connect_com("COM1", timeout=5)

    dev_init(cs2000)

    get_lv(cs2000)
    get_xylv(cs2000)

    serial_close(cs2000)

写在后面

设备调试的要义在于,一切操作要参考Datasheet:cs_2000_technicalnote_en,可以在官网支持中下载到。熟悉了手册之后,后面的调试环节可以节省很多时间,调制的过程也会非常顺利。这里例举几个调试过程中遇到的问题:

1.合理设定超时(要根据最长的测量时间设定),在发送数据之后就可以等待接收数据;

2.这里的分隔符使用的就是\n,转换为byte类型后进行串口发送;

3.一些模式设定可以只进行一次设定,不需要每次上电都进行设定,为保险起见,统一放在初始化里面;

4.暗光环境下测试暗光源,需要的时间会很长,手动测试版有24s之多,亮光源的测试时间在1s一次左右;

5.程序中将串口直接作为参数传递有些不妥,可以将该模块改为class

后面如果遇到了其他问题也会在此更新。

本项目源码地址:https://github.com/LJacki/CS2000

到此这篇关于总结Python连接CS2000的详细步骤的文章就介绍到这了,更多相关python连接CS2000内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python实现支持目录FTP上传下载文件的方法
Jun 03 Python
Python 对象中的数据类型
May 13 Python
Python开发微信公众平台的方法详解【基于weixin-knife】
Jul 08 Python
使用DataFrame删除行和列的实例讲解
Apr 08 Python
Python3 实现串口两进程同时读写
Jun 12 Python
Ubuntu18.04下python版本完美切换的解决方法
Jun 14 Python
python如何实现视频转代码视频
Jun 17 Python
python 计算两个列表的相关系数的实现
Aug 29 Python
PyTorch的SoftMax交叉熵损失和梯度用法
Jan 15 Python
Python warning警告出现的原因及忽略方法
Jan 31 Python
pycharm中导入模块错误时提示Try to run this command from the system terminal
Mar 26 Python
Python中的变量与常量
Nov 11 Python
python图片灰度化处理的几种方法
详解Python中的进程和线程
详解Go语言运用广度优先搜索走迷宫
常用的Python代码调试工具总结
Django+Celery实现定时任务的示例
Python django中如何使用restful框架
Python基础之变量的相关知识总结
Jun 23 #Python
You might like
PHP extract 将数组拆分成多个变量的函数
2010/06/30 PHP
destoon文章模块调用企业会员资料的方法
2014/08/22 PHP
JavaScript设置首页和收藏页面的小例子
2013/11/11 Javascript
JS截取url中问号后面参数的值信息
2014/04/29 Javascript
JavaScript中的lastIndexOf()方法使用详解
2015/06/06 Javascript
JavaScript中instanceof运算符的使用示例
2016/06/08 Javascript
jQuery筛选数组之grep、each、inArray、map的用法及遍历json对象
2016/06/20 Javascript
Jquery删除css属性的简单方法
2016/12/04 Javascript
ES6通过babel转码使用webpack使用import关键字
2016/12/13 Javascript
js图片轮播手动切换特效
2017/01/12 Javascript
js前端日历控件(悬浮、拖拽、自由变形)
2017/03/02 Javascript
CodeMirror js代码加亮使用总结
2017/03/25 Javascript
js Dom实现换肤效果
2017/10/21 Javascript
详解vue-router 初始化时做了什么
2018/06/11 Javascript
ES6 系列之 Generator 的自动执行的方法示例
2018/10/19 Javascript
Python中的多行注释文档编写风格汇总
2016/06/16 Python
Python实现将sqlite数据库导出转成Excel(xls)表的方法
2017/07/17 Python
Python使用当前时间、随机数产生一个唯一数字的方法
2017/09/18 Python
利用Python在一个文件的头部插入数据的实例
2018/05/02 Python
python正向最大匹配分词和逆向最大匹配分词的实例
2018/11/14 Python
详解pandas的外部数据导入与常用方法
2019/05/01 Python
PyQt5根据控件Id获取控件对象的方法
2019/06/25 Python
Python使用matplotlib 画矩形的三种方式分析
2019/10/31 Python
Django xadmin开启搜索功能的实现
2019/11/15 Python
浅谈Python中range与Numpy中arange的比较
2020/03/11 Python
Django def clean()函数对表单中的数据进行验证操作
2020/07/09 Python
Python爬虫小例子——爬取51job发布的工作职位
2020/07/10 Python
Python 如何展开嵌套的序列
2020/08/01 Python
Python用摘要算法生成token及检验token的示例代码
2020/12/01 Python
h5页面唤起app如果没安装就跳转下载(iOS和Android)
2020/06/03 HTML / CSS
香港太阳眼镜网上商店:SmartBuyGlasses香港
2016/07/22 全球购物
企业内部培训方案
2014/02/04 职场文书
总经理的岗位职责
2014/02/23 职场文书
2014年度安全生产目标管理责任书
2014/07/25 职场文书
生产操作工岗位职责
2014/09/16 职场文书
python tkinter Entry控件的焦点移动操作
2021/05/22 Python