samucoder

Samuel M.H. 's technological blog

Sunday, September 11, 2016

Reparación de la tapa de la bomba de gasolina de un Volvo S60

AUTOR: Samuel M.H. FECHA: 11-Septiembre-2016 LICENCIA: todos los derechos reservados.

Exención de responsabilidad.

Este documento es un registro fruto de mi experiencia solucionando un problema. No soy mecánico ni estoy cualificado para realizar reparaciones en vehículos. No obstante, todo lo he hecho bajo mi responsabilidad. He creído necesario documentar mi labor porque cuando afronté el problema no existían guías parecidas en castellano y la escasa información que encontré fue en foros. Recuerda que si intentas reproducir mis pasos, lo haces bajo tu propia responsabilidad y que no te garantizo el resultado final. Si tienes dudas, te puedo aconsejar, pero lo mejor que puedes hacer es llevar el vehículo a tu taller de confianza y dejarte aconsejar por un profesional.

Descripción del problema

El problema empezó con un retardo en el arranque del coche en frío. Con el coche parado más de 6 horas, cada vez le costaba más iniciar el motor de combustión, llegando al caso extremo de varios intentos y cerca de 10 segundos funcionando el motor de arranque antes de empezar la combustión. En esta fase se sospechó de un problema de bujías o de las bobinas que las alimentan.

A medida que el inicio del arranque se alargaba, empezó otro síntoma. El interior del habitáculo empezó a oler a gasolina, al principio casi inapreciable pero luego bastante intenso. En viajes de más de 30 minutos este olor era más apreciable y en las curvas o bajadas se acentuaba. El olor en el exterior con el coche estacionado era similar al de una gasolinera. El coche olía a gasolina por fuera.

Cuando el problema empezó a ser severo, a veces se veían 3 o 4 gotas debajo del coche.

El lector ODBII no me daba ningún fallo.

Detección del fallo

Llegado al punto anterior, investigué el fallo y busqué una posible solución. Consultando foros, descubrí que la tapa de la bomba de la gasolina de los Volvo S60, con el tiempo, se agrieta dando lugar a fugas. Eso explicaba la tardanza en arrancar del motor (había que cebar de nuevo el circuito del depósito al motor), así como el fuerte olor a gasolina debido al goteo.

Es un fallo de Volvo, notificado en el 2009, que afecta a los siguientes modelos/año de fabricación:
  • VOLVO / S60 2001-2004
  • VOLVO / S80 2002-2005
  • VOLVO / V70 2001-2004
  • VOLVO / XC70 2001-2004
  • VOLVO / XC90 2003-2005

En varios estados de EE.UU. Volvo llamó a revisón a ciertos modelos por este problema. ¿Y en España...?

Esta es la llamada a revisión por parte de Volvo, sacada de la National Highway Traffic Safety Administration (EE.UU.).

Make: VOLVO Model: XC90
Model Year: 2003
Manufacturer: VOLVO CARS OF N.A. LLC. Report Receipt Date: DEC 18, 2009
NHTSA CAMPAIGN ID Number: 09V483000 NHTSA Action Number: PE09039
Component: FUEL SYSTEM, GASOLINE:DELIVERY:FUEL PUMP

Summary:
VOLVO IS RECALLING CERTAIN MODEL YEAR 2001-2005 S80, MODEL YEAR 2001-2004 V70, S60, XC70
AND MODEL YEAR 2003-2005 XC90 VEHICLES SOLD IN OR REGISTERED IN THE STATES OF ALABAMA,
ARIZONA, ARKANSAS, CALIFORNIA, FLORIDA, GEORGIA, HAWAII, KENTUCKY, LOUISIANA, MISSISSIPPI,
NEVADA, NEW MEXICO, NORTH CAROLINA, OKLAHOMA, SOUTH CAROLINA, TENNESSEE, TEXAS, UTAH,
VIRGINIA AND THE U.S. TERRITORIES. WHEN EXPOSED TO CERTAIN ENVIRONMENTAL CONDITIONS (HOT
CLIMATE AND TEMPERATURE CYCLING) OVER TIME AND IN COMBINATION WITH VARYING FUEL QUALITY,
THE FUEL PUMP CAN DEVELOP CRACKS IN THE FUEL PUMP FLANGE.
Consequence:
IF THE CONDITION OCCURS VEHICLE OWNERS MAY NOTICE FUEL SMELL AND/OR FUEL LEAK WHICH, IN
THE PRESENCE OF AN IGNITION SOURCE, COULD RESULT IN A FIRE.
Remedy:
DEALERS WILL INSPECT THE FUEL PUMP INSTALLED IN THE VEHICLE, AND IF NECESSARY REPLACE THE
FUEL PUMP WITH A PART OF A MODIFIED DESIGN. THIS SERVICE WILL BE PERFORMED FREE OF CHARGE.
THE SAFETY RECALL BEGAN ON JANUARY 15, 2010. OWNERS MAY CONTACT VOLVO AT 1-800-458-1552.
Notes:
VOLVO SAFETY RECALL NO. R220. OWNERS MAY ALSO CONTACT THE NATIONAL HIGHWAY TRAFFIC SAFETY ADMINISTRATION'S VEHICLE SAFETY HOTLINE AT 1-888-327-4236 (TTY 1-800-424-9153), OR GO TO HTTP://WWW.SAFERCAR.GOV .
Había varias soluciones:
  • Llevar el coche al taller. La opción más cara.
  • Encargar una nueva bomba ya que Volvo no vende esa pieza suelta.
  • Reparar la pieza defectuosa fuga.

He de decir que el tener que encargar toda la bomba de la gasolina porque Volvo no provea de una mísera tapa de plástico de repuesto me parece una vergüenza.

Reparación

Sin nada que perder ya que el destino de la bomba entera era la basura, intenté repararla por si conseguía sellar la fuga.

Herramientas

  • Llave de tubo del 14.
  • Llave de tubo del 10.
  • Destornillador plano de electricista.
  • Guantes.
  • Aspirador.
  • Unas tijeras.
  • Paciencia, calma y cuidado.

Materiales

  • Nural 21, masilla epoxi resistente a hidrocarburos.
  • Un platito de plástico o similar (para mezclar).
  • Papel de cocina.
  • Mondadientes.
  • Papel de lija fino.
  • Un refrigerio

Pasos

Desmontar el cogín del asiento trasero

El cogín del asiento trasero sale sencillamente tirando hacia arriba de él. Una mano extra te será de ayuda.

Tumbar el respaldo trasero derecho

Abre el maletero y en el lado derecho tienes una palanca para poder librerar el respaldo del asiento del mismo lado. Inclínalo hacia adelante. Es el respaldo más grande porque contiene también el central.

Extraer el cogín del cinturón de seguridad trasero derecho

Debemos extraer esta pieza.

En la siguiente imagen, ya se muestra desmontado. Nota las espigas que tiene (lado derecho y superior) y la pestaña de liberación (lado izquierdo inferior).

Para poderlo desmontar, hay que acceder a la pestaña de liberación por el maletero. Esta es la pestaña que hay que liberar.

Desde el maletero, desmonta el embellecedor lateral derecho. Al lado de la pestaña de liberación del asiento hay una tapa que gira media vuelta, con eso se abate la primera parte. Luego quitas una grapita de plástico con cuidado para volverla a usar al montar todo y abates el embellecedor. Al fondo está la pestaña de liberación del cogín.

Extraer el respaldo del asiento trasero derecho

En la fotografía del asiento abatido, en el extremo inferior izquierdo, se vé el tornillo que fija el asiento. Con ayuda del destornillador, extrae el cabezal del sensor (cable amarillo) tirando suavemente hacia afuera. Quita el tornillo con la llave de tubo del 14. Levanta un poco el asiento y sácalo por la puerta. El respaldo tiene un vástago que inserta en el otro respaldo y los mantiene fijos.

Sin el respaldo, el coche se ve así.

En la siguiente imagen se ve tanto el agujero del tornillo como el cabezal hembra del sensor.

Este es el hueco del tornillo y el cabezal macho del asiento.

Retirar la manta protectora

Hay que retirar la manta textil que reposa sobre la chapa. Sale con facilidad y deja al descubierto la tapa metálica que cubre la bomba de gasolina.

Lo que hay debajo de la manta.

Quitar la tapa que cubre la bomba de gasolina

Con la llave de tubo del 10, quitar los 4 tornillos que sujetan la chapa. Ya hemos accedido a la tapa de la bomba de gasolina (en blanco).

En detalle.

Sorpresa

En este punto descubrí la gravedad de la avería que tenía entre manos. Había dos dedos de gasolina áltamente inflamable encharcados fuera de la bomba de gasolina. Con razón olía tan fuerte. Mucho cuidado en este punto, cualquier chispa o llama, y la gasolina empezará a arder.

Detalle de la gasolina encharcada.

Limpieza

En las imágenes anteriores se puede ver la suciedad y el charco de gasolina.

Lo primero es secar la gasolina con papel de cocina y minimizar el riesgo de incendio.

Después, con más papel y ayuda de los mondadientes y el aspirador, dejar la tapa blanca (tapa de la bomba de gasolina) más limpia que los chorros del oro.

Tal que así.

Inspección

En el punto anterior encontré residuo como de goma y arena, lo que me hizo sospechar que alguien intentó esta reparación con anterioridad usando pasta para juntas.

Ahora se puede apreciar que todo lo blanco es una sola pieza solidaria, pieza que no venden como recambio.

Con un poco de atención, se puede ver la grieta por donde gotea combustible. Al estar el coche apagado, no gotea, pero en mi caso se oía un silbido de que entraba aire al circuito.

Preparado de la pieza

Vista la fisura, se lija el interior de los 4 compartimentos con una lija fina para que agarre el producto sellador.

Resultado de la pieza lijada.

Sellado de la fisura

El producto a aplicar es Nural 21, una masilla epoxi resistente a los hidrocarburos. Se puede encontrar en ferreterías y tiendas de bricolaje por unos 8€.

En el platito de plástico, mezclamos dos partes iguales de cada tubo hasta conseguir una masa consistente y de un color gris homogéneo. Acto seguido lo aplicamos con cuidado y ayuda de un mondadientes en cada uno de los compartimentos a sellar.

Este paso es conveniente realizarlo en 4 veces, una por cada compartimento y con mucho cuidado. No es bueno aplicar toda la masa de golpe ya que no penetrará en la pieza y la resistencia será menor.

Este es el resultado una vez sellada la pieza.

Curado de la pieza

No arrancar el motor en 24 horas.

Montaje del coche

Se montan las piezas del coche en sentido inverso.
  • Tapa de metal con 4 tornillos.
  • Manta cubrechapa.
  • Asiento y sensor
  • Cogín lateral y embellecedor del maletero.
  • Cogín del asiento.

Resultado y conclusión

Estuve circulando 1 semana (500km) y revisé la reparación. No había signos de degradado en la masilla epoxi y el coche arrancaba a la primera. No se apreciaba fuga y el olor a gasolina se desapareció.

Revisión a los 500 km.

NOTA: en lo que dure el proceso de reparación no hay que arrancar el motor del coche. Se puede ver comprometida la limpieza de la pieza, la calidad de la reparación y la seguridad del reparador.

NOTA: gracias a Paleomán por ayudarme a montar todo, limpiar un poco el coche y dejarme su cámara.

Monday, April 18, 2016

Running a k-means Cluster Analysis

Notebook

Running a k-means Cluster Analysis

Author: Samuel M.H. <samuel.mh@gmail.com> Date: 17-04-2016

Instructions

This week’s assignment involves running a k-means cluster analysis. Cluster analysis is an unsupervised machine learning method that partitions the observations in a data set into a smaller set of clusters where each observation belongs to only one cluster. The goal of cluster analysis is to group, or cluster, observations into subsets based on their similarity of responses on multiple variables. Clustering variables should be primarily quantitative variables, but binary variables may also be included.

Your assignment is to run a k-means cluster analysis to identify subgroups of observations in your data set that have similar patterns of response on a set of clustering variables.

What to Submit

Following completion of the steps described above, create a blog entry where you submit syntax used to run a k-means cluster analysis (copied and pasted from your program) along with corresponding output and a brief written summary. Please note that your reviewers should NOT be required to download any files in order to complete the review.

This assignment does NOT require you to run your cluster analysis again on a test data set. You are welcome to do so, but you are only required to run your cluster analysis once on your training data set. If your data set has a relatively small number of observations, you do not need to split into training and test data sets. You can provide your rationale for not splitting your data set in your written summary.


Intro

Dataset

Variables

  • Cluster:
    • AGE -> AGE: age in years.
    • S1Q24LB -> WEIGHT: weight in pounds.
    • S1Q24FT,S1Q24IN-> HEIGHT: height in inches.
    • SEX -> MALE: 1 if the subject is a male.
    • NUMPERS -> HOUSE_PEOPLE: number of persons in household.
    • ETOTLCA2 -> ALCOHOL: average daily volume of ethanol consumed in past year, from all types of alcoholic beverages combined in ounzes.
    • S1Q4A -> MARRIAGE: age at first marriage (years).
    • S1Q8D -> WORK: age when first worked full time, 30+ hours a week (years).
    • S1Q12A -> INCOME: total household income in last 12 months (dolars).
  • Statistical test:
    • ETHRACE2A -> RACE: race/ethnical group of the subject.
In [19]:
%pylab inline

import numpy as np
import pandas as pd                                             
from scipy.spatial.distance import euclidean
from scipy.stats import chi2_contingency
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import statsmodels.formula.api as smf
import statsmodels.stats.multicomp as multi

#Visualization
import matplotlib.pylab as plt
import seaborn as sns


pylab.rcParams['figure.figsize'] = (15, 8)
Populating the interactive namespace from numpy and matplotlib

WARNING: pylab import has clobbered these variables: ['plt']
`%matplotlib` prevents importing * from pylab and numpy

Data

In [2]:
# Load data
data = pd.read_csv('../datasets/NESARC/nesarc_pds.csv', usecols=[
    'ETHRACE2A',
    'AGE','S1Q24LB','S1Q24FT','S1Q24IN','SEX','NUMPERS','ETOTLCA2','S1Q4A','S1Q8D','S1Q12A'
])
In [20]:
# Custom dataframe
df = pd.DataFrame()

# Hypothesis to test
df['RACE'] = data['ETHRACE2A'].replace(' ',np.NaN).astype(float)
races = {1:'white',2:'black',3:'indian(US)',4:'asian',5:'latino'}

# Cluster variables
df['AGE'] = data['AGE'].replace(' ',np.NaN).replace('98',np.NaN).astype(float)
df['WEIGHT'] = data['S1Q24LB'].replace(' ',np.NaN).replace('999',np.NaN).astype(float)
df['HEIGHT'] = (
    (data['S1Q24FT'].replace(' ',np.NaN).replace(99, numpy.nan)*12) +
    data['S1Q24IN'].replace(' ',np.NaN).replace(99, numpy.nan)
).astype(float)
df['MALE'] = data['SEX'].replace(' ',np.NaN).replace('2','0').astype(float)
df['HOUSE_PEOPLE'] = data['NUMPERS'].replace(' ',np.NaN).astype(float)
df['ALCOHOL'] = data['ETOTLCA2'].replace(' ',np.NaN).astype(float)
df['MARRIAGE'] = data['S1Q4A'].replace(' ',np.NaN).replace('99',np.NaN).astype(float)
df['WORK'] = data['S1Q8D'].replace(' ',np.NaN).replace('99',np.NaN).replace('0',np.NaN).astype(float)
df['INCOME'] = data['S1Q12A'].replace(' ',np.NaN).astype(float)


df = df.dropna()
In [4]:
TARGET = 'RACE'
PREDICTORS = list(df.columns)
PREDICTORS.remove(TARGET)

df_predictors = pd.DataFrame()

Standardize predictors

  • 0 Mean
  • 1 Standadrd deviation
In [5]:
for predictor in PREDICTORS:
    pred_data = df[predictor] 
    df_predictors[predictor] = (df[predictor] - df[predictor].mean()) / df[predictor].std()
df_predictors.describe()
Out[5]:
AGE WEIGHT HEIGHT MALE HOUSE_PEOPLE ALCOHOL MARRIAGE WORK INCOME
count 1.570200e+04 1.570200e+04 1.570200e+04 1.570200e+04 1.570200e+04 1.570200e+04 1.570200e+04 1.570200e+04 1.570200e+04
mean 2.117781e-16 -2.823708e-16 -8.398722e-16 2.104206e-17 9.412361e-17 3.439132e-17 -2.823708e-16 -3.330528e-16 -7.240278e-18
std 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00 1.000000e+00
min -2.015098e+00 -2.388372e+00 -4.858450e+00 -1.008153e+00 -1.216617e+00 -4.053539e-01 -1.873343e+00 -3.117579e+00 -8.835691e-01
25% -7.548403e-01 -7.321952e-01 -8.146992e-01 -1.008153e+00 -5.127884e-01 -3.916779e-01 -6.963413e-01 -4.496405e-01 -4.718053e-01
50% -8.764499e-02 -1.142190e-01 -5.649585e-02 9.918495e-01 -5.127884e-01 -3.192029e-01 -1.078406e-01 -2.273123e-01 -1.733846e-01
75% 6.536832e-01 5.779145e-01 7.017075e-01 9.918495e-01 8.948696e-01 -1.173722e-02 4.806602e-01 4.396724e-01 1.818782e-01
max 3.618996e+00 6.807115e+00 4.239990e+00 9.918495e-01 7.229331e+00 2.389725e+01 7.738836e+00 1.155608e+01 4.174762e+01

Model

K factor selection

In order to choose the optimum value for K, I'm calculating the average distance from a point to its asigned cluster versus for every K from 1 to 10.

In [6]:
K_MAX = 10
In [7]:
#Don't touch!
K_MAX += 1
meandist=[]

for k in range(1,K_MAX):
    model=KMeans(n_clusters=k)
    clusassign=model.fit_predict(df_predictors)    
    meandist.append(np.mean([
        euclidean(df_predictors.values[i], model.cluster_centers_[cluster])
        for i,cluster in enumerate(clusassign)
    ]))
In [8]:
plt.plot(range(1,K_MAX), meandist)
plt.xlabel('Number of clusters')
plt.ylabel('Average distance')
plt.title('Selecting k with the Elbow Method')
Out[8]:
<matplotlib.text.Text at 0x7f4f5dccb810>

In the plot, it is possible to see than adding a new cluster when we have 5 clusters do not decrease much the average distance.

In [9]:
increments = [0]+[ meandist[x]-meandist[x-1] for x in range(1,K_MAX-1)]
plt.plot(range(1,K_MAX), increments)
plt.xlabel('Number of clusters')
plt.ylabel('Increment in avg distance')
plt.title('Increments in avg distance when adding a new cluster')
Out[9]:
<matplotlib.text.Text at 0x7f4f5dbe4c50>

This plot represents the increment (or decrement) of the average intra-cluster distance when adding a new cluster. It is possible to see the increment stabilizes from cluster 5 with a peak on K=7 and then decreases logarithmically. So, I say the optimal number of clusters is 5.

In [10]:
K=5

5-cluster representation with PCA

In [11]:
#Color palette
colors = sns.color_palette("hls", K)

# Interpret 5 cluster solution
model5=KMeans(n_clusters=K)
model5.fit_predict(df_predictors)

# plot clusters
pca_2 = PCA(2)
plot_columns = pca_2.fit_transform(df_predictors)
plt.scatter(x=plot_columns[:,0], y=plot_columns[:,1], c=[colors[c]for c in model5.labels_])
plt.xlabel('Canonical variable 1')
plt.ylabel('Canonical variable 2')
plt.title('Scatterplot of Canonical Variables for {0} Clusters'.format(K))
plt.show()
In [12]:
print('PCA\n -Number of components: {0}\n -Variance explained: {1}'.format(pca_2.n_components_,pca_2.explained_variance_ratio_.sum()))
PCA
 -Number of components: 2
 -Variance explained: 0.410488357793

The 2-axis plot, coloured with 5 colors (same as the number of clusters), shows 4 clearly distinguishable clusters. This PCA model only captures a 41% of the variance, so I cannot say if the fifth cluster is not easily seen due to the visualization or its contribution to the K-means model.

To test this hypothesis, I will run a Chi-Square test of independence.

In [13]:
df_chi = pd.DataFrame()
df_chi[TARGET] = df[TARGET]
df_chi['CLUSTER'] = model5.labels_
In [14]:
#Contingency table, observations
ct1 = pd.crosstab(df_chi['CLUSTER'],df_chi['RACE'])
print ct1
RACE        1    2   3    4    5
CLUSTER                         
0        2276  425  50   60  344
1         217   67  11    6   49
2        2552  480  65   52  484
3        2855  567  73  117  961
4        2353  463  56  136  983

In [15]:
#Percentages
colsum = ct1.sum(axis=0)
colpct = ct1/colsum
print (colpct)
RACE            1         2         3         4         5
CLUSTER                                                  
0        0.221984  0.212288  0.196078  0.161725  0.121943
1        0.021165  0.033467  0.043137  0.016173  0.017370
2        0.248903  0.239760  0.254902  0.140162  0.171570
3        0.278455  0.283217  0.286275  0.315364  0.340659
4        0.229494  0.231269  0.219608  0.366577  0.348458

In [16]:
# chi-square test
cs1 = chi2_contingency(ct1)
print("X² Value = {0}".format(cs1[0]))
print("p-value = {0}".format(cs1[1]))
X² Value = 384.230240286
p-value = 7.31131755895e-72

The $\chi^2$ test of indepence gives a p-value lesser than 0.05, so the race and the clusster assignation are significantly associated.

Post hoc test - Bonferroni Adjustment

  • Number of categories: 5
  • Number of comparisons: $\binom{5}{2} = 10$
  • Adjusted p-value: $\frac{p-value}{number of comparisons} = \frac{0.05}{10} = 0.005$
In [17]:
from itertools import combinations
comparison_pairs = list(combinations(races.keys(),2))
ap_val = 0.05/len(comparison_pairs) #Adjusted p-value

for (v1,v2) in comparison_pairs:
    print("PAIR: {0}-{1}".format(races[v1],races[v2]))
    df2 = df_chi[(df_chi['RACE']==v1) | (df_chi['RACE']==v2)]
    ct2 = pd.crosstab(df2['CLUSTER'],df2['RACE'])
    cs2 = chi2_contingency(ct2)
    print("\t p-value: {0}".format(cs2[1]))
    print("\t Reject: {0}".format(cs2[1]<ap_val))
PAIR: white-black
  p-value: 0.0147537262383
  Reject: False
PAIR: white-indian(US)
  p-value: 0.165591902325
  Reject: False
PAIR: white-asian
  p-value: 5.07966700917e-11
  Reject: True
PAIR: white-latino
  p-value: 3.09820579923e-68
  Reject: True
PAIR: black-indian(US)
  p-value: 0.869722513026
  Reject: False
PAIR: black-asian
  p-value: 4.74267012052e-09
  Reject: True
PAIR: black-latino
  p-value: 9.03882670447e-35
  Reject: True
PAIR: indian(US)-asian
  p-value: 2.21147789828e-05
  Reject: True
PAIR: indian(US)-latino
  p-value: 3.18119315297e-08
  Reject: True
PAIR: asian-latino
  p-value: 0.136856284896
  Reject: False

After the Bonferroni adjustment, these are the two groups statistically different in terms of the 5-groups clustering.

  • white-black-indian
  • asian-latino

These two superclusters could indicate wether the subject have roots in the country (first group) or they is an inmigrant or a first/secod generation citizen. It will be nice to know wich clusters are associated with the race superclusters

The race seems to be correlated with the output of the clustering process. It is not possible to say the race of a subject knowing their 9 features (AGE, WEIGHT, HEIGHT, MALE, HOUSE_PEOPLE, ALCOHOL, MARRIAGE, WORK and INCOME) but it is possible to assign them to a group.

TODO: know the meaning of the group.

Copyright © Samuel M.H. All rights reserved. Powered by Blogger.