總結(jié)Python連接CS2000的詳細(xì)步驟
前言
記錄CS2000設(shè)備使用串口連接以及相關(guān)控制。
CS2000是一臺(tái)分光輻射亮度計(jì),也就是可以測(cè)量光源的亮度。詳細(xì)的規(guī)格網(wǎng)址參考CS2000/CS-2000A ,所有信息以柯尼卡美能達(dá)官網(wǎng)的參數(shù)以及使用手冊(cè)為主。
使用目的及環(huán)境
當(dāng)前的使用目的是使用PC端控制CS2000,測(cè)量屏幕的亮度數(shù)據(jù)。
PC端使用Python,在Win10環(huán)境下開(kāi)發(fā);
需要額外安裝的模塊:pySerial;
設(shè)備連接方法
這臺(tái)設(shè)備是支持USB1.1 Full-Speed和RS-232C的。其配套的軟件CS-S10是使用的USB1.1接口,如果安裝了軟件,也就相當(dāng)于安裝了對(duì)應(yīng)驅(qū)動(dòng)。當(dāng)然,我這里則是使用了配置串行通訊端口COM Port
(Cluster Communication Port)。
CS2000支持的通訊設(shè)定如下:
這里選用波特率115200,數(shù)據(jù)長(zhǎng)度8 bits, 無(wú)校驗(yàn),1 bit停止位的設(shè)定;至于Hardware(RTS/CTS),即Require To Send和Clear To Send信號(hào),這里先不做考慮。
程序主體流程
1.獲取電腦COM列表;
2.連接并打開(kāi)CS2000的設(shè)備端口;
3.設(shè)備初始化(設(shè)定控制模式,關(guān)閉測(cè)試按鍵操作,設(shè)定同步模式等);
4.單次測(cè)量并獲取測(cè)量值;
5.關(guān)閉串口;
接下來(lái)就開(kāi)始結(jié)合手冊(cè)進(jìn)行操作。
獲取端口
需要引入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ū)分多個(gè)端口。
連接端口
需要引入serial
模塊:
def connect_com(port, baudrate=115200, timeout=0): """ 配置串口參數(shù)并進(jìn)行連接; :param port: 端口號(hào),“COM1” :param baudrate: 波特率,115200 :param timeout: 超時(shí)時(shí)間,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ù),返回打開(kāi)串口之后的對(duì)象。
發(fā)送格式
分隔符
使用PC發(fā)送命令到測(cè)量設(shè)備的時(shí)候,需要使用如下分隔符:
CR
, LF
對(duì)應(yīng)的ASCII的0x0D
和0x0A
;也就是在命令結(jié)束后要加分隔符進(jìn)行分割;
數(shù)據(jù)字符格式
發(fā)送的數(shù)據(jù)中,數(shù)字發(fā)送,必須要跟數(shù)字的字符一樣。比如發(fā)送十進(jìn)制數(shù)據(jù)886
,就需要發(fā)送對(duì)應(yīng)的字符886
。如果需要輸入的字符長(zhǎng)度少,需要用空格補(bǔ)齊。
超時(shí)
PC通信的超時(shí)設(shè)定至少要10s。這里可以理解為設(shè)備測(cè)量亮度是需要積分時(shí)間的,比如說(shuō)測(cè)試比較暗的畫(huà)面,需要長(zhǎng)時(shí)間的積分,因此測(cè)量的返回?cái)?shù)據(jù)需要對(duì)應(yīng)延遲很長(zhǎng)時(shí)間,因此超時(shí)設(shè)定為至少10s。
實(shí)際使用的情況中,比較暗的畫(huà)面可能需要超過(guò)7s的測(cè)量時(shí)間。
初始化
初始化包含以下以幾個(gè)環(huán)節(jié),包括設(shè)置遠(yuǎn)端模式(SCMS),關(guān)閉測(cè)量按鍵(MSWE),設(shè)定同步模式(SCMS)等;這里仔細(xì)參考手冊(cè),很容易就能理解,下面就直接貼出代碼。
def remote_mode(ser): """ 對(duì)cs2000進(jìn)行遠(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è)備進(jìn)行初始化,包含設(shè)置為遠(yuǎn)程控制,關(guān)閉測(cè)量按鍵,設(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è)備均會(huì)返回?cái)?shù)據(jù)。如若返回的是OK00
,則說(shuō)明命令發(fā)送和接收都沒(méi)有出現(xiàn)問(wèn)題,如果返回的指令有ERxx
等字樣,需要根據(jù)手冊(cè)中的錯(cuò)誤代碼列表查詢錯(cuò)誤原因,并進(jìn)行改正。
測(cè)量數(shù)據(jù)
測(cè)量數(shù)據(jù)需要先發(fā)送測(cè)量指令,等待返回測(cè)量時(shí)間,等待測(cè)量結(jié)束;
再發(fā)送測(cè)量數(shù)據(jù)讀取指令。
def measure(ser): """ 向cs2000發(fā)出測(cè)量的命令 :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ā)出測(cè)量的命令 :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ā)出測(cè)量的命令 :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)
其中,返回?cái)?shù)據(jù)的格式需要根據(jù)發(fā)送的指令進(jìn)行解析,對(duì)應(yīng)在Datasheet中也有介紹。
串口收發(fā)數(shù)據(jù)的函數(shù)
對(duì)于串口收發(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)閉
串口使用之后一定要進(jìn)行合理的關(guān)閉,防止多個(gè)程序運(yùn)行,出現(xiàn)連接問(wè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)生的串口對(duì)象
作為參數(shù)傳遞。
if __name__ == '__main__': port_list() cs2000 = connect_com("COM1", timeout=5) dev_init(cs2000) get_lv(cs2000) get_xylv(cs2000) serial_close(cs2000)
寫(xiě)在后面
設(shè)備調(diào)試的要義在于,一切操作要參考Datasheet:cs_2000_technicalnote_en,可以在官網(wǎng)支持中下載到。熟悉了手冊(cè)之后,后面的調(diào)試環(huán)節(jié)可以節(jié)省很多時(shí)間,調(diào)制的過(guò)程也會(huì)非常順利。這里例舉幾個(gè)調(diào)試過(guò)程中遇到的問(wèn)題:
1.合理設(shè)定超時(shí)(要根據(jù)最長(zhǎng)的測(cè)量時(shí)間設(shè)定),在發(fā)送數(shù)據(jù)之后就可以等待接收數(shù)據(jù);
2.這里的分隔符使用的就是\n
,轉(zhuǎn)換為byte類型
后進(jìn)行串口發(fā)送;
3.一些模式設(shè)定可以只進(jìn)行一次設(shè)定,不需要每次上電都進(jìn)行設(shè)定,為保險(xiǎn)起見(jiàn),統(tǒng)一放在初始化里面;
4.暗光環(huán)境下測(cè)試暗光源,需要的時(shí)間會(huì)很長(zhǎng),手動(dòng)測(cè)試版有24s
之多,亮光源的測(cè)試時(shí)間在1s
一次左右;
5.程序中將串口直接作為參數(shù)傳遞有些不妥,可以將該模塊改為class
;
后面如果遇到了其他問(wèn)題也會(huì)在此更新。
本項(xiàng)目源碼地址:https://github.com/LJacki/CS2000
到此這篇關(guān)于總結(jié)Python連接CS2000的詳細(xì)步驟的文章就介紹到這了,更多相關(guān)python連接CS2000內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python編程應(yīng)用設(shè)計(jì)原則詳解
什么是好用的代碼呢?其實(shí)就是代碼質(zhì)量比較高,如何評(píng)價(jià)代碼質(zhì)量的高低呢?最常用的、最重要的評(píng)價(jià)標(biāo)準(zhǔn),就是代碼的可維護(hù)性、可讀性、可擴(kuò)展性、靈活性、簡(jiǎn)潔性、可復(fù)用性、可測(cè)試性2021-09-09教你怎么用python selenium實(shí)現(xiàn)自動(dòng)化測(cè)試
今天帶大家學(xué)習(xí)怎么用python selenium實(shí)現(xiàn)自動(dòng)化測(cè)試,文中有非常詳細(xì)的介紹及代碼示例,對(duì)正在學(xué)習(xí)python的小伙伴們很有幫助,需要的朋友可以參考下2021-05-05詳解如何使用SQLAlchemy連接數(shù)據(jù)庫(kù)
這篇文章主要為大家詳細(xì)介紹了如何使用 SQLAlchemy 連接數(shù)據(jù)庫(kù)、建立模型、操作表、以及查詢操作表數(shù)據(jù)等內(nèi)容,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11python3對(duì)拉勾數(shù)據(jù)進(jìn)行可視化分析的方法詳解
這篇文章主要給大家介紹了關(guān)于python3對(duì)拉勾數(shù)據(jù)進(jìn)行可視化分析的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Python3具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04使用Python的SymPy庫(kù)解決數(shù)學(xué)運(yùn)算問(wèn)題的方法
這篇文章主要介紹了使用Python的SymPy庫(kù)解決數(shù)學(xué)運(yùn)算問(wèn)題的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-03-03python自動(dòng)化工具之pywinauto實(shí)例詳解
這篇文章主要為大家詳細(xì)介紹了python自動(dòng)化工具之pywinauto實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08Python OpenCV學(xué)習(xí)之特征點(diǎn)檢測(cè)與匹配詳解
提取圖像的特征點(diǎn)是圖像領(lǐng)域中的關(guān)鍵任務(wù),不管在傳統(tǒng)還是在深度學(xué)習(xí)的領(lǐng)域中,特征代表著圖像的信息,對(duì)于分類、檢測(cè)任務(wù)都是至關(guān)重要的。這篇文章主要為大家詳細(xì)介紹了OpenCV特征點(diǎn)檢測(cè)與匹配,需要的可以參考一下2022-01-01Django 拆分model和view的實(shí)現(xiàn)方法
今天小編就為大家分享一篇Django 拆分model和view的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-08-08