总结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的Django框架中的select_related函数对QuerySet 查询的优化
Apr 01 Python
Djang中静态文件配置方法
Jul 30 Python
Python实现简易端口扫描器代码实例
Mar 15 Python
JSONLINT:python的json数据验证库实例解析
Nov 28 Python
python版微信跳一跳游戏辅助
Jan 11 Python
Python求解任意闭区间的所有素数
Jun 10 Python
Python实现登陆文件验证方法
Oct 06 Python
对sklearn的使用之数据集的拆分与训练详解(python3.6)
Dec 14 Python
Python使用os.listdir()和os.walk()获取文件路径与文件下所有目录的方法
Apr 01 Python
python 使用shutil复制图片的例子
Dec 13 Python
Python使用type动态创建类操作示例
Feb 29 Python
用pushplus+python监控亚马逊到货动态推送微信
Jan 29 Python
python图片灰度化处理的几种方法
详解Python中的进程和线程
详解Go语言运用广度优先搜索走迷宫
常用的Python代码调试工具总结
Django+Celery实现定时任务的示例
Python django中如何使用restful框架
Python基础之变量的相关知识总结
Jun 23 #Python
You might like
开启CURL扩展,让服务器支持PHP curl函数(远程采集)
2011/03/19 PHP
php使用curl打开https网站的方法
2015/06/17 PHP
PHP处理bmp格式图片的方法分析
2017/07/04 PHP
在线游戏大家来找茬II
2006/09/30 Javascript
jquery 的 $("#id").html() 无内容的解决方法
2010/06/07 Javascript
js 遍历对象的属性的代码
2011/12/29 Javascript
js弹出层(jQuery插件形式附带reLoad功能)
2013/04/12 Javascript
自定义ExtJS控件之下拉树和下拉表格附源码
2013/10/15 Javascript
ExtJS自定义主题(theme)样式详解
2013/11/18 Javascript
红米手机抢购的js代码
2014/03/10 Javascript
jquery 自定义容器下雨效果可将下雨图标改为其他
2014/04/23 Javascript
javascript实现分栏显示小技巧附图
2014/10/13 Javascript
整理Javascript基础语法学习笔记
2015/11/29 Javascript
JS给Array添加是否包含字符串的简单方法
2016/10/29 Javascript
javascript输出AscII码扩展集中的字符方法
2016/12/26 Javascript
javascript正则表达式模糊匹配IP地址功能示例
2017/01/06 Javascript
利用JS判断客户端类型你应该知道的四种方法
2017/12/22 Javascript
[01:59]深扒TI7聊天轮盘语音出处 1
2017/05/11 DOTA
Python3.6日志Logging模块简单用法示例
2018/06/14 Python
彻彻底底地理解Python中的编码问题
2018/10/15 Python
对pandas写入读取h5文件的方法详解
2018/12/28 Python
python 列表转为字典的两个小方法(小结)
2019/06/28 Python
Python unittest工作原理和使用过程解析
2020/02/24 Python
使用css3制作动感导航条示例
2014/01/26 HTML / CSS
html5利用canvas绘画二级树形结构图的示例
2017/09/27 HTML / CSS
ProBikeKit新西兰:自行车套件,跑步和铁人三项装备
2017/04/05 全球购物
芬兰设计商店美国:Finnish Design Shop US
2019/03/25 全球购物
ORLY官网:美国专业美甲一线品牌
2019/12/11 全球购物
大专生的学习自我评价
2013/12/04 职场文书
护士实习鉴定范文
2013/12/22 职场文书
商场活动策划方案
2014/01/24 职场文书
园林系毕业生求职信
2014/06/23 职场文书
2015年世界水日活动总结
2015/02/09 职场文书
Java基础之详解HashSet的使用方法
2021/06/30 Java/Android
Python自动化工具之实现Excel转Markdown表格
2022/04/08 Python
volatile保证可见性及重排序方法
2022/08/05 Java/Android