- Introducción -
La generación de numero aleatorios suele ser complicado mas cuando se programa en ensamblador ya que al hacerlo en un lenguaje de medio o alto nivel los mismos ya poseen funciones especificas para la tarea haciendo la programación mas fácil.
Ahora bien, ¿ que pasa cuando programamos en ansamblador ? Pues tendremos que crear nuestras propias funciones y aquí veremos como crear una de ellas.
- Aproximación -
Para generar números aleatorios se puede recurrir a numerosos procedimientos. Por ejemplo, Supongamos un dado electrónico en el que el usuario presiona un pulsador y, luego de la animación, aparece un valor aleatorio en el mismo. Una aproximación, sin cuidar demasiado la probabilidad de cada numero, es hacer correr el TMR0 (Temporizador), cuando el usuario presiona la tecla se lee el mismo y de ahí se calcula para terminar con un numero aleatorio entre 1 y 6 que sera luego lo que el dado mostrara.
En ese caso se cuenta con que el usuario no sabe en que numero esta el TMR0 y que presionara el pulsador de una manera aleatoria y no cada un tiempo especifico y preciso.
La aproximación funciona y haciendo un poco mas de trabajo podemos extraer un numero aleatorio. Ahora supongamos que el sistema tiene que mostrar cada 10 segundos un numero aleatorio. ¿ Serviría el método anterior ?
Veamos: digamos que son 10 números (1 al 10), el temporizador se incrementa cada 1 segundo por lo que tardara 10 segundos en rebalsar. Encendemos el sistema y el mismo, cuando lee el TMR0 este posee el numero 3.
Ahora el sistema espera 10 segundos y lee nuevamente el TMR0. Después de 10 segundos obviamente el TMR0 estará en 3. No muy aleatorio ¿ verdad ? :lol:
Una solución para el problema anterior seria crear una tabla de números aleatorios. El problema es que si necesitamos 255 numero ocuparía muchísima memoria en el programa.
Para solucionar eso creamos nuestra función que nos devolverá un numero aleatorio. Para este caso también hay muchas maneras, la que usaremos ahora esta basada en el desplazamiento y en compuertas XOR. Este método, si se aplica correctamente, nos devolverá un numero aleatorio de longitud máxima. ¿Que significa de longitud máxima ? que no repetirá ningún numero y al final obtendremos 255 números aleatorios hasta que la secuencia vuelva a comenzar. Hay que aclarar que debido a lo ultimo este método genera números Pseudos-aleatorios.
- Código -
El método se basa en el siguiente diagrama:
Se aprecia que el sistema toma 2 grupos de 2 bits cada uno, realiza una operación XOR con cada grupo y el resultado de cada uno alimenta otra compuerta XOR. Por ultimo el resultado de esta ultima compuerta alimenta el bit de mayor peso luego de que toda la cadena haya sido desplazada a la derecha.
La condición esencial del circuito es que la cadena no puede comenzar con el numero 0. De suceder esto el sistema quedara en 0 indefinidamente. Por lo que, antes de empezar habrá que cargar la cadena con un valor cualquiera distinto de cero -muchas veces llamado este valor "semilla" ya que es el que alimenta/genera el resto de los números-
Como código termine con el siguiente -debería recordar karnaugh y ver si se puede reducir a algo mas fácil pero seguí con las compuertas XOR-
Random
btfsc Dato, 4
incf Conta, f
btfsc Dato, 3
incf Conta, f
btfsc Dato, 2
incf Conta, f
btfsc Dato, 0
incf Conta, f
rrf Conta, f
rrf Dato, f
clrf Conta
return
Se preguntaran donde esta las operaciones XOR en el código. Es ahí donde radica un poco lo lindo del código:
Veamos como es la tabla de verdad de la compuerta XOR:
AB ----- Out
00 ------- 0
01 ------- 1
10 ------- 1
11 ------- 0
Ahora si observamos cual seria la salida de la compuerta que alimenta el registro de desplazamiento veremos algo curioso:
ABCD ---- Out ---- Cantidad de unos.
0000 ------ 0 ------------ 0
0001 ------ 1 ------------ 1
0010 ------ 1 ------------ 1
0011 ------ 0 ------------ 2
0100 ------ 1 ------------ 1
0101 ------ 0 ------------ 2
0110 ------ 0 ------------ 2
0111 ------ 1 ------------ 3
1000 ------ 1 ------------ 1
1001 ------ 0 ------------ 2
1010 ------ 0 ------------ 2
1011 ------ 1 ------------ 3
1100 ------ 0 ------------ 2
1101 ------ 1 ------------ 3
1110 ------ 1 ------------ 3
1111 ------ 0 ------------ 4
(Donde AB seria los bits 0 y 2 que alimentan una de las XOR, CD los bit 3 y 4 que alimentan otra de las compuertas XOR y por ultimo la salida es la que presenta la compuerta XOR que opera sobre los dos grupos mencionados anteriormente AB y CD)
Se ve que la salida de la tercera compuerta es alta solo cuando la cantidad de unos que alimentan las dos primeras compuertas es un numero impar. Por lo que solamente habrá que contar la cantidad de números 1 que aparecen en los 4 bit (bit 0, bit 2, bit 3 y bit 4), de ser impar alimentar la cadena con un 1 y en caso contrario con un 0. Todo esto obviamente luego de desplazar la cadena a la derecha.
- Conclusiones -
Cuando se inicializa el PIC habrá que cargar el registro "Dato" con algún numero distinto de 0 como explique anteriormente y luego de llamar la función esta cambiara el registro Dato con el nuevo valor aleatorio.
La función solo tarda 11 pulsos de reloj (si no contamos los 2 para llamar la función y los 2 para volver de la misma) con lo que es muy rápida.
martes, 21 de mayo de 2013
jueves, 16 de mayo de 2013
74HC595. y un poco de codigo para un PIC.
--- Introducción ---
Muchas
veces tenemos un microcontrolador que anda perfecto para una tarea pero
lamentablemente no posee la cantidad de pines que uno necesita.
Una
solución es comprar un microcontrolador con mas pines. Esta solución muchas veces presenta el problema de que la
diferencia en precio es grande. Otras veces uno puede estar experimentando en
fase de aprender y por eso, como yo, se decanta por otro método.
En
mi caso estoy trabajando con un PIC12f675 el cual posee solo 5 pines
I/O y 1 que solo es entrada. Como se ve la cantidad de pines disponible
no es mucha.
En el circuito que uso necesito disponer de 8 salidas
para comandar una red DAC R-2R. Acá es donde generalmente uno de afuera
diría: usa un PIC16f628 o, si necesitas un ADC, un PIC16F88.
Supongamos
ahora, para el que aconseja eso, que mi circuito es un POV LED que
tiene que comandar 36 LEDS. ¿ Irse a un PIC32 ? ¿ un FPGA ?.
Es acá donde un poco de conocimiento sobre los expansores de puertos puede ser útil y es a lo que apunta esta guía.
---- El registro de desplazamiento 74HC595 ---
El diagrama parece complicado pero no es tan así, veremos que es mas fácil de manejar de lo que parece.
Tenemos:
1 Linea de entrada de datos serial.
4 Lineas de control.
1 Linea para hacer cascadas (se pueden conectar "infinitos" circuitos).
8 Salidas de datos.
Pin a pin que hace cada cosa:
PIN desde el 1 al 7 y el 15: Empezando por lo mas fácil estos ocho pines serán por donde uno obtendrá la salida paralela. Acá se conectaran los LEDs, motores, circuitos, etc, que uno quiere comandar.
El pin 15 sera el de menos peso -LSB- y el 7 el de mayor peso o -MSB- (esto para tener en cuanta cuando se envíe los datos serialmente, luego debido a que es uno el que controla que dato aparece en cada salida el dato de menor peso o mayor peso podrá ser cualquiera).
PIN 10: Siguiendo por lo fácil, el pin 10 es el de reset. Este pin resetea la cuenta que lleva el dispositivo en el desplazamiento como así también limpia las salidas que pasaran a 0.
En el caso de no disponer de los suficientes pines en el micro habrá que poner este pin (pin 10) a Vcc para dejar al registro sin resetear.
PIN 13: Habilitador de salidas. Este pin "conecta" las salidas. En caso de que este a Vcc -salidas desconectadas- las mismas estarán flotantes o también llamado en HI-Z alta impedancia.
En caso de conectarlo a GND las salidas estarán "conectadas" con lo que ahora los pines están a 0 o 1 dependiendo de lo que se le haya enviado al registro a través del micro.
Como en el caso anterior si no se dispone de los suficientes pines en el micro este pin puede conectarse permanentemente a Vcc y así dejar las salidas permanentemente conectadas.
PIN14: Entrada serial de datos. Por este pin ingresan, uno a uno, los bits que compondrán la salida. Para validar y guardar cada bit habrá que hacer uso del siguiente pin:
PIN11: Pulsos de reloj para validar los bits de entrada. Al recibir este pin un flanco de subida desplaza el contenido del registro hacia la derecha almacenando el valor en el bit 0 del registro de desplazamiento.
PIN12: Una vez se haya enviado los 8 bit que compondrán la salida, se envía un pulso a este pin para que en el flanco de subida pase todo lo que este guardado en el registro de desplazamiento hacia las salidas (Registro de almacenamiento). La salida permanecerá inalterable aun cuando se vuelva a ingresar datos y solo cambiara cuando, mediante este pin (pin 12) se vuelva a dar un pulso para actualizar las salidas con el segundo valor que se cargo.
PIN9: Por ultimo, como dijimos que se pueden colocar mas registros en cascada el micro deberá enviar no ya 8 bits sino 16 bits (por ejemplo si tenemos solo 2 registros en cascada).
Al ingresar el 9no bit, el primero que se ingreso saldrá por este pin (pin 9) y entrara al pin 14 del siguiente registro para acumularse ahí.
Si es complicado de entender supongase lo siguiente: hay una mesa en donde entran 4 cajas; coloco una caja, luego y empujando a esta (desplazándola) coloco otra y así hasta que en la mesa haya 4 cajas. Ahora si coloco otra caja, al no entrar mas, la de la punta caerá al suelo perdiéndose.
En una cascada el pin 9 vendría a ser un puente por donde se deslizaría esta caja que en el otro caso se perdería e iría a parar a una segunda mesa. Obviamente cuando coloque 8 cajas terminare con las dos mesas llenas con 4 cajas cada una (osea dos registros de desplazamiento de 4 bits llenos y listo para transferir ese contenido a las salidas).
En el caso de una cascada todos los pines 10, 11, 12 y 13 estarían conectados a los respectivos pines 10, 11, 12 y 13 de los otros registros mientras que el pin 9 del primer registro estaría conectado al pin 14 del segundo, a su vez el pin 9 del segundo estaría conectado al pin 14 del tercero y así sucesivamente.
--- Código ASM para PIC y algo de optimización ---
El código para manejar un 74HC595 no es tan difícil:
Envia595
movlw 0x08
movwf Conta ; Cargamos un contador para contar los 8 bits.
A1
bcf GPIO, DS
btfsc Dato, 7
bsf GPIO, DS ; Ponemos en la salida el bit correspondiente MSB primero.
bsf GPIO, SHCP
bcf GPIO, SHCP ; Damos un pulso para validar el bit que acabamos de colocar.
rlf Dato, F ; Desplazo para colocar el siguiente bit a sacar.
decfsz Conta, f ; Compruebo si ya saque los 8 bits.
goto A1
bsf GPIO, STCP
bcf GPIO, STCP ; Doy un pulso para pasar los 8 bit almacenados a la salida.
return
Ahora bien, hagamos la cuenta de cuanto tardara en enviar los 8 bits suponiendo un tiempo de ejecución de cada instrucción de 1us (para hacer cálculos fáciles). Dado que es una función tengo:
1. 2us para ir, 2us para volver = 4us.
2. Cargar "Conta" con 8 = 2us.
3. Leer que valor es el bit y sacarlo = 3us.
4. Darle el pulso al registro para almacenar el bit = 2us.
5. Rotar el dato = 1us
6. Comprobar si ya se enviaron los 8 bits = 3us.
7. Dado que del paso 3 al 6 lo tengo que hacer 8 veces seria (3+2+1+3) * 8 = 72us
8. Por ultimo darle el pulso para pasar los datos guardados en el registro a las salidas = 2us.
Ahora si hacemos cálculos nos da que todo eso tarda: 4 + 2 + 72 + 2 = 80us para enviar un byte. O, lo que es lo mismo, actualizar la salida unas 12500 veces por segundo... No me gusta... MMM... me pregunto si se podrá hacer de otra forma... Veamos:
Envia595
bcf GPIO, DS
btfsc Dato, 7
bsf GPIO, DS
bsf GPIO, SHCP
bcf GPIO, SHCP
bcf GPIO, DS
btfsc Dato, 6
bsf GPIO, DS
bsf GPIO, SHCP
bcf GPIO, SHCP
bcf GPIO, DS
btfsc Dato, 5
bsf GPIO, DS
bsf GPIO, SHCP
bcf GPIO, SHCP
bcf GPIO, DS
btfsc Dato, 4
bsf GPIO, DS
bsf GPIO, SHCP
bcf GPIO, SHCP
bcf GPIO, DS
btfsc Dato, 3
bsf GPIO, DS
bsf GPIO, SHCP
bcf GPIO, SHCP
bcf GPIO, DS
btfsc Dato, 2
bsf GPIO, DS
bsf GPIO, SHCP
bcf GPIO, SHCP
bcf GPIO, DS
btfsc Dato, 1
bsf GPIO, DS
bsf GPIO, SHCP
bcf GPIO, SHCP
bcf GPIO, DS
btfsc Dato, 0
bsf GPIO, DS
bsf GPIO, SHCP
bcf GPIO, SHCP
bsf GPIO, STCP ; Pasa el valor alamacenado a las salidas.
bcf GPIO, STCP
return
Ahora bien, alguien que vea el código podrá pensar que tarda mas pero es lo mismo que preguntar: ¿ que vale mas un billete de 10 pesos o 10 de 1 peso ?. Por un lado tiene el problema de que ocupa mas código y cuando estamos apretados ya con el resto del código quizás no sea viable usarlo, pero en mi caso prefiero optimizar velocidad a código, así que hagamos los cálculos a ver cuanto tarda en enviar los 8 bits:
1. Como también es una función tendré 2us en llamarla y 2us en volver de ella = 4us.
2. Enviar un bit al pin del micro 3us.
3. Enviar el pulso al registro para validarlo = 2us.
4. Como se ve ese pedazo de código (paso 2 y 3) se repite 8 veces para enviar los 8 bits por lo que tardara (3 + 2) * 8 = 40us.
5. Enviar el pulso para pasar los datos guardados en el registro a las salidas = 2us.
Si hacemos las cuentas, en este caso, para enviar los 8 bits, tardara 4 + 40 + 2 = 46us o lo que es lo mismo, actualizara la salida cada 21739 veces... Pequeña diferencia ¿ No ?
--- Conclusión ---
Como se ve no es difícil usar el registro de desplazamiento y se obtienen varias ventajas.
Por el lado del software vimos que en cierto punto uno debe pararse y evaluar que es lo que necesita: ¿ Optimizar código ? u ¿ Optimizar velocidad ? es acá cuando saber un poco de ensamblador puede ser de una gran ventaja ya que un compilador no importa si fuese C, basic, pascal, habrá terminado con la primera aproximación que como vimos es la mas lenta. Desde luego los compiladores poseen opciones para incrustar pedazos de código en ensamblador y es ahí donde sobresaldremos si tenemos los conocimientos necesarios al usar las herramientas en tareas finas.
También hay que tener ne cuenta que si bien se pueden colocar "infinitos" registros en cascada para "llenarlos" se tardara "infinito" tiempo xD. La cuenta es fácil, en una cascada de X registros se tardara X veces lo que se tarda en cargar un solo registro.
Se puede pensar que con cargar mas rápido los registros se puede obtener mejores tiempo y eso es cierto hasta un determinado punto ya que el integrado 74HC595 tiene un limite de funcionamiento de 100Mhz (de todas formas, como se ve, es bastante rápido).
Saludos.
martes, 14 de mayo de 2013
Proyecto - Distorsionador. Circuito ADC/DAC.
--- Introducción ---
Hace tiempo que se me cruzo por la cabeza hacer un distorsionador de voz. Como no tenia ganas de comprar integrados específicos para la tarea decidí hacerlo por mi cuenta. Desde luego no pretendo lograr lo que los C.I. hacen y quizás no consiga nada pero es lo divertido de experimentar.
--- El circuito ---
El diagrama en bloques del circuito que tengo en mente es el siguiente:
Como se observa comienza por un micrófono que usare uno del tipo Elctret ya que poseo varios. La señal del micrófono pasara por un pre-amplificador acondicionador y luego a una de las entradas del PIC que posee un ADC (conversor analogo-digital). Este posee un pulsador que selecciona una distorsión a aplicarle a la señal de entrada.
Como el micro usado, un PIC12F675, no posee un DAC (conversor digital-analogo) hay que implementarlo por hardware. Para ello use el conocido DAC R2R ya que es fácil de implementar. Dado que el PIC tampoco posee los pines suficientes para manejar los 8Bits del DAC se usa el registro de desplazamiento 74HC595.
Luego la salida de la red R2R pasa a través de un buffer y por ultimo a un amplificador de audio que ataca un parlante para oír la señal.
--- Circuito 74595-R2R ---
Acá esta el diagrama usado en el 74595 mas la red R2R:
Para el que le interese, acá esta el PDF con el circuito impreso: http://www.mediafire.com/view/?6qcdwnx8fsuq3lj
Como se aprecia la placa tiene un detalle curioso y es la disposición de los pinheaders. Quizás ya lo habrán adivinado, la placa esta echa para ser "pinchada" sobre otra placa. Esto esta echo así porque esta misma placa puede ser usada para diferentes cosas. Por ejemplo, en mi caso, al estar diseñando una fuente de alimentación digital la placa me viene perfecto para controlar la tensión de salida del regulador. Debido a que me sobra un pin -GP5- sera el pin de comunicación desde otro micro para enviarle los comandos.
Lamentablemente la placa ya estaba echa cuando me di cuenta de que el pin GP3 tenia que haberle echo la conexión a un pin mas del pinheader así disponer de ese pin externamente ya que para la fuente de alimentación, por ejemplo, el pulsador no me sirve para nada.
También falta el regulador de 5V (el circuito puede ser alimentado desde 2.5v a 5v) y el amplificador operacional que hace las veces de buffer. Dado que quería hacer la placa lo mas chica posible decidí colocar esos componentes en la otra placa así me queda separado en dos placas la parte digital y la parte análoga.
--- Pruebas ---
Aun me falta jugar un rato con las demás partes. Ya había empezado montando todo en un protoboard pero la red R2R resulto ser complicada, los pines de las resistencias se tocaban, cables por todos lados, etc. Así que termine haciendo una placa.
Para probar la misma hice un pequeño programa que genera una señal senoidal: http://www.mediafire.com/download.php?5qe34a02q20q4cq
La salida en el osciloscopio es la siguiente:
Como queda la escalera de cada paso que compone la señal y por ultimo le agregue un capacitor de 100nf a la salida para suavizar la señal quedando así:
--- Conclusión ---
Por ahora quede satisfecho con el circuito que anda perfectamente. El siguiente paso es montar el pre-amplificador, buffer y amplificador en el protoboard y comenzar a jugar con el software a ver que puedo obtener en la salida como distorsiones.
Como adelanto el pre-amplificador que ensayare sera este:
Ya se que no me dará 5v en la salida ya que el LM358 no es rail to rail pero si llega a 0v. Debería alimentarlo con 12v pero prefiero perder 1v a la salida y estar seguro de que al PIC no le llegara mas tensión de la que el pin pueda manejar. También se me cruzo hacer los cálculos y alimentarlo con una tensión tal que la salida máxima llegue a 5v.
Pero bueno, eso sera en la próxima parte.
Saludos.
- Javier -
Hace tiempo que se me cruzo por la cabeza hacer un distorsionador de voz. Como no tenia ganas de comprar integrados específicos para la tarea decidí hacerlo por mi cuenta. Desde luego no pretendo lograr lo que los C.I. hacen y quizás no consiga nada pero es lo divertido de experimentar.
--- El circuito ---
El diagrama en bloques del circuito que tengo en mente es el siguiente:
Como se observa comienza por un micrófono que usare uno del tipo Elctret ya que poseo varios. La señal del micrófono pasara por un pre-amplificador acondicionador y luego a una de las entradas del PIC que posee un ADC (conversor analogo-digital). Este posee un pulsador que selecciona una distorsión a aplicarle a la señal de entrada.
Como el micro usado, un PIC12F675, no posee un DAC (conversor digital-analogo) hay que implementarlo por hardware. Para ello use el conocido DAC R2R ya que es fácil de implementar. Dado que el PIC tampoco posee los pines suficientes para manejar los 8Bits del DAC se usa el registro de desplazamiento 74HC595.
Luego la salida de la red R2R pasa a través de un buffer y por ultimo a un amplificador de audio que ataca un parlante para oír la señal.
--- Circuito 74595-R2R ---
Acá esta el diagrama usado en el 74595 mas la red R2R:
Como queda la placa una vez terminada con la disposición de los componentes y como queda la placa del lado de las pistas:
Para el que le interese, acá esta el PDF con el circuito impreso: http://www.mediafire.com/view/?6qcdwnx8fsuq3lj
Como se aprecia la placa tiene un detalle curioso y es la disposición de los pinheaders. Quizás ya lo habrán adivinado, la placa esta echa para ser "pinchada" sobre otra placa. Esto esta echo así porque esta misma placa puede ser usada para diferentes cosas. Por ejemplo, en mi caso, al estar diseñando una fuente de alimentación digital la placa me viene perfecto para controlar la tensión de salida del regulador. Debido a que me sobra un pin -GP5- sera el pin de comunicación desde otro micro para enviarle los comandos.
Lamentablemente la placa ya estaba echa cuando me di cuenta de que el pin GP3 tenia que haberle echo la conexión a un pin mas del pinheader así disponer de ese pin externamente ya que para la fuente de alimentación, por ejemplo, el pulsador no me sirve para nada.
También falta el regulador de 5V (el circuito puede ser alimentado desde 2.5v a 5v) y el amplificador operacional que hace las veces de buffer. Dado que quería hacer la placa lo mas chica posible decidí colocar esos componentes en la otra placa así me queda separado en dos placas la parte digital y la parte análoga.
--- Pruebas ---
Aun me falta jugar un rato con las demás partes. Ya había empezado montando todo en un protoboard pero la red R2R resulto ser complicada, los pines de las resistencias se tocaban, cables por todos lados, etc. Así que termine haciendo una placa.
Para probar la misma hice un pequeño programa que genera una señal senoidal: http://www.mediafire.com/download.php?5qe34a02q20q4cq
La salida en el osciloscopio es la siguiente:
Como queda la escalera de cada paso que compone la señal y por ultimo le agregue un capacitor de 100nf a la salida para suavizar la señal quedando así:
--- Conclusión ---
Por ahora quede satisfecho con el circuito que anda perfectamente. El siguiente paso es montar el pre-amplificador, buffer y amplificador en el protoboard y comenzar a jugar con el software a ver que puedo obtener en la salida como distorsiones.
Como adelanto el pre-amplificador que ensayare sera este:
Ya se que no me dará 5v en la salida ya que el LM358 no es rail to rail pero si llega a 0v. Debería alimentarlo con 12v pero prefiero perder 1v a la salida y estar seguro de que al PIC no le llegara mas tensión de la que el pin pueda manejar. También se me cruzo hacer los cálculos y alimentarlo con una tensión tal que la salida máxima llegue a 5v.
Pero bueno, eso sera en la próxima parte.
Saludos.
- Javier -
miércoles, 8 de mayo de 2013
Jugando con las tarjetas SD
Jugando con las tarjetas SD
Hola a todos. Después de mucho renegar y leer decenas de hojas de datos
pude por fin comunicarme con la tarjeta SD. Si bien lo había echo
enseguida en el simulador, este emula una tarjeta MMC y no una SD,
ademas que tiene todo simplificado con lo que al pasar a la realidad las
cosas pueden cambiar y si bien eso lo sabia no me desalentó sino mas
bien me sirvió porque al probar de todo para hacer andar la tarjeta aprendí mucho mas que si hubiese salido a la primera.
Así que acá las cosas que aprendí y si bien no es una guía completa sirve de muy buen ejemplo de lo que no hay que hacer.
En el mercado hay muchas tarjetas de memoria, entre ellas las MMC y las SD que, aunque son compatibles, son diferentes en el manejo de las mismas.
Así que acá las cosas que aprendí y si bien no es una guía completa sirve de muy buen ejemplo de lo que no hay que hacer.
En el mercado hay muchas tarjetas de memoria, entre ellas las MMC y las SD que, aunque son compatibles, son diferentes en el manejo de las mismas.
El otro protocolo es el SPI. El cual uso ya que ademas de requerir menos pines es mas fácil de implementar ya que esta mas documentado.
En un principio iba a montar todo en un protoboard, pero luego me decidi crear una pequeña placa ya que me ahorraria varios problemas.
Los valores de los componentes están en un TXT dentro del archivo adjunto al final del post.
En el esquema faltan las conexiones de alimentación del integrado
MAX232. No se porque el Eagle no me las pone, pero son: PIN 16 Vcc... y
PIN 15 GND.
Como se puede observar incluí el archiconocido MAX232 para tener una conexión RS232 ya que en un primer momento el PIC solamente iba a hacer de puente entre la tarjeta y la PC. Pero luego de que se me complicara programar la PC y siendo que eso sumaria otra fuente de problemas decidí usar el PIC y prescindir de la comunicación con la PC. Para depurar usaba la EEPROM del PIC.
Los conectores que se aprecian están porque puedo usar la placa con el MAX232 en otros proyectos y por eso la inclusión del conector JP1. El conector JP4, junto con un jumper, me permite seleccionar entre una salida hacia el LED para indicar cualquier problema en las pruebas o usar el pin para la comunicación RS232.
La placa quedo así:
Como se puede observar incluí el archiconocido MAX232 para tener una conexión RS232 ya que en un primer momento el PIC solamente iba a hacer de puente entre la tarjeta y la PC. Pero luego de que se me complicara programar la PC y siendo que eso sumaria otra fuente de problemas decidí usar el PIC y prescindir de la comunicación con la PC. Para depurar usaba la EEPROM del PIC.
Los conectores que se aprecian están porque puedo usar la placa con el MAX232 en otros proyectos y por eso la inclusión del conector JP1. El conector JP4, junto con un jumper, me permite seleccionar entre una salida hacia el LED para indicar cualquier problema en las pruebas o usar el pin para la comunicación RS232.
La placa quedo así:
Como la tarjeta es una Micro SD uso un adaptador. El conector de esta
ultima fue fabricado artesanalmente y la idea fue sacada de acá: Cheap DIY SD card breadboard socket
Quedando asi:
Ahora venia la parte dura de proyecto: Hacerlo andar XD.
Este tipo de tarjetas, al alimentarlas, quedan en el protocolo propietario debiendo pasarles ciertos comandos para que cambien al protocolo SPI. Las secuencias y los comandos que habrá que enviarles difieren si se usa una memoria MMC o una SD y dentro de estas ultimas hay variaciones si son V1 o V2.
Los pasos son los siguientes:
--> Se alimenta la tarjeta y luego se le envían mas de 74 pulsos de reloj teniendo la precaución de que el pin CS este a un nivel alto.
--> Se pone el CS a 0 para seleccionar la tarjeta y se le envía el comando 0 (CMD0) Lo que resetea la tarjeta y la deja en estado de espera.
--> Se envía el comando 8 (CMD8) Si la tarjeta responde que es un comando ilegal puede deberse a que sea una SD v1 o una MMC.
En mi caso era una V2 así que prosigue de esta forma:
--> Se envía el comando 58 (CMD58) para saber en que rango de tensión trabaja.
--> Por ultimo se envía repetidamente el comando especial 41 (ACMD41) hasta que la tarjeta responda con el dato 0x00 (tarjeta lista).
Con esto la tarjeta queda en modo SPI y la espera de comandos de lectura, escritura, borrado, etc.
En mi caso y el programa que esta a continuación lo que hace es inicializar la tarjeta en modo SPI y luego lee los primeros 128bytes (máxima capacidad de la EEPROM) para proceder a grabarlos en la EEPROM del PIC.
El único problema al que me enfrente es que por error soldé una resistencia equivocada en el regulador de 3.3V con lo que en realidad solo alimentaba la tarjeta a 2.7v. Al tratar de inicializarla me aceptaba todos los comandos con la excepción del comando ACM41. Al enviar este comando la tarjeta se moría y no contestaba mas a nada. Al parecer en los primeros comandos el consumo de energía es muy pequeño pero al iniciarse en el otro protocolo el consumo crece con lo que me bajaba la tensión del regulador y quedaba fuera de la tensión mínima de trabajo.
El regulador de 3.3v esta echo con zener y transistor por el simple echo de que no tenia ganas de ir a la casa de electrónica solo por un regulador.
Comandos CMD0, CMD8 y ACMD41
Las tarjetas SD poseen diversos comandos. Muchos de estos comandos son unicamente validos cuando las tarjetas trabajan en el modo SD propietario pero inválidos en el modo SPI.
Aquí pondré los mas usados (al menos por mi hasta el momento XD). Como se forman, con que parámetros y cual es la respuesta que debemos esperar.
Todos los comandos poseen la misma longitud de 6 bytes, pero no a todos latarjeta responde de la misma forma, a algunos comandos respondera con un byte, a otros con 2, otros con 4, etc.
El modo de crear un comando esta representado en la imagen superior.
Se puede apreciar que los dos primeros bits siempre son iguales 01, luego vendrán los siguientes 6 bits que forman el comando en si. Con esto ya tenemos un byte usado.
Los siguientes 4 bytes indican el parámetro. Por ejemplo la dirección a la cual leer.
Por ultimo el sexto byte es el que contiene el CRC (cyclic redundancy check) de 7 bits de longitud. El octavo bit siempre es 1.
Cuando se dice que se le envía el comando CMD1 por ejemplo, el primer byte del comando en realidad posee el valor 0x41(65 en decimal). Veamos porque:
Dijimos que los primeros dígitos valen 01. Y que los siguientes 6 representan el comando:
01 + 000001 = 01000001 (0x41).
Si lo programamos en C quedaría:
spi_write(comando | 0x40); // Xor 0x40 proque 0x40 = 01000000
Los siguientes 4 bytes no necesitan ser modificados porque son enviados tal cual son.
Por ultimo queda los 7 bit del CRC. El CRC es valor que sirve para comprobar que los 5 bytes enviados antes no sufrieron modificaciones en la comunicación. El octavo bit siempre es 1.
El CRC no es necesario en el protocolo SPI ya que por defecto esta deshabilitado con la excepción del comando CMD0 y del CMD8. Estos últimos comandos son utilizados en la inicializacion y poseen siempre el mismo CRC por lo que no hace falta calcularlos (en realidad el CMD8 si puede variar pero veremos porque digo que siempre tiene el mismo CRC).
La mayoría de los comandos responden con 1 byte que indica los posibles errores o no después de recibir un comando:
Traducido quedaría así:
Bit 8: Siempre en 0.
Bit 7: Error en el parámetro pasado.
Bit 6: Error en la dirección seleccionada.
Bit 5: Error en la secuencia de borrado.
Bit 4: Error en la comprobación del CRC.
Bit 3: El comando enviado es ilegal.
Bit 2: Erase Reset. ¿?
Bit 1: En estado de espera.
Comandos usados en la inicializacion de la tarjeta en modo SPI:
Antes que nada hay que aclarar que mientras dura la inicializacion la velocidad del puerto SPI no debe superar los 400Khz una vez la tarjeta se encuentre lista para trabajar se puede incrementar la velocidad sin problemas.
El primer comando que se envía es el CMD0. No posee parámetros, siempre son 0´s y por eso el CRC siempre es el mismo 0x95. Este comando le dice a la tarjeta que se resetee y quede en estado de espera:
spi_write(0x40); // 0x00 | 0x40 = 0x40.
spi_write(0x00);
spi_write(0x00);
spi_write(0x00);
spi_write(0x00);
spi_write(0x95);
Debido a que cada comando escrito así quedaría un poco confuso es mejor usar una función que aglomere todo quedando así:
send_cmd(0, 0x00, 0x00, 0x00, 0x00, 0x95);
Se aprecia que se envía el valor 0 y no el 0x40 ya que la función ya calcula el valor haciendo un XOR con 0x40.
Una vez enviado el CMD0 si todo estuvo bien la memoria nos responderá con 0x01. Si miramos el gráfico anterior 00000001 significa: Tarjeta en estado de espera. Que es precisamente lo que le dijimos que haga con el CMD0.
Un punto a aclarar es que la tarjeta no responde inmediatamente a un comando sino que puede tardar de 1 a 8 bytes en enviar la respuesta. Mientras si leemos el valor que obtendremos es 0xFF. Así que tendremos que leer los bytes siguientes al comando hasta que encontremos un valor diferente a 0xFF. Si después de 8 bytes seguimos sin respuesta es que hubo algún error en el proceso que impide a la tarjeta comunicarse.
El comando que le enviaremos a continuación es el CMD8(sen Interface Conection). Con este sabremos si es una SD v1, SD v2 o una MMC. Una tarjeta SDv1 o una MMC responderá con 0x04 (comando ilegal). En el caso de una SDv2 nos dará el rango de tensión en la que trabaja.
send_cmd(8, 0x00, 0x00, 0x01, 0xAA, 0x87);
El byte 4 (0x01) le pregunta a la tarjeta si puede trabajar entre el rango de 2.7v a 3.6v.
El byte 5 (0xAA) es un byte de chequeo, en la respuesta la tarjeta nos debe devolver el mismo valor. Este valor puede ser cualquiera pero se aconseja el 0xAA (por lo que el valor de CRC siempre es el mismo de usarse este valor).
La respuesta es como muestra la imagen:
Bit 8: Siempre en 0.
Bit 7: Error en el parámetro pasado.
Bit 6: Error en la dirección seleccionada.
Bit 5: Error en la secuencia de borrado.
Bit 4: Error en la comprobación del CRC.
Bit 3: El comando enviado es ilegal.
Bit 2: Erase Reset. ¿?
Bit 1: En estado de espera.
Comandos usados en la inicializacion de la tarjeta en modo SPI:
Antes que nada hay que aclarar que mientras dura la inicializacion la velocidad del puerto SPI no debe superar los 400Khz una vez la tarjeta se encuentre lista para trabajar se puede incrementar la velocidad sin problemas.
El primer comando que se envía es el CMD0. No posee parámetros, siempre son 0´s y por eso el CRC siempre es el mismo 0x95. Este comando le dice a la tarjeta que se resetee y quede en estado de espera:
spi_write(0x40); // 0x00 | 0x40 = 0x40.
spi_write(0x00);
spi_write(0x00);
spi_write(0x00);
spi_write(0x00);
spi_write(0x95);
Debido a que cada comando escrito así quedaría un poco confuso es mejor usar una función que aglomere todo quedando así:
send_cmd(0, 0x00, 0x00, 0x00, 0x00, 0x95);
Se aprecia que se envía el valor 0 y no el 0x40 ya que la función ya calcula el valor haciendo un XOR con 0x40.
Una vez enviado el CMD0 si todo estuvo bien la memoria nos responderá con 0x01. Si miramos el gráfico anterior 00000001 significa: Tarjeta en estado de espera. Que es precisamente lo que le dijimos que haga con el CMD0.
Un punto a aclarar es que la tarjeta no responde inmediatamente a un comando sino que puede tardar de 1 a 8 bytes en enviar la respuesta. Mientras si leemos el valor que obtendremos es 0xFF. Así que tendremos que leer los bytes siguientes al comando hasta que encontremos un valor diferente a 0xFF. Si después de 8 bytes seguimos sin respuesta es que hubo algún error en el proceso que impide a la tarjeta comunicarse.
El comando que le enviaremos a continuación es el CMD8(sen Interface Conection). Con este sabremos si es una SD v1, SD v2 o una MMC. Una tarjeta SDv1 o una MMC responderá con 0x04 (comando ilegal). En el caso de una SDv2 nos dará el rango de tensión en la que trabaja.
send_cmd(8, 0x00, 0x00, 0x01, 0xAA, 0x87);
El byte 4 (0x01) le pregunta a la tarjeta si puede trabajar entre el rango de 2.7v a 3.6v.
El byte 5 (0xAA) es un byte de chequeo, en la respuesta la tarjeta nos debe devolver el mismo valor. Este valor puede ser cualquiera pero se aconseja el 0xAA (por lo que el valor de CRC siempre es el mismo de usarse este valor).
La respuesta es como muestra la imagen:
Para finalizar la inicializacion de la tarjeta se envía el comando
especial ACMD41. Este comando en realidad son dos en uno. Primero se envía el CMD55 y luego el CMD41.
CMD55 le indica a la tarjeta que el siguiente comando es del tipo ACMD. y el CMD41 es el comando en si:
send_cmd(55, 0x00, 0x00, 0x00, 0x00, 0xFF);
send_cmd(41, 0x40, 0x00, 0x00, 0x00, 0xFF);
Si bien el CMD55 posee respuesta habrá que ignorarla. Pero no así la respuesta del CMD41.
Mientras la tarjeta se encuentra inicializandose responderá al ACMD41 con 0x01 (tarjeta ocupada) por lo que debemos seguir enviado el ACMD41 hasta que nos devuelva el valor 0x00 (tarjeta inicializada y lista para operar). A partir de acá ya podremos leer y escribir en ella.
¿ Cuantas veces debemos enviar el ACMD41 ? La tarjeta demorara un tiempo variable, se aconseja entonces enviar el ACMD41 un determinado tiempo, de no recibir respuesta algo habrá salido mal.
Cabe aclarar que una vez la tarjeta este en modo SPI para pasarla al protocolo SD propietario habrá que quitarle la alimentación para que se resetee. No hay comando para ello.
Acá esta el archivo con la placa, esquema, software, etc: SD.zip
CMD55 le indica a la tarjeta que el siguiente comando es del tipo ACMD. y el CMD41 es el comando en si:
send_cmd(55, 0x00, 0x00, 0x00, 0x00, 0xFF);
send_cmd(41, 0x40, 0x00, 0x00, 0x00, 0xFF);
Si bien el CMD55 posee respuesta habrá que ignorarla. Pero no así la respuesta del CMD41.
Mientras la tarjeta se encuentra inicializandose responderá al ACMD41 con 0x01 (tarjeta ocupada) por lo que debemos seguir enviado el ACMD41 hasta que nos devuelva el valor 0x00 (tarjeta inicializada y lista para operar). A partir de acá ya podremos leer y escribir en ella.
¿ Cuantas veces debemos enviar el ACMD41 ? La tarjeta demorara un tiempo variable, se aconseja entonces enviar el ACMD41 un determinado tiempo, de no recibir respuesta algo habrá salido mal.
Cabe aclarar que una vez la tarjeta este en modo SPI para pasarla al protocolo SD propietario habrá que quitarle la alimentación para que se resetee. No hay comando para ello.
Acá esta el archivo con la placa, esquema, software, etc: SD.zip
Protocolo SPI
Protocolo SPI
Por ahí leí algo así: El protocolo SPI es aquel que uno diseñaría si le dieran solo 10 minutos para ello. Y sinceramente, sin desmerecer el protocolo, concuerdo en que es bastante sencillo.
Es un protocolo serial y sincrónico en el que un maestro puede comunicarse con uno o mas esclavos.
Posee 3 lineas para la comunicación (MOSI, MISO, CLK) mas 1 para la selección de la tarjeta con la que se comunicara(CS).
Por ultimo existen 4 modos en los que cada uno especifica solamente en que polaridad y flanco se leen o envían los datos.
Detalle de las lineas:
MOSI: Siglas que significan Salida del Maestro - Entrada del esclavo (Master Output - Slave Input). Por esta linea el Maestro (en mi caso el microcontrolador) envia los datos hacia el esclavo (tarjeta SD).
MISO: Entrada del Maestro - Salida del Esclavo (Master Input - Slave Output). Es la linea por donde el maestro recibe los datos que le envia el esclavo.
CLK: Linea de reloj. Es la encargada de generar los pulsos de reloj que indicaran cuando un dato (bit) es valido. Osea cuando tiene que ser leído un bit o cuando hay que preparar otro para su lectura. Esta linea es manejada exclusivamente por el maestro.
CS: Selección del Esclavo (Chip Select). Por medio de esta linea el maestro habilita uno de los esclavos presentes (Si es que hay mas de 1). Es esencial para evitar que dos esclavos, por ejemplo, transmitan los datos al mismo tiempo creando colisiones (errores en la linea) con lo que se corromperían los datos.
Tanto las lineas MISO y MOSI son llamadas también DO (Data Out) y DI(Data In). En lo personal prefiero MISO y MOSI ya que a mi me crea menos confusiones.
La comunicación se establece cuando la linea CS se hace baja (!CS). A partir de acá, como dijimos hay 4 modos que son los siguientes:
Modo 0: (Y el usado por las tarjetas SD).
Datos se leen en el flanco de subida del pulso de reloj.
El micro mantiene el CLK en bajo. Pone el bit a transmitir, sube la linea CLK en alto y luego lee los datos.
Modo 1:
Datos se leen en el flanco de bajada del pulso de reloj.
El micro mantiene el CLK en bajo. Sube la linea de CLK, pone el bit a transmitir, baja la linea CLK y luego lee los datos.
Modo 2:
Datos se leen en el flanco de bajada del pulso de reloj.
El micro mantiene el CLK en alto. Pone el bit a transmitir, baja la linea CLK y luego lee los datos.
Modo 3:
Datos se leen en el flanco de subida del pulso de reloj.
El micro mantiene el CLK en alto. Baja la linea de CLK, pone el bit a transmitir, sube la linea CLK y luego lee los datos.
Básicamente el modo 0 y el 2, como así también el 1 y el 3, son similares. La única diferencia es en que nivel esta la linea de CLK al mandar el primer bit para hacer el desplazamiento de los datos. Por ejemplo, en el modo 0, el primer bit a transmitir se carga antes de subir la linea de CLK.
Como se puede apreciar en las imágenes los datos se envían empezando por el bit mas significativo (MSB).
La función en C seria así (para el Modo 0):
unsigned char spi_write(unsigned char byte)
{
unsigned char i, SPI_Valor = 0;
for (i = 0; i < 8; i++) { // 8 bit a transmitir
SCK = 0;
MOSI = (byte & 128) >> 7;
SCK = 1;
SPI_Valor = SPI_Valor << 1;
SPI_Valor = SPI_Valor | MISO;
byte = byte << 1;
}
MOSI = 1;
return SPI_Valor;
}
1) Linea de CLK en bajo. Recuerden que el primer bit se lee en el pulso de subida.
SCK = 0;
2) Preparo el bit MSB a ser transmitido y lo pongo en la linea de salida.
MOSI = (byte & 128) >> 7;
3) Subo la linea de CLK para validar los datos.
SCK = 1;
4) Las dos siguientes lineas leen el bit transmitido por la tarjeta SD y lo desplazan.
SPI_Valor = SPI_Valor << 1;
SPI_Valor = SPI_Valor | MISO;
5) Desplazo el byte a transmitir para comenzar otro ciclo en el paso 1.
byte = byte << 1;
Ojala que con las imágenes quede mas claro.
Como se aprecia, la función de escritura también lee el dato enviado por la SD. Con lo que la función debería llamarse spi_RW(). A mi me quedo mas claro llamarla como spi_write por lo que explicare a continuación.
Una cosa importante es que la linea MOSI nunca debe quedar en bajo cuando se lee los datos de la tarjeta. Cuando se leen datos de la tarjeta se le envía continuamente 1´s.
dato = spi_write(0xFF);
Para no confundirse, en C uno puede decirle que la función spi_read() sea igual que spi_write(0xFF) de la siguiente forma:
#define spi_read() spi_write(0xFF)
Con lo que al compilador al encontrarse con spi_read() lo reemplazara con spi_write(0xFF).
Otro punto a aclarar es que si bien parece que el protocolo SPI es full duplex (se transmite y recibe al mismo tiempo) es mas bien half duplex (los datos van en solo sentido a la vez, osea o se transmite o se recibe, pero no los dos a la vez). Por eso hay que enviarle el valor 0xFF para que la memoria nos devuelva el dato que necesitamos.
Espero que con esto me haya podido explicar bien como es la transmisión entre el micro y la SD en el protocolo SPI emulado en software. Tengan presente que si el micro a usar tiene ya un modulo SPI integrado la cosa se simplifica bastante.
Saludos.
Protocolo RS232
Protocolo RS232
Aunque dejado de lado cada día mas siendo desplazado por el USB. El protocolo RS232 se niega a morir.
¿ Porque aun sigue siendo usado ? Quizás porque es fácil de implementar, de programar, aun la mayoría de las placa madres traen uno.
Por el lado técnico es un protocolo serial y asincronico. Solo 2 lineas de comunicación (mínimo para la comunicación, dejando de lado las señales CTS, DSR, RTS, etc. Presentes en la era en la que los modems se conectaban por RS232).
Cada trama a transmitir contiene los siguientes datos en ella:
1 bit de arranque.
7 u 8 bits de datos comenzando por el LSB.
1 bit de paridad.
1 o 2 bits de parada.
¿ Porque aun sigue siendo usado ? Quizás porque es fácil de implementar, de programar, aun la mayoría de las placa madres traen uno.
Por el lado técnico es un protocolo serial y asincronico. Solo 2 lineas de comunicación (mínimo para la comunicación, dejando de lado las señales CTS, DSR, RTS, etc. Presentes en la era en la que los modems se conectaban por RS232).
Cada trama a transmitir contiene los siguientes datos en ella:
1 bit de arranque.
7 u 8 bits de datos comenzando por el LSB.
1 bit de paridad.
1 o 2 bits de parada.
Dado que es un protocolo asincronico no posee una linea de reloj que habilite cada bit. Por eso el tiempo de cada bit es crucial ya que la lectura esta determinada por el tiempo.
Es por esto que existe el bit de arranque el cual le dice al receptor cuando comenzar a contar y calcular así cuando llegara un bit determinado.
El bit de paridad es opcional y puede indicar una paridad par o impar (cantidad par o impar de 1´s transmitidos). Si se nota raro el que los datos puedan ser de 7 bits es porque el 8vo es el de paridad. En la imagen se puede interpretar el dato como:
Dato: 01010101 con 1 bit de arranque 1 de parada, sin paridad y 8 bits de datos.
Como así también:
Dato: 1010101 con 1 bit de arranque 1 de parada, paridad impar y 7 bit de datos.
Es por eso que se debe prestar atención en que tanto el receptor como el transmisor estén configurados de la misma forma.
Si es una comunicación binaria ¿ para que usar un integrado como puede ser el MAX232 ? Es por el echo de que las tensiones establecidas en el protocolo son muy distintas a los 0v y 5V que puede manejar la mayoría de los microntroladores. Por el contrario el protocolo usa, para representar un 0 lógico, una tensión comprendida entre +5 y +15V (positivos) y un 1 lógico con una tensión entre -5V y -15V(negativa).
Ejemplo del programa en C para el Micro:
#define UnBit 416 // 416us = 2400 baudios
#define UnoyMedio 624 // 624us = 2400 baudios
Acá defino cuanto tarda cada bit y cuanto esperar para leer un bit. UnoyMedio indica el tiempo desde que la linea se hace baja (arranque), descontando el tiempo del bit de arranque (un bit) y esperando la mitad de la duración de un bit para hacer la lectura en el medio del bit a leer (yMedio).
*Baudios = bits/seg.
1/Baudio = UnBit. ==> 1/2400 = aprox 416us.
// Rutina que envía un dato por el puerto RS232
void Envia_232(unsigned char dato)
{
// 2400 - 8 bits - no paridad - 1 stop.
unsigned char x;
TX = 0;
__delay_us(UnBit);
for(x = 0; x < 8; x++) {
TX = (dato & 1);
__delay_us(UnBit);
dato = dato >> 1;
}
TX = 1;
__delay_us(UnBit);
}
Pongo la linea TX en 0 y espero 1 bit para crear el bit de arranque:
TX = 0;
__delay_us(UnBit);
Selecciono el bit a transmitir y lo pongo en la linea TX:
TX = (dato & 1);
__delay_us(UnBit); // Duración del bit.
Roto a la derecha 1 posición para preparar el siguiente dato a enviar:
dato = dato >> 1;
Una vez enviados los 8 bit pongo la linea TX en alto y espero 1 bit de duración para crear el bit de stop:
TX = 1;
__delay_us(UnBit);
En el caso de la recepción por parte del microntrolador la función es:
// Rutina que recibe un dato por el puerto RS232
unsigned char Recive_232()
{
unsigned char dato, x;
dato = 0;
while(RX == 1); // Espera a que la linea baje.
__delay_us(UnoyMedio); // Espera 1 bit y medio.
for(x = 0; x < 8; x++) { // Recibe los 8 bits
dato = dato >> 1;
dato = dato | (RX << 7); // LSB primero.
__delay_us(UnBit);
}
return dato;
}
Espero a que la linea RX se haga baja indicándome el inicio del bit de arranque. Una vez detectado espero 1 bit y medio para poder leer el primer bit:
while(RX == 1); // Espera a que la linea baje.
__delay_us(UnoyMedio); // Espera 1 bit y medio.
Una vez pasado el tiempo y situados en la mitad del bit lo leo y lo acomodo en el registro que guardara el dato recibido:
dato = dato >> 1;
dato = dato | (RX << 7); // LSB primero.
__delay_us(UnBit);
Obviamente que la recepción del dato se puede hacer (y daría mas flexibilidad al programa) con interrupciones.
Como se ve, incluso con un microcontrolador que no posea interrupciones ni un transmisor/receptor integrado RS232 no deja de ser muy fácil y rápido implementarlo por software.
Con el protocolo RS232 el máximo alcance del enlace es de 15metros, si necesitas mas alcance se puede convertir a RS485 con integrados especialmente diseñados para eso, aumentando el alance a 1200 metros.
Saludos.
sábado, 4 de mayo de 2013
Proyecto - Recuperar valor configuración OSCCAL en PIC´s
----- Introducción ----------------
Hace tiempo me llamó la atención la cantidad de personas preguntando como recuperar el valor de calibración que viene grabado en ciertos PIC.
Grabado en la última posición del área de programa, este valor permite calibrar el oscilador interno a 4Mhz con una precisión de +-1%.
El problema viene, en estos micros, que si por error se borra todo el micro y no se guardo ese valor -si bien el micro seguirá funcionando normalmente- al requerir cálculos de tiempo ya no se sabrá la base a la que el oscilador interno esta trabajando.
Generalmente este valor permite variar el oscilador entre unos 780khz a 1300Khz (no todos tienen los mismos limites, aun si son del mismo modelo).
Los programadores generalmente avisan al intentar sobrescribir el valor que viene de fábrica, pero si no lo hace o se hace caso omiso a la advertencia y se sobrescribe habrá que buscar algún método para volver a recuperar dicho valor.
----- Aproximaciones --------------
Viendo por internet hay varios métodos pero todos tienen el problema de que son complicados.
Por ejemplo, Microchip presenta este método de calibración: http://www.microchip.com/stellent/idcpl ... e=en012094
El problema es que se necesita un osciloscopio, un generador de funciones, un tester con frecuencimetro (o frecuencimetro). Instrumentales que no siempre tiene cualquier aficionado a la electrónica.
Otro método es: http://picprojects.org.uk/projects/reca ... struction_
Requiere un transformador (hay que destacar el método empleado para obtener un generador de frecuencias) pero ademas de eso una PC.
Primero hay que grabar un programa dentro del micro, colocarlo en el circuito, hacerlo funcionar. Leer el valor de calibración que, una vez se halla encontrado, estará guardado en la EEPROM. Pasar ese valor a la última posición del programa, grabar el micro y recién ahí esta todo listo.
Demasiado complicado para un hombre vago como yo.
----- Circuito --------------------
Así que mas que por necesidad (ya que hasta ahora nunca perdí el valor de calibración) sino mas bien por curiosidad me puse a crear mi propio circuito para restaurar el valor.
En realidad solo tenia curiosidad de como se programan los micros... pero... ya que estaba... de paso...
El circuito que use es el siguiente:
Esta realizado en Switch-CAD(TM) para poder colocarle anotaciones.
El HEX para grabar el micro Maestro, el PDF con la placa lista para transferencia (método de la plancha) y la guía de los componentes: OSSCAL.zip
----- Funcionamiento -------------
Básicamente lo que hace es: grabar un programa en el micro esclavo, enviarle ordenes para que cargue diversos valores en el registro OSCCAL para variar la frecuencia. Mide esta frecuencia hasta que la misma este dentro del rango de 1Mhz +-1%. Cuando encuentra que la frecuencia es correcta borra todo el micro y graba en la última posición el valor hallado dejándolo como viene de fábrica.
Hay que tener en cuenta lo siguiente:
- El circuito borra todo el micro, así que si hay algo dentro que no debe borrarse habrá que hacerle un BackUp primero.
- El circuito salva los Band Gap bits.
- Solo funciona con los PIC 12F629 y 12F675
- El micro Maestro deberá tener el valor de calibración correcto (el que viene de fábrica) ya que el calculo de la frecuencia depende de ello.
----- Pruebas --------------------
En las pruebas que hice ha tenido un éxito de 100%. He probado con 3 12F629 y con 2 12F675, nuevos sin uso y con el valor original que viene de fábrica, al saber el valor que debería tener según Microchip puede comparar con el valor que recupera el circuito y de los 5 micros que probé, los 5 fueron idénticos al valor que traen de fabrica.
Como se observa no hace falta complicados métodos ni instrumentales que no siempre están en el taller, ni siquiera una PC. Solo colocar el micro en el zócalo, presionar el botón. Las luces verdes y rojas parpadearan, luego la luz verde quedara prendida un tiempo -En ese momento esta buscando la frecuencia- y al apagarse las luces verdes y rojas parpadearan nuevamente ya que están grabando el valor encontrado. Una vez esto el micro quedara limpio y con el valor salvado en la última posición.
----- A resolver/Agregar ---------
- Falta una parte que comprueba que micro esta insertado. Si se coloca otro micro que no sea los especificados puede llegar a dañarlos.
Tampoco comprueba si hay un micro o no colocado.
- Como se ve en el diagrama, hay un LED que debería indicar cuando el proceso terminó. Al ponerlo en el circuito encontré que de alguna forma la tensión presente en el pin 6 del micro esclavo pasa a VCC alimentando el micro y haciéndolo funcionar.Tengo que investigar que esta pasando ahí y porque hace eso.
Esa parte no esta implementada en el software.
-
Agregar una comprobación de que el programa primero y el código luego
fue correctamente grabado, en caso contrario hacer parpadear el LED de
"Done".
----- Aclaraciones ---------------
En el diagrama que puse se ve que las tensión VPP dice 13V pero si se observa detalladamente el regulador entrega 12v. En un principio había puesto 13v (se coloca 2 diodos en serie y en directa entre el pin GND del 7812 y GND misma con lo que en la salida habrá 12v + 0.7v + 0.7v ~= 13.4V) pero en las pruebas use 12v y no hubo problemas. De echo en las hojas de datos se señala que solo hace falta una tensión mínima de 8.5v para VPP.
Ademas, en el
diagrama me falto poner un capacitor de 100nf que iría lo mas cerca
posible al micro esclavo entre el pin 1 y el 8, osea entre la
alimentación del mismo. El error vino de dibujar los dos en paralelo
luego del 7805 cuando la alimentación del PIC esclavo esta comandada por
el transistor superior. Corregido en el esquema
----- Vídeo demostración -----
Warning - Achtung - Precaución: El vídeo que sigue no es apto para personas sensibles, puede contener lenguaje incomprensible, errores y/u omisiones.
Placa lista para bañarse en percloruro xD:
Vista de los componentes:
Versión 0.6: http://www.mediafire.com/view/1nqa07ua3 ... L_V0.6.HEX
- Al terminar de grabar el micro, ahora deja la configuracion con el pin MCLR como MCLR en vez de un pin I/O y la configuracion del oscilador como XT, evitando asi que el micro no pueda ser regrabado con un programador ICSP.
Versión 0.5: http://www.mediafire.com/view/xa4v3k745 ... L_V0.5.HEX
- Corrección de algunos errores menores.
Version 0.4: http://www.mediafire.com/view/wj5go0840 ... L_v0.4.HEX
- Añadida la comprobación del programa grabado.
- Si no hay micro a comprobar o el programa no esta bien grabado el LED verde destellara 3 veces.
- En caso de que por algún error no haya podido recuperar el valor de la calibración el LED verde destellara 2 veces.
Versión 0.2: http://www.mediafire.com/view/cu32nt17c ... AL_0.2.HEX
- Ahora el micro maestro puede ser tanto el 12f629 o el 12F675.
- De no hallar el valor del oscilador ahora borra el programa usado para la calibración.
Saludos
- Javier -
Hace tiempo me llamó la atención la cantidad de personas preguntando como recuperar el valor de calibración que viene grabado en ciertos PIC.
Grabado en la última posición del área de programa, este valor permite calibrar el oscilador interno a 4Mhz con una precisión de +-1%.
El problema viene, en estos micros, que si por error se borra todo el micro y no se guardo ese valor -si bien el micro seguirá funcionando normalmente- al requerir cálculos de tiempo ya no se sabrá la base a la que el oscilador interno esta trabajando.
Generalmente este valor permite variar el oscilador entre unos 780khz a 1300Khz (no todos tienen los mismos limites, aun si son del mismo modelo).
Los programadores generalmente avisan al intentar sobrescribir el valor que viene de fábrica, pero si no lo hace o se hace caso omiso a la advertencia y se sobrescribe habrá que buscar algún método para volver a recuperar dicho valor.
----- Aproximaciones --------------
Viendo por internet hay varios métodos pero todos tienen el problema de que son complicados.
Por ejemplo, Microchip presenta este método de calibración: http://www.microchip.com/stellent/idcpl ... e=en012094
El problema es que se necesita un osciloscopio, un generador de funciones, un tester con frecuencimetro (o frecuencimetro). Instrumentales que no siempre tiene cualquier aficionado a la electrónica.
Otro método es: http://picprojects.org.uk/projects/reca ... struction_
Requiere un transformador (hay que destacar el método empleado para obtener un generador de frecuencias) pero ademas de eso una PC.
Primero hay que grabar un programa dentro del micro, colocarlo en el circuito, hacerlo funcionar. Leer el valor de calibración que, una vez se halla encontrado, estará guardado en la EEPROM. Pasar ese valor a la última posición del programa, grabar el micro y recién ahí esta todo listo.
Demasiado complicado para un hombre vago como yo.
----- Circuito --------------------
Así que mas que por necesidad (ya que hasta ahora nunca perdí el valor de calibración) sino mas bien por curiosidad me puse a crear mi propio circuito para restaurar el valor.
En realidad solo tenia curiosidad de como se programan los micros... pero... ya que estaba... de paso...
El circuito que use es el siguiente:
Esta realizado en Switch-CAD(TM) para poder colocarle anotaciones.
El HEX para grabar el micro Maestro, el PDF con la placa lista para transferencia (método de la plancha) y la guía de los componentes: OSSCAL.zip
Básicamente lo que hace es: grabar un programa en el micro esclavo, enviarle ordenes para que cargue diversos valores en el registro OSCCAL para variar la frecuencia. Mide esta frecuencia hasta que la misma este dentro del rango de 1Mhz +-1%. Cuando encuentra que la frecuencia es correcta borra todo el micro y graba en la última posición el valor hallado dejándolo como viene de fábrica.
Hay que tener en cuenta lo siguiente:
- El circuito borra todo el micro, así que si hay algo dentro que no debe borrarse habrá que hacerle un BackUp primero.
- El circuito salva los Band Gap bits.
- Solo funciona con los PIC 12F629 y 12F675
- El micro Maestro deberá tener el valor de calibración correcto (el que viene de fábrica) ya que el calculo de la frecuencia depende de ello.
----- Pruebas --------------------
En las pruebas que hice ha tenido un éxito de 100%. He probado con 3 12F629 y con 2 12F675, nuevos sin uso y con el valor original que viene de fábrica, al saber el valor que debería tener según Microchip puede comparar con el valor que recupera el circuito y de los 5 micros que probé, los 5 fueron idénticos al valor que traen de fabrica.
Como se observa no hace falta complicados métodos ni instrumentales que no siempre están en el taller, ni siquiera una PC. Solo colocar el micro en el zócalo, presionar el botón. Las luces verdes y rojas parpadearan, luego la luz verde quedara prendida un tiempo -En ese momento esta buscando la frecuencia- y al apagarse las luces verdes y rojas parpadearan nuevamente ya que están grabando el valor encontrado. Una vez esto el micro quedara limpio y con el valor salvado en la última posición.
----- A resolver/Agregar ---------
- Falta una parte que comprueba que micro esta insertado. Si se coloca otro micro que no sea los especificados puede llegar a dañarlos.
- Como se ve en el diagrama, hay un LED que debería indicar cuando el proceso terminó. Al ponerlo en el circuito encontré que de alguna forma la tensión presente en el pin 6 del micro esclavo pasa a VCC alimentando el micro y haciéndolo funcionar.Tengo que investigar que esta pasando ahí y porque hace eso.
Esa parte no esta implementada en el software.
----- Aclaraciones ---------------
En el diagrama que puse se ve que las tensión VPP dice 13V pero si se observa detalladamente el regulador entrega 12v. En un principio había puesto 13v (se coloca 2 diodos en serie y en directa entre el pin GND del 7812 y GND misma con lo que en la salida habrá 12v + 0.7v + 0.7v ~= 13.4V) pero en las pruebas use 12v y no hubo problemas. De echo en las hojas de datos se señala que solo hace falta una tensión mínima de 8.5v para VPP.
----- Vídeo demostración -----
Warning - Achtung - Precaución: El vídeo que sigue no es apto para personas sensibles, puede contener lenguaje incomprensible, errores y/u omisiones.
Placa lista para bañarse en percloruro xD:
Vista de los componentes:
Versión 0.6: http://www.mediafire.com/view/1nqa07ua3 ... L_V0.6.HEX
- Al terminar de grabar el micro, ahora deja la configuracion con el pin MCLR como MCLR en vez de un pin I/O y la configuracion del oscilador como XT, evitando asi que el micro no pueda ser regrabado con un programador ICSP.
Versión 0.5: http://www.mediafire.com/view/xa4v3k745 ... L_V0.5.HEX
- Corrección de algunos errores menores.
Version 0.4: http://www.mediafire.com/view/wj5go0840 ... L_v0.4.HEX
- Añadida la comprobación del programa grabado.
- Si no hay micro a comprobar o el programa no esta bien grabado el LED verde destellara 3 veces.
- En caso de que por algún error no haya podido recuperar el valor de la calibración el LED verde destellara 2 veces.
Versión 0.2: http://www.mediafire.com/view/cu32nt17c ... AL_0.2.HEX
- Ahora el micro maestro puede ser tanto el 12f629 o el 12F675.
- De no hallar el valor del oscilador ahora borra el programa usado para la calibración.
Saludos
- Javier -
PIC12F629, 3 Canales PWM y algunas pruebas.
Hola a todos. El proyecto, como se deduce del titulo XD, se trata de obtener 3 canales PWM con un PIC12F629.
La idea es usar este circuito para comandar 3 cooler de una PC. Si bien es mas fácil hacerlo con tres 555, o con dos 556 y podría aumentarse a 4 canales. La idea era probar si se podía hacerlo con el micro para, mas que nada, ir aprendiendo en el camino, así que acá los resultados que obtuve de las experiencias.
Al principio, la idea, era tratar de obtener la mayor frecuencia de salida para evitar el ruido generado en los motores. De usarse para manejar LEDs, por ejemplo, no hubiese sido necesario. Pero este no era mi caso.
Como no podía usar un cristal para usar la máxima frecuencia (20Mhz) tuve que usar el oscilador interno (4Mhz) y de ahí el primer ensayo: ¿ Que frecuencia máxima podía sacarle al oscilador interno ?
Microchip graba en los micros que poseen oscilador interno, un valor de configuración, de usarse ese valor la frecuencia de oscilación es de 4Mhz 1%. ¿ Pero que pasa si se carga otro valor ? la frecuencia varia, en mi caso y con las pruebas que hice logre llevarlo a 1,43 Mhz máximo aproximadamente (5,7Mhz). En el otro extremo 890Khz aprox (3,56Mhz). Así que en un principio "overclokee" el oscilador para que me de la máxima frecuencia. Esto se logra de la siguiente forma:
El método que emplee es con 3 pulsadores. Complicando un poco las cosas logre hacerlo funcionar de la siguiente manera:
Presionando un pulsador se selecciona uno de los motores y mientras se mantiene presionado con lo otros dos pulsadores se aumenta o disminuye la velocidad.
Ejemplo: Mantengo presionado el pulsador 1 con lo que selecciono el primer motor.
Si presiono ahora el pulsador 2 aumento la velocidad.
Y si en cambio presiono el tercer pulsador la disminuyo.
Ahora estaba el tema del programa, con todo lo que ensaye no logre sacarle mas de 2Khz en la señal del PWM. Sabia que no le sacaría mas así que de nuevo a investigar.
Buscando encontré el siguiente texto de microchip al respecto que da algunos consejos.
http://ww1.microchip.com/downloads/e...tes/00771b.pdf
Finalmente me decante por usar un capacitor a masa en la salida del transistor de potencia. Debido a la inercia del mismo cooler comprobe que era mejor usar una baja frecuencia de PWM. Jugando con los valores me quedo bastante decente. En el diagrama dichos capacitores no están, estos van entre colector y masa y su valor depende de la frecuencia del PWM y del cooler con lo que hay que experimentar hasta encontrar el valor correcto.
En el programa esta implementado un sistema que guarda el valor de las velocidades de los motores en la memoria EEPROM del micro. A medida que se modifica algún valor se guarda en la memoria.
Cuando se alimenta el circuito lee los valores almacenados y empieza desde ahí.
La primera vez que se usa el programa tiene los valores en 0.
El diagrama que uso es este:
Así como esta implementado en C y en el programa que subí la resolucion
es de 40 pasos entre 0-100%, osea tiene un incremento de 2,5%. Con eso
la frecuencia de salida esta en el orden de los 725hz.
Si reduzco la cantidad de pasos a 15 por ejemplo, osea incrementos de 7% aprox la frecuencia sube hasta los 1,8Khz.
La cantidad de pasos esta en la siguiente linea:
Como en mi caso era mejor usar baja frecuencia de PWM por el tipo de carga que manejo (Cooler) incremente la resolucion a 40 y deje el valor de calibración del reloj a 4Mhz. Para la máxima frecuencia hay que agregar el siguiente código al principio de la funcion Main():
Un Vídeo del circuito en funcionamiento:
El ruido generado al extraer el capacitor que filtra la salida:
Antes que nada aclaro que esta echo para comandar 3 coolers de una PC. El programa esta echo para motores grandes, los que uso son de 12 Cm, dado su inercia motores mas chicos quizás no logren arrancar en las velocidades mas bajas.
Por si las dudas de los 3 motores ninguno es el que refrigera el Microprocesador y no lo recomiendo bajo ninguna circunstancia.
El programa posee una rutina la cual verifica si la velocidad esta en cero (Motor apagado), al subir a la primera velocidad (velocidad mínima) pone a los motores a máxima velocidad por 1/2 segundo para darles inercia, de otra forma no arrancarían.
En la placa se puede notar que faltan los capacitores de filtro, no están puesto porque aun no me convencía que valor usar. Encontré que lo mejor es usar (para el cooler que uso) uno de 220uf. Como los cables los tendré que alargar los pondré en el cooler mismo.
Algunas fotos de la placa terminada:
Y acá, para el que lo quiera, la placa con el código: Codigo.zip
La placa es la misma que use yo y por ahora no le encontré problemas. Esta echa para usar el método de la plancha. En caso de usar por ejemplo transparencias hay que hacer un espejo de la imagen.
La idea es usar este circuito para comandar 3 cooler de una PC. Si bien es mas fácil hacerlo con tres 555, o con dos 556 y podría aumentarse a 4 canales. La idea era probar si se podía hacerlo con el micro para, mas que nada, ir aprendiendo en el camino, así que acá los resultados que obtuve de las experiencias.
Al principio, la idea, era tratar de obtener la mayor frecuencia de salida para evitar el ruido generado en los motores. De usarse para manejar LEDs, por ejemplo, no hubiese sido necesario. Pero este no era mi caso.
Como no podía usar un cristal para usar la máxima frecuencia (20Mhz) tuve que usar el oscilador interno (4Mhz) y de ahí el primer ensayo: ¿ Que frecuencia máxima podía sacarle al oscilador interno ?
Microchip graba en los micros que poseen oscilador interno, un valor de configuración, de usarse ese valor la frecuencia de oscilación es de 4Mhz 1%. ¿ Pero que pasa si se carga otro valor ? la frecuencia varia, en mi caso y con las pruebas que hice logre llevarlo a 1,43 Mhz máximo aproximadamente (5,7Mhz). En el otro extremo 890Khz aprox (3,56Mhz). Así que en un principio "overclokee" el oscilador para que me de la máxima frecuencia. Esto se logra de la siguiente forma:
movlw 0xFC ; Los primeros 2 bit son ignorados por el micro.Dado que tenia que variar la velocidad de los motores necesitaba una método para decirle al micro que hacer. Con 5 pines de entrada/salida y uno que es solo de entrada había que optimizar las cosas un poco.
movwf OSCCAL
El método que emplee es con 3 pulsadores. Complicando un poco las cosas logre hacerlo funcionar de la siguiente manera:
Presionando un pulsador se selecciona uno de los motores y mientras se mantiene presionado con lo otros dos pulsadores se aumenta o disminuye la velocidad.
Ejemplo: Mantengo presionado el pulsador 1 con lo que selecciono el primer motor.
Si presiono ahora el pulsador 2 aumento la velocidad.
Y si en cambio presiono el tercer pulsador la disminuyo.
Ahora estaba el tema del programa, con todo lo que ensaye no logre sacarle mas de 2Khz en la señal del PWM. Sabia que no le sacaría mas así que de nuevo a investigar.
Buscando encontré el siguiente texto de microchip al respecto que da algunos consejos.
http://ww1.microchip.com/downloads/e...tes/00771b.pdf
Finalmente me decante por usar un capacitor a masa en la salida del transistor de potencia. Debido a la inercia del mismo cooler comprobe que era mejor usar una baja frecuencia de PWM. Jugando con los valores me quedo bastante decente. En el diagrama dichos capacitores no están, estos van entre colector y masa y su valor depende de la frecuencia del PWM y del cooler con lo que hay que experimentar hasta encontrar el valor correcto.
En el programa esta implementado un sistema que guarda el valor de las velocidades de los motores en la memoria EEPROM del micro. A medida que se modifica algún valor se guarda en la memoria.
Cuando se alimenta el circuito lee los valores almacenados y empieza desde ahí.
La primera vez que se usa el programa tiene los valores en 0.
El diagrama que uso es este:
Si reduzco la cantidad de pasos a 15 por ejemplo, osea incrementos de 7% aprox la frecuencia sube hasta los 1,8Khz.
La cantidad de pasos esta en la siguiente linea:
#define VelMax 40 // Velocidad máxima
También había probado con hacer la parte de la interrupción (la que
maneja el pwm) en ensamblador con lo que llegue a 2,1Khz con una resolución de 15 pasos. Para el que lo quiera solo hay que reemplazar
toda la parte de la interrupción por esta:
void interrupt isr() // Interrupcion { #asm bcf 0x0B, 2 // TOIF = 0; movf _VelMot1, w subwf _VMI1, w btfsc 0x03, 2 goto M1 bsf 0x05, Mt1 incf _VMI1, f goto M1a M1: bcf 0x05, Mt1 M1a: movf _VelMot2, w subwf _VMI2, w btfsc 0x03, 2 goto M2 bsf 0x05, Mt2 incf _VMI2, f goto M2a M2: bcf 0x05, Mt2 M2a: movf _VelMot3, w subwf _VMI3, w btfsc 0x03, 2 goto M3 bsf 0x05, Mt3 incf _VMI3, f goto M3a M3: bcf 0x05, Mt3 M3a: decfsz _Cuenta, f goto M4 movlw VelMax movwf _Cuenta clrf _VMI1 clrf _VMI2 clrf _VMI3 M4: movlw ValTMRO movwf 0x01 #endasm }
Como en mi caso era mejor usar baja frecuencia de PWM por el tipo de carga que manejo (Cooler) incremente la resolucion a 40 y deje el valor de calibración del reloj a 4Mhz. Para la máxima frecuencia hay que agregar el siguiente código al principio de la funcion Main():
También se me ocurrió una variante para ver si llego a 20Khz de PWM y es usando la RAM para guardar las salidas. Hay que tener presente que en 20Khz solo hay 50us para hacer todo y ya se pierde 2us en ir a la interrupción, 2us en volver de ella, 1us en desactivar la interrupción, 2us en cargar de nuevo el valor en el timer y 1us en activar la interrupción de nuevo. Ya con eso suma 8us. El valor del TMRO lo cargo con 252 para que me de una interrupción cada 6us (el micro pasa mas de 98% del tiempo en la interrupción). Ya con eso y haciendo cálculos a groso modo la máxima frecuencia esta en el orden de los 50Khz y aun no he incluido los tiempos de las instrucciones dentro de la rutina de la interrupción XD.OSCCAL = 0xFC;
Un Vídeo del circuito en funcionamiento:
El ruido generado al extraer el capacitor que filtra la salida:
Antes que nada aclaro que esta echo para comandar 3 coolers de una PC. El programa esta echo para motores grandes, los que uso son de 12 Cm, dado su inercia motores mas chicos quizás no logren arrancar en las velocidades mas bajas.
Por si las dudas de los 3 motores ninguno es el que refrigera el Microprocesador y no lo recomiendo bajo ninguna circunstancia.
El programa posee una rutina la cual verifica si la velocidad esta en cero (Motor apagado), al subir a la primera velocidad (velocidad mínima) pone a los motores a máxima velocidad por 1/2 segundo para darles inercia, de otra forma no arrancarían.
En la placa se puede notar que faltan los capacitores de filtro, no están puesto porque aun no me convencía que valor usar. Encontré que lo mejor es usar (para el cooler que uso) uno de 220uf. Como los cables los tendré que alargar los pondré en el cooler mismo.
Algunas fotos de la placa terminada:
Y acá, para el que lo quiera, la placa con el código: Codigo.zip
La placa es la misma que use yo y por ahora no le encontré problemas. Esta echa para usar el método de la plancha. En caso de usar por ejemplo transparencias hay que hacer un espejo de la imagen.
Suscribirse a:
Entradas (Atom)