tag:blogger.com,1999:blog-2454532468612134732024-03-13T23:56:34.320+01:00Tibu's WorksProyectos electrónicos de andar por casa. | <i>Electronic homespun projects</i>.Anonymoushttp://www.blogger.com/profile/11133658869560834508noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-245453246861213473.post-58126878111993816242013-06-08T17:32:00.002+02:002013-06-08T17:32:09.988+02:00PWM Síncrono con PCA9685 | Synchronous PWM with PCA9685<div class="ln" lang="es">
Gracias al auge de la iluminación LED han salido al mercado circuitos integrados capaces de generar varias salidas PWM. La mayoría de ellos son escalables permitiendo generar múltiples señales con un único bus de datos.<br />
<br />
Por ejemplo el <a href="http://www.ti.com/lit/ds/symlink/tlc5940.pdf" target="_blank">TLC5940</a>, que cuenta con 16 salidas de 12 bits de resolución (4096 pasos). El problema que encontramos con este integrado es que cada una de las salidas tiene un delay de 20ns con respecto a la anterior (Pag. 14), así entre la salida 0 y la 15 hay 300ns de delay.<br />
<br />
Otro integrado interesante es el <a href="http://www.nxp.com/documents/data_sheet/PCA9685.pdf" target="_blank">PCA9685</a> que, al igual que el anterior, dispone de 16 salidas de 12 bits de resolución, y a diferencia del anterior, son sincrónicas. A demás este integrado se controla mediante el bus de datos <a href="http://es.wikipedia.org/wiki/I2C" target="_blank">I2C</a>. El único problema que tiene es que la frecuencia máxima de señal utilizando el oscilador interno (25MHz) es de 1KHz. Usando un oscilador externo de 50MHz (máximo permitido), obtendríamos una frecuencia de 12KHz aproximadamente (Pag. 13).<br />
<br />
<ul>
<pre> 50Mhz / 4096 = 12207Hz
</pre>
</ul>
<br />
Hay otro de la misma familia que el anterior, se trata del <a href="http://www.nxp.com/documents/data_sheet/PCA9635.pdf" target="_blank">PCA9635</a>. Este cuenta con 16 salidas de 8 bits de resolución (256 pasos), son sincrónicas y con una frecuencia de 97KHz.<br />
<br />
Para la prueba de hoy he comprado el segundo (PCA9685), y usando el oscilador interno, a una frecuencia de 1KHz he obtenido buenos resultados, lástima del zumbido audible que produce esta frecuencia en el motor.</div>
<div class="ln" lang="en">
With the rise of LED lighting, have arrived to market integrated circuits capable of generating several PWM outputs. Most of them are scalable allowing multiple signals on a single data bus.<br />
<br />
For example <a href="http://www.ti.com/lit/ds/symlink/tlc5940.pdf" target="_blank">TLC5940</a>, which has 16 outputs 12-bit resolution (4096 steps). The problem we found with this chip is that each output has a delay of 20ns respect to previous output (p. 14), and there is 300ns delay between outputs 0 and 15.<br />
<br />
Another interesting IC is <a href="http://www.nxp.com/documents/data_sheet/PCA9685.pdf" target="_blank">PCA9685</a> which, as the previous one, has 16 outputs 12-bits resolution, but the outputs are synchronous. This integrated is controlled by <a href="http://en.wikipedia.org/wiki/I%C2%B2C" target="_blank">I2C</a> data bus. The only problem I have is that the maximum signal frequency using the internal oscillator (25MHz) is 1KHz. Using a 50MHz external oscillator (maximum allowed), we can obtain a frequency of about 12KHz (p. 13).<br />
<br />
<ul>
<pre>50Mhz / 4096 = 12207Hz
</pre>
</ul>
<br />
Another of the same family as above, it's <a href="http://www.nxp.com/documents/data_sheet/PCA9635.pdf" target="_blank">PCA9635</a>. It has 16 outputs 8-bit resolution (256 steps), are synchronous with a frequency of 97KHz.<br />
<br />
For testing today I bought the second one (PCA9685), and using the internal oscillator at a frequency of 1kHz I had good results, shame about the audible hum frequency produced by motor.</div>
<br />
<br />
<table>
<tbody>
<tr>
<td><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoNBwkoQgcZO2wglcNAlP79CmLpXfkTdpcCJuErStRb1rZUqBVh-DvOBiPtky6k8BtUO5K4rqxX69AMkzt_BFuv_DoibF3wyDzNR47u7PhyjGOVLcClGFdVEteZXtkdH0P3a5iOos7bN-g/s1600/PCA9685_1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoNBwkoQgcZO2wglcNAlP79CmLpXfkTdpcCJuErStRb1rZUqBVh-DvOBiPtky6k8BtUO5K4rqxX69AMkzt_BFuv_DoibF3wyDzNR47u7PhyjGOVLcClGFdVEteZXtkdH0P3a5iOos7bN-g/s200/PCA9685_1.jpg" width="112" /></a></div>
</td>
<td><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBAMM55amtyQDdIhfHtTI7oVdgW2uwp0Mn8Jgc2WVongSpHCoMO-iObc6msVA1l0Iuudrdz5QWGEfALMRjDTe_Uqd1BxJHR1y9GRMY6FyS8v-T_O81sQdyp4jvLYdNrVltR4ghH4aMWygn/s1600/PCA9685_2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBAMM55amtyQDdIhfHtTI7oVdgW2uwp0Mn8Jgc2WVongSpHCoMO-iObc6msVA1l0Iuudrdz5QWGEfALMRjDTe_Uqd1BxJHR1y9GRMY6FyS8v-T_O81sQdyp4jvLYdNrVltR4ghH4aMWygn/s200/PCA9685_2.jpg" width="200" /></a></div>
</td>
<td><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik-McYfhC_IGCg-rnF2b8kowBIazlZR6iyFRkLFf0f92j-vwmvcETLyoWkAHf0vJKbpWheNPgSN6f5_ERRHfGKDBOzAObkkuBWmIgAM2fF2qXOLD4_DM_gkUkDswoAZaE3scoviQZ4LUBV/s1600/PCA9685_3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik-McYfhC_IGCg-rnF2b8kowBIazlZR6iyFRkLFf0f92j-vwmvcETLyoWkAHf0vJKbpWheNPgSN6f5_ERRHfGKDBOzAObkkuBWmIgAM2fF2qXOLD4_DM_gkUkDswoAZaE3scoviQZ4LUBV/s200/PCA9685_3.jpg" width="200" /></a></div>
</td>
</tr>
</tbody></table>
<br />
<div class="ln" lang="es">
La verdad, pensaba que costaría más soldar los pins del encapsulado TSSOP28, pero no ha sido complicado, internet está lleno de manuales de cómo hacerlo. Aquí hay algunos interesantes de Sparkfun:<br />
<br />
Surface Mount Soldering Tutorials:<br />
<a href="https://www.sparkfun.com/tutorials/category/2" target="_blank">https://www.sparkfun.com/tutorials/category/2</a><br />
<br />
El siguiente esquema muestra la conexión entre PCA9685 y Arduino Nano. He usado también 2 transistores Darlington BD679 y la fuente de alimentación de Märklin Mini-Club. El potenciómetro de la fuente hay que ponerlo al máximo hacia la derecha, el conector rojo es el positivo y el marrón el negativo.</div>
<div class="ln" lang="en">
Actually, I thought it would be hard to solder TSSOP28 package pins, but it was not complicated, internet is full of how-to manuals. Here's an interesting one from Sparkfun:<br />
<br />
Surface Mount Soldering Tutorials<br />
<a href="https://www.sparkfun.com/tutorials/96" target="_blank">https://www.sparkfun.com/tutorials/96</a><br />
<br />
The following scheme shows the connections between PCA9685 and Arduino Nano. I used also 2 Darlington transistors BD679 and a Märklin Mini-Club power supply. The supply potentiometer must be put to maximum clockwise, the red connector is the positive and brown is the negative.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPd8kkCd4xmJWk6V8TpIrYqp9F1p-iC6zx5Vo2EISi-Ysq953bxhoN_zkHaI-lmRZzwSwYw5_OvK0zEu-9lshyphenhyphendvX_6tFIl_gQYD8gFsuMdV59Los8RJ0XP-NsjK9_WSWNP1EvUmSZQIGG/s1600/PCA9685_SCH.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPd8kkCd4xmJWk6V8TpIrYqp9F1p-iC6zx5Vo2EISi-Ysq953bxhoN_zkHaI-lmRZzwSwYw5_OvK0zEu-9lshyphenhyphendvX_6tFIl_gQYD8gFsuMdV59Los8RJ0XP-NsjK9_WSWNP1EvUmSZQIGG/s400/PCA9685_SCH.png" width="400" /></a></div>
<br />
<br />
<pre class="brush: Arduino">#include <Wire.h>
#define MODE1 0x00
#define MODE2 0x01
#define LED0 0x06
#define LED_SIZE 0x04
#define PRE_SCALE 0xFE
byte _address = B01000000;
void setup()
{
Wire.begin();
SetReg(MODE1, B00001001); // Sleep
SetReg(PRE_SCALE, 0); // Prescale. Minimum is 3 (Pag. 24)
SetReg(MODE1, B00000001); // Reset
SetReg(MODE1, B10100001); // Auto-Increment
SetReg(MODE2, B00000100); // Totem Pole
for(int i=0; i<16; i++)
SetPwm(i, 700);
}
void loop()
{}
void SetReg(byte reg, byte data)
{
Wire.beginTransmission(_address); // Address
Wire.write(reg); // Register
Wire.write(data); // Data
Wire.endTransmission();
}
void SetPwm(int led, unsigned int pwm)
{
Wire.beginTransmission(_address); // Address
Wire.write(LED0 + (led * LED_SIZE)); // Output
Wire.write(0); // LEDn_ON_L
Wire.write(0); // LEDn_ON_H
Wire.write(pwm); // LEDn_OFF_L
Wire.write(pwm>>8); // LEDn_OFF_H
Wire.endTransmission();
}
</pre>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid8sZGUpTOfGf1Mi3Y3E5bd5souL4s0U3XFIv45Kq2800I1IUrXWVpG8bAO_42NMd2lm6SnYMlGgGM2FylHR0JTGaa_uibL-Z6r_NxXWjStJsgLOo3AnxuztPodfhGFMNuThWhPt6FKWSd/s1600/PCA9685_4.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid8sZGUpTOfGf1Mi3Y3E5bd5souL4s0U3XFIv45Kq2800I1IUrXWVpG8bAO_42NMd2lm6SnYMlGgGM2FylHR0JTGaa_uibL-Z6r_NxXWjStJsgLOo3AnxuztPodfhGFMNuThWhPt6FKWSd/s400/PCA9685_4.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">
Las flechas señalan los puntos de aislamiento</div>
<div class="ln" lang="en">
Arrows indicates the isolation points</div>
</td></tr>
</tbody></table>
<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="360" src="http://www.youtube.com/embed/_kisokvaZxQ" width="640"></iframe>
<br />
<hr />
<br />
<b></b><br />
<div class="ln" lang="es">
<b>Descargas:</b></div>
<div class="ln" lang="en">
<b>Downloads:</b></div>
<b>
</b>
<br />
<a href="http://www.raulnd.com/TibuWorks/ArduinoPCA9685.zip" target="_blank">ArduinoPCA9685.zip</a>
<br />
<br />
<hr />
<br />
<b></b><br />
<div class="ln" lang="es">
<b>Enlaces:</b></div>
<div class="ln" lang="en">
<b>Links:</b></div>
<b>
</b>
<br />
TLC5940 (EN): <a href="http://www.ti.com/lit/ds/symlink/tlc5940.pdf" target="_blank">http://www.ti.com/lit/ds/symlink/tlc5940.pdf</a><br />
PCA9685 (EN): <a href="http://www.nxp.com/documents/data_sheet/PCA9685.pdf" target="_blank">http://www.nxp.com/documents/data_sheet/PCA9685.pdf</a><br />
PCA9635 (EN): <a href="http://www.nxp.com/documents/data_sheet/PCA9635.pdf" target="_blank">http://www.nxp.com/documents/data_sheet/PCA9635.pdf</a><br />
I2C (ES): <a href="http://es.wikipedia.org/wiki/I2C" target="_blank">http://es.wikipedia.org/wiki/I2C</a><br />
I2C (EN): <a href="http://en.wikipedia.org/wiki/I%C2%B2C" target="_blank">http://en.wikipedia.org/wiki/I%C2%B2C</a><br />
Surface Mount Soldering Tutorials (EN): <a href="https://www.sparkfun.com/tutorials/category/2" target="_blank">https://www.sparkfun.com/tutorials/category/2</a><br />
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/11133658869560834508noreply@blogger.com3tag:blogger.com,1999:blog-245453246861213473.post-48046540331982643082013-05-30T01:13:00.000+02:002013-05-30T01:13:05.784+02:00PWM síncrono | Synchronous PWM<div class="ln" lang="es">
Ya sabemos cómo controlar la velocidad y el sentido de la marcha de un tren con Arduino, ahora vamos a ver cómo aplicarlo a una maqueta analógica. El principal problema que se nos presenta es el de las transiciones entre <a href="http://es.wikipedia.org/wiki/Cant%C3%B3n_ferroviario" target="_blank">cantones</a> de vía alimentados con diferentes fuentes PWM. No voy a extenderme explicándolo ya que hay dos blogs que lo hacen estupendamente, mejor de lo que yo lo haría.<br />
<br />
El primero es “<a href="http://agp-schwarzwaldbahn.blogspot.com.es/" target="_blank">AGP SchwarzWaldBahn 220</a>” de A. G. Pino, dónde plantea el problema que ocurre cuando un tren toma la corriente de dos tramos de vía alimentados cada uno por una fuente PWM diferente:<br />
<ul>
<b><a href="http://agp-schwarzwaldbahn.blogspot.com.es/2009/03/transiciones.html" target="_blank">Transiciones (I)</a></b>: Pruebas con distintos reguladores.<br />
<a href="http://agp-schwarzwaldbahn.blogspot.com.es/2009/03/transiciones-ii.html" target="_blank"><b>Transiciones (II)</b></a>: Solución mediante conmutación de reguladores.<br />
</ul>
<br />
El segundo es “<a href="http://mimaquetaz.blogspot.com.es/" target="_blank">Mi Maqueta Marklin Z</a>”de Ignacio de la Fuente, donde explica una posible solución al problema planteado:<br />
<ul>
<b><a href="http://mimaquetaz.blogspot.com.es/2011/11/pwm-y-iii.html" target="_blank">PWM (y III)</a></b>: Solución bidireccional.<br />
<b><a href="http://mimaquetaz.blogspot.com.es/2012/01/cab-control.html" target="_blank">Cab Control</a></b>: Varios reguladores que pueden asignarse a cualquier cantón aislado del circuito.<br />
</ul>
<br />
Bueno, pues yo propongo otra solución. Una solución que sólo funciona en teoría pero no en la práctica ya que el ancho de los pulsos PWM dependerá de la tolerancia de los componentes utilizados.<br />
<br />
Mi idea es la de sincronizar un número n de generadores PWM alineados a la izquierda. ¿Y cómo se consigue esto? Pues muy sencillo, con una señal de reloj y n generadores de un único pulso de una duración menor o igual que la frecuencia de dicho reloj. Veamos la siguiente imagen:</div>
<div class="ln" lang="en">
We know how to control the speed and direction of a train with Arduino, now let's see how to apply it to an analog layout. The main issue we have to overcome are transitions between <a href="http://modeltrains.about.com/od/bmodelrailroadterms/g/block.htm" target="_blank">isolated blocks</a> of track using different PWM sources. I will not dwell explaining it as there are two blogs that do this great, better than I would do (Sorry, these blogs are only in spanish)<br />
<br />
The first is “<a href="http://agp-schwarzwaldbahn.blogspot.com.es/" target="_blank">AGP Schwarzwaldbahn 220</a>” by A. G. Pino, where the problem happens when a train is powered from two different sections of track, each with a different PWM source:<br />
<ul>
<b><a href="http://agp-schwarzwaldbahn.blogspot.com.es/2009/03/transiciones.html" target="_blank">Transitions (I)</a></b>: Tests with different controllers.<br />
<b><a href="http://agp-schwarzwaldbahn.blogspot.com.es/2009/03/transiciones-ii.html" target="_blank">Transitions (II)</a></b>: Solution by switching regulators between blocks.<br />
</ul>
<br />
The second one is “<a href="http://mimaquetaz.blogspot.com.es/" target="_blank">Mi Maqueta Marklin Z</a>” by Ignacio de la Fuente, explaining a possible solution to the problem:<br />
<ul>
<b><a href="http://mimaquetaz.blogspot.com.es/2011/11/pwm-y-iii.html" target="_blank">PWM (and III)</a></b>: Bidirectional solution.<br />
<b><a href="http://mimaquetaz.blogspot.com.es/2012/01/cab-control.html" target="_blank">Cab Control</a></b>: Several controllers can be assigned to any isolated block.<br />
</ul>
<br />
Well, I propose another solution. A solution which works only in theory but not in practice since the PWM pulse widths depend on the tolerances of the components used.<br />
<br />
My idea is to synchronize n left-aligned PWM sources. And how is this achieved? Very simple, with a clock signal and n single pulse sources with a pulse duration less or equal than clock frequency.<br />
Consider the following image:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5uO49-zw2DOWZaQUXdJ_nD_LEDEePQZ1nSVZVx1CSyl-kLHvrUO5dCM4yGMw0Uzj0wzu2Gk982nZpnaOuDixumfD4LkysUjnqC8WZ_FX-HNyxVUJlkPugDFwBejKiEAe4UJMwp5cDZkgS/s1600/MCP4131.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWmqZcY-JVoNboDGIble9Cu-SVSVJFzOOhXz-NR6_1p36EnaroINVWOevlAVkEz43tl6GmFHwHDIkBArXvw9DkstyDG-hSc8dGM7zCaItPF_eEFYOpEwFuS55z2Uiq8ZOf38dAWQhe3Fgz/s1600/PWMCLK.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="321" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWmqZcY-JVoNboDGIble9Cu-SVSVJFzOOhXz-NR6_1p36EnaroINVWOevlAVkEz43tl6GmFHwHDIkBArXvw9DkstyDG-hSc8dGM7zCaItPF_eEFYOpEwFuS55z2Uiq8ZOf38dAWQhe3Fgz/s640/PWMCLK.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">
Teoría de PWM síncrono</div>
<div class="ln" lang="en">
Synchronous PWM theory</div>
</td></tr>
</tbody></table>
<br />
<div class="ln" lang="es">
Cada una de las fuentes de pulso genera un único pulso cada vez que el reloj pasa de estado alto a bajo. Si el reloj es constante, se generarán pulsos constantes. Para construir estos circuitos se emplea el <a href="http://es.wikipedia.org/wiki/Circuito_integrado_555" target="_blank">circuito integrado 555</a> en configuración monoestable y para el reloj una salida PWM de Arduino con un valor de entre 240 y 250 (sobre 255). Para evitar disparos erróneos se coloca al final del reloj una resistencia pullup de 10K.
</div>
<div class="ln" lang="en">
Each of the pulse sources produces a single pulse each time clock goes from high to low. If clock is constant, constant pulses are generated. To make these circuits we have to use <a href="http://en.wikipedia.org/wiki/555_IC" target="_blank">555 ic</a> in monostable configuration and an Arduino PWM output for generating clock, with a PWM value of between 240 and 250 (about 255). To prevent erroneous triggering, a 10K pullup resistor must be placed at the end of the clock line.
</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCqNz_nkfOLHcp7zvkwvQVKSoAMRsW4En7nIy-z5271au750hrzs9TrCRanumB6Yk_lnDVV0EVcWHoFmnAWDpay6tVaKM2bTn9uvXr-zCvDJukb73uNs4URgdUf-i6OZMTx-t9RdKSb5PL/s1600/555Mono.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="325" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCqNz_nkfOLHcp7zvkwvQVKSoAMRsW4En7nIy-z5271au750hrzs9TrCRanumB6Yk_lnDVV0EVcWHoFmnAWDpay6tVaKM2bTn9uvXr-zCvDJukb73uNs4URgdUf-i6OZMTx-t9RdKSb5PL/s640/555Mono.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">
555 monoestable</div>
<div class="ln" lang="en">
Monostable 555</div>
</td></tr>
</tbody></table>
<div class="ln" lang="es">
La frecuencia que he elegido para el reloj es de 62500Hz, o lo que es lo mismo un pulso cada 16us. En Arduino UNO, por ejemplo, esta frecuencia sólo se puede conseguir con los pins 5 y 6 que son los que están conectados al TIMER0.<br />
<br />
Para calcular los valores de los componentes en configuración monoestable se utiliza la siguiente función:
</div>
<div class="ln" lang="en">
I've chosen 62500Hz as clock frequency, or a pulse every 16us. In Arduino UNO, for example, this frequency can only be achieved using pins 5 and 6, which are currently connected to TIMER0.<br />
<br />
Use the following function in order to calculate the values for the components in monostable configuration:
</div>
<pre><ul>T = 1.1 * R * C</ul>
</pre>
<div class="ln" lang="es">
Dónde los valores son en unidades:
<br />
<pre><ul>
T en segundos.
R en ohmios.
C en faradios.
</ul>
</pre>
</div>
<div class="ln" lang="en">
Where the values are in units:
<br />
<pre><ul>
T in seconds.
R in ohms.
C in farads.
</ul>
</pre>
</div>
<div class="ln" lang="es">
Para obtener 16us usando un potenciómetro de 10K tenemos que:</div>
<div class="ln" lang="en">
To obtain a 16us pulse using a 10K potentiometer we have:</div>
<pre><ul>
16us = 1.1 * 10K * C
C = 16us / (1.1 * 10K)
C = 1.45e-9
C ~ 1500pF
</ul>
</pre>
<div class="ln" lang="es">
Resolviendo T con C = 1500pF:</div>
<div class="ln" lang="en">
Solving T with C = 1500pF:</div>
<pre><ul>
T = 1.1 * 10K * 1500pF
T = 0.0000165s
T = 16.5us
</ul>
</pre>
<div class="ln" lang="es">
Obtenemos un tiempo superior al del reloj, por lo tanto el valor máximo que usaremos en el potenciómetro será:</div>
<div class="ln" lang="en">
We get a time higher than the clock time, therefore the maximum value that we will use in the pot will be:</div>
<pre><ul>
R = T / (1.1 * C)
R = 16us / (1.1 * 1500pF)
R ~ 9K70
</ul>
</pre>
<div class="ln" lang="es">
A partir del 97% del potenciómetro tendremos una señal PWM del 100%.<br />
<br />
Para la primera prueba he utilizado 3 circuitos monoestables con resistencias fijas de 4K7 para obtener aproximadamente la mitad del ciclo PWM en las tres salidas:
</div>
<div class="ln" lang="en">
With a pot value upper than 97% we will have a 100% PWM signal.<br />
<br />
For the first test I used three monostable circuit with 4K7 fixed resistors, to get about half of the PWM cycle at all three outputs:
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz7cE8pRzuf3GvdOfM4EAHM75wCgnDCjB8zm8L9fFnAxN55qlDFExm1ifNZEAL_HKMy9ejUEnjeMGaHEJQ97djTUkDyc2csPoA9wDK7ktCmCWBl0JTJDPO5LjSdeg752cVOjpkdo2Aic3Z/s1600/4K7sch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="161" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz7cE8pRzuf3GvdOfM4EAHM75wCgnDCjB8zm8L9fFnAxN55qlDFExm1ifNZEAL_HKMy9ejUEnjeMGaHEJQ97djTUkDyc2csPoA9wDK7ktCmCWBl0JTJDPO5LjSdeg752cVOjpkdo2Aic3Z/s640/4K7sch.png" width="640" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv8UHQDPKx4o7ciAUc6stMGV_-8DbSjnvieUkbstH0hXseVRw3YjSQKePn9xu7qrZqXYEmPDDCACbBWE2thM6P32IjLMaYX7q2KmToF028aLpUntfmlI0LmlvaCJ5tJPTVA3aDMIJO01qh/s1600/4K7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="369" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv8UHQDPKx4o7ciAUc6stMGV_-8DbSjnvieUkbstH0hXseVRw3YjSQKePn9xu7qrZqXYEmPDDCACbBWE2thM6P32IjLMaYX7q2KmToF028aLpUntfmlI0LmlvaCJ5tJPTVA3aDMIJO01qh/s640/4K7.png" width="640" /></a></div>
<br />
<br />
<div class="ln" lang="es">
Se puede observar como el inicio del pulso de las tres señales está perfectamente sincronizado, no ocurre lo mismo con el final, ya que ni las tres resistencias ni los tres condensadores son exactamente iguales entre sí. Las resistencias tienen una tolerancia de 5%, por lo tanto sus valores pueden variar entre 4465 y 4935 ohmios. Los condensadores que he utilizado también tienen una tolerancia del 5%, por lo tanto sus valores oscilan entre 1425 y 1757 picofaradios.<br />
<br />
Para la segunda prueba he sustituido las resistencias fijas de 4K7 por un potenciómetro digital de 10K de Microchip, el <a href="http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf" target="_blank">MCP4131</a>.
</div>
<div class="ln" lang="en">
It can be seen that the pulse start of all three signals are perfectly synchronized, not so with the signal end, as neither the three resistors and three capacitors are exactly equal. The resistors have a tolerance of 5%, so their values may vary between 4465 and 4935 ohms. The capacitors I've used also have a tolerance of 5%, so their values range are between 1425 and 1757 pF.<br />
<br />
For the second test I replaced the 4K7 fixed resistors by a digital 10K potentiometer from Microchip, the <a href="http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf" target="_blank">MCP4131</a>.
</div>
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcJDNn250gS-Ih2j54Nc0RIfDB5AFJLK4Pu1M_9HGh2gXQKjYBVie8W2iH-UX0MGZHrwawSbbtVIchGq7pG3LRPbJn9-RC4KZdBx-PEVPjetAg07Qis5xm74e_uv8kuR7jOut1uKNeutFP/s1600/MCP4131sch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="283" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcJDNn250gS-Ih2j54Nc0RIfDB5AFJLK4Pu1M_9HGh2gXQKjYBVie8W2iH-UX0MGZHrwawSbbtVIchGq7pG3LRPbJn9-RC4KZdBx-PEVPjetAg07Qis5xm74e_uv8kuR7jOut1uKNeutFP/s640/MCP4131sch.png" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5uO49-zw2DOWZaQUXdJ_nD_LEDEePQZ1nSVZVx1CSyl-kLHvrUO5dCM4yGMw0Uzj0wzu2Gk982nZpnaOuDixumfD4LkysUjnqC8WZ_FX-HNyxVUJlkPugDFwBejKiEAe4UJMwp5cDZkgS/s1600/MCP4131.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="369" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5uO49-zw2DOWZaQUXdJ_nD_LEDEePQZ1nSVZVx1CSyl-kLHvrUO5dCM4yGMw0Uzj0wzu2Gk982nZpnaOuDixumfD4LkysUjnqC8WZ_FX-HNyxVUJlkPugDFwBejKiEAe4UJMwp5cDZkgS/s640/MCP4131.png" width="640" /></a></div>
<br />
<br />
<div class="ln" lang="es">
Se puede apreciar una mayor diferencia en la salida ya que estos potenciómetros tienen una tolerancia del 20%.<br />
<br />
Como ya he dicho antes, esta es una solución teórica, una solución que sólo funcionaría si los componentes tuviesen tolerancia 0%.<br />
<br />
Para finalizar, me gustaría recomendar la lectura de los dos blogs a los que he hecho referencia al inicio de este artículo:<br />
<br />
<ul>
“<a href="http://agp-schwarzwaldbahn.blogspot.com.es/" target="_blank">AGP SchwarzWaldBahn 220</a>” de A. G. Pino.<br />
“<a href="http://mimaquetaz.blogspot.com.es/" target="_blank">Mi Maqueta Marklin Z</a>” de Ignacio de la Fuente.<br />
</ul>
</div>
<div class="ln" lang="en">
We can see a major difference at the outputs, as these potentiometers have a tolerance of 20%.<br />
<br />
As I said before, this is a theoretical solution, a solution that would only work if all of the components had a tolerance of 0%.<br />
<br />
Finally, I'd recommend reading the two blogs to which I referred at the beginning of this article: <br />
<br />
<ul>
“<a href="http://agp-schwarzwaldbahn.blogspot.com.es/" target="_blank">AGP SchwarzWaldBahn 220</a>” by A. G. Pino.<br />
“<a href="http://mimaquetaz.blogspot.com.es/" target="_blank">Mi Maqueta Marklin Z</a>” by Ignacio de la Fuente.<br />
</ul>
</div>
<br />
<br />
<hr />
<br />
<b></b><br />
<div class="ln" lang="es">
<b>Descargas:</b></div>
<div class="ln" lang="en">
<b>Downloads:</b></div>
<b>
</b>
<br />
<a href="http://www.raulnd.com/TibuWorks/TestFixRes.zip" target="_blank">TestFixRes.zip</a><br />
<br />
<a href="http://www.raulnd.com/TibuWorks/TestMCP4131.zip" target="_blank">TestMCP4131.zip</a><br />
<br />
<br />
<hr />
<br />
<b></b><br />
<div class="ln" lang="es">
<b>Enlaces:</b></div>
<div class="ln" lang="en">
<b>Links:</b></div>
<b>
</b>
<br />
Cantón ferroviario (ES): <a href="http://es.wikipedia.org/wiki/Cant%C3%B3n_ferroviario" target="_blank">http://es.wikipedia.org/wiki/Cantón_ferroviario</a><br />
<br />
Model RR blocks (EN): <a href="http://modeltrains.about.com/od/bmodelrailroadterms/g/block.htm" target="_blank">http://modeltrains.about.com/od/bmodelrailroadterms/g/block.htm</a><br />
<br />
Circuito integrado 555 (ES): <a href="http://es.wikipedia.org/wiki/Circuito_integrado_555" target="_blank">http://es.wikipedia.org/wiki/Circuito_integrado_555</a><br />
<br />
555 integrated circuit (EN): <a href="http://en.wikipedia.org/wiki/555_IC" target="_blank">http://en.wikipedia.org/wiki/555_IC</a><br />
<br />
NE555 (EN): <a href="http://www.ti.com/lit/ds/symlink/ne555.pdf" target="_blank">http://www.ti.com/lit/ds/symlink/ne555.pdf</a><br />
<br />
MCP4131 (EN): <a href="http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf" target="_blank">http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf</a><br />
<br />
<br />
AGP SchwarzWaldBahn 220 (ES): <a href="http://agp-schwarzwaldbahn.blogspot.com.es/" target="_blank">http://agp-schwarzwaldbahn.blogspot.com.es</a><br />
<ul>
Transiciones (I): <a href="http://agp-schwarzwaldbahn.blogspot.com.es/2009/03/transiciones.html" target="_blank">http://agp-schwarzwaldbahn.blogspot.com.es/2009/03/transiciones.html</a><br />
Transiciones (II): <a href="http://agp-schwarzwaldbahn.blogspot.com.es/2009/03/transiciones-ii.html" target="_blank">http://agp-schwarzwaldbahn.blogspot.com.es/2009/03/transiciones-ii.html</a><br />
</ul>
Mi Maqueta Marklin Z (ES): <a href="http://mimaquetaz.blogspot.com.es/" target="_blank">http://mimaquetaz.blogspot.com.es</a><br />
<ul>
PWM (y III): <a href="http://mimaquetaz.blogspot.com.es/2011/11/pwm-y-iii.html" target="_blank">http://mimaquetaz.blogspot.com.es/2011/11/pwm-y-iii.html</a><br />
Cab Control: <a href="http://mimaquetaz.blogspot.com.es/2012/01/cab-control.html" target="_blank">http://mimaquetaz.blogspot.com.es/2012/01/cab-control.html</a><br />
</ul>
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/11133658869560834508noreply@blogger.com6tag:blogger.com,1999:blog-245453246861213473.post-54162387769570151072013-05-19T16:46:00.000+02:002013-05-19T16:48:22.681+02:00Mejorando la lectura analógica | Improving analog reading<div class="ln" lang="es">
En la anterior versión del analizador lógico cometí un error, deshabilitaba las interrupciones mientras leía el puerto analógico, esto producía errores en el reloj encargado de calcular el tiempo total.
</div>
<div class="ln" lang="en">
In the previous version of the logic analyzer I made a mistake, I disabled the interrupts while reading the analog port, it causes errors in the clock that calculates the total time.
</div>
<br />
<br />
<pre class="brush: Arduino">...
Serial.end();
noInterrupts();
BeginRead();
interrupts();
Serial.begin(115200);
Serial.write(_data, DATA);
...
void ReadAnalog()
{
t = micros();
for(i=0; i<DATA; i+=2) // 2 cycles
{
/*** From wiring_analog.c ***/
// start the conversion
sbi(ADCSRA, ADSC); // 2 Cycles
// ADSC is cleared when the conversion finishes
while (bit_is_set(ADCSRA, ADSC)); // 13 * 16 Cycles
// we have to read ADCL first; doing so locks both ADCL
// and ADCH until ADCH is read. reading ADCL second would
// cause the results of each conversion to be discarded,
// as ADCL and ADCH would be locked when it completed.
_data[i+1] = ADCL; // 2 cycles
_data[i] = ADCH; // 1 cycle
/****************************/
}
t = micros() - t;
_data[DATA-4] = (byte)(t >> 24);
_data[DATA-3] = (byte)(t >> 16);
_data[DATA-2] = (byte)(t >> 8);
_data[DATA-1] = (byte)(t);
}
</pre>
<br />
<br />
<div class="ln" lang="es">
Se puede calcular el error de la siguiente manera:<br />
<br />
Tiempo de cada iteración:<br />
<br />
<ul style="font-family: "Courier New",Courier,monospace;">
for: 2 ciclos<br />
sbi: 2 ciclos<br />
leer analógico: 208 ciclos (13 ciclos ADC * 16 prescaler)<br />
leer ADCL : 2 ciclos (1 para incrementar el índice y 1 para asignar al array)<br />
leer ADCH: 1 ciclo<br />
Total: 215 ciclos<br />
</ul>
<br />
<bt>
Teníamos 898 iteraciones:<br /><br />
</bt><br />
<ul style="font-family: "Courier New",Courier,monospace;">
898 iteraciones * 215 ciclos = 193070 ciclos<br />
193070 ciclos * 62.5 ns = 12.07 ms<br />
</ul>
<br /><br />
Al deshabilitar las interrupciones y calcular el tiempo con la función "micros()" obteníamos aproximadamente 1200 us, unas mil veces menos de lo esperado.<br /><br />
Así que al final, he decidido no calcular el tiempo y leer 900 veces (1800 bytes), y actuar de la misma forma que en la lectura digital.
</div>
<div class="ln" lang="en">
Error can be calculated as follows:<br />
<br />
Time per iteration:<br />
<br />
<ul style="font-family: "Courier New",Courier,monospace;">
for: 2 cycles<br />
sbi: 2 cycles<br />
analog read: 208 cycles (13 ADC cycles * 16 prescaler)<br />
read ADCL: 2 cycles (1 for increasing index and 1 to assign the array)<br />
read ADCH: 1 cycle<br />
Total: 215 cycles<br />
</ul>
<br />
<br />
We had 898 iterations:<br />
<br />
<ul style="font-family: "Courier New",Courier,monospace;">
898 iterations * 215 cycles = 193070 cycles<br />
193070 cycles * 62.5 ns = 12.07 ms<br />
</ul>
<br />
<br />
By disabling interrupts and calculate the time using "micros()" we're getting about 1200 us, a thousand times less than expected.<br />
<br />
So in the end, I decided not calculate the time and read 900 times (1800 bytes), and act at the same way as digital reading.
</div>
<br /><br />
<hr />
<br /><br />
<div class="ln" lang="es">
<b>Descargas:</b></div>
<div class="ln" lang="en">
<b>Downloads:</b></div>
<b>
</b>
<br />
<a href="http://www.raulnd.com/TibuWorks/LogicAnalyzer.zip" target="_blank">LogicAnalyzer.zip</a>
<br />
<br />
<hr />
<br />Anonymoushttp://www.blogger.com/profile/11133658869560834508noreply@blogger.com0Barberá del Vallés, Barcelona, España41.5164233 2.140113899999960341.4688683 2.05943289999996 41.5639783 2.2207948999999605tag:blogger.com,1999:blog-245453246861213473.post-28553625643009282892013-05-08T09:30:00.002+02:002013-05-08T09:32:46.760+02:00Analizador lógico (analógico) | Logic analyzer (analog)<div class="ln" lang="es">
Para leer un canal analógico la cosa cambia. No podemos leer el puerto completo, tenemos que leer un pin analógico y esperar a que el microcontrolador haga la conversión del voltaje de entrada a un valor numérico legible. Por defecto, Arduino utiliza el prescaler del reloj del conversor analógico-digital con un valor de 128, que significa que el reloj ADC trabajará a una frecuencia de 125KHz.<br />
<br />
<ul style="font-family: "Courier New",Courier,monospace;">16 MHz / 128 = 125 KHz</ul>
<br />
Esto lo podemos ver en el archivo "Arduino \hardware\arduino\cores\arduino\wiring.c"</div>
<div class="ln" lang="en">
To read an analog channel things change. We can't read the full port, we have to read an analog pin and wait for the microcontroller do the conversion of the input voltage to a numerical value. By default, Arduino uses ADC clock prescaler with a value of 128, which means that the ADC clock work at a frequency of 125KHz.<br />
<br />
<ul style="font-family: "Courier New",Courier,monospace;">16 MHz / 128 = 125 KHz</ul>
<br />
This can be seen in the "Arduino\hardware\arduino\cores\arduino\wiring.c"</div>
<br />
<pre class="brush: Arduino">#if defined(ADCSRA)
// set a2d prescale factor to 128
// 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
// XXX: this will not work properly for other clock speeds, and
// this code should use F_CPU to determine the prescale factor.
sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
// enable a2d conversions
sbi(ADCSRA, ADEN);
#endif
</pre>
<br />
<br />
<div class="ln" lang="es">
Si miramos el <a href="http://www.atmel.com/Images/doc8161.pdf" target="_blank">datasheet de ATmega328</a>, en la página 263, en el punto 23.9.2 podemos ver la siguiente tabla:
</div>
<div class="ln" lang="en">
Looking at <a href="http://www.atmel.com/Images/doc8161.pdf" target="_blank">ATmega328 datasheet</a>, on page 263, in section 23.9.2 we can see the following table:
</div>
<br />
<br />
<table align="center" class="tbl">
<tbody>
<tr>
<td width="50"><b>7</b></td>
<td width="50"><b>6</b></td>
<td width="50"><b>5</b></td>
<td width="50"><b>4</b></td>
<td width="50"><b>3</b></td>
<td width="50"><b>2</b></td>
<td width="50"><b>1</b></td>
<td width="50"><b>0</b></td>
</tr>
<tr>
<td>ADEN</td>
<td>ADSC</td>
<td>ADATE</td>
<td>ADIF</td>
<td>ADIE</td>
<td>ADPS2</td>
<td>ADPS1</td>
<td>ADPS0</td>
</tr>
</tbody></table>
<br />
<br />
<div class="ln" lang="es">
Donde ADPSx son los 3 bits que corresponden al valor del prescaler del reloj. En la página siguiente (264), en la tabla 23-5, podemos ver qué valor debemos asignar a cada bit para establecer el factor de división:
</div>
<div class="ln" lang="en">
Where ADPSx are 3 bits corresponding to the clock prescaler value. On the next page (264), Table 23-5, we can see what value we have to assign each bit to set the division factor:
</div>
<br />
<br />
<table align="center" class="tbl">
<tbody>
<tr>
<td width="50"><b>ADPS2</b></td>
<td width="50"><b>ADPS1</b></td>
<td width="50"><b>ADPS0</b></td>
<td width="150"><b>Division factor</b></td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>2</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>4</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>8</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>16</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>32</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>64</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>128</td>
</tr>
</tbody></table>
<br />
<br />
<div class="ln" lang="es">
Una lectura ADC tarda aproximadamente 13 ciclos (pag 263), necesitamos un valor de prescaler que nos asegure velocidad a la vez que fiabilidad en el resultado. Si usamos un prescaler de 16, tenemos 76923 lecturas por segundo:
</div>
<div class="ln" lang="en">
ADC read takes about 13 cycles (p 263), we need a prescaler value that assures us speed and reliability in the result. If we use a prescaler of 16, we have 76923 scans per second:</div>
<br />
<br />
<ul style="font-family: "Courier New",Courier,monospace;">
16000000 / 16 = 1000000<br />
1000000 / 13 = 76923<br />
</ul>
<br />
<pre class="brush: Arduino"> sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
cbi(ADCSRA, ADPS0);
</pre>
<br />
<br />
<div class="ln" lang="es">
El tiempo total de la ejecución de lectura puede ser variable, así que lo mejor es leer el tiempo total y enviarlo también por puerto serie. Como en el modo digital hemos utilizado un buffer de 1800 bytes y sabiendo que la lectura analógica retorna un valor entero de 2 bytes y que el tiempo en microsegundos es un entero largo sin signo, sabemos que podremos llegar a leer 898 valores:
</div>
<div class="ln" lang="en">
The total execution time for reading can be variable, so the best is to read the total spend time and send it also via serial port. As digital mode we used a buffer of 1800 bytes and knowing that analog reading returns a 2-byte integer value and the time in microseconds is an unsigned long, we know we can get to read 898 values:</div>
<br />
<br />
<ul style="font-family: "Courier New",Courier,monospace;">1800 - 4 = 1796<br />1796 / 2 = 898</ul>
<br />
<br />
<pre class="brush: Arduino">#define DATA 1800
#define DATAA 1796
byte _data[DATA];
unsigned long t;
void setup()
{
sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
cbi(ADCSRA, ADPS0);
// DEFAULT Analog reference + A0 input pin
ADMUX = (DEFAULT << 6); // | (pin & 0x07);
}
void ReadAnalog()
{
t = micros();
for(i=0; i<DATAA; i+=2)
{
/*** From wiring_analog.c ***/
// start the conversion
sbi(ADCSRA, ADSC);
// ADSC is cleared when the conversion finishes
while (bit_is_set(ADCSRA, ADSC));
// we have to read ADCL first; doing so locks both ADCL
// and ADCH until ADCH is read. reading ADCL second would
// cause the results of each conversion to be discarded,
// as ADCL and ADCH would be locked when it completed.
_data[i+1] = ADCL;
_data[i] = ADCH;
/****************************/
}
t = micros() - t;
_data[DATA-4] = (byte)(t >> 24);
_data[DATA-3] = (byte)(t >> 16);
_data[DATA-2] = (byte)(t >> 8);
_data[DATA-1] = (byte)(t);
}
</pre>
<br />
<br />
<br />
<br />
<b></b><br />
<div class="ln" lang="es">
<b>PRUEBAS:</b></div>
<div class="ln" lang="en">
<b>TESTS:</b></div>
<br />
<br />
<div class="ln" lang="es">
Al igual que en el artículo anterior, he programado otra placa Arduino para que genere los datos a leer. Se trata de una <a href="https://es.wikipedia.org/wiki/Sinusoide" target="_blank">onda sinusoidal</a> que oscila entre 0 y 5V.<br />
<br />
Si miramos el enlace de la Wikipedia podemos ver la siguiente expresión. Tomamos la fase inicial como 0 (φ). Sabemos que si utilizamos una salida PWM para generar la onda podemos representar 256 valores de 0V a 5V. Así que la amplitud (A) corresponderá a la mitad, 128 (2.5V) y el periodo (T) a 255:
</div>
<div class="ln" lang="en">
As in the previous article, I have programed another Arduino to generate the data to read. It is a <a href="http://en.wikipedia.org/wiki/Sine_wave" target="_blank">sine wave</a> ranging between 0 and 5V.<br />
<br />
If we look at the Wikipedia link we can see the following expression. We take the initial phase as 0 (φ). We know that if we use a PWM output to generate the wave we can represent 256 values from 0V to 5V. So that the amplitude (A) correspond to half, 128 (2.5V) and the period (T) of 255:
</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9aseUOAwishJ_Xex4Z1drviuU2cwL7k8eXfuSkrMpPkvd8LZOvpC1JyLTdYDzIqLCHHuy0pRfSZScyNK-t36ILhwMQLNBNyq154Vv6BxCC8Ds_GqNfWssFaVjKy8uex6-q-Ry86mMtkbp/s1600/eq1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9aseUOAwishJ_Xex4Z1drviuU2cwL7k8eXfuSkrMpPkvd8LZOvpC1JyLTdYDzIqLCHHuy0pRfSZScyNK-t36ILhwMQLNBNyq154Vv6BxCC8Ds_GqNfWssFaVjKy8uex6-q-Ry86mMtkbp/s1600/eq1.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIZXDGBTaPgNTvvaJoNWYiNiC5gQbZl3glpm3ru0UhabRDyirnTJxnRkTs9cQnFTfoiJ6f7xF2ypFiA8OxvcC1p1XfVdouwe7-qdGyZ9n_FUaRCBKOlo_mAu0BfwltDZopzu9MdVOTuCs5/s1600/Sine1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="153" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIZXDGBTaPgNTvvaJoNWYiNiC5gQbZl3glpm3ru0UhabRDyirnTJxnRkTs9cQnFTfoiJ6f7xF2ypFiA8OxvcC1p1XfVdouwe7-qdGyZ9n_FUaRCBKOlo_mAu0BfwltDZopzu9MdVOTuCs5/s320/Sine1.png" width="320" /></a></div>
<br />
<br />
<div class="ln" lang="es">
Ahora tenemos un valor entre -2.5V y 2.5V, para obtener un valor entre 0V y 5V debemos sumar 2.5V al resultado final. Sabemos que el valor numérico en bytes para 2.5V es 128.
</div>
<div class="ln" lang="en">
Now we have a value between -2.5V and 2.5V, to obtain a value between 0V and 5V, must add 2.5V to the final result. We know that the numeric value in bytes is 128 for 2.5V.
</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZtPzbL9uDh0IS8mTAcv1B58OhEa-pSDiXDX2-MQVhe-HnjsxgJQfnjA3EugigBB04HcOmkBKM37Pk61Syioywqn1a_OmwJuApI_HwvQczVEftlMfGIgTbVyFB0tLsEZjFY6C5jF9eYiwk/s1600/eq2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZtPzbL9uDh0IS8mTAcv1B58OhEa-pSDiXDX2-MQVhe-HnjsxgJQfnjA3EugigBB04HcOmkBKM37Pk61Syioywqn1a_OmwJuApI_HwvQczVEftlMfGIgTbVyFB0tLsEZjFY6C5jF9eYiwk/s1600/eq2.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ9_o3DvvNXS4GNejAUGL0m7Om-tDTEAR7ZG7Hf5zH7CA2rHkP-sOWDFi0m0WU5HBHFzjchlNev0qr4T3nGLnLg_yKMqXGOBeGzwzehaL_lXGzHlAS-d3w0uWwtplcm_G2di1dgHmYq4mW/s1600/Sine2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="153" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ9_o3DvvNXS4GNejAUGL0m7Om-tDTEAR7ZG7Hf5zH7CA2rHkP-sOWDFi0m0WU5HBHFzjchlNev0qr4T3nGLnLg_yKMqXGOBeGzwzehaL_lXGzHlAS-d3w0uWwtplcm_G2di1dgHmYq4mW/s320/Sine2.png" width="320" /></a></div>
<br />
<br />
<div class="ln" lang="es">
Para convertir la señal PWM en una señal analógica se utiliza un filtro RC, yo he elegido unos valores un poco a ojo, 1K y 0.47uF.
</div>
<div class="ln" lang="en">
To convert the PWM signal into an analog signal, must use an RC filter, I have chosen values a little by eye, 1K and 0.47uF.
</div>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTB3oSHU2wGoGBWmm3JO3myibrHVPQE6K9pRUGMZPPqQJ7_3YA3aWYo13ncMbBBCLnX713rpeHdeFzT6iAQGgpJAS9meUOqPo7Imym2882EEUu7dsK9XT02bmD_Q_NWlJXWwtg6MEVaF9u/s1600/LAA.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="191" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTB3oSHU2wGoGBWmm3JO3myibrHVPQE6K9pRUGMZPPqQJ7_3YA3aWYo13ncMbBBCLnX713rpeHdeFzT6iAQGgpJAS9meUOqPo7Imym2882EEUu7dsK9XT02bmD_Q_NWlJXWwtg6MEVaF9u/s400/LAA.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">
Ejemplo de conexiones</div>
<div class="ln" lang="en">
Example of connections</div>
</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlLqBHL5UMJywGsRJXY_i-b1zgMzQYygw6jz3sdnaWQMVoMeqHlvGcS9z95j55xw2nxKeuMvNoU82iJJ5JT-9IekxMKIqafEkyLt9Qx31P2QHT2eFZKBg-DHv_5_18dNxIr46QfKLOmb0C/s1600/LAATest.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlLqBHL5UMJywGsRJXY_i-b1zgMzQYygw6jz3sdnaWQMVoMeqHlvGcS9z95j55xw2nxKeuMvNoU82iJJ5JT-9IekxMKIqafEkyLt9Qx31P2QHT2eFZKBg-DHv_5_18dNxIr46QfKLOmb0C/s400/LAATest.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">
Esquema</div>
<div class="ln" lang="en">
Schematic</div>
</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlRGDGFspcCAUx8pqC4rsB9MyED0nTdqUDHkIJwldXoYXwxJPPy9Va3aWkxyRQMwM-c-5UrAe_R61yFZMarL4upM-vm8SWJTv6Il3QhaDBDa1YfttYHUQ_gAG3ckuVZPwYbWIx-9LpzgAt/s1600/LogicAnalyzerA.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlRGDGFspcCAUx8pqC4rsB9MyED0nTdqUDHkIJwldXoYXwxJPPy9Va3aWkxyRQMwM-c-5UrAe_R61yFZMarL4upM-vm8SWJTv6Il3QhaDBDa1YfttYHUQ_gAG3ckuVZPwYbWIx-9LpzgAt/s400/LogicAnalyzerA.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">
Onda sinusoidal</div>
<div class="ln" lang="en">
Sene wave</div>
</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiybegK6H4Yky3u5z_YDvtTRiCFfArahQ3zkoAwlPsKoVm1KlmbRPOCPKh-2WS-M2Fx2UmhTT3UAQsfWjLIJOP1xUha0sYyPUVoOHqRbJOFUV6yGHJGPgmlGQCMNx3KoTKdwL0tmqggnVr6/s1600/LogicAnalyzerA2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiybegK6H4Yky3u5z_YDvtTRiCFfArahQ3zkoAwlPsKoVm1KlmbRPOCPKh-2WS-M2Fx2UmhTT3UAQsfWjLIJOP1xUha0sYyPUVoOHqRbJOFUV6yGHJGPgmlGQCMNx3KoTKdwL0tmqggnVr6/s400/LogicAnalyzerA2.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">
Cambiando 1K por 10K</div>
<div class="ln" lang="en">
Changing 1K for 10K</div>
</td></tr>
</tbody></table>
<br />
<br />
<hr />
<br />
<b></b><br />
<div class="ln" lang="es">
<b>Descargas:</b></div>
<div class="ln" lang="en">
<b>Downloads:</b></div>
<b>
</b>
<br />
<a href="http://www.raulnd.com/TibuWorks/LogicAnalyzer.zip" target="_blank">LogicAnalyzer.zip</a>
<br />
<br />
<hr />
<br />
<b></b><br />
<div class="ln" lang="es">
<b>Enlaces:</b></div>
<div class="ln" lang="en">
<b>Links:</b></div>
<b>
</b>
<br />
8-bit AVR® Instruction Set (EN): <a href="http://www.atmel.com/Images/doc0856.pdf" target="_blank">http://www.atmel.com/Images/doc0856.pdf</a><br />
ATmega 328 (EN): <a href="http://www.atmel.com/Images/doc8161.pdf" target="_blank">http://www.atmel.com/Images/doc8161.pdf</a> <br />
Sinusoide (ES): <a href="https://es.wikipedia.org/wiki/Sinusoide" target="_blank">https://es.wikipedia.org/wiki/Sinusoide</a><br />
Sine wave (EN): <a href="http://en.wikipedia.org/wiki/Sine_wave" target="_blank">http://en.wikipedia.org/wiki/Sine_wave</a><br />
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/11133658869560834508noreply@blogger.com0Barberà del Vallès, Barcelona, España41.5136208 2.125555299999973641.4898423 2.0852147999999735 41.5373993 2.1658957999999737tag:blogger.com,1999:blog-245453246861213473.post-67412460876366664042013-04-29T09:11:00.002+02:002013-04-30T18:27:02.347+02:00Analizador lógico (digital) | Logic analyzer (digital)<div class="ln" lang="es">
Una buena herramienta para trabajar con la lógica digital es el <a href="http://es.wikipedia.org/wiki/Analizador_l%C3%B3gico" target="_blank">analizador lógico</a>. Como necesito uno y ahora no es un buen momento para gastar dinero he decidido construir uno casero con Arduino.<br />
<br />
Lo primero que necesito es saber cuántas lecturas puedo llegar a hacer en un determinado tiempo. Lo más fácil sería leer el estado de un pin de entrada y enviarlo por el puerto serie y luego controlar el tiempo de lectura desde un software de PC, pero esto sería demasiado lento y podríamos perder muchos datos. Lo óptimo sería leer un determinado número de veces, guardarlo en la memoria SRAM de Arduino y luego volcarlo todo al puerto serie. Sabiendo el tiempo empleado para leer una vez, podemos calcular la gráfica a pintar en pantalla. La forma más precisa es trabajar con instrucciones de ensamblador. Para ello hay que echar un vistazo al <a href="http://www.atmel.com/Images/doc0856.pdf" target="_blank">set de instrucciones</a> de los chips ATmega y determinar que instrucciones usar y los ciclos de reloj que consume cada una de estas instrucciones. Además, si queremos leer varios pines a la vez, debemos acceder a ellos mediante los puertos internos del microcontrolador. Si utilizamos un Arduino UNO o un Arduino Nano (como en mi caso) tendremos el siguiente mapeado de puertos:
</div>
<div class="ln" lang="en">
A good tool for working with digital logic is the <a href="http://en.wikipedia.org/wiki/Logic_analyzer" target="_blank">logic analyzer</a>. As I need one and now is not a good time to spend money I decided to build a homemade one using Arduino.<br />
<br />
The first thing I need to know is how many readings I can get in a determinate time. The easiest way would be to read the state of an input pin and send it via the serial port and then control the reading time from a PC software, but this would be too slow and I could lose a lot of data. The optimum would be to read a certain number of times, save it in Arduino SRAM and then bounce everything to the serial port. Knowing the time used to read one time, we can calculate the graph displayed on the screen. The most accurate way is to work with assember instructions. This requires taking a look at the <a href="http://www.atmel.com/Images/doc0856.pdf" target="_blank">instruction set</a> of the ATmega chip and determining which instructions to use and how many clock cycles consume each of these instructions. Furthermore, if we read several pins at once, we have to access to the internal ports of the microcontroller. If we use an Arduino UNO or Arduino Nano (as in my case) we have the following port mapping:</div>
<br />
<br />
<br />
<table align="center" class="tbl">
<tbody>
<tr>
<td width="100"><b>BIT</b></td>
<td width="50"><b>7</b></td>
<td width="50"><b>6</b></td>
<td width="50"><b>5</b></td>
<td width="50"><b>4</b></td>
<td width="50"><b>3</b></td>
<td width="50"><b>2</b></td>
<td width="50"><b>1</b></td>
<td width="50"><b>0</b></td>
</tr>
<tr>
<td><b>PORTB</b></td>
<td>XTAL</td>
<td>XTAL</td>
<td>13</td>
<td>12</td>
<td>11</td>
<td>10</td>
<td>9</td>
<td>8</td>
</tr>
<tr>
<td><b>PORTC</b></td>
<td>NC</td>
<td>RST</td>
<td>A5</td>
<td>A4</td>
<td>A3</td>
<td>A2</td>
<td>A1</td>
<td>A0</td>
</tr>
<tr>
<td><b>PORTD</b></td>
<td>7</td>
<td>6</td>
<td>5</td>
<td>4</td>
<td>3</td>
<td>2</td>
<td>TX 1</td>
<td>RX 0</td>
</tr>
</tbody></table>
<br />
<div style="text-align: center;">
<a href="http://playground.arduino.cc/Learning/PortManipulation" target="_blank">http://playground.arduino.cc/Learning/PortManipulation</a></div>
<br />
<br />
<div class="ln" lang="es">
Si utilizamos el puerto B para leer las entradas, debemos utilizar los bits 0..5 ya que los bits 6 y 7 están conectados al cristal. Si utilizamos el puerto C, usaremos los bits 0..5 ya que en el bit 6 está conectado el reset y el bit 7 no está conectado. Y si usamos el puerto D, usaremos los bits 2..7 porque los bits 0 y 1 se utilizan para la comunicación por el puerto serie.<br />
<br />
Yo, concretamente, he decidido utilizar el puerto B para hacer las lecturas de lógica, así que podré leer 6 canales.<br />
<br />
Para leer los 8 bits de un puerto con Arduino utilizamos la siguiente instrucción:<br />
<ul style="font-family: "Courier New",Courier,monospace;">byte b = PINB;</ul>
<br />
Para leerlos con instrucciones a bajo nivel (ASM) lo leemos de la siguiente forma:<br />
<ul style="font-family: "Courier New",Courier,monospace;">IN Rd, A</ul>
<br />
Dónde Rd es el registro de memoria de destino y A es el puerto de entrada. Esta instrucción consume un ciclo de reloj (Pag 13).<br />
<br />
Para guardar la lectura en memoria y pasar a la siguiente posición de memoria usaremos la siguiente instrucción:<br />
<ul style="font-family: "Courier New",Courier,monospace;">ST z+, Rr</ul>
<br />
Dónde z es la posición de memoria donde vamos a guardar el dato y Rr es el registro donde previamente hemos leído el puerto de entrada. ST consume un ciclo de reloj y el incremento de posición de memoria otro ciclo más.<br />
Así, tenemos el siguiente bloque de código ensamblador:<br />
<ul style="font-family: "Courier New",Courier,monospace;">
in r0, A<br />
st z+,r0</ul>
<br />
A parte de esto tenemos que saber de cuanta memoria SRAM disponemos para almacenar lecturas. ATmega 328 dispone de 2Kb (2048 bytes), de los cuales una cantidad la consume el bootloader de Arduino. Haciendo unas pruebas he visto que puedo utilizar un buffer de 1800 bytes. Si sabemos que estamos consumiendo 3 ciclos por cada lectura podemos deducir lo siguiente:<br />
<br /></div>
<div class="ln" lang="en">
If we use the port B to read inputs, we use the bits 0..5 as bits 6 and 7 are connected to the xtal. If we use the port C, we will use the bits 0..5 as in the bit 6 is connected to the reset and bit 7 isn't connected. And if we use the port D, we use bits 2..7 because bits 0 and 1 are used for serial port communication.<br />
<br />
I, specifically, I decided to use port B to make logical readings, so I can read 6 channels.<br />
<br />
To read the 8 bits of a port with Arduino we use the following statement:<br />
<ul style="font-family: "Courier New",Courier,monospace;">byte b = PINB;</ul>
<br />
To read with low-level instructions (ASM) we read as follows:<br />
<ul style="font-family: "Courier New",Courier,monospace;">IN Rd, A</ul>
<br />
Where Rd is the destination memory register and A is the input port. This instruction consumes one clock cycle (Pag 13).<br />
To save the reading in memory and move to the next memory location we will use the following instruction:<br />
<ul style="font-family: "Courier New",Courier,monospace;">ST z+, Rr</ul>
<br />
Where z is the memory location where we will store the data and Rr is the register where we have already read the input port. ST consumes one clock cycle and increasing memory location another cycle.<br />
Thus, we have the following assembler code block:<br />
<ul style="font-family: "Courier New",Courier,monospace;">
in r0, A<br />
st z+,r0</ul>
<br />
Apart from this we have to know how much SRAM have to store readings. ATmega328 has 2K (2048 bytes), of which consumes an amount Arduino Bootloader. After doing some tests I have seen that I can use a buffer of 1800 bytes. If we know that we are consuming 3 cycles for each reading we can deduce the following:<br />
<br /></div>
<ul style="font-family: "Courier New",Courier,monospace;">
16 MHz / 3 Cycles = 5.33 MHz<br />
3 Cycles * 1800 Times = 5400 Cycles<br />
16 MHz = 62.5 ns per cycle<br />
5400 Cycles * 62.5 ns = 337.5 us<br />
</ul>
<br />
<div class="ln" lang="es">
Tenemos una frecuencia de lectura de 5.33 Mhz. El tiempo total de lectura es de 337.5 us.<br />
<br />
Para hacer las 1800 lecturas he decidido no utilizar un bucle porque perdería tiempo incrementando variables y saltando al inicio del bucle en cada vuelta.<br />
<br /></div>
<div class="ln" lang="en">
We have a 5.33 MHz reading frequency. The total reading time is 337.5 us.<br />
<br />
To make 1800 readings I decided not to use a loop, because it can make lose time increasing the index and looping back.<br />
<br /></div>
<br />
<br />
<pre class="brush: Arduino">#define DATA 1800
byte _data[DATA];
void ReadDigital()
{
__asm__ __volatile(
"in r0,%[port]\n\t"
"st z+,r0\n\t" // 1
"in r0,%[port]\n\t"
"st z+,r0\n\t" // 2
.
.
.
"in r0,%[port]\n\t"
"st z+,r0\n\t" // 1800
:
: [port] "i" (_SFR_IO_ADDR(PINB)), "z" (_data)
:
);
}
</pre>
<br />
<br />
<br />
<br />
<b></b><br />
<div class="ln" lang="es">
<b>PRUEBAS:</b></div>
<div class="ln" lang="en">
<b>TESTS:</b></div>
<br />
<br />
<div class="ln" lang="es">
He programado también una aplicación en VB.Net 4 para simular por pantalla los datos recogidos por el analizador. Más adelante, cuando esté perfeccionado, subiré el código, por ahora he subido el ejecutable.
<br />
<br />
Para probar el funcionamiento del analizador, he programado otra placa Arduino como un generador de señales PWM, de forma que cada una de las salidas genera una señal PWM del 50% a su máxima frecuencia. Pins 3, 9, 10 y 11 a 31250 Hz y pins 5 y 6 a 62500 Hz. He conectado estas salidas a los pins de entrada del analizador y este ha sido el resultado:
</div>
<div class="ln" lang="en">
I have also programmed an application in VB.Net 4 to simulate on screen the data collected by the analyzer. Later, when it is perfected, I'll upload the code, now I uploaded the executable.
<br />
<br />
To test the performance of the analyzer, I have programmed another Arduino board as a PWM signal generator, so that each of the outputs generates a PWM signal of 50% at maximum frequency. Pins 3, 9, 10 and 11 are 31250 Hz and pins 5 and 6 are 62500 Hz. I connected these to the analyzer input pins and this is the result:
</div>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVKTrgEQ8iL3A9cI1I0P8vNte8GAquPHKC9NIRyRHEyDUkwQjrIi_nZ4sh0teUrYausHvvfL9o6YWPxjC2aBd48AvlILzRv-s7u8ak83SY6id7jVfKzItKlUYmkc3Js2-vCKeJflWTu85r/s1600/LAD.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="191" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVKTrgEQ8iL3A9cI1I0P8vNte8GAquPHKC9NIRyRHEyDUkwQjrIi_nZ4sh0teUrYausHvvfL9o6YWPxjC2aBd48AvlILzRv-s7u8ak83SY6id7jVfKzItKlUYmkc3Js2-vCKeJflWTu85r/s400/LAD.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">
Ejemplo de conexiones</div>
<div class="ln" lang="en">
Example of connections</div>
</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCzsJtNe0pYa0SYd9yuDgjTAe_g1qQMTUYFIQM1PvYwQilV0vTma_meTQrmePMuGe-7A2DeZ8O14A1VCpcLUq4k65yxfqUhw_GZwthS5OCOF1e3BBr7Zf29XOEM2rjMn0DsvNTRrCWs81l/s1600/LADTest.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCzsJtNe0pYa0SYd9yuDgjTAe_g1qQMTUYFIQM1PvYwQilV0vTma_meTQrmePMuGe-7A2DeZ8O14A1VCpcLUq4k65yxfqUhw_GZwthS5OCOF1e3BBr7Zf29XOEM2rjMn0DsvNTRrCWs81l/s320/LADTest.jpg" width="292" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">
Esquema</div>
<div class="ln" lang="en">
Schematic</div>
</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoRzvJzTfvljTroZvxfZgA1SA5eQPnFRJc_w59hdVbbQuGtf6E6wuc3Z2WFayYMXY4OZP0ABAJnsxe4VJ7E_4DvKsOGc0qUcjtp24APcZsnVkWzjXzKSEh3CBs1xGiXY8xJCr7UK2y4FCL/s1600/LogicAnalyzerD.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoRzvJzTfvljTroZvxfZgA1SA5eQPnFRJc_w59hdVbbQuGtf6E6wuc3Z2WFayYMXY4OZP0ABAJnsxe4VJ7E_4DvKsOGc0qUcjtp24APcZsnVkWzjXzKSEh3CBs1xGiXY8xJCr7UK2y4FCL/s400/LogicAnalyzerD.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">
6 Señales PWM</div>
<div class="ln" lang="en">
6 PWM signals</div>
</td></tr>
</tbody></table>
<br />
<br />
<br />
<pre class="brush: Arduino">#include "PwmFrequency.h"
int pins[] = {3, 5, 6, 9, 10, 11};
void setup()
{
for(int i=0; i<6; i++)
{
setPwmFrequency(pins[i], 1);
pinMode(pins[i], OUTPUT);
analogWrite(pins[i], 127);
}
}
void loop()
{}
</pre>
<br />
<br />
<br />
<br />
<hr />
<br />
<b></b><br />
<div class="ln" lang="es">
<b>Descargas:</b></div>
<div class="ln" lang="en">
<b>Downloads:</b></div>
<b>
</b><br />
<br />
<a href="http://www.raulnd.com/TibuWorks/LogicAnalyzer.zip" target="_blank">LogicAnalyzer.zip</a>
<br />
<br />
<hr />
<br />
<b></b><br />
<div class="ln" lang="es">
<b>Enlaces:</b></div>
<div class="ln" lang="en">
<b>Links:</b></div>
<b>
</b><br />
<br />
Analizador lógico (ES): <a href="http://es.wikipedia.org/wiki/Analizador_l%C3%B3gico" target="_blank">http://es.wikipedia.org/wiki/Analizador_lógico</a><br />
Logic analyzer (EN): <a href="http://en.wikipedia.org/wiki/Logic_analyzer" target="_blank">http://en.wikipedia.org/wiki/Logic_analyzer</a><br />
8-bit AVR® Instruction Set (EN): <a href="http://www.atmel.com/Images/doc0856.pdf" target="_blank">http://www.atmel.com/Images/doc0856.pdf</a><br />
Arduino registro PORT (ES): <a href="http://arduino.cc/es/Reference/PortManipulation" target="_blank">http://arduino.cc/es/Reference/PortManipulation</a><br />
Arduino port registers (EN): <a href="http://arduino.cc/en/Reference/PortManipulation" target="_blank">http://arduino.cc/en/Reference/PortManipulation</a><br />
ATmega port manipulation (EN): <a href="http://playground.arduino.cc/Learning/PortManipulation" target="_blank">http://playground.arduino.cc/Learning/PortManipulation</a>
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/11133658869560834508noreply@blogger.com0Barberà del Vallès, Barcelona, España41.5136208 2.125555299999973641.4898423 2.0852147999999735 41.5373993 2.1658957999999737tag:blogger.com,1999:blog-245453246861213473.post-40474424567672090702013-04-26T19:46:00.000+02:002013-04-29T13:59:33.539+02:00Velocidad y sentido | Speed and direction:<div class="ln" lang="es">
Además de controlar la velocidad también nos interesa controlar el sentido de la marcha. Para lograr esto sin necesidad de utilizar componentes electromecánicos como los relés existen varias soluciones, una de ellas es el <a href="http://es.wikipedia.org/wiki/Puente_H_%28electr%C3%B3nica%29" target="_blank">puente H</a>.<br />
<br />
Un puente H consta de 4 interruptores que dejan pasar la electricidad en un sentido o en otro. Veamos el siguiente esquema:
</div>
<div class="ln" lang="en">
In addition to controlling the speed we also want to control the direction of travel. To accomplish this without the use of electromechanical elements as relays as there are several solutions, one of which is the <a href="http://en.wikipedia.org/wiki/H_bridge" target="_blank">H bridge</a>.<br><br>
An H bridge consists of 4 switches that let electricity in one direction or another. Consider the following diagram:</div><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMcPtHHnWcTfaWNlEKlL2wR2_4V5HIRy-zDUA4G5UE1NX4dfp3b4deSN25HnuaS4RG7jhxtYY_YxkARuqIvsHLS5fk8fHyGmpED2XPnpBjkrqafB5IK25RLvuoN9YyT95iMdI97_RnQfLF/s1600/HBridge.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMcPtHHnWcTfaWNlEKlL2wR2_4V5HIRy-zDUA4G5UE1NX4dfp3b4deSN25HnuaS4RG7jhxtYY_YxkARuqIvsHLS5fk8fHyGmpED2XPnpBjkrqafB5IK25RLvuoN9YyT95iMdI97_RnQfLF/s400/HBridge.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">Puente H.</div><div class="ln" lang="en">H Bridge.</div></td></tr>
</tbody></table>
<br />
<br />
<div class="ln" lang="es">
Si cerramos SW3 y SW2 dejamos pasar la corriente desde el polo positivo del motor al negativo, por lo tanto el tren se mueve hacia adelante. Si por el contrario, cerramos SW1 y SW4 dejamos pasar la corriente al revés y el tren se moverá hacia atrás. Este circuito se puede construir con cualquier tipo de interruptor, ya sea manual o electromecánico, pero lo óptimo es hacerlo con transistores. De hecho existen en el mercado circuitos integrados que contienen el puente H. Uno de estos circuitos es el <a href="http://www.ti.com/lit/ds/symlink/l293d.pdf" target="_blank">L293</a> (36V 1A).
<br />
<br />
Para controlar este circuito con Arduino necesitamos una salida PWM y dos salidas digitales para controlar el sentido de giro del motor.Una de estas salidas controla SW1 y SW4, y la otra controla SW2 y SW3.
</div>
<div class="ln" lang="en">
If we close SW3 and SW2 then the current pass from the positive pole to the negative pole of motor, so the train moves forward. If, however, we close SW1 and SW4 the current pass backwards and the train will move back. This circuit can be built with any type of switch, either manual or electromechanical, but it is optimal to do with transistors. In fact exist on the market integrated circuits containing the H bridge. One of these circuits is the <a href="http://www.ti.com/lit/ds/symlink/l293d.pdf" target="_blank">L293</a> (36V 1A).
<br /><br>
To control this circuit with Arduino we need a PWM output and two digital outputs for controlling the rotational direction of the motor. One of these outputs controls SW1 and SW4, and the other one controls SW2 and SW3.
</div><br>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTMY4qHFo95elPgfI9za7y0WY_zt5w-lceRfLnLxX4i8U5e6wXVWAeQqtStspvz3nCVpEVqqIHI5lYkMXbYbS-RW1X4GEsw6J9VfsW_dHNQ8Ky_FbmKm2nUYp0rcAGbYxoIGLMs_FaRZ0R/s1600/ArduinoL293.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTMY4qHFo95elPgfI9za7y0WY_zt5w-lceRfLnLxX4i8U5e6wXVWAeQqtStspvz3nCVpEVqqIHI5lYkMXbYbS-RW1X4GEsw6J9VfsW_dHNQ8Ky_FbmKm2nUYp0rcAGbYxoIGLMs_FaRZ0R/s400/ArduinoL293.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">Ejemplo de conexiones.</div><div class="ln" lang="en">Example of connections.</div></td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdhpc9d4L_k0OzbE5wBSBnVvV2jdmvDY75K8zdb52LMPzFlw0T23p_knnC-W1KNgEQuIfDHGX7yu2CytbXlQ3JkrXdVu7FoaVEgJ0GveW8d-D5dlUw8Aw_BZY86heJyMyoPPiNbWqVVw1s/s1600/SCH_ArduinoL293.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdhpc9d4L_k0OzbE5wBSBnVvV2jdmvDY75K8zdb52LMPzFlw0T23p_knnC-W1KNgEQuIfDHGX7yu2CytbXlQ3JkrXdVu7FoaVEgJ0GveW8d-D5dlUw8Aw_BZY86heJyMyoPPiNbWqVVw1s/s400/SCH_ArduinoL293.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">Esquema.</div><div class="ln" lang="en">Schematic.</div></td></tr>
</tbody></table>
<br />
<br />
<div class="ln" lang="es">
El siguiente bloque de código muestra la forma de cambiar de sentido, simplemente activando y desactivando los pins asignados al L293:
</div>
<div class="ln" lang="en">
The following piece of code shows how to change direction by simply activating and deactivating the assigned pins to the L293:
</div>
<br><br>
<br />
<pre class="brush: Arduino">
...
void SetDirection()
{
switch(_dir)
{
case Left:
digitalWrite(dirPin0, LOW);
digitalWrite(dirPin1, HIGH);
break;
case Right:
digitalWrite(dirPin0, HIGH);
digitalWrite(dirPin1, LOW);
break;
default:
digitalWrite(dirPin0, LOW);
digitalWrite(dirPin1, LOW);
break;
}
}
...
</pre>
<br />
<br />
<div class="ln" lang="es">
Como en el artículo anterior, he hecho un pequeño ejecutable en VB.Net 4.0 para controlar tanto la velocidad como el sentido del tren.
</div>
<div class="ln" lang="en">
As in the previous post, I made a small executable in VB.Net 4.0 to control both the speed and the direction of the train.
</div>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMbrY1fySU4NQutE1UbfvzdsrCHBs42dP8TsxSzU-jGNRJMuMtl3PwG9RypuJI3dCOOF-OMz9Wkwf1DxoIydZqxfWuoisSD8GEP1PaEAd5I_kzcWCJqE0-JkuWWZwSoMXB8xQ_199kjbI9/s1600/VB_L293.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMbrY1fySU4NQutE1UbfvzdsrCHBs42dP8TsxSzU-jGNRJMuMtl3PwG9RypuJI3dCOOF-OMz9Wkwf1DxoIydZqxfWuoisSD8GEP1PaEAd5I_kzcWCJqE0-JkuWWZwSoMXB8xQ_199kjbI9/s1600/VB_L293.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">Ejecutale VB.</div><div class="ln" lang="en">VB Executable.</div></td></tr>
</tbody></table>
<br />
<br />
<hr />
<br />
<b><div class="ln" lang="es">Descargas:</div><div class="ln" lang="en">Downloads:</div>
</b><br />
<br />
<a href="http://www.raulnd.com/TibuWorks/ArduinoL293.zip" target="_blank">ArduinoL293.zip</a>
<br />
<br />
<hr />
<br />
<b><div class="ln" lang="es">Enlaces:</div><div class="ln" lang="en">Links:</div>
</b><br />
<br />
L293 (EN): <a href="http://www.ti.com/lit/ds/symlink/l293d.pdf" target="_blank">http://www.ti.com/lit/ds/symlink/l293d.pdf</a><br />
Puente H (ES): <a href="http://es.wikipedia.org/wiki/Puente_H_%28electr%C3%B3nica%29" target="_blank">http://es.wikipedia.org/wiki/Puente_H_(electrónica)</a><br />
H Bridge (EN): <a href="http://en.wikipedia.org/wiki/H_bridge" target="_blank">http://en.wikipedia.org/wiki/H_bridge</a><br />
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/11133658869560834508noreply@blogger.com0Barberà del Vallès, Barcelona, España41.5136208 2.125555299999973641.4898423 2.0852147999999735 41.5373993 2.1658957999999737tag:blogger.com,1999:blog-245453246861213473.post-53818301037164382592013-04-22T21:12:00.000+02:002013-04-29T13:52:09.949+02:00Mover un tren con Arduino | Move a train with Arduino<div class="ln" lang="es">
Uno de mis hobbies es el modelismo ferroviario. Un día, buscando algún tipo de placa que me proporcionase entradas y salidas mediante una conexión USB a un PC, di con Arduino. Pronto descubrí que podía utilizarse para cualquier cosa que pudiese imaginar, así que decidí comprar un Arduino Mega para probar. Hoy en día tengo varios tipos diferentes de Arduino que uso para diferentes proyectos.<br />
<br />
Hoy voy a explicar la forma más sencilla de controlar el movimiento de un tren de escala Z (1/220) mediante <a href="http://arduino.cc/en/Main/arduinoBoardUno" target="_blank">Arduino UNO</a>.<br />
<br />
<b>Velocidad:</b><br />
<br />
Esta forma de control consiste en utilizar una salida <a href="http://es.wikipedia.org/wiki/Modulaci%C3%B3n_por_ancho_de_pulsos" target="_blank">PWM</a> (Modulación por Ancho de Pulso) para controlar la velocidad del motor. El PWM es un tipo de señal digital de una duración determinada que se repite indefinidamente. Cada uno de estos ciclos consta de un estado a nivel alto (Tensión máxima) y uno a nivel bajo (Tensión mínima). La suma del tiempo que dura el estado alto y el bajo es la duración total del ciclo. En Arduino UNO concretamente la tensión de los estados es de 5V y 0V respectivamente. Al utilizar una señal PWM estamos utilizando señales del voltaje máximo aceptado por el motor, así aprovechamos toda su potencia.
</div>
<div class="ln" lang="en">
One of my hobbies is model railroading. One day, looking for some kind of pc board that can provide inputs and outputs through an USB connection to a PC, I found Arduino. I soon discovered that it could be used for anything I could imagine, so I decided to buy an Arduino Mega to try. Today I have several different types of Arduino to use for different projects.<br /><br />
Today I will explain the easiest way to control the movement of a Z scale (1/220) train using <a href="http://arduino.cc/en/Main/arduinoBoardUno" target="_blank">Arduino UNO</a>.
<br />
<br />
<b>Speed:</b><br />
<br />
This way of control is to use a <a href="http://en.wikipedia.org/wiki/Pulse-width_modulation" target="_blank">PWM</a> (Pulse Width Modulation) to control motor speed. The PWM is a digital signal type of fixed duration that repeats indefinitely. Each of these cycles consists of a high-level state (high voltage) and one low (low voltage). The sum of the duration of the high and the low is the total cycle. In Arduino UNO specifically states voltage are 5V and 0V respectively. By using a PWM signal we are using maximum voltage accepted by motor and we get full power.
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq99oTBjfs_HEiULFTUG5CSYdObov1DRfhmtk8VigaYzNkjYsrEJhZYTDYCTZ8a03MxgxoseDh5NKsiandvzzq0WHXWDne1WaiBtN3eKjIrvNy2ExzSb6vjuRX97IJ2UTGBLwzDI3oc6Ra/s1600/PWM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq99oTBjfs_HEiULFTUG5CSYdObov1DRfhmtk8VigaYzNkjYsrEJhZYTDYCTZ8a03MxgxoseDh5NKsiandvzzq0WHXWDne1WaiBtN3eKjIrvNy2ExzSb6vjuRX97IJ2UTGBLwzDI3oc6Ra/s400/PWM.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">Diferentes ejemplos de pulsos PWM.</div><div class="ln" lang="en">Different examples of PWM pulses.</div></td></tr>
</tbody></table>
<br />
<br />
<div class="ln" lang="es">
En la imagen anterior vemos varios ejemplos de pulsos PWM (rojo) y su equivalente en tensión (verde). La diferencia entre usar pulsos de 9V y de usar tensiones de 0V a 9V es que usando PWM siempre alimentamos el motor con su máxima tensión.
<br />
<br />
Arduino UNO puede proporcionar 5V y 40ma por pin, esto no es suficiente para mover un motor de 9V y aproximadamente 300mA. Para ello necesitamos usar un transistor. Yo he utilizado para hacer la prueba un transistor darlington que me permite trabajar hasta con 80V y 4A. Se trata del transistor <a href="http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/CD00000939.pdf" target="_blank">BD679</a>.
<br />
<br />
Cuando trabajamos con motores y PWM debemos tener en cuenta la frecuencia de ciclo de la fuente de PWM. Si utilizamos frecuencias bajas, de entre 20Hz y 20KHz, entraremos dentro del <a href="http://es.wikipedia.org/wiki/Espectro_audible" target="_blank">espectro audible</a> del ser humano y el motor producirá un zumbido desagradable. Con Arduino UNO no hay problema ya que los pins que proporcionan PWM trabajan con el Timer 0 (62500Hz) o con los Timers 1 y 2 (31250Hz).
</div>
<div class="ln" lang="en">
In the picture above we can see several
examples of PWM pulses (red) and the equivalent voltage (green). The
difference between using 9V pulses and using voltages from 0V to 9V is
that we always feed the engine with maximum voltage. <br />
<br /><br />
Arduino UNO can provide 5V and 40mA per pin, this is not enough to move a 9V and approximately 300mA motor. For this reason we need to use a transistor. I've used for the test a darlington transistor that allows me to work up to 80V and 4A. This transistor is a <a href="http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/CD00000939.pdf" target="_blank">BD679</a>.
<br><br>
When we are working with motors we must consider PWM cycle frequency. If we use low frequencies, from 20Hz to 20KHz, we are entering in human <a href="http://en.wikipedia.org/wiki/Hearing_range" target="_blank">hearing range</a> and it causes an unpleasant humming. With Arduino UNO there is no problem because the pins that can provide PWM are working with the Timer 0 (62500Hz) or with Timers 1 and 2 (31250Hz).
</div>
<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFvIHcEY5egr-Z1WuGNvQBbmAodEeDTRn_ONJU8fQGvnXq4U_YCORQpSo-2mjlGbMuk_74H8OcDFvopGsib3ApFvw5eqKI7jivYeGq-x3nt324uzippV3kS7FJS2phnzyCOpzdNFrsdyej/s1600/ArduinoBD679.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFvIHcEY5egr-Z1WuGNvQBbmAodEeDTRn_ONJU8fQGvnXq4U_YCORQpSo-2mjlGbMuk_74H8OcDFvopGsib3ApFvw5eqKI7jivYeGq-x3nt324uzippV3kS7FJS2phnzyCOpzdNFrsdyej/s400/ArduinoBD679.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">Ejemplo de conexiones.</div><div class="ln" lang="en">Example of connections.</div></td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjikg4uh-ljtoQncoKIRF0yQ4kjrf5rGFqHWD8l1aACCesLug-VpVr67nYwVQI1xwfSa6AjelfIrrfXduTc8eXmq5StQYMB6QTySXTb17gig1HgU7BGhuqO29pfNwiunNux4_9jQyuieX1E/s1600/SCH_ArduinoBD679.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjikg4uh-ljtoQncoKIRF0yQ4kjrf5rGFqHWD8l1aACCesLug-VpVr67nYwVQI1xwfSa6AjelfIrrfXduTc8eXmq5StQYMB6QTySXTb17gig1HgU7BGhuqO29pfNwiunNux4_9jQyuieX1E/s400/SCH_ArduinoBD679.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">Esquema</div><div class="ln" lang="en">Schematic.</div></td></tr>
</tbody></table>
<br />
<br />
<div class="ln" lang="es">
En la imagen anterior podemos ver el esquema necesario para mover un tren por una vía usando el pin 6 de Arduino que nos proporciona 62.5KHz. He utilizado el transistor BD679 y un diodo <a href="http://www.diodes.com/datasheets/ds28002.pdf" target="_blank">1N4007</a> (1000V 1A) para eliminar los picos de tensión provocados por la bobina del motor.
<br />
<br />
El siguiente bloque de código muestra la lectura de un byte del puerto serie y la asignación del byte a la salida PWM:
</div>
<div class="ln" lang="en">
In the picture above we can see the schematic required to move a train by the track using the Arduino's pin 6 that gives us 62.5KHz. I used a BD679 (80V 4A) transistor and a <a href="http://www.diodes.com/datasheets/ds28002.pdf" target="_blank">1N4007</a> diode (1000V 1A) to eliminate voltage spikes caused by the motor coil.
<br /><br>
The next piece of code shows reading an incoming byte from the serial port and then output this byte to the PWM pin:</div>
<br />
<br />
<pre class="brush: Arduino">
...
// Velocity
byte vel = Serial.read();
analogWrite(pwmPin, vel);
...
</pre>
<br />
<div class="ln" lang="es">
Para hacer la prueba he creado un pequeño ejecutable en Visual Basic (.NET 4.0) que se puede descargar junto con todo el material de este post.
</div>
<div class="ln" lang="en">
To test I created a small executable in Visual Basic (. NET 4.0) which can be downloaded along with all the material in this post.</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE1vzBuNSePWQuuvPYJKTzhydC2xV2iW6n5IptuJHgfJlZfwz1qYmEJPlVoXL3eZEnRi4kUknwYqF0Jo72KF9RCtooRon7K47tVmnsyY2qvEuxV8g_PaBsDQ8dpfHbFe7ISw47pW5SsbSo/s1600/VB_BD679.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE1vzBuNSePWQuuvPYJKTzhydC2xV2iW6n5IptuJHgfJlZfwz1qYmEJPlVoXL3eZEnRi4kUknwYqF0Jo72KF9RCtooRon7K47tVmnsyY2qvEuxV8g_PaBsDQ8dpfHbFe7ISw47pW5SsbSo/s1600/VB_BD679.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div class="ln" lang="es">Ejecutale VB.</div><div class="ln" lang="en">VB Executable.</div></td></tr>
</tbody></table>
<br />
<br />
<br />
<br />
<hr />
<br />
<b><div class="ln" lang="es">Descargas:</div><div class="ln" lang="en">Downloads:</div></b><br />
<br />
<a href="http://www.raulnd.com/TibuWorks/ArduinoBD679.zip" target="_blank">ArduinoBD679.zip</a><br />
<br />
<hr />
<br />
<b><div class="ln" lang="es">Enlaces:</div><div class="ln" lang="en">Links:</div></b><br />
<br />
Arduino UNO (EN): <a href="http://arduino.cc/en/Main/arduinoBoardUno" target="_blank">http://arduino.cc/en/Main/arduinoBoardUno</a><br />
PWM Wikipedia (ES): <a href="http://es.wikipedia.org/wiki/Modulaci%C3%B3n_por_ancho_de_pulsos" target="_blank">http://es.wikipedia.org/wiki/Modulación_por_ancho_de_pulsos</a><br />
PWM Wikipedia (EN): <a href="http://en.wikipedia.org/wiki/Pulse-width_modulation" target="_blank">http://en.wikipedia.org/wiki/Pulse-width_modulation</a><br />
PWM Arduino (ES): <a href="http://arduino.cc/es/Tutorial/PWM" target="_blank">http://arduino.cc/es/Tutorial/PWM</a><br />
PWM Arduino(EN): <a href="http://arduino.cc/en/Tutorial/PWM" target="_blank">http://arduino.cc/en/Tutorial/PWM</a><br />
Espectro audible (ES): <a href="http://es.wikipedia.org/wiki/Espectro_audible" target="_blank">http://es.wikipedia.org/wiki/Espectro_audible</a><br />
Hearing range (EN): <a href="http://en.wikipedia.org/wiki/Hearing_range" target="_blank">http://en.wikipedia.org/wiki/Hearing_range</a><br />
BD679 (EN): <a href="http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/CD00000939.pdf" target="_blank">http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/CD00000939.pdf</a><br />
1N4007 (EN): <a href="http://www.diodes.com/datasheets/ds28002.pdf" target="_blank">http://www.diodes.com/datasheets/ds28002.pdf</a><br />
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/11133658869560834508noreply@blogger.com0Barberà del Vallès, Barcelona, España41.5136208 2.125555299999973641.4898423 2.0852147999999735 41.5373993 2.1658957999999737tag:blogger.com,1999:blog-245453246861213473.post-41868495644523661012013-04-19T19:11:00.000+02:002013-04-29T12:59:02.183+02:00Intro<div class="ln" lang="es">
Desde que empecé con mi <a href="http://raulnd.blogspot.com.es/" target="_blank">antiguo blog</a>, hace algo más de un año, siempre he estado desarrollando proyectos caseros con <a href="http://www.arduino.cc/" target="_blank">Arduino</a>. Proyectos que nunca he publicado ya que nada tenían que ver con el contenido del blog, pero siempre me ha rondado por la cabeza la idea de que vieran la luz. Por eso hoy empiezo un nuevo blog con la idea de dar a conocer todo aquel material que anda disperso entre hojas de papel y discos duros. Así como todo el material que aún está por desarrollar.<br />
<br />
¡Empezamos!<br />
</div>
<div class="ln" lang="en">
First of all, sorry for my bad english. I'll try to explain my projects in english too because I think it's important for the visitors to read some text that isn't translated by robots (Though I help myself with <a href="http://translate.google.es/" target="_blank">Google Translate</a>). So if you find any kind of grammar or syntax error, please, feel free to let me know, I'll be happy to learn.<br /><br />
Since I started with my <a href="http://raulnd.blogspot.com.es/" target="_blank">old blog</a>, a little more than a year ago, I have always been developing some homespun projects with <a href="http://www.arduino.cc/" target="_blank">Arduino</a>. Projects that I've never posted and that had nothing to do with the content of the blog, I've always been thinking about the idea that they should be released. So today I start a new blog with the idea to give out all the material that is scattered between paper and hard drives. Just as all the material that is yet to develop.<br /><br />
Let's go!<br />
</div>
<br /><br /><br />
Anonymoushttp://www.blogger.com/profile/11133658869560834508noreply@blogger.com0Barberà del Vallès, Barcelona, España41.5136208 2.125555299999973641.4898423 2.0852147999999735 41.5373993 2.1658957999999737