Estadística de los exámenes tipo test

La semana pasada hice un examen tipo test. Eran 150 preguntas y pedían, para aprobar, el 70%. La pregunta es ¿ese 70% tiene su justificación matemática o es más bien un limite arbitrario? Vamos a hablar de cómo interviene el azar al responder preguntas y de las diferentes formas de compensarlo.

Artículo completo >>

Electrocardiograma y electrorretinograma.

Este es un artículo sobre DSP con un trasfondo de electromedicina. En una entrada anterior ya vimos lo que era una transformada de Fourier y cómo se utilizaba. La Transformada de Fourier no es magia. Para entender mejor lo que sigue te recomiendo que la leas si aún no lo has hecho. Hoy vamos a aplicarla para limpiar una señal todo lo que podamos. Pero ¿qué es limpiar? Pues para nosotros es seleccionar, de todo lo que capten nuestros sensores, sólo aquello que nos interesa; eliminando el ruido y otras interferencias.

Este experimento lo hice en el 2006 y consiste en construir un electrocardiógrafo. Pero ya desde el principio os advierto: si bien captar señales eléctricas en el cuerpo es relativamente sencillo, lo difícil es hacerlo bien. Y con hacerlo bien quiero decir que lo que registremos sirva para algo. Cuando un cardiólogo interpreta un electro, espera que los electrodos estén puestos siempre en el mismo sitio, que el gel tenga una conductividad determinada, que el circuito aplique unos filtros ya tipificados (homologación), etc. Así que la forma de onda que nosotros vamos a obtener no va a pasar de ser una mera curiosidad electrónica pues no tiene, ni mucho menos, valor médico alguno.


Artículo completo >>

La Transformada de Fourier no es magia

Este no es el típico artículo en plan "¡Ey, no es magia: sólo son matemáticas avanzadas y te da igual porque no vas a entender ni jota!".


Hace tiempo que quería hablaros de la Transformada de Fourier. Pero no encontraba una forma de presentar el artículo sin que me quedara demasiado matemático. Espero que el enfoque que le voy a dar hoy os sirva para aclarar algunas dudas. Como no quiero entrar en demostraciones muchos puntos los tendré que introducir por las buenas y otros dejarlos a medias. Si algo no os termina de convencer profundizad en el tema, necesitaréis cierto nivel de matemáticas pero comprobaréis que todo está atado y bien atado.

Artículo completo >>

Rastreador de redes inalámbricas

Hoy os traigo un artículo breve de programación. Este programa nos ayudará a localizar la fuente de una wifi siempre y cuando tengamos una antena directiva. A modo de radar, el sistema emitirá un tono cada vez que recibamos una baliza de la red seleccionada, y de una frecuencia más alta mientras mayor sea la potencia recibida.

Artículo completo >>

Frecuencímetro para el PC

Después de un par de artículos más bien teóricos ahora os quiero presentar un montaje práctico. Vamos a ver cómo hacer un frecuencímetro que sea lo más sencillo posible, pero que sea a la vez útil y preciso.


Empezaremos viendo una característica poco conocida de los PICs y construiremos un circuito para aprovecharla. En el firmware del PIC haremos que mande el valor por puerto serie al PC utilizando el conversor USB->RS232. Pero la frecuencia no será exacta, y hará falta calibrarlo. Para terminar escribiremos una pequeña interfaz en Perl/Tk para que nos indique la frecuencia.


Artículo completo >>

El transistor, ese gran desconocido: Regulador V-I

El transistor se inventó en el 1947 y desde entonces raro es el circuito en el que no lo usamos, bien sea en como componente individual o en grupo formando un operacional, o un microcontrolador. Sin embargo, a pesar de esta omnipresencia, es un componente poco comprendido en general por nosotros los aficionados. Las ecuaciones que lo definen son complicadas y para simularlo se necesitan modelos con decenas de parámetros sutiles. Fijaos en el modelo SPICE para el 2N2222:

.model Q2N2222A NPN (IS=14.34F XTI=3 EG=1.11 VAF= 74.03 BF=255.9
+NE=1.307 ISE=14.34F IKF=.2847 XTB=1.5 BR=6.092 NC=2 ISC=0 IKR=0
+RC=1 CJC=7.306P MJC=.3416 VJC=.75 FC=.5 CJE=22.01P MJE=.377
+VJE=.75 TR=46.91N TF=411.1P ITF=.6 VTF=1.7 XTF=3 RB=10)

Y son solo los parámetros para una simulación decente, en un datasheet completo vienen bastantes más. Por suerte para nosotros, para el uso diario hay modelos simplificados y con conocer cuatro relaciones simples nos basta. Pero no caigamos en el error de pensar que eso es todo, el transistor es una maravilla de la física de estado sólido.

Como electrónicos no nos interesa tanto el modelo matemático como sus consecuencias. Así que lo que vamos a hacer es coger un simulador y plantear algunos circuitos simples para ver lo que pasa. Usaré el LTSpice, que es gratuito. Si no lo conocéis, echadle un vistazo: LT Spice. Los diagramas que hace no son vistosos, pero para análisis es muy cómodo y potente.


Regulador de tensión



Empezaremos por una fuente de tensión. Que es un circuito muy sencillo para empezar. Tomamos el transistor y alimentamos la base con una tensión fija. En el circuito de la izquierda la tensión la obtenemos de un diodo zener. En el de la derecha, por simplificar, conecto una referencia de voltaje. Cuando el transistor trabaja en la zona activa, la tensión en el emisor es igual a la de base menos la caída base-emisor, que viene a estar entre 0.6 y 0.7 voltios. Matemáticamente

\[V_E = V_B - V_{BE}\]
por eso elegimos el zener de 4.6V.

Aunque en realidad eso tampoco es así. La caída de tensión en la unión base-emisor depende:
  • De la corriente de base.
  • De la tensión colector-emisor para una intensidad de colector fija.
  • Y de la temperatura.

Más información aquí. La dependencia con la temperatura de usa mucho para hacer sensores. Aunque no es nada lineal sale más barato que una resistencia NTC. De manera gráfica:


Como no hay manera de controlarlo, asumimos una caída de tensión de 0.6 voltios y ya está. Al fin y al cabo un regulador que varía con la temperatura y con la carga no es muy estable, así que por una diferencia de medio voltio arriba o abajo no nos vamos a morir. Si la carga fuera muy crítica utilizaríamos otro circuito.

Como decíamos, la tensión en el emisor es más o menos constante. Vamos a hacer la prueba. Conectamos una resistencia que varía antes 100 y 2000Ω y medimos la tensión en sus extremos y la intensidad que la atraviesa:


Vemos como a medida que la resistencia aumenta pasa menos corriente por ella, sin embargo la tensión es más o menos la misma siempre. Va desde 3.83V para una intensidad de 38.3mA (100Ω de resistencia) hasta 3.91V cuando la intensidad es de 1.95mA (2000Ω).



Regulador de intensidad

Por la ley de ohm sabemos que, para una resistencia dada, la intensidad es proporcional a la tensión. Eso lo podemos aprovechar para construir una fuente de corriente constante. Cogemos el regulador de antes y ponemos de carga una resistencia fija. Como la tensión era siempre la misma, por esa resistencia pasará siempre una intensidad concreta. Y además es independiente de la tensión de alimentación, así que podemos variar la tensión de colector sin alterar el circuito. Pues ya está:



En el circuito de arriba la caída base-emisor es de aproximadamente 0.837V (medido en la simulación). Así que la tensión en el emisor es de

\[V_E = V_B - V_{BE} = 2V - 0.837V = 1.16V\]
La resistencia de emisor esta vez es fija y vale 100ohm, pasarán por ella $${1.16V \over 100\Omega} = 11.6mA$$ . De esos 11.6mA la gran parte vendrá del colector, salvo una mínima parte que viene de la base. ¿Cuanta corriente pasa por la base? Pues es fácil de calcular a partir de la ganancia en corriente $$\beta$$ del transistor. El transistor ideal del ltspice tiene una ganancia de 101:

\[I_B = {I_E \over \beta} = {11.63mA \over 101} = 115\mu A\]
Así que la corriente de colector vendrá a ser de 11.5mA. Lo normal es que el cálculo de arriba no se haga, y se desprecie la corriente de base en comparación con la de colector. Y terminemos diciendo que por el emisor para la misma corriente que por el colector, no es cierto del todo, pero casi.

Entonces por el colector van a pasar 11.5mA. ¿Independiente de la carga que le pongamos no? Vamos a probar con una carga de 1Ω y la iremos subiendo hasta por ejemplo 500. Se supone que el transistor mantendrá la corriente en 11.5mA durante todo el recorrido.



¡Funciona! A medida que aumenta la resistencia, el transistor le mete más tensión para que la intensidad no varíe. ¿Cómo lo hace? Pues cuando aumentamos la resistencia de colector, en el transistor desciende la tensión emisor-colector. Así cae menor voltaje en el transistor y más en la resistencia.

Pero... un momento. No puede durar siempre, porque llegará un momento en que la tensión colector-emisor llegue a cero. El transistor no genera nada, es sólo un grifo que deja pasar más o menos. Y cuando está abierto por completo, ya no deja pasar más.

Lo que va a pasar es esto:


La tensión Vce comienza siendo muy alta, porque al principio con una resistencia baja la caída de tensión en el transistor tiene que ser grande para no exceder la intensidad. Pero a medida que aumenta la resistencia, el transistor se abre y va dejando pasar más... hasta que la tensión Vce llega a un valor mínimo. Es la tensión de saturación, que en un modelo ideal es prácticamente 0.

Está claro que la intensidad ya no se va a mantener constante:


A partir de 750Ω más o menos la intensidad comienza a decaer. Sin embargo se mantiene la tensión porque la unión base-colector está ahora polarizada en directa. Y es como si fuera un diodo. De echo la tensión se estabiliza en

\[V_R = V - V_2 - V_{BC}\]

Se ve bien en este gráfico:


La línea roja es la ganancia en corriente (beta) del transistor. Durante la zona activa se mantiene en un valor constante (fijaos en eso) igual a 100, que es la ganancia del transistor ideal. Y en cuanto entramos en la zona de saturación se va a 0.

¿Constante...? Oye, ¿no te parece raro que la ganancia sea constante a lo largo de toda la fase activa? Podría ser, pero no, es una consecuencia de haber tomado el transistor ideal.

Componente reactivo

Bien, hasta aquí la parte aburrida de repaso. Ahora vamos a coger nuestra fuente de intensidad y en lugar de aplicarle una resistencia le vamos a conectar una bobina. Recordemos que la bobina se opone a los cambios de corriente. Lo vimos en la entrada anterior: El circuito RLC serie: oscilaciones amortiguadas.


Así pensando un poco esperamos que al principio oponga una resistencia muy grande, tendiendo a infinito. Con una resistencia muy grande el transistor estaba saturado, y lo que le aplicaba era una tensión constante. Sabíamos que la ecuación de una bobina era:

\[v = L\frac{di}{dt}\]
la v la sabemos, la aplica el transistor. Si despejamos la i:

\[ i = \frac{1}{L} \int v dt \]
Entonces con una tensión constante,

\[i = cte \cdot t\]
o sea, que la intensidad va a crecer en línea recta mientras el transistor esté saturado. En el momento en que la resistencia de la bobina decrezca hasta cierto valor entraremos en la zona activa. Ahí lo que se mantiene constante es la intensidad. Pero la bobina sólo reacciona a los cambios de corriente ¿qué pasará ahora que no hay cambios de corriente? Pues se supone que actuará como si no estuviera, resistencia prácticamente nula.

Veamos si estamos en lo cierto:


En efecto, la V es continua al principio, mientras la I crece linealmente. En cuanto la I alcanza la corriente de saturación (los 11.5mA) se queda ahí y no crece más. Al no haber más cambio en la intensidad la bobina no ofrece resistencia alguna, y la tensión en sus extremos cae a 0.

Vamos a dibujar ahora la relación entre la tensión y la corriente que atraviesa la bobina, lo que sería la resistencia, para ver cómo evoluciona en el tiempo.


Al principio es muy grande, luego va bajando... y llega un momento en que cae de golpe a cero.


Pero... ¿Un ángulo recto? Está claro que ni de coña. En la naturaleza las cosas no son así. Es porque el transistor es ideal, luego vamos a ver qué pasa de verdad.


Efecto Early

Decíamos antes que lo de la ganancia constante era porque habíamos cogido un transistor ideal. Vamos a coger otro, por ejemplo un 2N2222.


Vamos a graficar de nuevo la ganancia en corriente, como hicimos antes:


Curioso ¿no? Ahora la ganancia ya no es constante, sino que hace pendiente. Es el efecto Early. Para entender por qué ocurre debemos fijarnos en la diferencia de potencial base-colector. Antes habíamos hablado de ella en la etapa de saturación, que está polarizada en directa con una caída similar a la de un diodo. Pero en la fase activa tiene un efecto importante: resulta que a medida que aumenta la polarización inversa, la frontera entre la unión N del colector y P de la base de amplía. Como en un diodo normal. Por eso se llama también Modulación del ancho de la base. Una imagen para ilustrarlo:


La imagen es de esta página An Inside Look at Light Emitting Diodes (LEDs). Habla sobre todo de LEDs, pero también de diodos en general. Os recomiendo que la miréis.

El caso es que cuando un diodo se polariza en directa (aplicando tensión positiva al ánodo y negativa al cátodo) la frontera se estrecha y permite un paso fácil de la corriente. En cambio si lo polarizamos al revés, la frontera se ensancha e impide el paso. Pues lo mismo pasa con la unión base-colector. Una base más estrecha repercute en una mayor ganancia (las razones son muy técnicas como para meterme ahora con ellas). Por eso al principio, que es cuando la polarización inversa base-colector es mayor, tenemos una ganancia grande; mientras que al final, cuando la polarización es más suave, la ganancia se hace más pequeña. Hasta que, llegando a la saturación, la polarización inversa desaparece y la unión queda polarizada en directa, en ese momento la ganancia ya tiende definitivamente a cero.


Capacidad parásita

Decíamos antes que ese corte súbito de la resistencia en una bobina no era normal. Y no lo es. Vamos a ver qué pasa cuando la conectamos a un transistor un poco más "real".


Ya vimos en la entrada anterior, sobre oscilaciones amortiguadas, que la bobina actúa como una masa que tiene inercia. Y que cuando le cambiamos la corriente no reacciona al momento sino que siempre se pasa un poquito. ¡Y eso es justamente lo que hace también en este caso!


Lo que antes era un ángulo recto se ha convertido en una oscilación amortiguada.


Ya vimos que eso sólo pasa en un circuito RLC y sin embargo no vemos ningún condensador por ahí. No hace falta decir que se trata de la capacidad parásita de la unión BC en el transistor. La vamos a calcular y esperamos que nos dé del orden de picofaradios.

Como sabemos el valor de la inductancia, vamos a usar la ecuaciones que explicamos al hablar de oscilaciones amortiguadas. Solo que las aplicaremos al la tensión en la bobina en lugar de a la intensidad por simplificar.

Habíamos visto que el voltaje en un momento dado venía dado por:

\[ V(t) = V_0 e^{-\frac{R}{2L} t } \cos (\omega t)\]
con

\[\omega = \sqrt{\frac{1}{LC}-\left(\frac{R}{2L}\right)^2}\]
donde $$V_0$$ es la amplitud inicial y R, L y C los valores de los componentes.

De momento vamos a calcular la resistencia. La L la sabemos, vale 100mH o sea 0,1H. Partimos del gráfico y nos quedamos con lo que valen los picos -máximos y mínimos-. En los picos el coseno vale 1 o -1, así que tomamos el valor absoluto y nos quitamos el signo.

\[V_{max}(t) = V_0 e^{-\frac{R}{2L} t }\]
Para eliminar la dependencia con $$V_0$$ dividimos la amplitud de un pico entre la del anterior y le llamamos k, por ejemplo:

\[k=\frac{V_{max2}}{V_{max1}} = \frac{V_0 e^{-\frac{R}{2L} t_2 }}{V_0 e^{-\frac{R}{2L} t_1 }}\]
\[k=e^{-\frac{R}{2L}(t_2-t_1)}\]
y de ahí, tomando el logaritmo neperiano despejamos la resistencia:

\[R = -\frac{2L\ln(k)}{t_2-t_1}\]
Una vez que tenemos la resistencia, utilizamos la expresión de antes para la frecuencia angular y despejamos la capacidad:

\[C = \frac{1}{L\left(\omega^2 - \frac{R^2}{4L^2}\right)}\]
Aunque nos falta saber el valor de $$\omega$$. Sin embargo lo calculamos también a partir del tiempo entre picos. La diferencia entre dos máximos o dos mínimos consecutivos es un periodo (T). Como aquí tenemos máximos y mínimos, la diferencia entre dos picos consecutivos es un semiperiodo ( $$\frac{T}{2}$$ ).

Puesto que

\[\omega = \frac{2\pi}{T}\]
ahora nos queda

\[\omega = \frac{\pi}{t_2-t_1}\]
He plasmado esas ecuaciones en esta hoja de cálculo para varios picos, excluyendo el primero. Como no da lo mismo para todos los picos, al final hago la media. Se podría haber hecho una regresión, pero no merece la pena meterme ya en más berenjenales:



El resultado es 81kΩ en promedio para la resistencia entre el colector y la base, y 4pF para la capacidad parásita.

Y ahora representaremos, en valor absoluto, los valores que nos da el ltspice y los nuestros propios calculados a partir de la R y C que nos han salido, a ver cuánto se aproximan:

La aproximación es más o menos buena. Era de esperar porque la capacidad parásita no es constante sino que va variando a medida que cambia la tensión Vcb.


Estos fenómenos que acabamos de ver son importantes en general para profundizar un poco en cómo funciona un transistor, y en particular para entender el oscilador del que hablábamos en la pasada entrada. Espero no haberos aburrido mucho.
Artículo completo >>

El circuito RLC serie: oscilaciones amortiguadas

Antes de nada, os quiero pedir disculpas por el parón que ha sufrido el blog lo que va de año. Todos necesitamos un respiro de vez en cuando, y otras aficiones me han comido mucho tiempo.

Para esta ocasión he elegido un artículo doble sobre cómo funciona uno de esos circuitos que parecen sencillos pero que luego no lo son tanto. Voy a hablaros de esos osciladores de FM con un sólo transistor. Seguro que los habéis visto. Muchas veces se presentan como micrófonos espía, o transmisores simples de FM.

Pues bien, para saber cómo van, primero hay que tener muy claro lo que es un oscilador RLC en serie. Y como es costumbre voy a empezar por lo más sencillo para formar una base y poder construir el resto sobre ella. Así que vamos a ver primero cómo se comporta por separado cada componente. Luego, partiendo de nuestra experiencia intuiremos las ecuaciones que los describen. Haremos un desarrollo matemático de cómo esperamos que se comporten estando juntos e iremos viendo con un simulador el resultado.


La resistencia

Queremos saber la diferencia de potencial en cada elemento. Por empezar en algún sitio, también podríamos hacer las cuentas con la intensidad, va a dar lo mismo. El desarrollo que sigue no pretende en absoluto ser riguroso (aunque es correcto -salvo error- no lo hagas en un examen); mi objetivo es obtener la frecuencia y la amplitud de las oscilaciones utilizando herramientas básicas de matemáticas.

Así que veamos la diferencia de potencial entre los bornes de una resistencia. Esto ya está más que sabido. La Ley de Ohm nos dice que la caída de tensión en una resistencia es proporcional a la intensidad que la atraviesa, y a su valor. Escrito matemáticamente sería algo así:

\[V = IR\]

No tiene más misterio (a menos que queramos obtener la R en función de los parámetros microscópicos del hilo como el grosor, el material, etc, que podríamos, pero por hoy nos vale así).


El condensador

Primero vamos a pensar cómo se comporta un condensador en un circuito. Un par de ejemplos, situamos un condensador...
  • A la salida de un rectificador de corriente alterna, para obtener corriente continua.
  • En paralelo con una batería en un circuito que maneja cargas instantáneas como un relé.

Cuando ponemos el condensador en una tensión continua, se carga, y ya deja de pasar intensidad a través de él hasta que haya alguna variación en la tensión de entrada. Cuando hay, por ejemplo, una caída de la tensión de alimentación por un exceso de consumo del circuito, el condensador se empieza a descargar y suple durante un instante la alimentación, con lo que el resto del circuito no nota el corte. Diríamos que el condensador se opone a los cambios de tensión. Y cuando cambia, intenta recuperar el valor que tenía antes.

Es decir, cuando variamos el potencial de un condensador, que en principio está en equilibrio y por el que no fluye ninguna intensidad, empieza a pasar una corriente que es más grande cuanto mayor es el cambio en el potencial, y este efecto es proporcional a la capacidad que tenga el componente. Matemáticamente lo expresaríamos así:

\[I_C = C {dV_C \over dt}\]

Pensemos en esa ecuación, la intensidad es la derivada de la tensión... ¿Y si le metemos una señal senoidal, de una frecuencia que queramos? Ojo, que utilizar una senoidal no es por capricho, es importante porque hay un teorema que dice que cualquier señal periódica, de la forma que sea, al final es una suma de señales senoidales. Pues eso, le aplicamos una onda al condensador:

\[V = V_0 \cos (\omega t)\]

V0 es una constante, de hecho es la amplitud de la onda. Lo que nos interesa ahora es la forma, no su valor. La derivada del coseno es el seno cambiado de signo:

\[I = {dV \over dt } = - V_0 \omega \sin (\omega t)\]

Pero por la forma periódica de las funciones seno y coseno, se demuestra que:

\[- \sin(\alpha) = \sin(-\alpha) = \cos(\alpha + 90^\circ)\]

Y utilizando esto nos sale:

\[I = V_0 \omega \cos (\omega t + 90^\circ)\]

O sea que la intensidad, está adelantada 90º respecto a la tensión. No significa que el condensador sea un adivino que sabe en cuánto va a estar la tensión para poner la intensidad en ese valor un momento antes. Hablamos de señales que se repiten, y lo mismo se puede decir que está adelantada 90º como que está retrasada 270º. Son sólo formas de hablar. Fijaos en esta gráfica, los picos en la I suceden un tiempo antes que los de la V. Ese tiempo es un cuarto del periodo total, lo que es justamente 90 grados.


Podéis hacer click en los gráficos para verlos más grandes.

Volviendo a lo de antes, tenemos la intensidad en función de la tensión, pero para dejarlo parecido a como lo hemos hecho antes con la resistencia me interesa lo contrario, la tensión en función de la intensidad. Así que despejo la V. Como es una derivada tendré que integrar, y la C (que es constante) pasa dividiendo sin más:

\[V_C = {1 \over C} \int I_C\,dt\]

Esta expresión es un poco fea pero no os preocupéis, que nos la vamos a quitar de encima rápidamente.

El artículo de la wikipedia en español es muy breve, pero el de la wikipedia inglesa está bastante bien: RC circuit.


La bobina

Seguro que hemos oído alguna vez que una bobina en serie es parecida a un condensador en paralelo, en relación a que ambos dejan pasar las bajas frecuencias y filtran los ruidos en la línea de alimentación. Con una cierta experiencia en electrónica esto ya nos sugiere que la ecuación va a ser muy parecida a la del condensador, sólo que cambiando tensión por intensidad.

Supongamos que tenemos una bobina y le aplicamos 5 voltios de una batería. Cuando pasan unos segundos llegamos a un estado estacionario, donde la corriente que pasa sólo la limita su resistencia interna; porque está hecha de cobre y el cobre tiene resistencia. Ahora llegamos y duplicamos la tensión, le metemos 10 voltios; y como la resistencia interna sigue siendo la misma, tendrá que pasar el doble de intensidad. Y se supone que mediríamos el doble de tensión, por la ley de Ohm. Pero resulta que no es instantáneo. Al medir, durante unos instantes la tensión es mucho mayor de lo que esperaríamos según la ley de Ohm. Se debe a que la intensidad que recorre una bobina no puede cambiar de golpe, la bobina es un dispositivo que se opone a los cambios de intensidad. Diríamos que tiene cierta inercia.

Lo mismo pasa cuando desconectamos la tensión. Esta cae a cero, pero la bobina intenta mantener la intensidad a toda cosa. Con lo que se genera un pico de tensión. Se dice que la bobina genera una tensión inducida de tal sentido que se opone al cambio que la produce. Es la llamada fuerza contra-electromotriz y es la que aprovechamos para dar calambre, pero también es causante de que pongamos un diodo en paralelo con un relé cuando lo activamos mediante un transistor y de que nos tengamos que quebrar la cabeza para controlar un motor con un TRIAC. De lo contrario esa tensión auto-inducida va a quemar el transistor de salida o va a alterar el TRIAC haciendo que permanezca encendido siempre.

Luego la caída de potencial en una bobina es proporcional al cambio en la tensión y, claro está, al valor de su inductancia.

\[V_L = L {dI_L \over dt}\]

Por eso se dice que hay un desfase entre la tensión y la intensidad, igual que con el condensador pero con signo contrario.

Ahora vemos lo que pasa cuando le aplicamos una una senoidal:



Sí, los picos en la V ocurren antes que en la I. Decimos que la corriente va retrasada respecto a la tensión, o bien que la tensión se adelanta respecto a la intensidad. Como son señales periódicas lo mismo nos da.

Os dejo este enlace a la wikipedia, lo mismo que para el condensador, por si os interesa verlo con más detalle: RL circuit.


El circuito RLC en serie

Este artículo, tiene un doble propósito. Además de hacer un desarrollo para que veáis cómo funciona un oscilador, quiero que seáis conscientes de una de las cosas más fascinantes de la ciencia: cómo dos fenómenos, completamente distintos en apariencia, que superficialmente nada tienen que ver el uno con el otro, se describen con la misma ecuación. Porque, en el fondo, son lo mismo.

En este caso hablamos de un circuito RLC, pero también podríamos hablar de un muelle con una pesa. Totalmente distintos en apariencia. Por debajo son iguales: osciladores armónicos. Ambos tienen una variable (la velocidad, la posición), un elemento que fuerza a que esa variable se quede en el centro como está (un condensador, un muelle) y un elemento que tiene inercia (la bobina, la pesa), y hace que esa variable no se centre nunca en la posición de reposo sino que pase de largo en un sentido y otro, o sea que oscile. He aquí una muestra del poder de abstracción que dota a las matemáticas de su potencia, y las hace ser la herramienta que son.


Desarrollo matemático

Decíamos antes que no voy a ser del todo formal, pero si pongo algo que es claramente erróneo por favor dejad un comentario.

Partimos de las ecuaciones que hemos justificado antes. Fijaos que no las hemos deducido, simplemente os he puesto la ecuación y os he dado una justificación más o menos buena para convenceros de que así tiene que ser.

La resistencia es nuestra fuerza de rozamiento que amortigua las oscilaciones. Decíamos que es lineal, que cuando crece la tensión crece la corriente y viceversa.

\[V_R = RI\]

Para el condensador, nuestra fuerza recuperadora, habíamos obtenido esta ecuación:

\[V_C = {1 \over C} \int I\,dt\]

Y para la bobina, nuestra inercia:

\[V_L = L {dI \over dt}\]

Esto que voy a hacer normalmente se hace con la carga, pero la carga almacenada en una bobina es un concepto difícil de imaginar, así que voy a hacerlo con la intensidad.


Tenemos este circuito RLC serie, sin fuentes de alimentación externas. Se trata de una malla cerrada y por primera ley de Kirchoff o Ley de Tensiones de Kirchoff la suma de todas las tensiones debe ser cero.

\[V_L+V_R+V_C = 0\]

Sustituyendo cada tensión por su valor:

\[L {dI \over dt} + RI + {1 \over C} \int I\,dt = 0\]

Esa ecuación es fea, sobre todo por la integral, eso la afea un montón. Así que vamos a derivar todo para quitarla:

\[L {d^2I \over dt^2} + R {dI \over dt} + {1 \over C} I = 0\]

Esto es una ecuación diferencial lineal de segundo orden. Y para resolverla hay varias formas. Como ya sé lo que va a salir, para no complicarme voy a proponer una solución genérica y la amoldaremos según el caso. La solución tendrá que ser necesariamente de la forma

\[I = A e^{Bt}\]

y sus derivadas:

\[ {dI \over dt} = ABe^ {Bt} \]

y

\[ { d^2I \over dt^2 } = AB ^ 2 e ^ {Bt} \]

A y B son dos coeficientes que tendremos que ajustar. A priori no exigiremos que sean reales o complejos, ya veremos lo que sale. Sustituimos, pues, en la ecuación esa solución genérica:

\[L AB^2e^{Bt} + R ABe^{Bt} + {1 \over C} A e^{Bt} = 0\]

Ahora simplificamos: el término $A e^{Bt}$  aparece multiplicando en todos los sumandos, así que podemos dividir por él la ecuación. Claro que para eso tenemos que exigir que A no sea 0, porque la exponencial sólo se haría cero para $t \rightarrow \infty$ . De paso dividimos todo por L para que la forma que queda sea más fácil de reconocer.

\[ B^2 + {R \over L} B + {1 \over LC} = 0\]

Sí, es una ecuación de segundo grado, corriente y moliente. Y se resuelve con la conocida fórmula:

\[x = \frac{-b \pm \sqrt {b^2-4ac}}{2a}\]

sólo que aquí $x=B$ , $a=1$ , $b = {R \over L}$  y $c = {1 \over LC}$ . Así que nos queda:

\[B = \frac{-{R \over L} \pm \sqrt {{R^2\over L^2} - {4 \over LC}}}{2}\]

Cómo se comporte el circuito ahora depende del valor que tome esto de aquí abajo:

\[ {R^2\over L^2} - {4 \over LC} \]

¿Por qué? Pues veamos algunas posibilidades.


Caso ideal: R = 0

Vale muy bien, si quitamos la resistencia, lo mismo que si quitamos el rozamiento, nos queda un oscilador armónico ideal. A ver qué raíces tiene la ecuación de antes cuando damos a R el valor 0.

\[B = \frac{-{0 \over L} \pm \sqrt {{0^2\over L^2} - {4 \over LC}}}{2}\]
\[B = \frac{ \pm \sqrt { - {4 \over LC}}}{2}\]
\[B = \pm {1 \over \sqrt {LC}} i \]

Parece que B sale un número imaginario puro. Así que lo sustituimos en la solución que habíamos puesto al principio:

\[ I(t) = A e^{i{1 \over \sqrt {LC}} t} \]

Recordad que tenemos que quedarnos sólo con la parte real de esa ecuación, que será un seno o un coseno. Es un resultado lógico. Una oscilación pura, sin más efectos. La intensidad sube y baja con el tiempo.



Para ver cuánto vale A tomamos la expresión de antes cuando $t=0$ , aprovechando que cualquier número elevado a 0 vale 1.

\[I(t=0) = A e^{i{1 \over \sqrt {LC}} 0} = A\]

Claro, A es el valor de la intensidad en el instante inicial. Ojo, aquí hay un poco de miga, porque si digo que A vale cero, entonces la intensidad en cualquier momento valdría 0 y no habría oscilación. En la realidad la intensidad inicial puede ser cero pero el condensador estar cargado a tope así que cuando lo conectamos sí que oscila. Pero es que A no es tan simple, porque A también es complejo, y como complejo tiene dos componentes. Veamos cómo funciona esto:

\[A=a+bi\]

\[I(t) = \Re (A e^{iBt}) = \Re \left((a+bi)(\cos Bt +i \sin Bt)\right) \]

\[I(t) = \Re (a \cos Bt + a i \sin Bt + bi \cos Bt - b \sin Bt) \]

\[I(t) = a \cos Bt - b \sin Bt \]

Sustituyendo el valor que habíamos obtenido para B:

\[I(t) = a \cos {1 \over \sqrt {LC}}t - b \sin {1 \over \sqrt {LC}}t \]

Ahora sí. Si A vale cero, completamente 0 (o sea que tanto a como b valgan cero a la vez) entonces no hay oscilación ninguna. Pero en cualquier otro caso sí. Si hubiéramos expresado A en coordenadas polares, en lugar de salirnos un seno y un coseno nos habría salido sólo un coseno más un ángulo: es la fase inicial.

Y la frecuencia de oscilación es justamente $\omega_0 = {1 \over \sqrt {LC}}$ .

¿Por qué le llamo $\omega_0$  con el subíndice 0? Pues para indicar que es el caso ideal, porque en la siguiente parte la frecuencia variará.





Oscilador sobre-amortiguado

El primero que vamos a suponer es el caso en que tenemos una resistencia muy grande, o una inductancia muy pequeña. Si la resistencia es grande comparada con la inductancia, la energía se disipa en seguida en forma de calor. Y si la inductancia es muy pequeña en relación a la resistencia hay muy poquita energía de partida. En ambas situaciones se pierde la energía tan rápidamente que no llega siquiera a ocurrir una sola oscilación.

Fijaos, físicamente pasa esto:


Matemáticamente por debajo, en la ecuación de movimiento que vimos antes está actuando la diferencia que hay dentro de la raíz cuadrada:

\[ {R^2\over L^2} - {4 \over LC} \]

Lo que está ocurriendo es que $\frac{R^2}{L^2}$  se está haciendo mayor que $\frac{4}{LC}$ . Y el radicando se vuelve positivo. La raíz de un número negativo sale un número complejo, con la solución de senos y cosenos que vimos antes; pero la raíz de un número positivo es real, no hay parte imaginaria, no hay exponencial compleja: no hay oscilación. Tan sólo hay una exponencial real que decae rápidamente.



Amortiguamiento crítico

Así que cuando $\frac{R^2}{L^2} > \frac{4}{LC}$  no oscila, y cuando es menor pues sí. Entonces tiene que haber un punto de inflexión, un punto intermedio entre una condición y otra. Según vamos ajustando los valores para que el circuito esté un poco más libre llegamos a un punto en que

\[ {R^2\over L^2} = {4 \over LC} \]

Esa situación se llama amortiguamiento crítico. Y en un gráfico se ve así:


Tiene la propiedad de que la energía decae más rápido que en los otros casos. ¿Y para qué sirve? Pues para detener las oscilaciones en el menor tiempo posible. Si hablamos de un oscilador mecánico nos referimos a, por ejemplo, los amortiguadores de los coches. ¿Verdad que no nos interesa que después de pillar un bache el coche bote arriba y abajo durante un rato? Pero por otro lado no podemos hacerlos rígidos, porque entonces no amortiguan nada.

Lo mismo, en un oscilador eléctrico lo empleamos para eliminar las oscilaciones no deseadas, ¿os acordáis del efecto de Gibbs que habíamos visto en esta entrada?


Oscilador sub-amortiguado

Y por fin el caso que nos interesa más: hay oscilación, pero decae porque también hay resistencia.

\[ {R^2\over L^2} < {4 \over LC} \]

La raíz cuadrada sale compleja, decíamos, así que el resultado tendrá una parte real y otra imaginaria. O sea, un número de la forma a+bi. ¿no? Ojo que ahora no hablamos ya de A sino de B.

\[ B = \frac{-{R \over L} \pm \sqrt {{R^2\over L^2} - {4 \over LC}}}{2} = a+bi \]

Según habíamos puesto de condición, lo que hay dentro de la raíz es negativo, así que le doy la vuelta y saco i fuera de la raíz (es una forma de hablar).

\[B = \frac{-{R \over L} \pm i \sqrt { {4 \over LC} - {R^2\over L^2}}}{2} = a+bi\]

Separando ahora la parte real de la parte imaginaria nos queda:

\[a = - {R \over {2L}}\]

\[b = \frac{ \pm \sqrt { {4 \over LC} - {R^2\over L^2}}}{2} = \pm \sqrt { {1 \over LC} - {R^2\over {4L^2}}}\]

Como el signo no es más que la fase inicial, me voy a quedar con la parte positiva por simplicidad. Volvemos si os parece a la solución para la intensidad que habíamos propuesto al principio:

\[I = A e^{Bt}\]

Y sustituimos lo que nos ha salido para B. La A es quien contiene, como en el caso ideal, las condiciones iniciales del sistema. No voy a volver a hacer el desarrollo porque sale igual que antes.

\[I = A e^{Bt} = A e^{(a+ib)t} \]

\[I = A \, e^{at} \, e^{ibt}\]

Sustituimos primero lo que vale a, y vemos qué sale.

\[I = A \, e^{-{R \over {2L}}t} \, e^{ibt}\]

Fijaos, nos sale la amplitud inicial, A; una exponencial compleja, que es el término que oscila; y, en el medio, una exponencial negativa. Si recordamos, $e^{-\infty} = 0$ . Lo que significa que a medida que avance el tiempo ese término del medio será cada vez más pequeño, hasta que acabe por desaparecer. Como va multiplicando al resto de la expresión, modifica la amplitud de las oscilaciones. Ahí tenemos nuestras oscilaciones amortiguadas.

El cuánto duran va a depender del término $\frac{R}{2L}$ , curiosamente aquí vemos que el condensador no afecta para nada al tiempo que está oscilando. Nos va a ser útil después, cuando ampliemos la frecuencia sin variar el tiempo total.

Mirad en este gráfico como la oscilación pierde amplitud en con el tiempo.



Y aquí variando el condensador. La amplitud al final es la misma en ambos casos.



Y ahora que sabemos la duración, vamos a ver la frecuencia. ¿Os acordáis del caso ideal? La habíamos llamado $\omega_0$  y valía $\omega_0 = {1 \over \sqrt {LC}}$ , o también puede decirse

\[\omega_0^2 = {1 \over {LC}}\]

La frecuencia que nos ha salido ahora, con resistencia, se corresponde con lo que había llamado antes 'b'. Porque es la que afecta a la exponencial imaginaria. Ahora que sé que es la frecuencia, le voy a cambiar el nombre y en vez de llamarlo 'b' voy a llamarlo por su nombre: $\omega$ .

\[\omega = \sqrt { {1 \over LC} - {R^2\over {4L^2}}}\]

De lo que hay dentro de la raíz, la primera parte era nuestra frecuencia natural de oscilación libre, $\omega_0^2$ . Y lo otro... lo otro es el cuadrado de $\frac{R}{2L}$ . ¿No os recuerda a nada? ¡Es justamente la 'a' de antes, el rozamiento! Bueno vale, la 'a' era negativa antes, pero el cuadrado de un número negativo es positivo igualmente. Y ya que estamos, no se le llama 'a' sino $\alpha$ . Así que la frecuencia cambia:

\[\omega = \sqrt {\omega_0^2 - \alpha^2}\]

Tiene sentido. Al aumentar la resistencia la frecuencia se hace menor. Le cuesta avanzar. Por otra parte, si quitamos la resistencia, $\alpha$  se hace 0, y recuperamos la frecuencia del oscilador libre.

¿Y qué pasa cuando $\alpha$  se hace muy grande y justamente iguala a $\omega_0$  de forma que la raíz vale cero? Pues pasa el amortiguamiento crítico. Y si la supera, y el radicando se vuelve negativo, la frecuencia de oscilación sería imaginaria. Pues eso, que nos la imaginamos, porque no oscila nada: estamos en régimen sobre-amortiguado.


Envolventes

Lo que os decía antes es aumentar la frecuencia (reduciendo el condensador) para que se junten las crestas y veáis gráficamente cómo la amplitud decae siguiendo una exponencial.

Este es el caso sub-amortiguado.



Este es el amortiguamiento crítico. Veis que las oscilaciones se paran más o menos en el mismo tiempo que el caso de baja frecuencia.



Y este es el sobre-amortiguado:



Vaya, era demasiado bonito. Algo no cuadra. Porque en el de antes tardaba mucho en decaer, más que en el crítico, sin embargo aquí decae en seguida. Pero tiene explicación porque antes el circuito no oscilaba en los últimos dos casos y en estos ejemplos oscila en todos. La comparación es válida en el sub-amortiguado y en el crítico. Pero ya deja de ser válida y se hace muy evidente en el sobre-amortiguado.


Oscilaciones forzadas

Y hemos llegado al final. Y después de toda esta teoría, este artículo ¿a dónde nos ha llevado?

Pues nos hemos quedado a las puertas de saber cómo funciona un sencillo transmisor de FM como los que hay en esta página. ¿Podría habéroslo contado sin más en plan teoría de circuitos? Pues sí, claro, sin duda. Un par de ecuaciones, una transformada y sale. Personalmente, como pasa con muchas cosas, creo que hay una diferencia abismal entre describir cómo funciona un circuito y entender internamente qué pasa. No hay tiempo en la vida para entender con detalle todas las cosas que conocemos cómo funcionan. Por eso estaré satisfecho si puedo aportar un granito de arena ayudándoos a entender bien cómo trabaja un oscilador de ese tipo. Y para eso hay que tener muy claro primero cómo funciona un oscilador RLC en serie.

En la próxima entrada describiré el oscilador continuando desde aquí. Después de todo ya que tenemos el oscilador, y hemos comprendido por qué se para, sólo hay que conseguir que no se pare, y meterle energía a intervalos regulares para contrarrestar el amortiguamiento.
Artículo completo >>

Dimmer controlado por mando a distancia: el software

Si no seguís el blog o no recordáis de qué iba este proyecto, hay un resumen en esta entrada donde presentábamos el hardware: Dimmer controlado por mando a distancia: el hardware. Os recomiendo que la leáis porque hoy os traigo el software que hay que programar en el micro para hacer funcionar ese hardware.

Empezaremos con una lista de características que nos gustaría que tuviera. Que ya que lo hemos diseñado nosotros y lo vamos a programar, por lo menos que sea como nosotros queramos. Luego recordaremos cómo se regula la luz usando un triac y de ahí entraremos en el software. En lugar del código fuente, que sería extenso, lo explicaremos con ayuda de diagramas.


Características

Veamos lo que le pediríamos a un Dimmer controlado por infrarrojos:
  • Que se puedan memorizar los comandos. No es práctico que los comandos NEC del mando a distancia estén grabados en el código. Porque si mañana queremos utilizar otros botones o incluso otro mando a distancia (siempre que utilice el protocolo NEC) tendríamos que desinstalar el circuito, recompilar el código y volver a grabar el chip y luego volverlo a dejar donde estaba. Por tanto hay que buscar un método para grabar los comandos nuevos, una especie de modo programación.
  • Que se pueda graduar la luz en pasos. A ser posibles en pasos de igual intensidad luminosa, con los cálculos que hicimos aqui.
  • Que se pueda encender y apagar con el mando a distancia. Y que al encenderse lo haga con la potencia que lo apagamos. Lógicamente para eso tendrá que guardar la potencia anterior en la EEPROM y recuperarla cuando lo encendamos.
  • Pero ¿y si perdemos el mando? En ese caso que sea transparente, o sea que cuando lo apaguemos del interruptor de la luz se apague la bombilla (eso es fácil, no queda más remedio porque va en serie) y que cuando lo encendamos, no del mando, sino del interruptor principal se encienda al 100%.
  • De nuevo, si perdemos el mando ya no podremos reprogramarlo fácilmente. Así que mejor incorporamos un comando en el propio código que nos sirva de emergencia. Lo mismo se podría hacer con un interruptor, que al pulsarlo entrase en modo programación.
  • También estaría bien que el encendido y apagado fuese lentamente, para que no deslumbre si encendemos en plena noche y para que quede más bonito.

Lo que hemos pedido casi parece la carta a los reyes magos, y programar todo eso en el chip va a requerir cierto esfuerzo mental para seguir la ejecución y no perdernos. Podríamos dividir el software en dos partes:
  • Los procesos en segundo plano: Está claro que tenemos que hacer varias cosas a la vez. Por un lado tenemos que estar pendientes de cuando la tensión pasa por cero para dispara el TRIAC justo un instante después (el tiempo dependerá de la potencia). Mientras tanto tenemos que poder recibir un comando por el sensor del mando a distancia. Sin embargo no es preciso utilizar un sistema multitarea aún, ya que al ser reacciones sencillas, las dos cosas anteriores las manejamos usando interrupciones.
  • El bucle principal: Es la parte que ejecuta los procesos más elaborados o que más tiempo requieren, como subir o bajar la potencia gradualmente, leer o escribir de la EEPROM, etc. Los procesos en segundo plano (disparados por interrupciones) activan flags globales que más adelante (cuando ha terminado la interrupción) main interpreta y actúa en consecuencia.


Disparo del TRIAC

Al final, por muchas vueltas que demos, la función principal del dimmer es regular la intensidad de luz. Vamos a recordar en dos líneas cómo lo hacemos antes de meternos con el software.

Un TRIAC es un dispositivo electrónico con tres patillas. Una de ellas es la puerta y las otras dos actúan de interruptor. Cuando metemos tensión en la puerta, pasa corriente entre los dos terminales principales siempre y cuando entre estos dos haya un mínimo de diferencia de potencial. Y se queda conduciendo mientras siga habiendo esa tensión por encima del mínimo, aunque hayamos desconectado la puerta.

En este caso hemos utilizado un optotriac para aislar el micro de la alta tensión (es recomendable cuando además tenemos una fuente de alimentación sin transformador, y una patilla directamente a la red para ver cuando pasa por cero). Lo malo del optotriac es que tiene por dentro un LED que hay que alimentar, y que puede consumir desde 5mA en algunas versiones, hasta 20mA en otros modelos. Y la fuente que teníamos iba justita para alimentar el micro, no nos sobran 15mA para alimentar el LED de continuo.

Afortunadamente no es un problema mayor, ya que habíamos dicho que una vez disparado el TRIAC este conducirá hasta que la tensión alterna pase por cero. Así que lo que vamos a hacer es:
  1. Detectar el paso por cero.
  2. Poner a contar un cronómetro (que va a ser TIMER0) durante un tiempo determinado. Si queremos más luz dispararemos antes, si queremos menos luz esperaremos un poco antes del disparo.
  3. Disparar el TRIAC.
  4. Poner a contar el mismo cronómetro de antes, pero esta vez contaremos un tiempo fijo, de algunos microsegundos. Suficiente para que el TRIAC pase a conducción.
  5. Desactivar el LED del optotriac. Que no tiene ningún efecto porque el TRIAC ya está conduciendo, hasta el próximo paso por cero.

Así, mandando pulsos breves al LED en cada transición no agotamos la fuente y el micro sigue funcionando. ¿Y cómo sabemos el momento en que hay que encender el TRIAC después de cada paso por cero para obtener el brillo deseado? Pues con la variable tmr0_ticks. Es la variable más importante del programa y tendremos especial cuidado con ella. Pero antes, volvamos al proceso de disparo. Todo eso sucede en las rutinas de las interrupciones. Veámoslo más de cerca.


Servicios de atención a las interrupciones

Este es un diagrama de flujo muy simplificado de las tareas en segundo plano.


Hay tres eventos que queremos capturar:
  • Un cambio en los pines de entrada, que puede ser en dos patas distintas: Si se trata de la pata que va conectada al sensor infrarrojo significa que estamos recibiendo una señal del mando a distancia. Y va a la máquina de estados que interpreta la codificación NEC como habíamos explicado en esta entrada. La otra opción es que sea el pin de Zero Crossing y nos indica un cambio de polaridad en la corriente alterna que alimenta la bombilla. Cuando eso pasa el TRIAC se apaga; y tenemos que volverlo a encender pasado un breve retardo que, como hemos dicho, va en función del brillo que queramos.
  • Un desbordamiento de TIMER1, que significa que no hemos recibido más señales en el sensor de infrarrojos. Lo que hacemos es reiniciar la máquina de estados NEC por si se hubiera quedado un comando a medias.
  • Un desbordamiento de TIMER0. Es el evento más importante de todos, junto con el detectar el paso por cero. En el apartado anterior hemos descrito el algoritmo. Cuando detectamos el paso por cero, habíamos programado el TIMER0 para que se desbordara según el valor de la variable tmr0_ticks. Entonces al desbordarse TIMER0 hay dos posibilidades. Si el TRIAC estaba apagado lo encendemos y programamos el TIMER0 para que se desborde al cabo de unos pocos microsegundos. Se desbordará. Llegaremos a la misma interrupción y en esta caso el TRIAC estará encendido. Lo apagamos y desactivamos la interrupción de TIMER0, a la espera de que otro paso por cero la vuelva a activar repitiendo el ciclo.


Llamadas a funciones

Aquí tenemos un gráfico simplificado de llamadas:

Hay una función que es main. Main tiene un bucle que se encarga de ver cuando hay un comando NEC listo y actúa llamando a la función comando que corresponda. La potencia va de 0% a 100%.

Las funciones de color verde son comandos que llegan por el mando a distancia:
  • sube_pow: Incrementa la potencia (el brillo) en 20 unidades. Por tanto tenemos 6 posibles niveles: luz apagada (0%), 20%, 40%, 60%, 80% y luz totalmente encendida (100%).
  • baja_pow: Igual que la anterior pero baja la intensidad luminosa en lugar de subirla.
  • on_off_pow: Apaga la luz o la encente, recuperando el brillo de la última vez. Está claro que tiene que llamar a las funciones que trabajan con la EEPROM para para almacenar el último valor y recargarlo más tarde.
  • aprender_IR: Uno de los comandos es el modo programación, donde podemos pulsar botones del mando y asociarlos a los diferentes comandos. Para ello los tenemos que escribir en la EEPROM.
  • set_pow: Sin embargo ninguna de estas funciones modifica la potencia directamente, sino que llaman a una función que se llama set_pow para hacer la transición. set_pow tiene además un parámetro para indicarle si queremos que el cambio se haga inmediatamente o de forma gradual.
  • pow2ticks: Pero ni siquiera set_pow juega con la variable tmr0_ticks. Es otra función pow2ticks quien hace una conversión entre el valor en tanto por ciento se la potencia y el valor que tiene que asignarle a tmr0_ticks para que los desbordamientos de TIMER0 den como resultado esa potencia. En pow2ticks hay una tabla de conversión, en la variable valores que da los valores de la variable en incrementos del 5%. Con esos valores hacemos una interpolación lineal para calcular los intermedios. ¿De donde hemos sacado esos números? Pues de aquí: Curva de respuesta del Dimmer IR. Nos quedamos con el valor de la columna inicio reloj para una sensación del 5%, 10% etc. Si sois observadores veréis que los números no coinciden, y es sencillamente porque los cálculos no son perfectos y la sensación luminosa depende también del tamaño de la habitación, tipo de pintura y color de las paredes, altura y forma de la lámpara, etc. Ni siquiera dos personas perciben la misma sensación igual cantidad de luz. Así que al final lo terminé adaptando a ojo.

Una vez que pow2ticks actualiza el valor de tmr0_ticks ese valor entra en los procesos de segundo plano (las interrupciones que habíamos visto antes) y la potencia cambia inmediatamente.

No obstante main llama de forma excepcional directamente a set_pow. ¿Por qué llama por su cuenta a una función que sólo deberían llamar los comandos? Es algo que ocurre durante el arranque, cuando pulsamos el interruptor de la luz. Como el circuito no se había apagado con el mando (no estaba en stand-by sino apagado del interruptor) main asume una situación excepcional (por ejemplo que no tenemos el mando a mano), así que conecta la bombilla a plena potencia. Igualmente al arrancar lee los códigos NEC asociados a comandos y los carga para que cuando llegue uno sepa interpretarlo.


Modo de empleo

Bien, pues ya tenemos nuestro circuito montado, y os he dado una buena paliza contándoos cómo va el software. Lo habéis programado y lo vamos a probar.

La primera parte es tediosa. Pero más abajo os confieso por qué no me he molestado en depurarla.

Lo primero que deberíais hacer es tomar un mando a distancia distinto del que pensáis utilizar. Tenemos que captar un código de ese mando que nos servirá de código maestro. Por si se corrompen los datos en la EEPROM o se rompe el mando bueno, por ejemplo. Para captar el código correspondiente hay dos formas, o bien montáis en un momento el circuito receptor que hay en esta entrada; o bien os vais al archivo main.h, ponéis el código en modo depuración descomentando la última línea y recompiláis. Si hacéis esto montad el PIC en una protoboard porque no es recomendable conectarlo al puerto USB y a la tensión de red al mismo tiempo. Os recuerdo que para conectar el PIC al puerto PC, si no tenéis puerto serie podéis utilizar este conversor.

Una vez que tengamos el código maestro, lo ponemos en la variable IR_CODE_MASTER de main.h y recompilamos. Para recompilar es imprescindible tener el compilador CCS.

Programamos el PIC y lo montamos en la placa. Enchufamos la bombilla y la tensión a la clema. Asumo que habéis hecho todo tipo de comprobaciones de que todo está en su sitio, que tenéis un fusible intercalado y cierta experiencia trabajando con media tensión. Una sacudida de 220V no es lo mismo que un corto de 5V, la tensión de red no se anda con bromas.

Ahora tomad el mando que pensáis usar y el maestro. Cuando pulséis la tecla maestra, la función aprender_IR llamará a set_pow y hará parpadear la bombilla indicando que estamos en modo programación. Ahora id pulsando teclas en el mando en el siguiente orden:
  1. Encender / apagar
  2. Bajar potencia
  3. Subir potencia
tras introducir cada comando la bombilla debe parpadear indicando que ha reconocido la pulsación. Una vez introducidos los tres comandos parpadea dos veces y se apaga. Ahora ya tenemos el PIC listo para funcionar.


Conclusión

Os decía antes que la puesta en marcha es un lío. Y se podía haber simplificado simplemente poniendo un interruptor que al pulsarlo entrase en modo programación. Podéis hacerlo, os lo dejo a vosotros. La verdad es que tras tenerlo instalado unos meses no me ha terminado de convencer. Porque al tener la luz baja se observa un leve parpadeo y un ligero zumbido de alterna. Próximamente quiero proyectar un dimmer, esta vez basado en MOSFET, con una frecuencia de conmutación mucho más alta que espero que solucione esos defectos. Para eso hay que rectificar previamente la tensión, lo que permite más carga en la fuente de alimentación, entre otras cosas. Hay que olvidarse de la fase del disparo y pensar en PWM.

En definitiva, como experimento, cada una de las entradas del proyecto DimmerIR me ha enseñado cosas y me ha dado la experiencia necesaria para ahondar en este tipo de proyectos. Espero que, tanto si os habéis animado a construir el circuito, como si sólo lo habéis seguido por encima os haya aportado ideas que os sirvan para vuestros futuros proyectos.

Os dejo el software en este enlace. Y si tenéis cualquier duda escribid un comentario.
Artículo completo >>

Programación PIC para decodificar RC5

Para decodificar el protocolo RC5 hay dos formas de hacerlo. Una es muestreando el puerto cada cierto tiempo, y comprobando si está a nivel alto o nivel bajo. En función del resultado lo interpretamos.

Esto es un ejemplo de codificación Manchester:


Hace ya tiempo conté una forma de decodificar el protocolo RC5 utilizando un PIC: Decodificacion del protocolo RC5 usando un PIC. Por algunos correos que he recibido parece que no terminó de quedar claro, y además prometí dedicarle otra entrada al código C. Sería muy conveniente que repasaras la entrada a la que me refiero, porque esta no es más que una especie de nota aclaratoria.

Para empezar supongamos que nos llega una señal como la de arriba. Las lineas verticales separan los periodos y es más fácil de ver donde empieza y acaba cada símbolo. Recordemos la dos reglas de oro:
  1. Siempre, siempre hay una transición en mitad de un periodo. Precisamente porque tiene la señal de reloj incorporada. Recordad que es para ayudarnos a sincronizar el reloj del receptor con el del transmisor. Aunque casi nunca se ajusta dinámicamente; simplemente sincronizamos al principio y nos limitamos a dar error si se desincroniza. Aunque ya vimos como se puede ajustar dinámicamente la frecuencia de reloj para decodificar señales tipo Aiken Biphase cuando leímos la banda magnética de las tarjetas de crédito.
  2. Si la transición es hacia arriba (de 0 a 1) se interpreta como un 1, si es hacia abajo, se interpreta como un 0. Lo que también podría decirse como si el pulso positivo está a la izquierda del periodo es un 0 y si está a la derecha es un 1. Mira la imagen de abajo, te ayudará.


El programa

No quiero resultar cansino, así que voy a suponer que has leído la entrada anterior, o que la recuerdas y me voy a saltar las explicaciones.

Tenemos la señal de ejemplo de arriba, voy a quitar las líneas divisorias y a numerar las transiciones.


Los números en la parte de arriba son correlativos e indican de qué transición se trata. La línea de abajo corresponde a la interpretación que s ele da a las transiciones. Las marcas de confirmación, que representan bits, están representadas por números grandes, mientras que los número pequeños indican una marcas de continuación.

Pegamos el código y a continuación os explico cómo funciona.

#include "rc5.h"

// 100 tmr1 =~ 200us =~ +- 20% (sobre 889us)
#define TMR1_TOL 100
#define IR_PIN  PIN_A0

/*
 Estados de la máquina:
 0 - Reset
  - Se resetan las variables
 1 - S1 recibido
  - Calculado t
 2 - S2 recibido
  - Calculado t en función de la media
  - Totalmente inicializada.
 3 - Marca de continuidad no recibida
 4 - Marca de continuidad recibida
*/

#define RC5_RESET 0
#define RC5_S1  1
#define RC5_S2  2
#define RC5_DONE 3
#define RC5_MARK 4



unsigned int16 rc5_COMANDO = 0; // S1 y S2.
unsigned int16 rc5_t;
unsigned char rc5_stad = 0;


#int_TIMER1
void  TIMER1_isr(void) 
{
 // Si el ultimo pulso fue hace más de X ms da timeout y resetea la máquina de estados RC5.
 // El prescaler de TMR1 es 2: 2 x 256 x 256 =~ 131 ms.
 // Teoricamente un semiperiodo deben ser (889us) tmr1 = 444.
 rc5_stad = 0; // maquina de estados RC5 reiniciada
}

#int_RA
void  RA_isr(void) 
{
 unsigned int16 int_time;
 unsigned char semiperiodos;

 int_time = get_timer1();
 
 
 semiperiodos = input(IR_PIN); // para limpiar la interrupción
 clear_interrupt(INT_RA);
 semiperiodos = 0;

 
 // Calculamos cuantos semiperiodos dura el lapso de tiempo
 // para ahorrar el cálculo después
 if (rc5_stad > RC5_S1) {
  signed int16 lapso;
  lapso = (signed int16) (rc5_t - int_time);
  
  if (lapso < 0)  lapso = - lapso;
  lapso -= TMR1_TOL;
  
  if (lapso < 0) {
   semiperiodos = 1;
  } 
  else if (lapso < rc5_t) {
   semiperiodos = 2;
  }
  else {
   rc5_stad = RC5_RESET;
   goto END; 
  } 

 } 
 
 // COMENZAR AQUI
 // Es el pulso de start1
 if (rc5_stad == 0) {
  rc5_COMANDO = 0b0000000000000011;
  rc5_stad++;  // maquina iniciada (estado 1)
 }
 
 // es el segundo pulso (marca de continuidad del start1)
 else if (rc5_stad == RC5_S1){
  rc5_t = int_time;
  rc5_stad++;  // primer pulso recibido (estado 2)
 }
 
 // es el tercer pulso (confirmación de start2)
 else if (rc5_stad == RC5_S2) {

  if (semiperiodos != 1) {
   //error("No parece RC5.");
   rc5_stad = 0;
   goto END;
  }
  rc5_t += int_time;
  rc5_t /= 2;  // media entre los dos
  rc5_stad++;  // cálculo del periodo completado (estado 3)
 }
 
 // transición sin marca de continuación
 // se ha invertido el bit
 else if ( semiperiodos == 2 ) {
  // El estado 4 es para esperar la confirmación de continuidad
  // No debería darse el caso
  #bit OLDlastBit = rc5_COMANDO.1
  #bit NEWlastBit = rc5_COMANDO.0
  
  if (rc5_stad == RC5_MARK) {
   //error("Error de protocolo.");
   rc5_stad = 0;
   goto END;
  }
  
  rc5_COMANDO <<= 1;
  NEWlastBit = ~OLDlastBit;
 }
 // se trata de una marca de continuación o una confirmación
 else if ( semiperiodos == 1 ) {
  // es una marca, espero la confirmación
  if (rc5_stad == RC5_DONE) {
   rc5_stad = RC5_MARK;
  }
  // es una confirmación
  // se continua el bit anterior
  else {
   #bit OLDlastBit = rc5_COMANDO.1
   #bit NEWlastBit = rc5_COMANDO.0
   rc5_COMANDO <<= 1;
   NEWlastBit = OLDlastBit;
   
   rc5_stad = RC5_DONE;
  }
 }
 
 else {
  rc5_stad = RC5_RESET; // algún error
 } 

END:
 set_timer1(0);
}




void main()
{

   port_a_pullups(TRUE);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_2);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(INT_RA);
   enable_interrupts(GLOBAL);
   setup_oscillator(OSC_4MHZ);


 for (;;) {
  if (bit_test (rc5_COMANDO, 7)) {
   rc5_COMANDO = 0; 
  }   
 } 

}


El bucle de recepción está en la interrupción RA. Lo primero que hacemos cuando detectamos el cambio del puerto es quedarnos con el valor del timer 1. Ese valor puede ser aleatorio si es la primera transición, pero a partir de la segunda ese valor nos indica el tiempo transcurrido desde el último cambio porque precisamente lo que hacemos como última instrucción al salir de la interrupción es reiniciar timer1. Luego limpiamos la interrupción haciendo un input del puerto; he reutilizado la variable semiperíodos por no definir otra, pero ni que decir tiene que eso no son los semiperíodos.

Hay que tener en cuenta que este programa es sólo para que veais el algoritmo. En la vida real tendríamos que poner una condición para ver si lo que ha cambiado es el pin al que tenemos conectado el sensor o es otro distinto.

Todo gira alrededor de una máquina de estados. El estado inicial es el estado cero. Las variables están en sus valores por defecto y el sistema está listo para empezar a recibir un comando.


Inicialización

Llega la primera transición. Nuestro objetivo ahora es calcular el semiperíodo para cuando lleguen las transiciones de los datos poder saber qué significan. Sabemos, por definición del protocolo, que lo primero que nos va a llegar son dos bit de start y van a ser sendos unos. Mirad la imagen de arriba, son las transiciones 1, 2 y 3 y entre cada una hay un semiperíodo. Podría calcular la duración del semiperíodo simplemente basándome en la diferencia entre la 1ª y la 2ª. Pero ya que son dos marcas de start es más fiable si calculo la diferencia de tiempos entre la 1 y la 2, y también de la 2 a la 3 y luego hago una media.

Como decíamos, llega la primera transición. Id a la línea 80, donde dice "Comenzar aquí". Estamos en el estado cero, todo reseteado. A lo más que podemos aspirar aquí es a poner los dos unos de start en la variable COMANDO y poco más. Pero lo más importante que hacemos es pasar al estado uno y salir reiniciando timer 1 como habíamos dicho.

Llega otra transición, sería la 2ª. Estamos en el estado uno. Lo que nos indica que no es la primera y que tenemos otra para calcular cuanto tiempo ha pasado entre ambas. La variable int_time, calculada al principio del bucle contiene el valor de timer1, y puesto que lo habíamos reiniciado antes, contiene el tiempo desde la transición anterior, que como sabemos es un semiperíodo.

Notad que cuando hablo de tiempos, no me refiero a segundos, ni a instrucciones, sino a tics del timer1. El tiempo real en segundos dependerá de la velocidad del reloj y de cómo esté configurado el prescaler. En cualquier caso no nos interesa el tiempo real, sino una medida con la que comparar para saber si entre dos transiciones hay una medida (semiperíodo) o dos (un periodo). A cuántos microsegundos equivale es irrelevante.

Calculado el primer semiperíodo avanzamos al estado dos. Cuando llega la tercera transición, como el estado es dos, vamos a la línea 58. Ahí comparamos la duración con la variable rc5_t, que es la que dice cuanto dura un semiperíodo. Hablaremos luego de cómo funciona la comparación.

Volvemos a la parte del código que controla la máquina de estados, a partir de la línea "Comenzar aquí". En este caso como el estado es dos, aterrizamos en la línea 92. Acto seguido miramos si la duración entre las transiciones 2 y 3 es equiparable a la duración entre la 1 y la 2. Porque si no es así puede que hayamos hecho mal la medida. Si son comparables, hacemos la media aritmética y nos quedamos con el resultado. Esa será nuestra variable rc5_t para toda la ráfaga que sigue. Pasamos al estado tres: inicialización completada. El estado tres también implica Marca de continuidad no recibida, que significa que hemos terminado de recibir un bit. Y así es porque los bits de start son unos. Ya podemos empezar a recibir datos de verdad.


Comparación

Ahora sí vamos a explicar cómo hacemos la comparación, vamos a la línea 58 del código. Tenemos, por un lado la duración de un semiperíodo (recordemos, en pulsos de timer 1) en la variable rc5_t; y por el otro, en int_time el tiempo desde la última transición. Lo que quiero es comparar ambos valores, dentro de unos márgenes de tolerancia, para saber si int_time equivale a un periodo, a dos, o a ninguna de las dos cosas.

Si estuviéramos programando en un PC, para saber si int_time es equivalente a rc5_t con una tolerancia del 10% haríamos una comparación tal que así:
if (int_time > 0.90*rc5_t) &&
   (int_time < 1.10*rc5_t) ...
Pero en un microcontrolador este tipo de cosas conviene evitarlas, principalmente porque los compiladores no suelen estar tan optimizados y malgastan los limitados bits de RAM. Además implícitamente estamos obligando al compilador a:

  • Usar aritmética de coma flotante: Que implica cargar unas librerías más que pesadas y nos van a agotar la ROM si es un PIC pequeñito. Tal vez el compilador se diera cuenta de lo que queremos hacer y usara aritmética de punto fijo, pero en ese caso...
  • ... forzamos una o varias divisiones. Y las divisiones son las operaciones más lentas, a menos que se trate de dividir por una potencia de dos, que entonces es tan simple como desplazar los bit hacia la derecha. No olvidéis que todo esto se ejecuta dentro de un servicio de interrupción, donde la rapidez y la ligereza son imprescindibles. No podemos permitirnos tener al procesador ocupado atendiendo una interrupción durante mucho tiempo, porque mientras tanto no hace lo que tiene que hacer.
En resumidas cuentas, que siendo esto una rutina para reconocer comandos por mando a distancia, estamos obligados a hacerla lo más compacta y eficiente posible. Lo ideal sería hacerla en ensamblador... eso ya os lo dejo a vosotros jejeje.

Así que recurriré a una vuelta un poco menos evidente, pero que una vez compilada, en comparación es más eficaz.
  1. Para empezar sólo se ejecuta esta parte cuando hemos pasado el estado 1, o sea cuando ya tenemos un valor de rc5_t con el que comparar.
  2. Definimos una tolerancia fija, TMR1_TOL, en este caso de 100 tics de timer1 (vedlo en la linea 4).
  3. Definimos una variable temporal, llamada lapso, y le asignamos la diferencia entre int_time y rc5_t. Lapso tiende a 0 cuando ambas fueran iguales (un semiperíodo) y tendería a rc5_t si es el doble de este valor (dos semiperíodos).
  4. Nos interesa sólo el valor absoluto de lapso, ya que ahora vamos restarle la tolerancia.
  5. Si lapso era menor que la tolerancia significa que int_time está dentro de los márgenes para ser considerada igual a rc5_t, o sea, un semiperíodo.
  6. Si, por el contrario, lapso es mayor que la tolerancia, pero no llega a sobrepasar rc5_t diremos que dura dos semiperíodos.
  7. En el caso que lapso fuera mayor que rc5_t, implica que int_time es mayor que el doble de rc5_t más la tolerancia. Significa que nos hemos saltado alguna transición o que el protocolo no es RC5, así que ponemos el estado cero para que la máquina de estados se reinicie.

He tenido en cuenta la forma en la que el compilador CCS optimiza. Por ejemplo, las comparaciones con 0 o con un número fijo son más rápidas que las comparaciones con variables, por eso sólo se hace una vez. En general siempre es esí, pero puede depender del compilador. Cuando se realizan operaciones implícitas dentro de la comparación se está utilizando espacio de almacenamiento temporal y da lugar a un código más complejo. Estas son cosas que sólo se ven en el código compilado. Si estáis programando un microcontrolador para un proyecto crítico siempre es bueno repasar el código una vez compilado, sobre todo en ciertas partes "problemáticas" como las comparaciones, y las rutinas que más se ejecutan. Para proyectos profesionales hay herramientas de tipo perfiladores para micros, pero si no disponemos de ellas pues nos toca hacerlo a mano.


Recepción de los datos

Vale, ahora ya sabemos si el tiempo desde la última transición es (aproximadamente) un semiperíodo o dos. A partir de la línea 106 y de la 122 se aplica el algoritmo que habíamos descrito en la entrada que cito al principio. Y cuando se trata de una marca de confirmación rotamos todos los bit de la variable rc5_COMANDO hacia la izquierda y metemos el bit nuevo.

La máquina de estados se pone en el estado tres cuando recibimos una marca de confirmación o de cambio. En ambos casos se fija el bit. Mientras el estado cuatro es un estado temporal que indica que hemos recibido una marca de continuación, pero aún no hemos recibido la confirmación. Si en este estado la comparación nos devuelve 2 semiperiodos se trata de una sitación que no tiene sentido, así que asignamos el estado 0 y salimos.


Parada

Hay dos situaciones en que la máquina de estados deja de recibir.

La primera es cuando la comparación de la línea 162 en la función main es verdadera. Recordad que main se está ejecutando continuamente, siendo interrumpida ocasionalmente cuando cambia el pin del sensor infrarrojo para meter más bit en la variable rc5_COMANDO. Pues bien, a medida que vamos metiendo bits por la derecha, los bits de start van avanzando hacia la izquierda. Si yo sé que mi comando tiene 7 bits de largo, voy fijándome en la variable para que en cuando los bits de start alcancen la posición 7ª interpretar el comando completo.

Hay otra situación, y es que la máquina de estados se reinicia automáticamente cuando no se reciben datos por un tiempo. Recordad que la última intrucción de la rutina que examinamos antes es reinicial el contador timer1. Si un comando se corta y llega a la mitad no se reinicia más, y llegará el momento que timer 1 se desborde. Cuando eso ocurre se llega a la rutina en la línea 34, que lo único que hace es poner el estado a cero, para volver a empezar la recepción de nuevo.
Artículo completo >>

Adaptador de USB a Serie

La primera entrada de este blog (Conversor USB - RS232) la dediqué a contaros cómo hacernos un adaptador sencillo y muy cómodo para conectar un microcontrolador al PC cuando no teníamos puerto serie. Y aún cuando tuviéramos, a mi me resulta mucho más práctico este adaptador que un puerto serie de verdad.

Recordemos que nos basamos en un adaptador comercial barato (2.86 USD) y de poca calidad: http://www.dealextreme.com/details.dx/sku.24799. En esta segunda versión voy a aportaros alguna foto con más calidad, para facilitaros el montaje. También quiero explicaros por qué se hacen los puentes que se hacen. Y por último voy a añadir un cuarto cable de alimentación positiva para alimentar el dispositivo directamente desde el puerto USB.


Aquí tenemos cuatro cables:
  • Positivo de alimentación +5V (rojo)
  • Transmisión de datos hacia el PC (blanco)
  • Recepción de datos desde el PC (naranja)
  • Negativo de alimentación y masa de la señal, 0V (negro)

Aunque el conector USB también tiene cuatro hilos, la transmisión de datos es muy diferente. Y aunque yo lo he planteado como un adaptador externo, por el precio que tiene bien se podría dejar dentro de algún que otro invento que nos sea práctico. En ocasiones vale más eso que comprar un PL2303 (que es el chip en que se basa) y un cuarzo y montarlo nosotros, con las dificultades para comprarlo (generalmente online), el coste del chip más los gastos de envío, y los problemas que da soldar placas con componentes SMD. Estoy hablando de cacharros para nosotros, claro. A la hora de diseñar algo para la venta hay mejores opciones.

Decía antes que es de mala calidad, pero son detalles que bien nos benefician o que podemos solucionar fácilmente, me explico:
  • Los niveles de salida no son RS232 (+-12V), sino que son TTL (0-5V). Pues bien, eso que para algunos módems no sirve, para nosotros que queremos conectarlo a un microcontrolador, que precisamente usa niveles TTL nos viene de perlas. Porque si llevara un conversor de nivel como el MAX232 tendríamos que quitárselo.
  • A veces me he encontrado soldaduras mal hechas y pistas cortocircuitadas. Pero el circuito tiene tan pocos componentes que a poco que uno mire se da cuenta.
  • El oscilador es inestable. No termino de ver el motivo pero en todos los adaptadores de este modelo que he comprado falla el oscilador. De forma que cuando lo conectas, Windows no reconoce el dispositivo y lo da por defectuoso, y Linux no sabe indicar qué has conectado. Una forma fácil y rápida de arreglarlo es colocar una resistencia de 100kohm en paralelo con el cristal, como veréis en las fotos siguientes.

Montaje

Se trata nada más de que eliminar las clavijas USB y RS232 y conectar sendos cables. Conectar la resistencia de la que hablábamos antes y hacer unos cuantos puentes para el handshake y el conrol de flujo. De qué lineas puentear hablaremos en el apartado siguiente.






Handshake y control de flujo

Habréis notado que he puenteado tres lineas por un lado, y dos por otro. En principio no hace falta, porque las aplicaciones que vamos a usar van destinadas a un microcontrolador, no esperan encontrarse un módem. Sin embargo no viene mal un poco del culturilla sobre cómo funcionaba antaño un puerto serie.

Vamos a describir las líneas más importantes que son las que aparecen en un conector DB9, después os contaré cómo es la secuencia para conectar telefónicamente un módem con otro y entenderéis perfectamente qué es lo que el ordenador entiende cuando puenteamos juntas las lineas. Uso un módem porque el propósito original del puerto serie era conectar un módem. Aunque más adelante resultaba idóneo para conectar el ratón no se inventó para eso sino que fue una utilidad posterior.

  1. Data Carrier Detect (DCD): Indica que se ha establecido una conexión con el destino, y que estamos preparados para recibir y enviarle datos. Tenemos una portadora. Si la conexión se pierde, por ejemplo el destinatario de la llamada colgara el teléfono, nuestro módem pone inmediatamente a 0 la linea DCD y así el PC entiende que se ha perdido la conexión.
  2. Receive Data (RxD): Sirve para que el PC reciba los datos que le envía el módem.
  3. Transmit Data (TxD): Sirve para que el PC transmita datos al módem o al dispositivo que esté conectado.
  4. Data Terminal Ready (DTR): Cuando iniciamos un programa que va a hacer uso de un aparato conectado al puerto serie, el PC activa la línea DTR preguntando al dispositivo si está listo.
  5. Masa. Observad que no existe ninguna línea de alimentación positiva y los circuitos que quisieran alimentarse por el puerto serie (lo cual sólo es posible si consumían poco) debían hacerlo por la línea DTR, lo que es muy poco fiable.
  6. Data Set Ready (DSR): Esta línea sirve para que el hardware que hay conectado al puerto indique al PC que está conectado, encendido y listo para usarse.
  7. Request to Send (RTS): Como los módems antiguos eran torpes, el PC tenía que avisar antes de enviarles datos, porque si los enviaba antes de que el módem estuviera listo para recibirlos se perdían. Así cuando el PC quiere enviar datos pone a 1 esta línea y espera la confirmación por la siguiente.
  8. Clear to Send (CTS): Podríamos traducirlo por vía libre para enviar Cuando el módem tiene buffers libres para recibir nuevos datos activa esta línea. O al menos esa era la idea original. Porque con el tiempo la misión de las líneas RTS y CTS cambió ligeramente y pasaron a emplearse de otra manera.
  9. Ring Indicator (RI): Si el módem recibe una llamada entrante lo indica al PC poniendo a 1 esta línea. El PC genera una interrupción que recibe el sistema operativo y ejecuta lo que tenga que hacer para aceptar una conexión entrante.

Resumiendo:
  • Iniciamos el programa terminal en el PC para marcar un número de teléfono y conectarnos con otro PC. El PC activa la línea DTR, y el módem, que está conectado y listo reacciona activando DSR.
  • El PC quiere enviar los comandos de inicialización y conexión (por lo general comandos Hayes: descolgar y marcar un número) así que activa RTS y espera. Como no hay ningún problema para recibir los datos, el módem activa CTS y comienza la transmisión del comando.
  • El módem descuelga, marca el número de teléfono y espera respuesta. Cuando el otro extremo contesta hay una negociación de velocidades (o no) y nos envía una portadora de datos en señal de que la conexión está operativa. En ese momento se activa la línea DCD. Pudiera pasar que al otro extremo de la línea no haya otro módem sino una persona de carne y hueso. En ese caso no se activaría la línea DCD.
  • Ahora ya hay conexión, se ha completado la primera fase (lo que se llama el handshake) y lo que se usa a partir de ahora son las líneas RTS y CTS (control de flujo por hardware).
  • Supongamos que el otro extremo cuelga: la linea DCD se va a 0 lógico y nuestro programa terminal nos avisa de que se ha terminado la conexión (NO CARRIER ).
  • Y supongamos ahora que los que queremos colgar somos nosotros: damos la orden de terminar la conexión nuestro y en ese momento nuestro PC lleva a cero la línea DTR, indicando al módem un mensaje, algo como "ya no estoy listo". El módem lo entiende e interrumpe la llamada.

Entonces ¿qué conseguimos puenteando las líneas 1, 4 y 6 (DCD, DTR y DST)? Pues falsear el handshake, de forma que en cuanto el PC esté preparado, le llegue la señal de que el hardware también está preparado y conectado.

El puente entre las líneas 7 y 8 (RTS y CTS) falsea el control de flujo por hardware. De forma que en cuanto el PC envíe la señal de que quiere enviar datos, le llegue por el puente que hemos hecho la señal de que el dispositivo también está listo para recibirlos.

¿Os habéis fijado en que el módem en cualquier momento puede pedir al PC que no le mande más datos (llevando a cero CTS) pero el PC no puede decirle que haga una pausa? Esto es así porque no tendría sentido que el PC pidiera al módem que haga una pausa si el otro extremo le sigue enviando datos. Para eso está el control de flujo por software, que es una forma de decirle al sistema remoto que estamos saturados y que no envíe nada más hasta nueva orden.

Para otras aplicaciones sí tiene sentido que tanto el PC como el aparato puedan decirse mutuamente que están preparados o no para recibir datos. Para ese caso os decía arriba que la misión de RTS y CTS ha cambiado un poco. Lo que se hace es dejar CTS para lo que estaba, indicarle al PC si el dispositivo conectado puede o no recibir datos en ese momento; y hacer que RTS sea lo mismo pero para el PC, indicándole al aparato si el PC está o no listo para recibir en ese momento.
Artículo completo >>