PCB 鑽孔補償那點事


 沒有優秀的個人,只有優秀的團隊,在團隊共同的協作下,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; }
}

 

六.為什么鑽孔補償和板厚有關呢

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

        要計算出【厚徑比】需要板厚這個值,所以板厚也參與到了,鑽孔補償的規則中來了,當高【厚徑比】(如12:1)的鑽孔補償會多補償一些.

        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM