總結(jié)Python連接CS2000的詳細(xì)步驟
前言
記錄CS2000設(shè)備使用串口連接以及相關(guān)控制。
CS2000是一臺分光輻射亮度計,也就是可以測量光源的亮度。詳細(xì)的規(guī)格網(wǎng)址參考CS2000/CS-2000A ,所有信息以柯尼卡美能達(dá)官網(wǎng)的參數(shù)以及使用手冊為主。
使用目的及環(huán)境
當(dāng)前的使用目的是使用PC端控制CS2000,測量屏幕的亮度數(shù)據(jù)。
PC端使用Python,在Win10環(huán)境下開發(fā);
需要額外安裝的模塊:pySerial;
設(shè)備連接方法
這臺設(shè)備是支持USB1.1 Full-Speed和RS-232C的。其配套的軟件CS-S10是使用的USB1.1接口,如果安裝了軟件,也就相當(dāng)于安裝了對應(yīng)驅(qū)動。當(dāng)然,我這里則是使用了配置串行通訊端口COM Port(Cluster Communication Port)。
CS2000支持的通訊設(shè)定如下:

這里選用波特率115200,數(shù)據(jù)長度8 bits, 無校驗,1 bit停止位的設(shè)定;至于Hardware(RTS/CTS),即Require To Send和Clear To Send信號,這里先不做考慮。
程序主體流程
1.獲取電腦COM列表;
2.連接并打開CS2000的設(shè)備端口;
3.設(shè)備初始化(設(shè)定控制模式,關(guān)閉測試按鍵操作,設(shè)定同步模式等);
4.單次測量并獲取測量值;
5.關(guān)閉串口;
接下來就開始結(jié)合手冊進行操作。
獲取端口
需要引入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))
獲取端口列表后,可以打印端口的描述和制造商,用于區(qū)分多個端口。
連接端口
需要引入serial模塊:
def connect_com(port, baudrate=115200, timeout=0):
"""
配置串口參數(shù)并進行連接;
: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!")
定義的函數(shù),返回打開串口之后的對象。
發(fā)送格式
分隔符
使用PC發(fā)送命令到測量設(shè)備的時候,需要使用如下分隔符:
CR, LF對應(yīng)的ASCII的0x0D和0x0A;也就是在命令結(jié)束后要加分隔符進行分割;
數(shù)據(jù)字符格式
發(fā)送的數(shù)據(jù)中,數(shù)字發(fā)送,必須要跟數(shù)字的字符一樣。比如發(fā)送十進制數(shù)據(jù)886,就需要發(fā)送對應(yīng)的字符886。如果需要輸入的字符長度少,需要用空格補齊。
超時
PC通信的超時設(shè)定至少要10s。這里可以理解為設(shè)備測量亮度是需要積分時間的,比如說測試比較暗的畫面,需要長時間的積分,因此測量的返回數(shù)據(jù)需要對應(yīng)延遲很長時間,因此超時設(shè)定為至少10s。
實際使用的情況中,比較暗的畫面可能需要超過7s的測量時間。
初始化
初始化包含以下以幾個環(huán)節(jié),包括設(shè)置遠(yuǎn)端模式(SCMS),關(guān)閉測量按鍵(MSWE),設(shè)定同步模式(SCMS)等;這里仔細(xì)參考手冊,很容易就能理解,下面就直接貼出代碼。
def remote_mode(ser):
"""
對cs2000進行遠(yuǎn)程控制設(shè)置
: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):
"""
關(guān)閉cs2000設(shè)備上的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):
"""
同步模式設(shè)定
: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設(shè)備進行初始化,包含設(shè)置為遠(yuǎn)程控制,關(guān)閉測量按鍵,設(shè)置同步模式,查詢同步模式數(shù)據(jù)
:param ser: cs2000的串口
:return: None
"""
remote_mode(ser)
meas_key_off(ser)
sync_mode_set(ser, SYNC_FREQ)
sync_mode_read(ser)
注意:這里每次發(fā)送命令之后,設(shè)備均會返回數(shù)據(jù)。如若返回的是OK00,則說明命令發(fā)送和接收都沒有出現(xiàn)問題,如果返回的指令有ERxx等字樣,需要根據(jù)手冊中的錯誤代碼列表查詢錯誤原因,并進行改正。
測量數(shù)據(jù)
測量數(shù)據(jù)需要先發(fā)送測量指令,等待返回測量時間,等待測量結(jié)束;
再發(fā)送測量數(shù)據(jù)讀取指令。
def measure(ser):
"""
向cs2000發(fā)出測量的命令
: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發(fā)出測量的命令
: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發(fā)出測量的命令
:param ser: cs2000的串口
:return: 色坐標(biāo),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):
"""
獲取色坐標(biāo)X,Y和亮度LV。
:param ser: cs2000的串口
:return: 色坐標(biāo),X,Y,亮度,LV
"""
measure(ser)
return xylv_read(ser)
其中,返回數(shù)據(jù)的格式需要根據(jù)發(fā)送的指令進行解析,對應(yīng)在Datasheet中也有介紹。
串口收發(fā)數(shù)據(jù)的函數(shù)
對于串口收發(fā)數(shù)據(jù),也封裝了一層函數(shù),方便調(diào)用:
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!")
串口關(guān)閉
串口使用之后一定要進行合理的關(guān)閉,防止多個程序運行,出現(xiàn)連接問題。
def serial_close(ser):
"""
關(guān)閉串口連接
:return: None
"""
# noinspection PyBroadException
try:
ser.close()
print("Port {} has been closed!".format(ser.name))
except Exception:
print("----serial_close failed!")
主函數(shù)
所有的參數(shù)傳遞,都是將產(chǎn)生的串口對象作為參數(shù)傳遞。
if __name__ == '__main__':
port_list()
cs2000 = connect_com("COM1", timeout=5)
dev_init(cs2000)
get_lv(cs2000)
get_xylv(cs2000)
serial_close(cs2000)
寫在后面
設(shè)備調(diào)試的要義在于,一切操作要參考Datasheet:cs_2000_technicalnote_en,可以在官網(wǎng)支持中下載到。熟悉了手冊之后,后面的調(diào)試環(huán)節(jié)可以節(jié)省很多時間,調(diào)制的過程也會非常順利。這里例舉幾個調(diào)試過程中遇到的問題:
1.合理設(shè)定超時(要根據(jù)最長的測量時間設(shè)定),在發(fā)送數(shù)據(jù)之后就可以等待接收數(shù)據(jù);
2.這里的分隔符使用的就是\n,轉(zhuǎn)換為byte類型后進行串口發(fā)送;
3.一些模式設(shè)定可以只進行一次設(shè)定,不需要每次上電都進行設(shè)定,為保險起見,統(tǒng)一放在初始化里面;
4.暗光環(huán)境下測試暗光源,需要的時間會很長,手動測試版有24s之多,亮光源的測試時間在1s一次左右;
5.程序中將串口直接作為參數(shù)傳遞有些不妥,可以將該模塊改為class;
后面如果遇到了其他問題也會在此更新。
本項目源碼地址:https://github.com/LJacki/CS2000
到此這篇關(guān)于總結(jié)Python連接CS2000的詳細(xì)步驟的文章就介紹到這了,更多相關(guān)python連接CS2000內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python利用partial偏函數(shù)生成不同的聚合函數(shù)
本文主要介紹了Python利用partial偏函數(shù)生成不同的聚合函數(shù),利用偏函數(shù)的概念,可以生成一些新的函數(shù),在調(diào)用這些新函數(shù)時,不用再傳遞固定值的參數(shù),這樣可以使代碼更簡潔,感興趣的可以了解一下2024-03-03
Python實現(xiàn)的字典排序操作示例【按鍵名key與鍵值value排序】
這篇文章主要介紹了Python實現(xiàn)的字典排序操作,結(jié)合實例形式分析了Python針對字典分別按照鍵名key與鍵值value進行排序的相關(guān)操作技巧,需要的朋友可以參考下2018-12-12
python使用beautifulsoup4爬取酷狗音樂代碼實例
這篇文章主要介紹了python使用beautifulsoup4爬取酷狗音樂代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-12-12
Window 64位下python3.6.2環(huán)境搭建圖文教程
這篇文章主要為大家詳細(xì)介紹了Window 64位下python3.6.2環(huán)境搭建圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-09-09
Python調(diào)整數(shù)組形狀如何實現(xiàn)
這篇文章主要介紹了Python調(diào)整數(shù)組形狀如何實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-12-12

