管理員
統計數據
原文網址 石小川 2020-02-23 11:33:02
玩模型飛機、直升機所得到的科技知識,遠遠超過課堂所學N年,想要當科技強國一定要從小紮根,當官的不能只是禁東禁西便宜行事。早年玩火箭被查水表,現在換機瘟,假日只好將長灰塵的直升機隊放在"地上"保養,乘機把玩一番。
原文網址 石小川 2020-02-22 21:15:58
DM542 採用共陽接法, 如圖。
其中加了ULM2003達靈頓是因為Pi4輸出準位是3.3V, 無法推動DM542驅動器,故須加上當作緩衝器,一來調整準位至+5V, 另外為加大推動電流, 很多朋友沒成功就是這個原因。
測試程式是用Python寫的, 有兩種方式, 提供給朋友參考 :
Program 1是 Time sleep方式。
Program 2是PWM方式。
#----------------------------------------------------------------
# Program 1: StepMotor_TIME.py
from time import sleep
import RPi.GPIO as gpio
PUL = 11
DIR = 12
ENA = 13
CW = 1
CCW = 0
gpio.setmode(gpio.BOARD)
gpio.setup(PUL, gpio.OUT)
gpio.setup(DIR, gpio.OUT)
gpio.setup(ENA, gpio.OUT)
gpio.output(ENA, gpio.HIGH)
# Main body of code
try:
gpio.output(ENA, gpio.LOW)
while True:
sleep(2)
gpio.output(DIR, CW)
for x in range(51200):
gpio.output(PUL, gpio.LOW)
sleep(0.00001)
gpio.output(PUL, gpio.HIGH)
gpio.output(DIR,CCW)
except KeyboardInterrupt: # If there is a KeyboardInterrupt (when you press ctrl+c), exit the program and cleanup
print("Cleaning up!")
gpio.cleanup()
#Program 2: StepMotor_PWM.py
pwm = gpio.PWM(PUL, 100000)
bDir = False
pwm.start(50)
if bDir == True:
sleep(5)
else:
gpio.output(DIR, CCW)
bDir = True
# 程式1 : stepmotor _ time. Py
從時間進口睡眠
匯入rpi. Gpio作為gpio
泳池= 11
Dir = 12
Cw = 1
Ccw = 0
Gpio. 設定模式(gpio). 年十二月()
Gpio. 設定(pul, gpio). 出局
Gpio. 設定(你, gpio). 出局
Gpio. 設定(ena, gpio). 出局
Gpio. 輸出(ena, gpio). 高(高)
# 主要程式碼
嘗試:
Gpio. 輸出(ena, gpio). 低)
雖然事實:
睡眠(2)
Gpio. 輸出(dir, cw)
X在範圍(51200):
Gpio. 輸出(pul, gpio). 低)
睡眠(0.00001)
Gpio. 輸出(pul, gpio). 高(高)
Gpio. 輸出(dir, ccw)
除了鍵盤中斷如果有鍵盤中斷(當你按下ctrl+c), 退出程式並清理
列印("清理!")
Gpio. 清理()
# 項目2 : stepmotor _ pwm. Py
Pwm = gpio. Pwm (pul, 100000)
Bdir =假
Pwm. 開始(50)
如果bdir ==真的:
睡眠(5)
其他:
Bdir =真實
原文網址 石小川 2020-02-21 11:12:09
RPI.GPIO使用手册, 請參考下面網址:
# 中文
https://blog.csdn.net/qq_35893742/article/details/53428679
# 英文
https://sourceforge.net/p/raspberry-gpio-python/wiki/Inputs/
原文網址 石小川 2020-02-20 15:45:07
Windows 10 IoT Core作業系統下載 在樹莓派安裝Windows 10 IoT Core作業系統,也可跑C#、Python程式,對熟悉C#想開發IoT物聯網的朋友應該是一大福音。 安裝方法很簡單,官網有詳細介紹,在此就不在贅述,跟寫iPhone手機程式很像,不過似乎只支援到Pi3, Pi4尚未支援的樣子, 微軟積極想搶這塊大餅, 應該很快。 下面是官方下載網址: https://docs.microsoft.com/en-us/windows/iot-core/downloads
楊先民 2020-02-20 16:08:41
老師請問c# 的元件在這上也能跑嗎? 這樣做GUI就簡單了
Claude Hsu 2020-02-20 17:05:39
請問這作業系統裝在樹莓派要付費買嗎?謝謝
Wei-Hsiung Huang 2020-02-20 17:31:19
Why?
原文網址 石小川 2020-02-18 20:45:06
繼昨天貼文 ' Python 呼叫 DLL 的方法 '後, 但能夠做甚麼呢? 下面給出Source code實例是Python模組PyCNC程式庫,我將C++運動控制驅動程式封裝給Python呼叫的範例,控制動作很流暢, 因為程式長所以就節錄部份程式碼給對控制硬體有興趣的朋友參考一下。 圖1. Python + PyQt5控制機台程式 影片 2. Python控制機台程式執行實例 影片 3. 程式控制機台實例 影片 4. TCP/IP遠距通信監控機台程式執行實例 使用Python語言做開發平台的三大動機 [語法簡單明瞭] Python語法簡單易學,最重要的是還有大量功能強大的免費模組可下載,其強大的應用層面已經發展到令人不可忽視的重要地位,甚至NASA也拿來當作航太人機介面的控制語言。早期接的專案我都是用Assembly、C、C++、C#等設計自動控制系統,這幾年我很多是改用Python來撰寫,好處是取得系統傳回的資料後,可很容易且快速的結合各種海量模組演算法發展出很專業的人工智慧機器。 [Python是跨平台語言] Python本身沒有支援特定硬體控制的功能,也正因為如此它才能夠跨平台,但這不是原罪,相反的卻是它的優點,換句話說,在x86、Arm、Arduino、PC、手機或平板等不同的作業系統環境下,相同的程式皆可以很容易互相移植過去正常執行,這 print('免費資源 + 免費的模組 + 簡單易學') 根本是一場世界革命,能不紅嗎! 綜合以上講了一大堆,無非就是要說服工程師們是該改變自已接受世界脈動的時候了,我也不例外,以此共勉之! [軟體IC] 接下來進入主題談論如何用 Python 開發一個多軸的 CNC 平台,會舉這個 CNC 專題當作例子是因為在我眼裡,CNC 其實就是一個機器人,我的經驗是 - 只要搞懂 CNC 軟硬體知識後,無論是自駕車、四軸無人機或是工具機皆是囊中物,至於想要用它做些甚麼,端看你無限的想像力而定! 因為 Python 沒有直接存取硬體的介面,我的方法是用 Python 當作主程式,將底層存取硬體的 API 程式(動態連結程式庫 DLL)封裝成Python 可調用的格式即可,如此一來多年使用 C、C++、C# 寫的程式庫都可調用了。將來使用者只要將封裝的軟體看成是黑箱直接呼叫就對了,而不須知道內部的演算法,事實上 Python 模組就是軟體IC的概念。 # -*- coding: utf-8 -*- ''' 石小川 / Michael Shih 光騰高科技工作室 / Quantum Tek. ''' import ctypes import ctypes.wintypes #------------------------------------------------------------------------------ class __IMC_EventType(): IMC_Allways = 0 #"無條件執行" IMC_Edge_Zero = 1 #"邊沿型條件執行——變為0時" IMC_Edge_NotZero = 2 #"邊沿型條件執行——變為非0時" IMC_Edge_Great = 3 #"邊沿型條件執行——變為大於時" IMC_Edge_GreatEqu = 4 #"邊沿型條件執行——變為大於等於時" IMC_Edge_Little = 5 #"邊沿型條件執行——變為小於時" IMC_Edge_Carry = 6 #"邊沿型條件執行——變為溢出時" IMC_Edge_NotCarry = 7 #"邊沿型條件執行——變為無溢出時" IMC_IF_Zero = 8 #"電位型條件執行——若為0" IMC_IF_NotZero = 9 #"電位型條件執行——若為非0" IMC_IF_Great = 10 #"電位型條件執行——若大於" IMC_IF_GreatEqu = 11 #"電位型條件執行——若大於等於" IMC_IF_Little = 12 #"電位型條件執行——若小於" IMC_IF_Carry = 13 #"電位型條件執行——若溢出" IMC_IF_NotCarry = 14 #"電位型條件執行——若無溢出" IMC_EventType = __IMC_EventType() #------------------------------------------------------------------------------ #define WR_MUL_DES, *pWR_MUL_DES class __WR_MUL_DES(ctypes.Structure): _fields_ = [ ("addr", ctypes.c_int16), ("axis", ctypes.c_uint16), ("len", ctypes.c_uint16), ("data_0", ctypes.c_uint16), ("data_1", ctypes.c_int16), ("data_2", ctypes.c_int16), ("data_3", ctypes.c_int16) ] #------------------------------------------------------------------------------ class __EventInfo(ctypes.Structure): _fields_ = [ ("EventCMD", ctypes.c_short), ("EventType", ctypes.c_short), ("Src1_loc", ctypes.c_short), ("Src1_axis", ctypes.c_short), ("Src2_loc", ctypes.c_short), ("Src2_axis", ctypes.c_short), ("reserve1", ctypes.c_int), ("dest_loc", ctypes.c_short), ("dest_axis", ctypes.c_short), ("reserve2", ctypes.c_int) ] #------------------------------------------------------------------------------ def CharArrayToList(array, num): btext = False text = "" List = [] if(num == 0): return List for i in range(len(array)): if(text != ""): btext = True if(array[i] == b'\x00'): array[i] = b'\n' text += str(array[i].decode('utf-8')) if(i%255 == 0 and btext == True): text = text.strip() text = str(text) if(len(text) > 0): List.append(text) text = "" btext = False return List #------------------------------------------------------------------------------ class __IMC_Pkg(): def __init__(self): self.ptr = ctypes.WinDLL('IMC_Pkg.dll') #_stdcall #--------------------------------------------------------------------------- def FindNetCard(self): charArray = ctypes.c_char * 4096 #16 x 2156 = 4096 array = charArray() num = ctypes.c_int() #ptr = ctypes.WinDLL('IMC_Pkg.dll') #_stdcall self.ptr.PKG_IMC_FindNetCard.argtypes = (ctypes.POINTER(charArray), ctypes.POINTER (ctypes.c_int)) self.ptr.PKG_IMC_FindNetCard.restype = ctypes.c_int status = self.ptr.PKG_IMC_FindNetCard(ctypes.byref(array), ctypes.byref(num)) return status, CharArrayToList(array, num) #--------------------------------------------------------------------------- def Open(self, netcardId, imcId): self.ptr.PKG_IMC_Open.argtypes = (ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_Open.restype = ctypes.POINTER(ctypes.c_voidp) return self.ptr.PKG_IMC_Open(netcardId, imcId) #--------------------------------------------------------------------------- def OpenX(self, netcardId, imcId, timeout, openMode): self.ptr.PKG_IMC_OpenX.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_OpenX.restype = ctypes.POINTER(ctypes.c_voidp) return self.ptr.PKG_IMC_OpenX(netcardId, imcId) #--------------------------------------------------------------------------- def OpenUsePassword(self, netcardId, imcId, password): self.ptr.PKG_IMC_OpenUsePassword.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes. c_char_p)) self.ptr.PKG_IMC_OpenUsePassword.restype = ctypes.POINTER(ctypes.c_voidp) return self.ptr.PKG_IMC_OpenUsePassword(netcardId, imcId, password) #--------------------------------------------------------------------------- def Close(self, handle): self.ptr.PKG_IMC_Close.argtypes = (ctypes.POINTER(ctypes.c_voidp), ) #單獨也必須加上括弧 self.ptr.PKG_IMC_Close.restype = ctypes.c_int return self.ptr.PKG_IMC_Close(handle) #--------------------------------------------------------------------------- def InitCfg(self, handle): self.ptr.PKG_IMC_InitCfg.argtypes = (ctypes.POINTER(ctypes.c_voidp), ) #單獨也必須加上括弧 self.ptr.PKG_IMC_InitCfg.restype = ctypes.c_int return self.ptr.PKG_IMC_InitCfg(handle) #--------------------------------------------------------------------------- def ClearIMC(self, handle): self.ptr.PKG_IMC_ClearIMC.argtypes = (ctypes.POINTER(ctypes.c_voidp), ) #單獨也必須加上括弧 self.ptr.PKG_IMC_ClearIMC.restype = ctypes.c_int return self.ptr.PKG_IMC_ClearIMC(handle) #--------------------------------------------------------------------------- def ClearAxis(self, handle, axis): self.ptr.PKG_IMC_ClearAxis.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int) self.ptr.PKG_IMC_ClearAxis.restype = ctypes.c_int return self.ptr.PKG_IMC_ClearAxis(handle, axis) #--------------------------------------------------------------------------- def SetPulWidth(self, handle, ns, axis): self.ptr.PKG_IMC_SetPulWidth.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_uint, ctypes.c_int) self.ptr.PKG_IMC_SetPulWidth.restype = ctypes.c_int return self.ptr.PKG_IMC_SetPulWidth(handle, ns, axis) #--------------------------------------------------------------------------- def SetPulPolar(self, handle, pul, dir, axis): self.ptr.PKG_IMC_SetPulPolar.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_SetPulPolar.restype = ctypes.c_int return self.ptr.PKG_IMC_SetPulPolar(handle, pul, dir, axis) #--------------------------------------------------------------------------- def SetEncpEna(self, handle, ena, axis): self.ptr.PKG_IMC_SetEncpEna.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_SetEncpEna.restype = ctypes.c_int return self.ptr.PKG_IMC_SetEncpEna(handle, ena, axis) #--------------------------------------------------------------------------- def SetEncpMode(self, handle, mode, dir, axis): self.ptr.PKG_IMC_SetEncpModer.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_SetEncpModer.restype = ctypes.c_int return self.ptr.PKG_IMC_SetEncpModer(handle, mode, dir, axis) #--------------------------------------------------------------------------- def SetEncpRate(self, handle, rate, axis): self.ptr.PKG_IMC_SetEncpRate.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_double, ctypes.c_int) self.ptr.PKG_IMC_SetEncpRate.restype = ctypes.c_int return self.ptr.PKG_IMC_SetEncpRate(handle, rate, axis) #--------------------------------------------------------------------------- def SetVelAccLim(self, handle, vellim, acclim, axis): self.ptr.PKG_IMC_SetVelAccLim.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_double, ctypes.c_double, ctypes.c_int) self.ptr.PKG_IMC_SetVelAccLim.restype = ctypes.c_int return self.ptr.PKG_IMC_SetVelAccLim(handle, vellim, acclim, axis) #--------------------------------------------------------------------------- def SetEna(self, handle, ena, axis): self.ptr.PKG_IMC_SetEna.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_SetEna.restype = ctypes.c_int return self.ptr.PKG_IMC_SetEna(handle, ena, axis) #--------------------------------------------------------------------------- def Setlimit(self, handle, plimEna, plimPolar, nlimEna, nlimPolar, axis): self.ptr.ptr.PKG_IMC_Setlimit.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int) self.ptr.ptr.PKG_IMC_Setlimit.restype = ctypes.c_int return self.ptr.PKG_IMC_Setlimit(handle, plimEna, plimPolar, nlimEna, nlimPolar, axis) #--------------------------------------------------------------------------- def SetAlm(self, handle, ena, polar, axis): self.ptr.ptr.PKG_IMC_SetAlm.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_int, ctypes.c_int) self.ptr.ptr.PKG_IMC_SetAlm.restype = ctypes.c_int return self.ptr.PKG_IMC_SetAlm(handle, ena, polar, axis) #--------------------------------------------------------------------------- def SetINP(self, handle, ena, polar, axis): self.ptr.ptr.PKG_IMC_SetINP.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_int, ctypes.c_int) self.ptr.ptr.PKG_IMC_SetINP.restype = ctypes.c_int return self.ptr.PKG_IMC_SetINP(handle, ena, polar, axis) #--------------------------------------------------------------------------- def SetEmstopPolar(self, handle, polar, axis): self.ptr.PKG_IMC_SetEmstopPolar.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_SetEmstopPolar.restype = ctypes.c_int return self.ptr.PKG_IMC_SetEmstopPolar(handle, polar, axis) #--------------------------------------------------------------------------- def SetInPolar(self, handle, polar, inPort): self.ptr.PKG_IMC_SetInPolar.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_SetInPolar.restype = ctypes.c_int return self.ptr.PKG_IMC_SetInPolar(handle, polar, inPort) #--------------------------------------------------------------------------- def SetStopfilt(self, handle, stop, axis): self.ptr.PKG_IMC_SetStopfilt.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_SetStopfilt.restype = ctypes.c_int return self.ptr.PKG_IMC_SetStopfilt(handle, stop, axis) #--------------------------------------------------------------------------- def SetExitfilt(self, handle, exit, axis): self.ptr.PKG_IMC_SetExitfilt.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_SetExitfilt.restype = ctypes.c_int return self.ptr.PKG_IMC_SetExitfilt(handle, exit, axis) #--------------------------------------------------------------------------- def SetRecoupRange(self, handle, range, axis): self.ptr.PKG_IMC_SetRecoupRange.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_SetRecoupRange.restype = ctypes.c_int return self.ptr.PKG_IMC_SetRecoupRange(handle, range, axis) #--------------------------------------------------------------------------- #--------------------------------------------------------------------------- def MoveAbs(self, handle, pos, startvel, tgvel, wait, axis): self.ptr.PKG_IMC_MoveAbs.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_double, ctypes.c_double, ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_MoveAbs.restype = ctypes.c_int return self.ptr.PKG_IMC_MoveAbs(handle, pos, startvel, tgvel, wait, axis) #--------------------------------------------------------------------------- def MoveAbs_P(self, handle, pos, startvel, tgvel, wait, axis): #P 輔助座標 self.ptr.PKG_IMC_MoveAbs_P.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_double, ctypes.c_double, ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_MoveAbs_P.restype = ctypes.c_int return self.ptr.PKG_IMC_MoveAbs_P(handle, pos, startvel, tgvel, wait, axis) #--------------------------------------------------------------------------- def MoveDist(self, handle, dist, startvel, tgvel, wait, axis): self.ptr.PKG_IMC_MoveDist.argtypes = (ctypes.POINTER(ctypes.c_voidp), ctypes.c_int, ctypes.c_double, ctypes.c_double, ctypes.c_int, ctypes.c_int) self.ptr.PKG_IMC_MoveDist.restype = ctypes.c_int return self.ptr.PKG_IMC_MoveDist(handle, dist, startvel, tgvel, wait, axis)
Wilson Kao 2020-02-26 15:59:35
有人有紡織業瑕疵檢測紡織的經驗嗎? 謝謝
原文網址 石小川 2020-02-17 10:59:39
使用Python開發自動控制或為了提高Python程式效率,我們經常要呼叫C++的動態連結程式庫(DLL),下面是如何調用DLL範例,提供給有需要的朋友參考。 1. 3 Python 呼叫 DLL 的方法 Python 與 C/C++ 程式互相溝通最簡單的方式就是使用 Python的ctypes模組,下面我會舉一些簡單的範例讓讀者熟悉Python與DLL呼 叫的各種規則,這樣以後封裝驅動程式給 Python 調用就不再是難題了。 1. 3. 1 [範例 1] 整數參數 int Int Add (int x, int y) //------------------------------------------------- //示範 C++ 產生 DLL (用 _stdcall 方式編譯) //函數 : int IntAdd(int , int) //輸入類型 : (int, int) //返回類型 : int //------------------------------------------------- //Header 檔案 ex1.h //------------------------------------------------- #define DLL_API extern "C" __declspec(dllexport) //------------------------------------------------- //CPP 檔案 ex1.cpp //------------------------------------------------- #include ex1.h DLL_API int __stdcall IntAdd(int a, int b) { return a + b; } #-------------------------------------------------- #示範 Python 調用DLL 函數 int IntAdd(int , int) #-------------------------------------------------- #檔案名稱 : ex1.py #-------------------------------------------------- from ctypes import * ptr = ctypes.WinDLL('ex1.dll') #__stdcall 編譯須用WinDLL #屬性賦值 **ptr.IntAdd.argtypes = (ctypes.c_int, ctypes.c_int) ** #宣告屬性為整數輸入類型 **ptr.IntAdd.restype = ctypes.c_int ** #宣告屬性為整數返回類型 c = ptr.IntAdd(3, 6) print(c) 因為Python ctypes 系統輸入、返回類型預設是int, 所以上面argtypes 、restype 宣告是可省略的,但為了跟下面非整數類型對照還是加上,不影響結果。 需要特別注意的是Python在調用DLL函數時,如果DLL編譯時是_cdecl格式,則調用函數必須用 ctypes.CDLL('dll') 或 ctypes.cdll.LoadLibrary('dll'),而 _stdcall格式,則調用函數必須用ctypes.WinDLL('dll') 或 ctypes.windll.LoadLibrary('dll') 1. 3. 2 [範例 2] 浮點參數 float Float Add (float x, float y) //------------------------------------------------- // 示範 C++ 產生 DLL (用 _stdcall 方式編譯) //函數 : float Float Add (float x, float y) //輸入類型 : (float, float) //返回類型 : float //------------------------------------------------- //Header 檔案 ex2.h //------------------------------------------------- #define DLL_API extern "C" __declspec(dllexport) //------------------------------------------------- //CPP 檔案 ex2.cpp //------------------------------------------------- #include ex2.h DLL_API float __stdcall FloatAdd(float a, float b) { return a + b; } #-------------------------------------------------- #示範 Python 調用DLL 函數 float FloatAdd(float , float) #-------------------------------------------------- #檔案名稱 : ex2.py #-------------------------------------------------- from ctypes import * ptr = WinDLL('ex2.dll') **ptr.FloatAdd.argtypes = (ctypes.c_float, ctypes.c_float) ** #宣告屬性為浮點輸入類型 **ptr.FloatAdd.restype = ctypes.c_float ** #宣告屬性為浮點返回類型 c = ptr.IntAdd(3.14, 1.2) print(c) 因為 DLL 輸入類型 : (float, float)、返回類型 : float 都是 float, 所以argtypes 及 restype 也必須填上相對應的c_float類型 1. 3. 3 [範例 3] 整數指標參數 int Int Pointer (int *num) //------------------------------------------------- // 示範 C++ 產生 DLL (用 _stdcall 方式編譯) //函數 : int Int Pointer(int *num) //輸入類型 : (int *) //返回類型 : int //------------------------------------------------- //Header 檔案 ex3.h //------------------------------------------------- #define DLL_API extern "C" __declspec(dllexport) //------------------------------------------------- //CPP 檔案 ex3.cpp //------------------------------------------------- #include ex3.h DLL_API int __stdcall IntPointer(int *num) { int value = *num; return value; } #-------------------------------------------------- #示範 Python 調用DLL 函數 int IntPointer(int *) #-------------------------------------------------- #檔案名稱 : ex3.py #-------------------------------------------------- from ctypes import * ptr = WinDLL('ex3.dll') **ptr.IntPointer.argtypes = (ctypes.c_voidp, ) ** #宣告屬性為指標輸入類型 **ptr.IntPointer.restype = ctypes.c_int ** #宣告屬性為整數返回類型 num = ctypes.c_int(12) c = ptr. IntPointer ( ctypes.byref (num)) #byref () 相當於 C的(&num)傳址 print(c) 指標稍微複雜些,注意一下argtypes,及byref()傳址的寫法,這些規則用久了自然會熟練,隨時翻閱就好不需要強記。 1. 3. 4 [範例 4] 位元組指標參數 **void **BytePointer(char *) //------------------------------------------------- // 示範 C++ 產生 DLL (用 _stdcall 方式編譯) //函數 : **void **BytePointer(char *) //輸入類型 : (char *) //輸出類型 : (char *) //返回類型 : None //------------------------------------------------- //Header 檔案 ex4.h #define DLL_API extern "C" __declspec(dllexport) //------------------------------------------------- //CPP 檔案 ex4.cpp //------------------------------------------------- #include ex4.h DLL_API void __stdcall BytePointer(char *pw) { pw[0] = '0'; pw[1] = '1'; pw[2] = '2'; pw[3] = '3'; } #-------------------------------------------------- #示範 Python 調用DLL 函數 int BytePointer(char *) #-------------------------------------------------- #檔案名稱 : ex4.py #-------------------------------------------------- from ctypes import * ptr = WinDLL('ex4.dll') charArray = c_char * 4 #宣告一個 charArray類型 array = charArray() #產生一個4位元組的陣列 array[4] **ptr.BytePointer.argtypes = (POINTER(charArray), ) ** #宣告屬性為輸入類型 ,只有一個輸入參數時須加上逗號 **ptr.BytePointer.restype = None ** #宣告屬性為返回類型 **ptr.BytePointer(byref(array)) ** #byref () 等效於 C的(&array)傳址 for i in array: # print(i) 執行結果 runfile('e4.py') b'0' b'1' b'2' b'3' 1. 3. 5 [範例 5] 結構參數 char * Get StructPointer(StructPointer *pStruct) //------------------------------------------------- // 示範 C++ 產生 DLL (用 _stdcall 方式編譯) //函數 : char * Get StructPointer(StructPointer *pStruct) //輸入類型 : (StructPointer *) //輸出類型 : (StructPointer *) //返回類型 : char * //------------------------------------------------- //Header 檔案 ex5.h //------------------------------------------------- #define DLL_API extern "C" __declspec(dllexport) #define LENGTH 10 struct StructPointer { char cArray[LENGTH]; int iArray[LENGTH]; }; //------------------------------------------------- //CPP 檔案 ex5.cpp //------------------------------------------------- #include ex5.h DLL_API char * __stdcall GetStructPointer(StructPointer *pStruct) { for (int i = 0; i < LENGTH; i++) { pStruct->cArray[i] = i + 40; pStruct->iArray[i] = i; } return "OK"; } #-------------------------------------------------- #示範 Python 調用DLL 函數 char * GetStructPointer(char *) #-------------------------------------------------- #檔案名稱 : ex5.py #-------------------------------------------------- from ctypes import * charArray10 = c_char * 10 intArray10 = c_int * 10 #ctypes Structure 與 c struct class __structInfo(Structure): fields = [ ("cArray", charArray10), ("iArray", intArray10) ] ptr = WinDLL("ex5.dll") ptr.GetStructPointer.argtypes = (POINTER(__structInfo), ) #宣告屬性 為結構指標輸出入類型,只有一個參數時須加上逗號 ptr.GetStructPointer.restype = c_char_p #宣告屬性為字串返回類型 structInfo = __structInfo() text = ptr.GetStructPointer(byref(structInfo)) #byref () 等效於 C的 (&structInfo)傳址 print(text) print(" ") s = "" for i in structInfo.cArray: s += chr(i) + ' ' print(s) print(" ") s = "" for i in structInfo.iArray: s += str(i) + ' ' print(s) 執行結果 runfile('e5.py') b'OK' A A B A B C A B C D A B C D E A B C D E F A B C D E F G A B C D E F G H A B C D E F G H I A B C D E F G H I J 0 1 2 3 4 5 6 7 8 9 比對一下表 **1. 3. 5 **,可以很清楚地明白他們的對應關係,注意class __structInfo(Structure): 的類別必須是繼承Structure,其中 _fields_是欄位關鍵字,中括號內[ ( , ), ( , ) ]就是封裝C結構變數的地方,小括號的格式(左邊 C++ struct 變數, 右邊 ctypes Structure 變數 )。 表 **1. 3. 5 **C++ struct 與 ctypes Structure對照表 //C++ struct --------------------------------------------- struct StructPointer { char cArray[LENGTH]; int iArray[LENGTH]; }; #ctypes Structure--------------------------------------- charArray10 = c_char * 10 intArray10 = c_int * 10 class __structInfo(Structure): fields = [ ("cArray", charArray10), ("iArray", intArray10) ] 1. 4 再論Python ctypes模組 表格1-1是ctypes type與 C type 和 Python type 互相對應的類型,讀者可參考圖1-7 的方式用 IDLE ( Python Shell )輸入,自行練習一下ctypes類型的使用方式,加深讀者對ctypes的瞭解程度。 對於ctypes 模組有興趣的讀者可連上官網查閱。 https://docs.python.org/2/library/ctypes.html 圖1-7 ctypes類型使用方式 ? 表格1-1 ?
原文網址 石小川 2020-02-16 00:47:45
實現遠距工程的第一步,這是時代的趨勢! Python語言做自動控制 – 講義 使用Python語言做自動控制的方法 - I I I通信篇
原文網址 石小川 2020-02-15 12:40:11
光騰二月份遠距教學 'TCP/IP通信程式實作班' 持續招生中...........,隨時歡迎報名! 課程: 實作C#、Python遠端監控機台和即時影像傳輸程式 課程內容: *TCP/IP通訊協定基本知識 *Socket常用函式介紹 *主從式系統程式分析 *剖析網路聊天室程式 *剖析遠端監控和即時影像傳輸程式 *實作C#、Python主從式軸控遠端機台程式 *程式最佳化須注意的事項 學習目標---------------------------------- 由淺入深熟悉(A)、(B)、(C)三套程式碼通信信號交握原理。 (A) C#主從式聊天室程式 (B) C#主從式遠端監控和即時影像傳輸程式 (C) C#、Python主從式軸控遠端機台 學員可自行修改或設計網路監控通信程式,集中管理遠端機器或影像、資料的回傳,更進一步,也可將資料輸入Python模組做影像或深度學習分析後回饋機器(下一季課程),達到精簡人力,效能提升的智慧型機器。 此次開課採用遠距指導教學,實作還是以師徒方式比較有效率,使用messenger or line 個別指導學員學習,後期就以學員建立的程式溝通測試, 每一梯次是一個月,目的是想引導有C#、Python基礎的朋友進入自動控制有趣的領域,學習後學員可自行用C#、Python設計TCP/IP遠距監控通信應用程式。 日期: 2020/2/19(星期三) 註1 . 確定要來上課的朋友請在此留言報名(A+),會用messenger主動聯絡您匯款,金額酌收NT$3500,並傳Quantum講義及程式給您。 註2. 對上一梯次課程: Python軸控有興趣的朋友也可在此留言(B+),讓我統計一下上課人數。 Python人工智慧圖控 - 研習交流廳 : https://www.facebook.com/groups/523498395047153/ ? ? ?
原文網址 石小川 2020-02-14 08:43:41
使用Python語言做自動控制的方法 - I I I通信篇 網路發達後要做到機器設備遠端監控已非遙不可及了,網路通信在無人工廠的監控設備上會越來越重要。 圖中展示的系統是TCP/IP通訊協定的主從(Server-Client)式架構,TServer伺服端程式負責現場機器設備運作及回傳Sensor數據和即時影像給TClient用戶端處理。 為了方便教學緣故,已將網路封包加密演算法及帳號管理拿掉,通信程式精簡許多,比較容易理解,伺服端是以C#實作,用戶端會以C#及Python各實作一個版本。建議伺服端以C++或C#為主,而用戶端可用Python設計遠端控制APP,將來回傳的遙測大數據可很容易的用Python模組分析。 熟悉遠端操控軟硬體對將來有志設計無人工廠機器設備的朋友幫助很大,習得一技之長絕對增加競爭力。2月分我將開此TCP/IP主從式通信實作課程,因為現在病毒肆虐,採遠距教學方式較適合,沒有機器設備的同學我會提供兩台三軸機台做遠距連線操控練習,可在家寫Python程式做遠端連線操控,詳細辦法及日期我再擇期公布,歡迎有興趣的朋友來報名上課。 第五章 實作C#、Python軸控遠端機台 Python很適合做數據擷取及分析,有幾萬個套件模組讓你發揮,全世界的網路根本就是一個取之不竭,用之不盡的海量資料庫。Python 只要引入模組,要寫個爬蟲程式沒幾行代碼,就可抓你關注的網頁資料做數據分析,真的只是小菜一碟而已,這是筆者會喜歡它的原因之一 。 Python既然在人工智慧、深度學習領域都有它的蹤跡,那麼自動控制的機台也必定不會缺席的,自動化工廠的機器設備和感測器交握信號彙整起來可能有上萬種數據需要及時處理並回傳,此時Python會是一個不錯的選擇。 本章通訊系統中的伺服端仍然採用第四章的C#版本 : TServer,用戶端則是Python版本 : PyClient,理由無他,伺服端需要具備同時快速處理許多用戶及機器設備,負擔較重,建議伺服端實作還是以C++或C#為主,處理速度會快很多。 Python標準庫支援的TCP/IP稍微陽春些,筆者這裡是採用PyQt5 QtNetwork通訊模組,函式庫支援豐富,因已封裝底層API,通訊程式也比較好寫,故推薦用此方式,學習道路可少走一些遠路。 伺服端程式命名為 :TServer(C#),用戶端程式命名 : PyClient(Python)。 TServer 第四章已介紹過,在此略過, 請讀者再複習一下內文。 下列程式碼是Python版本用戶端TCP/IP通訊模組部分原始碼,有興趣的朋友歡迎報名參加遠距指導教學課程(開課日期 : 2020/02/19, 下星期三)。 # -*- coding: utf-8 -*- ''' 石小川 / Michael Shih 光騰高科技工作室 / Quantum Tek. ''' import time #OpenCV模組 import cv2 from PyQt5.QtNetwork import QTcpSocket, QHostAddress, QAbstractSocket, QNetworkInterface,\ QNetworkAddressEntry, QHostInfo,QNetworkConfiguration,\ QNetworkConfigurationManager from PyQt5.QtCore import QObject, pyqtSignal from PyQt5.QtCore import Qt, QByteArray, QDataStream, QIODevice from TStream import TStream #------------------------------------------------------------------------------ #Client通信處裡類別 #------------------------------------------------------------------------------ class TcpClient(QTcpSocket): #signal define def __init__(self, parent=None): super(TcpClient, self).__init__(parent) self.__serverIP = QHostAddress() self.__serverPort = 8000 #int self.__userName = "" self.__clientSocket = None self.__pImage = None self.__chunkMode = False #切換接收mode是 command 或 chunkBytes self.__chunkCount = 0 self.__chunkLength = 0 self.__chunkBytes = QByteArray() self.__Dro = [] #------------------------------------------------------------------------ def Open(self, ip, port, userName): if not self.__serverIP.setAddress(ip): return False self.__serverPort = port self.__userName = userName if(self.__userName == ''): return False self.__clientSocket = QTcpSocket(self) self.__clientSocket.abort(); self.__clientSocket.connected.connect(self.Connected) self.__clientSocket.disconnected.connect(self.Disconnected) self.__clientSocket.readyRead.connect(self.dataReceived) self.__clientSocket.connectToHost(self.__serverIP, self.__serverPort) self.SendCommand_Connect(self.__userName) #------------------------------------------------------------------------ def Close(self): try: self.SendCommand_Disconnect(self.__userName) self.__clientSocket.disconnectFromHost() except Exception as e: print(e) #------------------------------------------------------------------------ def ListenServer(self, byteArray): stream = TStream() #byteArray Data structure : command(4) + datalength(4) + data(dataLength) if(self.__chunkMode == False): command = stream.GetPackCommand(byteArray) bData = stream.GetPackBytes(byteArray) #bData是純資料存 , 扣掉command(4)和扣掉datalength(4) length = len(bData) #接收到資料的長度 if(command == 9999): #新用戶者上線通知 data = stream.BytesToString(bData) #not used self.SendCommand_JogMode(0) elif(command == 1): #user要求對所有 Client廣播 data = stream.BytesToString(bData) #not used elif(command == 2): #//user 私密Client data = stream.BytesToString(bData) #not used elif(command == 3): #//image 需分多次接收 self.__chunkMode = True #接下來開始接收大塊資料 (>65536 都是大塊資料) self.__chunkCount = 0 self.__chunkBytes.clear() self.__isImage = False; nCols, nRows, nChannels = stream.ImageSize(bData) #一張影像大小 4(nCols) + 4(nRows) + 4(nChannels) + 320x 240 x3 = 230412 #減去已接收到的資料 (65536-4 = 65528) self.__chunkLength = nCols*nRows*nChannels + 12 self.__chunkCount = length self.__chunkBytes.append(bData) elif(command == 4): #//接收Server送來三軸位置資料 data = stream.BytesToString(bData) codes = data.split('|') #print (codes) self.__Dro.clear() for code in codes: #字串轉浮點 self.__Dro.append(float(code)) else: #chunkMode length = len(byteArray) self.__chunkCount += length self.__chunkBytes.append(byteArray) if(self.__chunkCount >= self.__chunkLength): self.__pImage = stream.ByteArrayToMat(self.__chunkBytes) self.SendCommand_Position(self.__userName) self.__chunkMode = False #切換回command模式
王登程 2020-02-14 20:16:43
如果待加工料可以自动化输送到加工台,那技术上真的可以远程加工了。
原文網址 石小川 2020-02-07 18:23:33
版主推薦!
裡面有很多自動控制的寶貝可挖寶,新的、二手都有,老闆號稱是我的徒弟,我的教材很多是他友情贊助, 歡迎朋友淘寶去^^
討論主題
發文排行榜
回文排行榜
熱門關鍵字