总结Python连接CS2000的详细步骤

作者:ShareWow丶 时间:2023-04-21 20:26:33 

前言

记录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

来源:https://blog.csdn.net/sinat_31206523/article/details/117900657

标签:python,连接,CS2000
0
投稿

猜你喜欢

  • Django REST Framework序列化外键获取外键的值方法

    2022-02-23 16:03:14
  • 用python脚本24小时刷浏览器的访问量方法

    2022-07-16 18:21:33
  • M1芯片Mac上Anaconda的暂时替代(miniforge)

    2022-12-12 00:32:43
  • 使用python处理题库表格并转化为word形式的实现

    2023-07-25 12:33:18
  • Python实现双X轴双Y轴绘图的示例详解

    2021-10-17 17:33:58
  • 关于MYSQL中每个用户取1条记录的三种写法(group by xxx)

    2024-01-22 02:08:38
  • 通过Python把学姐照片做成拼图游戏

    2022-03-24 17:21:01
  • MySQL Server层四个日志的实现

    2024-01-21 11:16:58
  • Python实现字典的key和values的交换

    2021-08-18 03:45:49
  • Python实现字符串模糊匹配方式

    2023-11-10 09:30:35
  • JavaScript的陷阱

    2008-10-28 19:52:00
  • 关于php unset对json_encode的影响详解

    2023-07-06 08:33:52
  • Goland 2020或2019软件版本去掉a...或fmt...提示的方法

    2024-04-25 15:06:44
  • python实现美团订单推送到测试环境,提供便利操作示例

    2023-03-23 13:39:54
  • Python3.4编程实现简单抓取爬虫功能示例

    2022-04-23 17:48:15
  • Vue3 全局实例上挂载属性方法案例讲解

    2023-07-02 16:46:14
  • python识别验证码的思路及解决方案

    2022-02-02 16:05:13
  • 用css和js实现firefox和IE支持局部打印

    2008-05-23 13:04:00
  • python数据可视化pygal模拟掷骰子实现示例

    2021-06-21 07:31:35
  • 一文学会VSCode使用python

    2022-07-26 16:06:46
  • asp之家 网络编程 m.aspxhome.com