科技N次方
說一點我個人在電氣自動化行業中對於編程語言的一些認識吧!
個人的工作經驗中需要用到編程語言的就是PLC程序的編程和上位機軟件的編程,因此就說一下關於這2方面編程過程中需要哪些高級語言!
1,做PLC程序的話,在使用結構化文本(ST或者SCL)編程時候需要用到一些C語言的知識!
最常用的就是IF THEN , IF ELSE這種!在西門子的編程軟件中就叫做SCL編程,如下圖就是在博圖軟件中建立一個塊的時候,就可以選擇對這個塊的編程語言是什麼!
還需要說一點的是西門子PLC中還有一種STL(語句表)的編程語言,它比梯形圖語言要難理解一點,但是又沒有C語言的指令語法,是一種特殊的編程語言,但是應用也是很廣泛的,看一下其程序的語句如下:
STL語句表編程語言,算不上高級語言,但也是比較特殊的語言,依然是有必要學習的!
2,做上位機監控軟件的組態編程的時候,通常要用到一些VB或者C語言的知識!
下圖就是西門子Wincc上位機軟件中支持的2種腳本,一種是C腳本,一種是VBS腳本!
其實,不單單是在上位機軟件中,在一些觸摸屏的組態軟件中也同樣存在類似於C或者VB的宏指令。
因此C語言和VB語言,可以說是應用最多的兩種編程語言了,不管是PLC編程能用到,還是組態軟件中也可以用到。甚至,這些年比較流行的labview軟件,它裡邊的一些指令依然和C語言這些有理解上的相似性!--
也就是說C和VB,應該說還是計算機應用中最重要且應用廣泛的兩種語言,我們做電氣自動化,其實也是在計算機平臺上,因此還是很有必要學一學這兩門語言!就說這麼多了,希望能對你有點幫助,感謝閱讀,謝謝!
控制研究控
電氣自動化需要哪些高級語言?
市面上高級語言挺多,好用的也挺多。
工業自動化裡常見到的有VB,C++,C#等等。
需要哪些?一般一個公司要求並不多,熟悉一種就好。
具體可以根據自己身情況選擇。
為什麼需要學習高級語言?
我也是從事工業自動化.
自動化控制更多的是編寫PLC程序,觸摸屏程序。
但隨著工業4.0,智能化的需求,
會一門電腦高級語言編程,真的是太迫切。
比如,你只會PLC編程。
那麼你學習西門子產品時,一些腳本程序你就不會編寫。
那麼硬件通訊程序也會編寫不順,
那麼觸摸屏裡類似C語言的宏指令也用不好。
如我剛完結的威綸觸摸屏宏指令教程,你看教程都覺得吃力。
這些都是跟PLC關係比較密切的。
還有其他的就更不用說了。
比如運行卡,圖像採集卡,數據採集卡等等這些應用於工控機上的工業產品。
視覺開發,深度學習這些更多深層次的應用也只有觀看的份了。
所以真的需要學習一門高級語言。
這也是也什麼平臺相似的問題非常多。
因為廣大一線的自動化同行,都已經意識到了或是有了迫切的需求。
更何況現在AI,大數據這麼流行。
緊跟潮流,玩玩開源庫也是很享受的一件事。
選擇哪種語言學習?
這個應該是剛接觸想學習高級語言編程的朋友最為棘手的問題了。
平臺一提問,答案也是五花八門。
網友的回答也是對自己經歷的總結。
熟悉哪門語言,常用哪門語言,就建議學哪門語言。
我也是眾多網友中的一個,也來談談選哪種語言好。
答案是:
選C++語言,框架選擇MFC。
回答過相似問題好多,原因也總結了很多,
總的原因是自動化行業追求程序執行效率,各廠家硬件兼容性。
不追求界面,不追求跨平臺。生產效率高就好。
另外MFC學習相對還是挺煩人的,
C#也是非常好的選擇,更簡單,更好學。
唯一麻煩的是要顧忌工業上眾多MFC程序。
工控編程
基礎的,你得會梯形圖語言,然後是語句表,有些上位機組態是用的VB,機械手有些用的python,C語言也是要的。
自動化工控小劉
高級語言,個人認為這個說法並不完全正確,有電路設計方面的知識,運用常用的語言工具實現這種需求而已。
電氣這方面,從編程語言來看,FBD編程可以學一波,要對數字電子技術理論基礎及實操掌握紮實,LAD編程,STL語言都可以掌握,微機原理與彙編語言這門課一定要學好,這樣方能熟練操作STL裡面的累加器,寄存器等。
祝好(✪▽✪)•笑生
笑生看世界
C#,在工控上位機領域也算是全能型的比較簡單的高級語言,Labview侷限於測量設備,C++太難,JAVA不太適合建桌面應用程序,C#正好
Debugging
你這裡問的高級語言,不知道你說的是哪一些?C#,Java或者其他的?VB又算是什麼?
既然你的範疇在電氣自動化領域,又問這樣的問題,姑且當提問的是一個大學生,剛接觸到這一方面而又對未來不是很明確吧。
正常工控領域使用最多的就是LAD,也就是梯形圖。但是除了LAD之外,好多老外喜歡用FBD(功能塊圖),以前SIEMENS處理多個數據的時候有的時候使用STL(語句表),但是自從博圖平臺後,SCL(結構化文本語言)使用的比較多。當然有的順序結構使用Graph(順序功能圖)。
1,SIEMENS 博圖平臺SCL範例。
下面的語句,輸入一個字符串,在這個字符串裡面尋找測量的數值。是為Ateq洩露測試儀用的。測試一個,會輸出一個字符串,這個字符串裡面有一個或者兩個real,採集裡面的數值。
注意這個數值有可能是負數。
IF #iEnable THEN
IF #ioClear THEN
#tString := '';
FOR #Index := 0 TO 255 BY 1 DO
#oBool[#Index] := 0;
#oReal[#Index] := 0;
#IndexReal[#Index] := 0;
END_FOR;
#ioStart := 0;
#ioClear := 0;
ELSE
IF #ioStart THEN
FOR #Index := 0 TO 255 BY 1 DO
#IndexReal[#Index] := DINT_TO_REAL(IN := BYTE_TO_DINT(IN := #tAtString[#Index] - 16#30));
#oBool[#Index] := 0;
#oReal[#Index] := 0;
END_FOR;
#IndexPointPosition := 0;
FOR #Index := 0 TO 255 BY 1 DO
IF #tAtString[#Index] = '.' THEN
//尋找所有有'.'號的位置
FOR #i := -3 TO 3 BY 1 DO
IF #IndexReal[#Index + #i] >= 0.0 AND #IndexReal[#Index + #i] <= 9.0 THEN
CASE #i OF
-3:
#oReal[#IndexPointPosition] := #oReal[#IndexPointPosition] + #IndexReal[#Index + #i] * 100.0;
-2:
#oReal[#IndexPointPosition] := #oReal[#IndexPointPosition] + #IndexReal[#Index + #i] * 10.0;
-1:
#oReal[#IndexPointPosition] := #oReal[#IndexPointPosition] + #IndexReal[#Index + #i] * 1.0;
1:
#oReal[#IndexPointPosition] := #oReal[#IndexPointPosition] + #IndexReal[#Index + #i] / 10.0;
2:
#oReal[#IndexPointPosition] := #oReal[#IndexPointPosition] + #IndexReal[#Index + #i] / 100.0;
3:
#oReal[#IndexPointPosition] := #oReal[#IndexPointPosition] + #IndexReal[#Index + #i] / 1000.0;
END_CASE;
END_IF;
END_FOR;
//尋找所有有'-'號的位置
FOR #i := -3 TO 3 BY 1 DO
IF #tAtString[#Index + #i] = '-' THEN
#oReal[#IndexPointPosition] := #oReal[#IndexPointPosition] * -1;
END_IF;
END_FOR;
#oBool[#IndexPointPosition] := 1;
#IndexPointPosition := #IndexPointPosition + 1;
END_IF;
END_FOR;
#ioStart := 0;
END_IF;
END_IF;
ELSE
#ioStart := 0;
END_IF;
這個小程序是一個FB塊,非優化。使用AT指令。
原理就是先在字符串裡面尋找‘.’號,然後再在該點號左側和右側尋找數字,然後在在這裡面尋找‘-’負號。
2,EPSON四軸機械手
EPSON四軸機械手,用到的是從托盤裡面取產品,這裡只粘貼了一部分程序。
Function pick
Pallet 1, P10, P11, P12, P13, 3, 4 '定義托盤1(取料盤)
'Out oPositionID, 0 'Wait
BB: If i = 13 Then
Print "請確認料盒已經清零"
GoTo BB
Else
Print i
GoTo CC
EndIf
CC: Jump Pallet(1, i) +X(x1) +Y(y1) +U(u1) :Z(0)
'到達掃碼位置信號
Out oPositionID, 2 'oScanPos
'等待夾爪打開
Wait Sw(561) = On 'iClampOff
DD: Print "請給去取料或者下一個掃碼位置信號"
'等待去取料信號
If Sw(546) = On Then 'iGoPickPos
GoTo FF
ElseIf Sw(550) = On Then 'iGoNextScanPos
GoTo EE
Else
GoTo DD
EndIf
EE: i = i + 1 '料盤計數 +1
'Out oPositionID, 0 'Wait
Wait Sw(550) = Off
GoTo BB
'Wait Sw(546) = On 'iGoPickPos
'Call NUM;
FF: If i = 10 Or i = 11 Or i = 12 Then
bRotateU = True
bRotateU2 = False
Jump Pallet(1, i) +U(intRotateU)
ElseIf i = 2 Then
bRotateU = False
bRotateU2 = True
Jump Pallet(1, i) +U(intRotateU2)
Else
bRotateU = False
bRotateU2 = False
Jump Pallet(1, i)
EndIf
'到達取料點信號
Out oPositionID, 3 'oPickPos
'夾緊產品
Wait Sw(560) = On 'iClampOn
i = i + 1 '料盤計數 +1
Go Here :Z(0) 'Z-Axis back Zero
Jump hompos
Out oPositionID, 1 'oHomePos
' '等待放料信號
'BB: If Sw(547) = On Then 'iGoPutPos_Nissan
' Call put_VW
' ElseIf Sw(548) = On Then 'iGoPutPos_VW
' Call put_Nissan
' ElseIf Sw(549) = On Then 'iGoNGPos
' Call NGput
' Else
' Print "取料後放料點選擇(放料1、2和NG放料)"
' GoTo BB
' EndIf
'If i = 12 Then i = 1
Fend
這裡面的作用是先到Cognex相機掃碼位置,PLC觸發掃碼。如果有二維碼,PLC告訴EPSON取產品,沒有二維碼,EPSON繼續到掃碼下一個位置。
取料的托盤是3x4結構。由於取料的產品比較深,夾爪是3個腿。第1行2列位置要旋轉35°。最後1列要旋轉120°,避免夾爪碰到托盤外邊。
3,SIEMENS SIMOTION D410 跟PC TCP/IP信號交互
D410打開TCP/IP端口,並且等待PC段建立連接。如果連接了,發送數據
發送和接收的緩存取都是1024個Byte
PROGRAM PB_Communication
//Program Variables
VAR
i : DINT;
intReveiveTimes : INT;
bytesReceiveFromIPC : ARRAY[0..1023] OF BYTE;
dintNext : DINT;
TOF_Send : TOF;
myRetCloseConnection : DINT;
myRetCloseServer : DINT;
myRetTCPSend : DINT;
FT_Connected : F_TRIG;
END_VAR
FT_Connected(g_Connected);
IF FT_Connected.q THEN
myRetCloseConnection :=_tcpCloseConnection(connectionId :=OpenSvr.connectionId );
myRetCloseServer :=_tcpCloseServer(port :=2001 );
OpenSvr.functionResult:=16#EEEEEEEE;
END_IF;
// Try and Check IPC Connection
IF NOT g_Connected THEN
OpenSvr :=
_tcpOpenServer(
port := 2001
,backlog := 2
,nextCommand := IMMEDIATELY
);
IF OpenSvr.functionResult=0 THEN
g_Connected:=TRUE;
g_SendData:=TRUE;
END_IF;
ELSE
TcpRCV :=
_tcpReceive(
connectionId := OpenSvr.connectionId
,nextCommand := IMMEDIATELY
,receiveVariable := bytesReceiveFromIPC
);
//END_IF;
IF TcpRCV.functionResult = 16#0000 THEN
intReveiveTimes := intReveiveTimes + 1;
IF intReveiveTimes = 1 THEN
dintNext := 0;
END_IF;
FOR i := 0 TO 1023 DO
g_ReceiveBytes[ i] := bytesReceiveFromIPC[i];
END_FOR;
dintNext := dintNext + UDINT_TO_DINT(TcpRCV.dataLength);
IF g_Connected THEN
//Deal with the ByteBit From IPC
IPC_Get_Trig :=_getbit(g_ReceiveBytes[0],0);
IPC_Get_LScan_Deg := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,8));
IPC_Get_LScan_Vel := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,12));
IPC_Get_LScan_Acc := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,16));
IPC_Get_LScan_Dec := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,20));
IPC_Get_SScan_Deg := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,24));
IPC_Get_SScan_Vel := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,28));
IPC_Get_SScan_Acc := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,32));
IPC_Get_SScan_Dec := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,36));
IPC_Get_Shift_Deg := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,40));
IPC_Get_Shift_Vel := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,44));
IPC_Get_Shift_Acc := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,48));
IPC_Get_Shift_Dec := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,52));
IPC_Get_Engage_TorqueLim := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,56));
IPC_Get_Engage_Vel := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,60));
//IPC_Get_LScan_Time := REAL_TO_LREAL(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,64));
IPC_Get_SScan_Time := REAL_TO_DINT(LITTLEBYTEARRAY_TO_ANYTYPE(g_ReceiveBytes,64));
END_IF;
ELSIF TcpRCV.functionResult = 16#7002 THEN
intReveiveTimes := 0;
dintNext := 0;
ELSIF TcpRCV.functionResult < 0 THEN
g_Connected := FALSE;
END_IF;
IF NOT TOF_Send.Q THEN
g_SendData := TRUE;
END_IF;
TOF_Send(g_SendData,t#100ms);
IF g_Connected THEN
//Get data From Axis
IPC_Display_acturalspeed:=LREAL_TO_REAL(_to.Axis_1.servodata.pValue);//_to.Axis_1.actorData.actualSpeed
IPC_Display_acturalposition:=LREAL_TO_REAL(_to.Axis_1.servodata.actualPosition);
IPC_Display_acturaltorque:=LREAL_TO_REAL(_to.Axis_1.actualTorque.value);
IPC_Display_alarmNO:=TSI#AlarmNumber;
//Send data to IPC
g_SendBytes := ANYTYPE_TO_LITTLEBYTEARRAY(IPC_Display_acturalspeed ,8);
g_SendBytes := ANYTYPE_TO_LITTLEBYTEARRAY(IPC_Display_acturalposition ,12);
g_SendBytes := ANYTYPE_TO_LITTLEBYTEARRAY(IPC_Display_acturaltorque ,16);
g_SendBytes := ANYTYPE_TO_LITTLEBYTEARRAY(IPC_Display_alarmNO ,20);
myRetTCPSend :=
_tcpSend(
connectionId := OpenSvr.connectionId
,nextCommand := IMMEDIATELY
,dataLength := 1024
,data := g_SendBytes
);
;
IF myRetTCPSend=0 THEN
g_SendData := FALSE;
END_IF;
END_IF;
END_IF;
END_PROGRAM
從上面3個例子可以看出,電氣自動化,將來的方向使用的好多都是一些基礎的語句。主要的方面在編程的思想。而不是工具。