Horno para soldar PCBs

Llevo un tiempo con este proyecto para el taller: un horno para soldar placas. No he querido hacer varios posts «diarios» comentando las actualizaciones del proyecto, básicamente porque no tenía muy claro qué componentes utilizar, y si podría programar el firmware en un tiempo más o menos razonable.

Al final, ha salido todo mucho más rápido de lo que pensaba, asi que os voy a hacer un resumen del proyecto, y quizás escriba algún artículo sobre algun tema concreto, ya que han salido distintos temas muy interesantes. La idea general es usar un horno normal y corriente, y controlar la temperatura con un arduino. Para ello usaremos una sonda de temperatura para ir tomando la medida, y un relé de estado sólido para encender y apagar las resistencias del horno (Usaremos un relé de estado sólido, porque el relé mecánico se estropearía con el tiempo de tanto on/off).

 

ImagenImagen

 

El horno lo conseguí de segunda mano en ebay. He probado uno de 1300W, pequeñito, totalmente mecánico (sin electrónica ni circuitos). Estos hornos tienen 2 resistencias, que simplemente están conectadas a la corriente principal. El funcionamiento es bastante simple. Trae un potenciómetro básico para controlar la potencia de las resistencias, y un cronómetro con una campanilla para apagar el horno tras un tiempo. Lo que haremos será, poner el potenciómetro a tope (controlaremos nosotros mismos la potencia), y simplemente desconectamos los dos cables de cronómetro y los conectamos en el relé de estado sólido. El Arduino irá encendiendo y apagando las resistencias (mediante pulsos) controlando la temperatura del interior del horno.

Este es el esquema del circuito de control:

Imagen

Para alimentar el arduino, he comprado una fuente de 12V para LEDs super económica de 2 Amperios. Realmente con 1A sería suficiente, pero por el precio que tienen, he visto que era la opción más económica. Podrías alimentar al arduino por el conector de 12V, pero no es muy recomendable porque cuando el arduíno envía pulsos al ventilador y relé, la pantalla también parpadea. Lo mejor es usar alimentaciñón externa, y que cada cosa vaya independiente.

 

Imagen

Sobre el control de la placa, podéis leer mi anterior artículo sobre encoders para entender mejor los detalles de estos dispositivos.

He probado varias pantallas LCDs, y me quedo con las pantallas gráficas de Nokia 5110, que son muy baratas, y puedo hacer una gráfica con la temperatura, etc. Lo malo es que el LCD usa 3.3V, y como el arduino funciona a 5V, hay usar un «conversor de niveles». Yo he usado uno de adafruit, que es bidireccional, pero se podría usar algo más económico unidireccional, ya que esta pantalla no envía los datos de vuelta al arduino. He incluido un pequeño potenciometro para controlar el contraste de la pantalla. Dejaré los detalles del LCD para un futuro artículo.

 

Imagen

Las salidas del Arduino Uno de 5V, no tienen potencia suficiente para mover el ventilador y activar el relé, así que necesitamos transistores que amplifiquen la corriente. Se puede usar un MOSFET, pero no es necesario tanto. Con unos simple transistores bipolares, tenemos fuerza suficiente para mover el ventilador, y activar el relé.

El esquema del transistor del relé es muy simple. Cuando la base tiene 5V, el transistor se activa y permite pasar los 12V al relé. Una resistencia proteje la base del transistor (los bipolares necesitan resistencias, en los MOSFETs no es necesario). Otra resistencia hace de pulldown para que, en el caso que la señal del arduino quede flotando, la base del transistor se mantenga siempre apagada y la corriente no pase de forma aleatoria.

 

Imagen

 

El esquema del ventilador es igual, pero incluye un condensador de 10uF , que sumada a los 2.2K de la resistencia, filtra un poco los pulsos que envía el Arduino. De esta forma, los pulsos no son tan bruscos y reducen las vibraciones del ventilador. Ambos transistores no llevan el típico diodo de protección, porque el relé no devuelve energía de vuelta al transistor, y el ventilador tiene su propio circuito de protección en el motor brushless. De todos modos, si no sabes muy bien qué vas a conectar, entonces es aconsejable conectar un diodo flyback que proteja el transistor de voltajes de vuelta.

 

Para medir la temperatura, he usado un thermopcoupler de alta temperatura (aguanta perfectamente hasta 300º). Los thermocouplers dan un voltaje proporcional a la temperatura. El problema es que ese voltaje es muy muy pequeño, millivoltios, asi que hace falta un amplificador para poder leer un valor útil. El amplificador que he escogido tiene 2 salidas: un voltaje para la sonda, y otro para la temperatura ambiente. He incluido un condensador para filtrar el voltaje de la sonda, y evitar «ruido» indeseado al leer la temperatura. El problema es que esto hace que tengamos un «retraso» entre la lectura y la realidad, pero la lectura es más estable.

La otra opción es usar un económico termistor, una resistencia variable que, aplicando un voltaje conocido, serviría para leer la temperatura. El problema es que no funciona muy bien en temperaturas altas, y ya que los componentes pueden llegar a estropearse si nos pasamos, asi que he decido apostar por la sonda, que además, está protegida para aguantar temperaturas muy altas. Quizás escriba otro artículo sobre las sondas, amplificadores usando un opamp, etc.

Ojo, es importante usar algun separador de nylon entre el ventilador y el horno, porque el plástico ABS funde a unos 230º grados y se podría derretir con el calor!!

Imagen

 

Para depurar, he incluido un buzzer y un LED con un jumper que me permite conectarlo al pin del PWM, o usar otro pin del arduino a modo de depuración, avisos, etc. El código está disponible en github , tal cual lo estoy usando ahora mismo. Seguramente sea muy mejorable, pero es suficiente para usar el horno de forma estable. Soldar mediante reflow tiene varias etapas. Se comienza haciendo un «preheat» hasta que llegamos a los 150º. Luego nos quedamos unos 2 minutos manteniendo la temperatura estable, dónde se activa el flux de la pasta de soldadura. Después metemos un golpe de 220º de 60 segundo para que el estaño se vuelva líquido y los componentes se colocan en su sitio. Posteriormente reducimos la temperatura despacio, para evitar que el estaño enfríe demasiado rápido.

El algoritmo de PID también se merece un artículo propio. Yo he usado el código basandome en la librería PID de arduino, adaptado a C normal (últimamente soy un poco alérgico al C++). PID significa «proporcional, intergral y derivada», y es un algoritmo que nos permite saber cuanta potencia hay que mandar al horno para llegar a la temperatura deseada, de forma más o menos óptima. Durante el horneado, el ventilador se mantiene al mínimo, oscilando aproximadamente entre un 50% y un 30% de velocidad , que permite mover lo mínimo el aire, sin enfriar el interior, pero sin llegar a pararse. De esta forma conseguimos que la temperatura sea uniforme dentro del horno. De todos modos tengo que comenzar a realizar pruebas para ver cómo afecta a la calidad de las soldaduras.

La primera versión del circuito lo pasé a una PCB muy sencilla de una cara, a modo de shield de arduino. He puesto unos pines hembra para conectar la pantalla y el conversor de niveles. Es suficiente para hacer las primeras soldaduras, y probar bien el circuito. Os dejo unas fotos del proceso de la PCB

 

. ImagenImagenImagen

 

Ahora queda la parte de cerrar todo de alguna forma, meter la pantalla y la placa dentro, etc. Pero he decidido usar el horno varias veces antes de ponerme  a cortar. Quizás saque una versión nueva de la PCB, con el chip del AVR y de doble capa, y con la pantalla y el encoder por separado. De esta forma es sencillo atornillar esta placa al frontal del horno. Pero eso para más adelante. Estoy a la espera de unas placas y de pasta de soldadura nueva, para realizar los primeros test, y publicar aquí resultados.

Cómo usar un Encoder con un Arduino

Un encoder es muy parecido a un potenciómetro por fuera, pero en realidad son muy distintos. El potenciómetro nos da un valor analógico que tenemos que leer, pero el encoder nos envía información «digital» que vamos leyendo según la ruedecita gira. Un modelo común es el PEC11-4215F-S0024, que nos envía 24 «pulsos» en una vuelta completa.

El encoder tiene 3 patillas para los pulsos, y 2 patillas para el boton principal (si pulsas el eje hacia dentro actua como un pulsador).  Este sería el esquema del encoder. Los puntos rojos es donde conectamos los pines del arduino:

sche

BTN es el pin del Botón. Cuando pulsamos, se conectan los 5V con tierra, y BTN vale 0. El resto del tiempo, se mantiene alto.

Para detectar el giro, la idea es conectar una patilla común a tierra, y las otras dos a 5V (con una resistencia de pull up de por ejemplo, 10k). Según vamos girando, el encoder conecta la patilla A y la patilla B a tierra, con un ligero desfase, efectuando así un pulso, que podremos detectar en nuestro arduino.

Si la patilla A baja antes que la patilla B, vamos en el sentido del reloj, y si la patilla B baja antes, vamos hacia atrás.

Esto es una foto del osciloscopio, mostrando las patillas A y B superpuestas, cuando giramos el encoder:

osc

En «reposo», el encoder tiene las 2 patillas en 1. Al girar, se conecta la patilla A con GND, y el voltaje se pone a 0,  seguimos girando y la patilla B, más o menos a la mitad del pulso toca GND, y ambas se ponen a 0. Segun seguimos girando, la patilla A deja de estar conectada a GND, asi que vuelve a 1, y luego la patilla B, volviendo ambas a 1. La longitud del pulso depende de la velocidad a la que nosotros giramos la ruedecita.

Aqui tenemos 1 pulso del encoder :

img1

Podemos pasar esto a binario, 1 cuando el voltaje está alto, 0, cuando está bajo, tomando los valores en distintos momentos del tiempo:

img2

Esto lo podemos traducir a binario:

img3

O sea, la secuencia seria 3 2 0 1 3. Así que, ¿cómo leer esto, y tener control del encoder?

Yo voy a leer todo en la interrución del timer, a intervalos regulares, a una velocidad constante de 125khz. Lo hago así porque luego voy a comunicarme con otros dispositivos, y asi puedo aprovechar la interrupción más tarde. Asi que 125 veces por milisegundo, voy a leer el estado de las 2 patillas para ver si estamos en un pulso o no.

Pero aqui surge un problema. Si mirais la foto del osciloscopio, vemos que hay unos picos raros:

osc2

Esto es debido a que los contactos metálicos producen vibraciones, como minichispazos, cuando se separan, y es posible que durante un tiempo la carga se mantenga saltando (bouncing en inglés). Asi que no nos podemos fiar de una lectura simple. Lo que hacemos generalmente es leer varias veces el valor de las patillas, y ver que no han cambiado en el tiempo. Si tras varias lecturas, por ejemplo 125, o lo que es lo mismo, 1 milisegundo, el valor es el mismo, pues aceptamos esa lectura. Este proceso se denomina «debouncing«.

static volatile uint8_t enc_value;
static volatile uint8_t enc_tests;

# define PINS_READ_ENC PINB
# define PINS_WRITE_ENC PORTB
# define PINS_DDR_ENC DDRB
# define PINS_OFFSET_ENC_A 0
# define PINS_OFFSET_ENC_B 1

void encoder_read (void )
{
// leo las 2 patillas al mismo tiempo. Debeis de conectar las 2 patillas del encoder en el mismo puerto!
const uint8_t input = PINS_READ_ENC;
const uint8_t read = ( BitIsSet ( input , PINS_OFFSET_ENC_B ) << 1 ) |
                     ( BitIsSet ( input , PINS_OFFSET_ENC_A ) << 0 ) ;

if ( read != enc_value )
{
enc_tests = 125; // 1 ms a 125khz
enc_value = read;
return;
}

if (enc_tests > 0)
{
-- enc_tests ;
return;
}

if ( enc_tests == 0 )
{
// comprobamos si estamos en un pulso
}

}

El código es C puro, pero facilmente lo podréis pasar al arduino. Realmente q la interrupción sea de 125Khz no es relevante. 1 ms es suficiente para la mayoria de usos.

¿Cómo saber si estamos o no estamos girando, y la direccion? Aqui muchos tutoriales se lian un poco con la secuencia. Si miramos el osciloscopio, vemos que un pulso lo tenemos cuando ambos pines están a 0. Y el valor previo nos dice si estamos girando hacia un lado o hacia otro. Asi que cuando el valor de los 2 pines sea 0, incrementamos o decrementamos en función de la posición.

Técnicamente necesitaríamos salir del pulso, pero en general estos encoders se usan para mover un cursor en el menú de la pantalla y no tiene sentido conocer los pasos intermedios del giro. Si tuviesemos un encoder para medir la posición de un servo entonces usaríamos otras formas de leer los datos, y seguramente, otro encoder más caro :)

Asi que si recordamos la imagen del osciloscopio, vemos que cuando ambos pines están a 0, o bien el A o bien el B tienen que estar abajo antes. Esto es 01 ó 10 en binario: 1 ó 2 en decimal.

Para incrementar el valor de la posición actual (index), sumamos 1 al contador, pero luego comprobamos que no nos pasamos de los pulsos por vuelta (24 según este modelo de encoder). Asi que sumamos 1 y aplicamos el módulo, para que al llegar a 23+1, volvamos a 0. De este modo index se moverá de 0 a 23.

Para decrementar, en vez de restar 1, damos una vuelta entera, sumando 23 y aplciando el módulo. De esta forma, no tenemos que lidiar con valores negativos, y todo es más sencillo luego.

El bit más alto, el signo, del índice, lo reservo para indicar la dirección de giro. 0 significa al sentido del reloj, 1 al revés.

Al guardar el indice de esta forma, digamos que tenemos una representacion angular del encoder, que representa de 0 a 360 grados (con el valor de 0 a 23), con el signo para decirnos qué dirección tomamos para girar.

static volatile uint8_t enc_value;
static volatile uint8_t enc_tests;
static volatile uint8_t enc_index;
static volatile uint8_t enc_previ;

# define PINS_READ_ENC		PINB
# define PINS_WRITE_ENC		PORTB
# define PINS_DDR_ENC		DDRB
# define PINS_OFFSET_ENC_A		0
# define PINS_OFFSET_ENC_B		1

# define ENC_STEPS			24

# define ENC_INDEX_INC		(enc_index = 0< 0)
	{
		-- enc_tests ;
		return;
	}

	if ( enc_tests == 0 )
	{
		if ( ENC_READ_AB == 0)
		{
		     if ( enc_previ == 1 ) ENC_INDEX_INC ;
		else if ( enc_previ == 2 ) ENC_INDEX_DEC ;
		}
 		enc_previ = ENC_READ_AB ;

	}
}

Tambien podemos incluir aqui el valor del pulsador. Al incluir la rutina de «debounce«, nos ahorramos tambien el tema del ruido, pero eso hace que el pulso sea de al menos 1 ms, que depende de lo rapido que seamos, puede ser o no suficiente. Usamos el bit 6 del index para representar el estado actual del pulsador. El código final quedaría asi:

static volatile uint8_t enc_value;
static volatile uint16_t enc_tests;
static volatile uint8_t enc_index;
static volatile uint8_t enc_previ;

# define PINS_READ_ENC PINB
# define PINS_WRITE_ENC PORTB
# define PINS_DDR_ENC DDRB
# define PINS_OFFSET_ENC_A 0
# define PINS_OFFSET_ENC_B 1
# define PINS_OFFSET_ENC_BTN 2

# define ENC_STEPS 20

# define ENC_INDEX_INC (enc_index = 0<<7 | ( (enc_index & 0x3f) + 1 ) % ENC_STEPS)
# define ENC_INDEX_DEC (enc_index = 1<<7 | ( (enc_index & 0x3f) + (ENC_STEPS-1) ) % ENC_STEPS)

# define ENC_READ_AB (read & 0x03)
# define ENC_READ_BTN (read & 1<<2)

void encoder_read (void )
{
 // sure both reads same time
 const uint8_t input = PINS_READ_ENC;
 const uint8_t read = ( BitIsSet ( input , PINS_OFFSET_ENC_BTN ) << 2 ) | ( BitIsSet ( input , PINS_OFFSET_ENC_B ) << 1 ) | ( BitIsSet ( input , PINS_OFFSET_ENC_A ) << 0 ) ;

 if ( read != enc_value )
 {
 enc_tests = 125; // 1 milliseconds on 125khz timer (PEC11 datasheet max debounce rate)
 enc_value = read;
 return;
 }

 if (enc_tests > 0)
 {
 -- enc_tests ;
 return;
 }

 if ( enc_tests == 0 )
 {
 if ( ENC_READ_AB == 0)
 {
 if ( enc_previ == 1 ) ENC_INDEX_INC ;
 else if ( enc_previ == 2 ) ENC_INDEX_DEC ;
 }
 enc_previ = ENC_READ_AB ;

 if ( ENC_READ_BTN )
 {
 ClearBit (enc_index,6);
 }
 else
 {
 SetBit (enc_index,6);
 }
 }
}

Como ejercicio para el lector, queda poder medir la velocidad de giro, contando los «ticks» que han pasado desde que dejan de estar ambos pines a 1, hasta que vuelven a estar ambos pines a 1. Y si tienes ganas, pasarlo a arduino para que la gente pueda usarlo rápidamente.

Por ahora funciona bien, si giras muy muy rápido puede perder algun paso, sobre todo por el «debouncer», pero no es relevante, ya que personalmente voy a usar el encoder para controlar el menú de una pantalla, y es más que suficiente.