0
$\begingroup$

Context: For university I have to write a program that calculates the position and value of a runout error for drills.

Idea: My idea is with Fourier transformation I only look at the noise and calculate the runout error only of that signal

Problem: The values of the error are way too small to be true. The series I copied below is made with a "Concentricity standard" (translated with google. basically a bar with 4/100 mm error). You could use min max functions here but not with a real drill

Values below are in 1/1000 mm The calculated error here is 4.0689482653531e-17

    1;1174
    2;1174
    3;1174
    4;1174
    5;1174
    6;1174
    7;1174
    8;1174
    9;1174
    10;1174
    11;1174
    12;1174
    13;1176
    14;1176
    15;1176
    16;1176
    17;1176
    18;1176
    19;1176
    20;1176
    21;1178
    22;1178
    23;1178
    24;1180
    25;1178
    26;1180
    27;1180
    28;1180
    29;1182
    30;1182
    31;1182
    32;1182
    33;1184
    34;1184
    35;1184
    36;1184
    37;1186
    38;1186
    39;1186
    40;1186
    41;1188
    42;1188
    43;1188
    44;1188
    45;1188
    46;1188
    47;1190
    48;1190
    49;1190
    50;1190
    51;1190
    52;1192
    53;1192
    54;1194
    55;1194
    56;1194
    57;1195
    58;1195
    59;1195
    60;1197
    61;1195
    62;1197
    63;1197
    64;1199
    65;1199
    66;1199
    67;1199
    68;1199
    69;1201
    70;1201
    71;1201
    72;1203
    73;1203
    74;1203
    75;1203
    76;1205
    77;1203
    78;1205
    79;1205
    80;1207
    81;1205
    82;1207
    83;1207
    84;1207
    85;1207
    86;1209
    87;1209
    88;1209
    89;1209
    90;1211
    91;1211
    92;1211
    93;1211
    94;1213
    95;1213
    96;1213
    97;1213
    98;1215
    99;1213
    100;1215
    101;1213
    102;1215
    103;1215
    104;1215
    105;1215
    106;1215
    107;1217
    108;1217
    109;1217
    110;1217
    111;1217
    112;1217
    113;1219
    114;1217
    115;1219
    116;1219
    117;1217
    118;1219
    119;1219
    120;1219
    121;1220
    122;1220
    123;1220
    124;1219
    125;1220
    126;1219
    127;1219
    128;1219
    129;1220
    130;1220
    131;1220
    132;1220
    133;1220
    134;1220
    135;1220
    136;1220
    137;1220
    138;1220
    139;1220
    140;1220
    141;1220
    142;1220
    143;1220
    144;1220
    145;1220
    146;1220
    147;1220
    148;1220
    149;1220
    150;1220
    151;1219
    152;1220
    153;1219
    154;1219
    155;1219
    156;1220
    157;1219
    158;1219
    159;1219
    160;1220
    161;1219
    162;1219
    163;1219
    164;1219
    165;1219
    166;1217
    167;1217
    168;1217
    169;1217
    170;1217
    171;1217
    172;1217
    173;1217
    174;1215
    175;1215
    176;1215
    177;1215
    178;1215
    179;1215
    180;1213
    181;1213
    182;1213
    183;1213
    184;1213
    185;1213
    186;1211
    187;1213
    188;1211
    189;1211
    190;1209
    191;1209
    192;1209
    193;1209
    194;1209
    195;1209
    196;1209
    197;1207
    198;1207
    199;1207
    200;1205
    201;1205
    202;1205
    203;1205
    204;1203
    205;1205
    206;1203
    207;1201
    208;1201
    209;1201
    210;1201
    211;1201
    212;1199
    213;1199
    214;1199
    215;1199
    216;1197
    217;1197
    218;1197
    219;1195
    220;1197
    221;1195
    222;1195
    223;1195
    224;1195
    225;1195
    226;1194
    227;1194
    228;1192
    229;1192
    230;1192
    231;1190
    232;1192
    233;1190
    234;1188
    235;1190
    236;1188
    237;1188
    238;1186
    239;1186
    240;1186
    241;1186
    242;1186
    243;1184
    244;1184
    245;1184
    246;1184
    247;1182
    248;1182
    249;1182
    250;1180
    251;1180
    252;1180
    253;1180
    254;1178
    255;1178
    256;1178
    257;1178
    258;1178
    259;1178
    260;1176
    261;1174
    262;1174
    263;1174
    264;1174
    265;1172
    266;1172
    267;1172
    268;1172
    269;1171
    270;1172
    271;1172
    272;1171
    273;1171
    274;1171
    275;1171
    276;1169
    277;1169
    278;1169
    279;1169
    280;1167
    281;1169
    282;1167
    283;1167
    284;1167
    285;1167
    286;1167
    287;1167
    288;1167
    289;1165
    290;1165
    291;1165
    292;1165
    293;1163
    294;1163
    295;1163
    296;1163
    297;1163
    298;1163
    299;1163
    300;1163
    301;1161
    302;1163
    303;1161
    304;1161
    305;1161
    306;1163
    307;1161
    308;1163
    309;1161
    310;1161
    311;1161
    312;1161
    313;1161
    314;1161
    315;1163
    316;1161
    317;1163
    318;1161
    319;1161
    320;1161
    321;1163
    322;1161
    323;1161
    324;1161
    325;1163
    326;1163
    327;1163
    328;1161
    329;1161
    330;1161
    331;1161
    332;1163
    333;1161
    334;1163
    335;1163
    336;1161
    337;1163
    338;1163
    339;1163
    340;1163
    341;1165
    342;1163
    343;1163
    344;1163
    345;1165
    346;1163
    347;1163
    348;1165
    349;1165
    350;1165
    351;1165
    352;1165
    353;1167
    354;1165
    355;1167
    356;1167
    357;1167
    358;1167
    359;1167
    360;1167

You have to look at the graphics manually and find a point for the cutoff.

Do you have ideas to improve this or an even better way to solve this problem?

def fourier_analysis(data, cutoff = 10_000):
    n = len(data.Degree)
    fhat = np.fft.fft(data.Distance, n )
    PSD = fhat * np.conj(fhat) / n
    freq = (1 / n) * np.arange(n)
    L = np.arange(1,np.floor(n/2), dtype='int')
    
    
    # Frequenzen filtern 
    yf = np.fft.fft(data['Distance'].values)
    filtered_yf = np.where(np.abs(fft(data['Distance'].values)) < cutoff, 0, yf)
    filtered_noise = np.where(np.abs(fft(data['Distance'].values)) > cutoff, 0, yf)
    
    # Inverse FFT  
    reconstructed_signal = ifft(filtered_yf)
    noise_signal = ifft(filtered_noise)
    return noise_signal , reconstructed_signal , PSD, L , freq

def calc_runout_error(noise_signal):
    df = pd.DataFrame()
    noise = np.real(noise_signal)
    for i , j in enumerate(noise):
        df.loc[i,'x'] = j * np.cos(math.radians(i))
        df.loc[i,'y'] = j * np.sin(math.radians(i))
    center_x = np.mean(df['x'])
    center_y = np.mean(df['y'])
    
    deg = math.degrees(math.atan2(center_y, center_x))

    if deg < 0:
        deg += 360
    
    distance = math.sqrt(center_x**2 + center_y**2)
    
    return deg , distance , df

def show_runout_error(df, cutoff=10_000, plots = False, y_lim_value=500, x_lim_left= -0.01, x_lim_right= 0.1):
    print(df.loc[0,'Filename'])
    # Analysis
    noise_signal , reconstructed_signal , PSD, L , freq = fourier_analysis(df,cutoff)
    deg , distance, df_error = calc_runout_error(noise_signal)
    
    if plots == True:
        min_val = min(df['Distance'].min(), np.real(reconstructed_signal).min()) 
        max_val = max(df['Distance'].max(), np.real(reconstructed_signal).max()) 
    
        # plot results
        fig = plt.figure(figsize=(10,16))
    
        # show original
        plt.subplot(3, 2, 1)
        plt.plot(df['Degree'], df['Distance'])
        plt.title('original data')
        plt.xlabel('deg')
        plt.ylabel('distance')
        plt.ylim(min_val, max_val)
    
        # show filtered
        plt.subplot(3, 2, 2)
        plt.plot(df['Degree'], np.real(reconstructed_signal))
        plt.title('filtered data')
        plt.xlabel('deg')
        plt.ylabel('distance')
        plt.ylim(min_val, max_val)
    
        #show fourier
        plt.subplot(3, 2, 3)
        plt.plot(freq[L], np.real(PSD[L]), color='r', linewidth=2)
        plt.ylim(0,y_lim_value)
        plt.xlim(x_lim_left, x_lim_right)
        plt.title('fourier transformation')
        plt.xlabel('frequency')
        plt.ylabel('power spectrum density (PSD)')
    
        # show scatter
        plt.subplot(3, 2, 4)
        plt.scatter(x=df_error['x'], y=df_error['y'], color='blue', s=5)
        plt.xlabel('x-coordinate')
        plt.ylabel('y-coordinate')
        plt.title('runout error in cartesian')
        plt.grid(True)
        
        # Noise
        plt.subplot(3, 1, 3)
        plt.plot(df.Degree, np.real(noise_signal), color='red')
        plt.title('runout error (noise)')
        plt.xlabel('deg')
        plt.ylabel('distance')
        
        plt.show()
        print('Degree: ', deg , ' Distance: ', distance)

    
    return deg , distance, reconstructed_signal

deg,distance,  reconstructed_signal = show_runout_error(list_df[5],
                        cutoff=2500,
                        plots=True,
                        y_lim_value=20_000,
                        x_lim_right=0.1
                       )

fourier-graphics

$\endgroup$
4
  • $\begingroup$ but that is not the Problem ... then, what is the problem $\endgroup$
    – jsotola
    Commented Jun 4 at 19:03
  • $\begingroup$ I know what runout is, but I do not know what "runout error" is, nor do I understand why you need to calculate something you can measure. $\endgroup$
    – Tiger Guy
    Commented Jun 4 at 21:57
  • $\begingroup$ What are your sensors actually measuring? Are you trying to replace a dial gauge with something like a range finder? Simply spinning the drill may not be enough- what about axially shifting? What about the cutting flutes? $\endgroup$
    – Abel
    Commented Jun 12 at 3:25
  • $\begingroup$ 1. We measure the distance between the range finder and the drill 2. The drills are very short so we have to measure on the height of the cutting edges. 3. Using a dial gauge was never really an optiom becuase of wear and damage to the drills 4. We want to find the runout error to "remove" it (restore concentricity) 5. We were hoping to solve this problem by measuring only once, but because of lack of progress we i will try it with multiple measurements 6. What do you mean with your last question? $\endgroup$ Commented Jun 12 at 18:36

0

Browse other questions tagged or ask your own question.