1. 程式人生 > >PCB CAM 鉆孔補償那點事

PCB CAM 鉆孔補償那點事

image toolinfo 邊緣 pla 情況下 進階 範圍 null 單位

沒有優秀的個人,只有優秀的團隊,在團隊共同的協作下,PCB CAM自動化【net處理】與【鉆孔處理】 第一階段開發項完成了,,後續工作可以轉向PCB規則引擎開發了。這裏說說PCB工程鉆孔補償的那點事,身為一個PCB工程開發人員,有必要知其然,而且還要知其所以然,這裏將鉆孔補償的知識點分享一下。

一.為什麽對鉆孔進行補償?

客戶來的PCB文件中的孔徑一般指成品孔徑,而PCB生產會在孔內鍍上銅(或表面處理:噴錫,沈金,OSP,沈錫),這樣一下來孔徑就會縮小;為了滿足成品孔徑大小符合要求,工程CAM會進行鉆孔補償,進行孔徑大小的校正.

實際例子:成品孔徑是1.00mm,表面處理:沈金 (鎳厚:2.54um,金厚:0.0254um),IPC標準II級(平均孔銅:20um),孔徑按0.10mm補償,那麽工程會選取1.10mm鉆刀鉆孔

技術分享圖片

二.如何進行鉆孔也補償?

先得說說鉆孔補償3個關鍵參數【鉆刀的進制】,【補償值】,【進階值】這3個參數決定了鉆孔如何補償了.

【鉆刀的進制】---由公司采購鉆刀決定,行業常規為50um進制

一般鉆刀大小範圍在:0.1mm到6.35mm之間,而常規鉆刀最小相鄰間隔是0.05mm,那麽鉆刀庫鉆刀為: 0.10mm,0.15mm,0.20mm,0.25mm 等等。。。。

【補償值】---由工藝部結合工廠生產能力測試結果制定補償值規則, 其實整個行業鉆孔補償值差了多少,大同小異

通常:噴錫板:補償0.15mm, 非噴錫板(沈金,鍍金,沈錫,OSP等):補償:0.10mm.

【進階值】---由工藝部結合工廠生產能力測試結果制定選取鉆刀的策略.

進階值類似四舍五入,比如:進制值按是20um,那麽鉆孔補償後的余數是>=20um,則向上進50um,否則不進按0um 。

例如:成品孔徑是:1.025mm,補償值:0.10mm,鉆孔補償後是 :1.125mm,實際鉆刀庫中沒有1.125mm,那得就得進階值發揮作用了。

1.125mm余數為25um,此25um>20um,那麽向上進50um,鉆孔選取1.15mm

實際鉆孔補償例子:

技術分享圖片

選取鉆刀大小的計算過程,將補償後的鉆孔,分解為整數部份與余數部份

1.125mm整數部份: 1.125 / 0.05 = 22.5 向下取整為22,接著 22*0.05 = 1.10mm

1.125mm余數部份 1.125 % 0.05 = 0.025mm

通過判斷:余數部份是否大於20um,如果大於那麽按 整數部份+0.05mm,否則按:整數部份+0mm.

【進階值】小結:

當鉆刀進制為50um 【進階值】對於鉆刀選取至關重要,因為這個值是對鉆孔補償的又一個鉆刀尺寸效正,【進階值】決定是鉆刀是進還是舍,

【進階值】變化也決定了鉆刀大小也發生了變化,看看下面這個例子

技術分享圖片

上面例子可見【進階值】直接決定了鉆刀大小的選擇, 那麽【進階值】設為多少合適也是一個研究的課題了

對【進階值】設定多少合適的個人看法:

1.通過利蔽分析:假如鉆孔補償,導致PCB成品孔徑尺寸大了或孔徑尺寸小了,可以評估對客戶插件哪個影響最大,

成品孔徑尺寸大了至少還是可以插件的,如果孔徑尺寸小了插元件器插不進去.

所以:【進階值】一般定在20um,而不是25um,當然這也得跟據不同工藝決定補償值決定,

2.鉆孔【補償值】: 拿噴錫板工藝來說,鉆孔補償值為0.15mm,其實這個補償值是多補償了,會導致成品孔徑尺寸大一點

比如:1.0mm孔,鉆刀:1.15mm,那麽這個孔會比實際客戶要求孔徑大一點,

所以:當鉆孔【補償值】存在本身多補償了,那麽【進階值】可以設在25um也沒問題,就近取刀

三.如何保證鉆孔補償後成品孔徑符合要求

方法1.采購特殊鉆刀

PCB鉆孔進制常規是50um,即相鄰鉆刀間隔0.05mm, 如1.00mm,1.05mm.1.10mm,1.15mm

一般PTH公差+/-3mil公差采用50um進制鉆刀可以保障成品公差要求了,但孔徑公差小於這個值時,可以采用特殊鉆刀。

例1:50um與25um進制選刀對比

原始孔徑 0.922mm 鉆孔補償 0.10mm,補償後是1.022mm

技術分享圖片

差值對比 1.050-1.022 =0.028mm

1.025-1.022=0.003mm

差值越小;鉆刀選取越合理,那麽這裏選用1.025mm最佳

例2:50um與特殊鉆刀 選刀對比

原始孔徑 0.611mm 鉆孔補償 0.10mm,補償後是0.711mm

技術分享圖片

差值對比 0.700-0.711 =0.011mm

0.711-0.711 =0.000mm

差值越小;鉆刀選取越合理,那麽這裏選用0.711mm最佳

方法2.工藝與設備改進

1.增加二次板鍍,減少圖鍍時間,減少圖形分布不均造成電鍍厚度不均的影響

2.改負片直蝕工藝, 全部采用整板鍍銅,減少圖形分布不均造成電鍍厚度不均的影響

3.電流密度減少,通常電流密度 19ASF,適當降低電流密度電鍍效果越好,但電鍍時間延長了

4.更新更先進的水平電鍍線,常規的垂直電鍍線對於高厚徑比,表面或孔邊緣銅厚比孔壁中心銅厚要厚.

方法3.工程CAM改進

1..獨立孔區域鉆孔,鉆刀多補償一個進制鉆刀

獨立區域,銅比較少,電鍍時是高電流區域,鍍上銅會比其它區域的銅會厚一些,就會導致孔小了

2.一邊密集線路,而另一邊稀疏線路(記得電源板經常這樣設計), 稀疏的線路朝板內,而密集的線路朝板外, 進行倒扣拼板

整個PNL電鍍時,越靠近PNL板邊單位電流密度越大,所以越靠近板邊鍍上去的銅厚越多.

3. TOP與BOTTOM面 銅面積相差大,進行陰陽拼板.

對鉆孔的影響會行成喇叭孔,當板厚與孔銅越厚時,孔側面形狀越明顯,采用陰陽拼板改善兩邊銅面積分布不均

4.獨立區域鉆孔,當靠近板邊或鑼槽較近的,可以在板邊或鑼槽中心,鋪搶電銅皮或搶電銅PAD

獨立區域鉆孔會孔銅越厚,孔會變小, 允許的情況下周邊增加銅皮或PAD,可以減少獨立區域的高電流.

四.鉆孔要補償多少,如何得出來的.

經過測試得出來的,看一組鉆孔補償後,在經過各工序後;鉆孔大小變化(報告摘自百度文庫)

工藝流程:

技術分享圖片

工藝參數:

技術分享圖片

測試PNL數量與切邊位置:

技術分享圖片

鉆孔後---孔徑變化:

技術分享圖片

圖形電鍍後---孔銅變化:

技術分享圖片

圖形電鍍後---孔徑變化:

技術分享圖片

噴錫後---孔徑變化:

技術分享圖片

孔徑變化情況:

技術分享圖片

可以測試結果得出結論:

噴錫板鉆孔補償:0.15mm,是多補償了,會導致成品孔徑偏大一點,所以最佳補償因該是補償0.125mm

五.鉆孔補償代碼實現.

1.補償值與進階值規則:

技術分享圖片

2.特殊刀徑(公差小於3mil 采用特殊刀徑與25um進制刀徑,就近取刀原則)

    List<double> ContainDrillToolList = new List<double>();
    ContainDrillToolList.AddRange(new double[] { 610, 635, 711, 838, 914, 1016, 1320, 3120 });

3.補償鉆孔代碼

/// <summary>
/// 通過鉆孔補償參數計算鉆孔刀徑
/// </summary>
/// <param name="ToolInfo"></param>
/// <param name="UpParam"></param>
///<param name="ContainDrillToolList"></param>
/// <returns></returns>
public static int getDrillUpSize(Mod_tool ToolInfo, gToolUpParam UpParam, List<double> ContainDrillToolList)
{
    if (ContainDrillToolList == null) ContainDrillToolList = new List<double>();
    gToolUpParamHole UpParamHole = new G_Helper.gToolUpParamHole();
    switch (ToolInfo.type)
    {
        case "via":
            UpParamHole = UpParam.Via;
            break;
        case "plate":
            UpParamHole = UpParam.Pth;
            break;
        case "nplate":
            UpParamHole = UpParam.Npth;
            break;
    }
    ToolInfo.max_tol = Math.Round(UpParamHole.Max_Tol, 0);
    ToolInfo.min_tol = Math.Round(UpParamHole.Min_Tol, 0);
    if (ToolInfo.finish_size < 50)
    {
        ToolInfo.finish_size = ToolInfo.drill_size;
    }
    double DrillSlotLevel = (ToolInfo.shape == "slot") ? UpParam.SlotLevel : UpParam.DrillLevel;  //鉆孔階級距   圓孔有2類階級25 50  槽孔有一類階級:50
    double UpLevel;
    if (UpParam.DrillLevel > 49) //進制為50時,不取特殊鉆刀
    {
        ContainDrillToolList = new List<double>();
        UpLevel = UpParamHole.UpLevel;
    }
    else
    {
        UpLevel = UpParam.DrillLevel * 0.5;  //通過進制的一半取刀
    }

    double Drillfinish_size = ToolInfo.finish_size + (ToolInfo.max_tol - ToolInfo.min_tol) * 0.5;  //上限下限公差平分
    int DrillLevelCount = (int)(Math.Floor((Drillfinish_size + UpParamHole.UpVal) / DrillSlotLevel)); //孔階數
    double DrillsizeInt = DrillLevelCount * DrillSlotLevel; //化整鉆孔
    double DrillsizeFloat = (Drillfinish_size + UpParamHole.UpVal) % DrillSlotLevel;//余數鉆孔
    double DrillsizeLevel = (DrillsizeFloat > UpLevel) ? DrillSlotLevel : 0;//余數是否進舍
                                                                            //包含特殊鉆刀
    int ContainDrillIndex = ContainDrillToolList.FindIndex(tt => (int)(Math.Floor(tt / DrillSlotLevel)) == DrillLevelCount);
    if (ContainDrillIndex > -1)
    {
        double ContainDrillFloat = ContainDrillToolList[ContainDrillIndex] % DrillSlotLevel;//特殊鉆孔--余數鉆孔
        if (DrillsizeFloat > UpLevel) // 38 > 20
        {
            double diff1 = Math.Abs(DrillsizeFloat - DrillSlotLevel);  //40-50
            double diff2 = Math.Abs(DrillsizeFloat - ContainDrillFloat);  //40-38
            DrillsizeLevel = (diff1 < diff2) ? DrillSlotLevel : ContainDrillFloat;
        }
        else //if (ContainDrillFloat < UpLevel)
        {
            double diff1 = Math.Abs(DrillsizeFloat - 0);  //12-0
            double diff2 = Math.Abs(DrillsizeFloat - ContainDrillFloat);  //12-16
            DrillsizeLevel = (diff1 < diff2) ? 0 : ContainDrillFloat;
        }
    }
    ToolInfo.drill_size = DrillsizeInt + DrillsizeLevel;

    double DiffDrillSizeUp = ToolInfo.drill_size - ToolInfo.finish_size;
    if (ToolInfo.shape == "slot") //槽長補償
    {
        if (UpParam.isSlotUpLevel) //槽長是否進制化
        {
            Drillfinish_size = ToolInfo.slot_len + (ToolInfo.max_tol - ToolInfo.min_tol) * 0.5;  //上限下限公差平分
            DrillLevelCount = (int)(Math.Floor((Drillfinish_size + UpParamHole.UpVal + UpParam.SlotLengthUp) / DrillSlotLevel)); //孔階數
            DrillsizeInt = DrillLevelCount * DrillSlotLevel; //化整鉆孔   50
            DrillsizeFloat = (Drillfinish_size + UpParamHole.UpVal + UpParam.SlotLengthUp) % DrillSlotLevel;//余數鉆孔
            DrillsizeLevel = (DrillsizeFloat > UpParamHole.UpLevel) ? DrillSlotLevel : 0;//余數是否進舍
            ToolInfo.slot_len = DrillsizeInt + DrillsizeLevel;
        }
        else
        {
            DrillsizeInt = Math.Floor((ToolInfo.slot_len + DiffDrillSizeUp) / 10) * 10; //化整鉆孔  10 
            ToolInfo.slot_len = DrillsizeInt;
        }
        ToolInfo.drill_size += UpParam.SlotEndNumber;  //Slot槽分刀  加尾數
    }
    ToolInfo.bit = Math.Round((ToolInfo.drill_size * 0.001), 3).ToString();
    return 1;
}
public class gToolUpParam
{
    /// <summary>
    /// VIA孔補償值參數
    /// </summary>
    public gToolUpParamHole Via { get; set; } = new gToolUpParamHole();
    /// <summary>
    /// PTH孔補償值參數
    /// </summary>
    public gToolUpParamHole Pth { get; set; } = new gToolUpParamHole();
    /// <summary>
    /// NPTH孔補償值參數
    /// </summary>
    public gToolUpParamHole Npth { get; set; } = new gToolUpParamHole();
    /// <summary>
    /// 鉆孔階級距
    /// </summary>
    public double DrillLevel { get; set; } = 50;
    /// <summary>
    /// Slot槽孔階級距
    /// </summary>
    public double SlotLevel { get; set; } = 50;
    /// <summary>
    /// Slot槽尾數(用於分刀)
    /// </summary>
    public int SlotEndNumber { get; set; } = 0;
    /// <summary>
    /// Slot槽多補償值(微米)
    /// </summary>
    public double SlotLengthUp { get; set; } = 0;
    /// <summary>
    /// Slot槽長是否進制化
    /// </summary>
    public bool isSlotUpLevel { get; set; } = false;
}
public class gToolUpParamHole
{
    /// <summary>
    /// 補償值(微米)
    /// </summary>
    public double UpVal { get; set; } = 100;
    /// <summary>
    /// 進制(微米)
    /// </summary>
    public double UpLevel { get; set; } = 25;
    /// <summary>
    ///正公差(微米)
    /// </summary>
    public double Max_Tol { get; set; } = 76;
    /// <summary>
    /// 負公差(微米)
    /// </summary>
    public double Min_Tol { get; set; } = 76;

}

/// <summary>
/// Mod_layer 層類型
/// </summary>
public class Mod_tool
{
    public int num { get; set; }
    public double finish_size { get; set; }
    public double drill_size { get; set; }
    public string bit { get; set; } = "";
    public double slot_len { get; set; }
    public double min_tol { get; set; }
    public double max_tol { get; set; }
    public int count { get; set; }
    public string shape { get; set; }
    /// <summary>
    /// via 改via non_plated 改nplate plated 改plate
    /// </summary>
    public string type { get; set; }
    public string type2 { get; set; }
}

六.為什麽鉆孔補償和板厚有關呢

這個問題之前我也沒明白,主要是因為高厚徑比了,會導致孔中心的孔銅薄一些,而孔邊緣銅厚厚一些,會形成如下圖片所示效果,

要計算出厚徑比需要板厚的參數,所以板厚也參與到鉆孔補償的規則中來了,當高厚徑比的鉆孔補償會多補償一點.

技術分享圖片

PCB CAM 鉆孔補償那點事