2019年5月23日 星期四

同軸度 Coaxiality

同軸度和同心度是兩個非常容易搞混的幾何公差.
同軸度的符號如下:
跟正位度的符號是一樣的!
有這種設定,主要是它的定義和正位度的使用方法很像,反而跟同心度沒這麼相似.
首先來個範例:
由於這個不是繪圖軟體做的,只是示意用,不合工程圖規範的部分還請包涵.
這個是一個軸的側面視圖,直徑較大的部分為基準,直徑較小的部分是要比較的部分.
同軸度要怎麼解讀呢? 首先以大圓柱作為基準,畫出基準軸,如下圖:



而作為比較的小圓柱,也畫出自己的軸,小圓柱本身的軸偏差不能超過以大圓柱軸為中心,直徑0.5的圓柱體公差帶範圍內,如下圖所示.
而同心度,則是取一個截面圓的中心點作為基準,而被量測的特徵也是取一個截面的圓的中心點作為判斷依據,可以說是點對點的比較.
雖然同軸度和同心度名字上聽起來很像,但是操作和執行量測上的方式可是完全不同的,希望這篇文有解除大家的疑惑.


2019年5月21日 星期二

同心度 Concentricity

同心度和正位度都是幾何公差的一種,同心度的定義(作者自己的定義),以參考圓的中心點為基準點,所量測圓的中心點必須落在基準點為圓心的特定直徑的範圍內。
用圖來解釋比較快:
同心度的符號如下,
由於同心度也得需要基準作為比對,因此在符號後面會註記所對應的基準特徵.
下圖是比例沒有很好的範例:
大家可以看到,基準A是外圓,而內圓是要比對的部分,首先找到外圓的中心點

在工程圖上大家可以看到,圖紙的要求是直徑0.5,接著在外圓中心點畫出直徑為0.5的圓(黃色部份).
如果內圓的中心點有落在這個黃色範圍內,就算符合公差.
如果沒在黃色範圍內,則NG.

以上是同心度的簡單介紹,由於同心度和內外圓的直徑大小沒有關聯,除非有考量材料條件,因此在工程圖上就沒標示,以免誤導.

以C# 實作MODBUS TCP

最近在弄MODBUS TCP的東西,但又不想引用第三方的LIBRARY,所以就從底層做起。
簡單來說, 用socket傳送 byte array就搞定了。 不好處理的是byte array的設定,以下是簡易的設定說明。


寫入output register

MODBUS TCP的 byte array如下:

 byte[] array=
{
0,0,// transaction id , no use in this case
0,0,// id no use in this case
0,0x6,// length of data
0,// device number, no use in this case
0x6,//function code
0x1F, 0xBB,// Start Address
0x0,0x1//Force data
};

解釋一下這些的意義:
0,0,// transaction id , no use in this case
在MODBUS TCP可以不指定,或是任意指定也可,SLAVE裝置回傳的前兩個byte就是這兩碼。
0,0,// id no use in this case
這個也是可以隨意指定。
0,0x6,// length of data 這兩個byte代表要傳輸的訊息的byte length,


0,// device number, no use in this case
0x6,//function code
0x1F, 0xBB,// Start Address
0x0,0x1//Force data

到這裡總共有6個bytes,所以長度為6

0,// device number, no use in this case
裝置號碼,在有IP位置的情況下可以不用設定。

0x6,//function code
這個就是重點了,MODBUS的指令,
這個是寫入特定output register的代碼,
不同廠商的function code有些許不同,但大致如下:

讀取多個registers : 0x3
讀取單個 input register : 0x4
寫入 coil : 0x5
寫入單個 output register : 0x6
(其他的網路上都找得到,這邊只列常用的)

0x1F, 0xBB,// Start Address
這邊是指定要寫入的位址,每家廠商定義的位址都不一樣,得自己慢慢看原廠手冊。

0x0,0x1//Force data
這邊是讓該位址ON的指令,每家廠商設定不一樣,得自己慢慢看原廠手冊。


讀取register狀態

 byte[] array=
{
0,0,// transaction id , no use in this case
0,0,// id no use in this case
0,0x6,// length of data
0,// device number, no use in this case
0x3,//function code
0x00, 0xAB,// Start Address
0x0,0x2//Number of registers
};


大部分都和上面一樣,不同的是function code,這邊是0x3,另外是最後的兩個bytes,是一對High/Low byte,用來指定要讀取的register的數量。在這邊Address和register是同義。
回傳的資訊就是該Address的IO狀態了。

以下是簡易實作的程式碼:

var socket=new Socket( SocketType.Stream, ProtocolType.Tcp);
var Addr=new IPAddress (new byte[]{168,192,1,1});//slave device ip
int port=502;
var IEP = new IPEndPoint(Addr,port);

socket.Connect(IEP as EndPoint);

if(socket.Connected)
{
socket.send(array);
var buffer=new byte[1024];
int L= socket.recieve(buffer);
}

以上就是Modbus TCP的實作。

2021.Mar.24 Add:
Modbus specification:
https://modbus.org/specs.php











2018年5月7日 星期一

自建C#機器學習核心

這篇心得是應之前python spark decision tree 的老師Mercel Wang邀約所寫的,不過我也不清楚怎麼寫才適合,所以就先交待一下那門課的狀況吧.當時他是在FB的python Taiwan開了一個關於spark和決策樹的討論串,我當時剛好也好奇machine learning到底在幹嘛,就跟著討論串+1.

這門課以交作業的方式進行,當有人貼出該次作業後,就繼續發放下一週的作業,前幾個禮拜都要搜集和消化不少資料和文獻,不過好處是如果不知道作業怎麼寫,也能參考其他先做出來的人的作品,這門課對上班族來說負擔不算輕,得在下班和假日處理作業的事情,不過也因此從完全不知道ML是什麼東西的人,變成能夠講述ML大概是怎樣的東西.

不過我比較沒定力,從作業9之後,就沒再繼續了,一個是老師沒繼續出作業就懶得繼續下去,另一個是工作和生活上碰不到需要Hadoop的情境,加上hadoop/spark/scala的版本真是一團亂,所以一整個發懶.時間推移到今年三月,我在公司建構機聯網,蓋到一半突然想到用ML來判斷製程的參數到底好或壞,也許是好玩又可行的案子,因此又重新把之前看過的文獻和資料找了出來.

本來我是想說用現成的lib就好,但是沒想到公司的網路完全把python lib wheel擋起來,我又很懶得研究如何翻牆,於是就想說來看看這些lib的原始碼怎麼寫的好了~原本不看還好,看過才發現,「我根本看不懂他們在寫啥...」想說這樣不行,這樣根本寫不出東西呀!

我想了想,決定還是用最笨的方法好了,從數學方法一步步來蓋自己看得懂的ML(反正工控和製程的數據壓根稱不上“大”數據,一天有個2GB就不錯了,因此效率就不是我的首要考量),由於在工業控制和機械領域,C#是王道(c/c++是大神級玩的,小的玩不起),所以就以C#來撰寫,首先是以類神經網路開刀,花了個半天寫了個最初級的感知器,就覺得其實也不難嘛~哈哈!我就串了十幾個一樣的感知器來跑iris data來玩,感覺還ok.隔天就來挑戰SVM.結果發現我想得太單純了,這個有夠難懂.

SVM網路的資料非常非常非常非常的多,但是能夠把數學方法解釋得詳細的沒幾個,甚是錯誤不少,比如說向量和純量的表示法搞錯,符號定義不明,亂用之類的(暈).暈了幾天後,總算找到一個非常淺顯易懂的教材,MIT的machine learning課程[1],用它教學的步驟總算把一個可以二分類的SVM蓋起來了,分類的邏輯搞定,但是需要大量的矩陣運算,因此在一個禮拜內惡補了不少線性代數的東西(以前只有大二修過工程數學,有講到半個學期的線代,但早還給教授了,畢竟她研究有需要用到,她要用的時候沒有會很困擾的),總算蓋了一個高斯消去運算器來處理矩陣,不過實際跑的時候發現,遇到[20*20]以上的矩陣就爆炸了.後來找了找其他替代方案,找到了一個叫做SMO的演算法[2],他是使用軼代法的方式來代替掉大量的矩陣運算,並能夠保證運算的正確性,看到這個的時候,覺得發明這個的人根本是天才!後來我採用的方式是簡易版的SMO[3],在演算法上比原本論文寫得更好懂,超推薦!把SMO寫好後,實際跑的感覺超棒的,it works!(拿iris data試跑有90%up準確率)而且沒想到整個演算法也才不到300行,心情超好.

經過SVM的摧殘後,寫決策樹就輕鬆多了,只要補好統計學的基礎知識,像是binominal distribution,就能寫出一個C4.5的node,但後來發現決策樹在決定像double/float型別的資料上範圍,沒這麼好用(主要是我文獻和資料的搜集還不夠多,目前看到的範例都是字串資料當教材),所以目前就只拿它來玩字串資料的分類了,像是分類MES上面的資料.

目前是把SVM拿來推論新增的製程參數的好壞,不過由於累積的樣本數還不夠多,所以還沒有一個明顯趨勢出現.也許根本沒趨勢也有可能,或是資料量大起來後發現自己寫的是錯的也難說.

沒想到當初無心參與python spark課程,找過的資料以及學到的ML知識,會真的應用到我工作的領域上,無心插柳呀.算是一個奇特的經驗,在這跟大家分享~哈.

參考資料
[1]https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-034-artificial-intelligence-fall-2010/tutorials/MIT6_034F10_tutor05.pdf
[2]http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.43.4376&rep=rep1&type=pdf
[3]http://cs229.stanford.edu/materials/smo.pdf

2018年5月5日 星期六

Control Beckhoff I/O module by C#

This method can directly control I/O module without PLC.
1. Install TwinCAD3
2. Refer the Library of Beckhoff
using TwinCAT.Ads;
3.declare the client object and output array
private TwinCAT.Ads.TcAdsClient client; UInt32[][] OUTPUTs = new UInt32[16][];

4. Using connect method of client object
client.Connect(11);

5. the data structure of IO array: assume there are 16 output ports, then the length of array is 16. Each port has 2 elements, both data type of elements are Uint 32. The first element is the practical address of IO module, the second element is the virtual address of the port. For instance, if the virtual address of output port 1 is 0xC10000D0, then output port 2 is 0xC10000D0+(Uint32)1=0xC10000D1.

6.As we acquire the practical address and virtual address of IO module and its ports. we can use
client.WriteAny(master_address,IO_address,bool);
to control output ports directly.

Or
client.ReadAny(master_address,IO_address, typeof(var));
to read the current state of ports.

the sample code is as below:
for (int i = 0; i < OUTPUTs.Length; i++) { OUTPUTs[i] = new UInt32[2]; OUTPUTs[i][0] = 0x3040030; OUTPUTs[i][1] = 0xC10000D0 + (UInt32)i; object c = client.ReadAny(OUTPUTs[i][0], OUTPUTs[i][1], typeof(byte)); if ((byte)c == 1) { client.WriteAny(OUTPUTs[i][0], OUTPUTs[i][1], (bool)false); rds[i].Checked = false;//radio button object cbs[i].Checked = false;//check box object } else { client.WriteAny(OUTPUTs[i][0], OUTPUTs[i][1], (bool)true); rds[i].Checked = true; cbs[i].Checked = true; } listBox1.Items.Add(c);

2018年4月12日 星期四

傾斜度 Angularity

傾斜度 Angularity
#以下圖是用keynote畫出來的,所以並不完全符合工程規範,單純適意用
傾斜度本來是想翻成角度度,但聽起來又很奇怪,後來看到一本書是寫傾斜度,那就這樣用囉.
傾斜度是說,以一個面當基準時,和它有夾角的傾斜面的起伏程度.
傾斜度的符號如圖一
圖一
在工程圖上的範例如圖二
圖二
一般就筆者的經驗,即使是工程人員,不少也會以為說這個公差的讀法是70+-0.3度,但實際上,如果照角度公差來配的話,會在組裝和製造上弄出非常大的問題.
因此,該公差的讀法是,在以A基準為零點,該面和A基準之夾角為70度,而該面有上下0.3的帶狀公差,如圖三所示.
圖三
以上為傾斜度之簡介



2018年4月10日 星期二

正位度之二-考量材料條件

考量材料條件的正位度
在講這之前,得先說明什麼是材料條件,一般來說我們會在工程圖上的位置公差上看到下面兩個符號(圖一):
圖一
M代表最大材料條件/邊界(Maximum Material Condition/Boundary),在實心特徵(如插銷,boss, pin...)上就代表取其最大值,在空心特徵(如孔)則是取其最小值,以保證工件的材料是在最多的狀況.

L代表最少材料條件/邊界(Least Material Condition/Boundary),在實心特徵(如插銷,boss, pin...)上就代表取其最小值,在空心特徵(如孔)則是取其最大值,以保證工件的材料是在最少的狀況.

考量材料狀況的正位度並不是說把目標的孔或是柱體做到最大或者最少材料,而是以最大或最小材料狀況作為參考標準,去變動公差範圍.

參考材料狀況的正位度標註如圖二
圖二
在正位度公差後面標注材料條件符號
以一個例子來講解有材料條件的正位度,見圖三



圖三
該範例是一個鈑件上面有一個孔,在正位度標明最大材料條件的前提下,此公差的解讀方式為“在孔的直徑最小的情況下(19.8),有直徑0.2的公差帶,當孔的直徑變大時,其公差帶也會隨之增加",其公差帶如表一
表一


用圖來解釋,則如圖四和圖五



圖四

圖五
在這種情況下,孔的半徑越大,可擁有的公差帶就越大,這個是考量材料條件的正位度特別之處.這種公差設計可以減少在製造過程中機器或人所造成的加工誤差所造成的組裝困難,並減少加工之成本和困難度.

至於最小材料條件也是相同的概念,以圖六為例
圖六
以最少材料條件為基準,即以直徑20.2的時候,有正位度公差帶直徑0.2,之後孔徑越小,所擁有的正位度公差就越大,如表二所示
表二

以圖來表示,及圖七和圖八
圖七

圖八
在這種情況下,孔越小,所擁有的公差帶越大,一般來說,最小材料條件的正位度公差比較少用在孔上,以組裝的觀點來說較不符合需求,但還是得看工件設計和製造上的需求來選擇適合的公差分配方法,沒有絕對.






同軸度 Coaxiality

同軸度和同心度是兩個非常容易搞混的幾何公差. 同軸度的符號如下: 跟正位度的符號是一樣的! 有這種設定,主要是它的定義和正位度的使用方法很像,反而跟同心度沒這麼相似. 首先來個範例: 由於這個不是繪圖軟體做的,只是示意用,不合工程圖規範的部分還請包涵. 這個是...