martes, 1 de septiembre de 2015

Monta tu propio Arduino en una protoboard


Hola, buenas a todos. Entramos en el segundo capítulo de mi nueva sección.

Hoy vamos a ver cómo podemos montar nuestro propio Arduino en una placa de prototipos (protoboard) siguiendo unos sencillos pasos. Este capítulo tiene la particularidad de que lo estoy escribiendo a medida que yo mismo realizo el proceso. De esta forma puedo entrar más en detalle en cada paso y no me voy dejando nada por el camino.

En primer lugar, además de vuestro Arduino (en este caso Arduino UNO), necesitaréis:
  • 2 condensadores de 22 pF.
  • 1 cristal de 16 MHz.
  • 1 condensador de 100 µF.
  • 1 resistencia de 10K.
  • Cables.
  • 1 microcontrolador ATMega 328P (también puede hacerse con otros modelos).
  • USB/Regulador de tensión/Transformador para la alimentación autónoma.
El proceso se divide en dos grandes partes: en primer lugar se carga el bootloader dentro del microcontrolador que queremos convertir en un Arduino y en segundo lugar, cargaremos el programa deseado a nuestro nuevo Arduino.

Para los que a estas alturas no entienden aún en qué consiste esto, resumo un poco lo que vamos a hacer: vamos a programar un ATMega 328P como el de la figura de forma que funcione de manera autónoma sin necesidad de estar integrado en una placa Arduino. De esta forma podremos hacer montajes más compactos y sobretodo más baratos (nos bastará con comprarnos el micro, que tan sólo vale unos euros, en lugar de comprar la placa Arduino que puede acabar siendo más costosa). A esto lo hemos llamado “montar nuestro propio Arduino”, pero tranquilos, no vamos a montarnos una placa Arduino entera, vamos a lo mínimo para que el micro pueda funcionar de manera autónoma.

ATMega328P

Vamos con los diferentes pasos del proceso.
  1. Programar Arduino UNO como ISP. En primer lugar hay que programar nuestro viejo Arduino UNO para que él mismo sea capaz de programar el ATMega 328. Para ello, en el entorno de desarrollo Arduino haremos click en Archivo > Ejemplos > ArduinoISP. De esta forma se nos abrirá automáticamente el código para lograr que Arduino funcione como un ISP (programador integrado, del inglés in-System Program).

    image

    Una vez contemos con el código, le damos a cargar y programamos nuestro Arduino UNO con el ISP.

  2. Montamos el circuito para la carga del bootloader. Desconectamos nuestro Arduino UNO del PC  y montamos el circuito necesario para poder cargar el bootloader. Aquí os dejo el esquema de cómo debe quedar la protoboard:

    Bootloader_circuito

    La resistencia es la de 10K y los condensadores de 22 pF.

    Si nos fijamos en el código que habíamos cargado, en los comentarios del principio aparecían las instrucciones para el cableado, no obstante os he facilitado esta imagen para simplificar el montaje. En la figura aparece un ATMega 168, pero no temáis, tienen la misma disposición de pines y el circuito que se debe montar es el mismo.

    También es posible conectar al pin 7 del Arduino UNO un LED (antecedido por una resistencia de entre 330Ω y 1 K) y de esta forma podemos seguir de forma visual cómo va la programación. Pero bueno, esto es totalmente opcional y por eso no está incluido en el dibujo.

  3. Cargamos el bootloader. Una vez montado podemos conectar de nuevo nuestro Arduino UNO al PC. Ahora iremos de nuevo al entorno Arduino y haremos click en Herramientas > Programador > Arduino as ISP.

    image

    Y una vez hecho esto le daremos a Herramientas > Grabar Secuencia de Inicio. Y tocará esperar un minuto (el entorno nos lo indica en la barrita aguamarina de la parte inferior). También es posible, si usáis las versiones nuevas de Arduino IDE, que este último paso aparezca como Herramientas > Quemar Bootloader.

    Si os aparece un error de firma, seguid los pasos que se indican en el primer mensaje de este tema.

    Cuando concluya el proceso aparecerá el mensaje “Quemador de bootloader completado”, indicando que el bootloader ya ha sido cargado en el ATMega. Con esto habremos realizado la primera mitad del proceso, vamos ahora con la segunda mitad, consistente en cargar el propio programa en sí para que se quede instalado en nuestro ATMega.
       
  4. Programar el ATMega328P. Con el bootloader listo, desconectaremos nuestro Arduino UNO del PC y procederemos a extraer el ATMega328P que lleva dentro para sustituirlo por el nuestro. Esto sólo se podrá hacer en caso de que nuestro Arduino emplee este tipo de encapsulado en lugar del SMD. En la siguiente figura podemos ver la diferencia entre ambos encapsulados.

    SMDvsDIP

    Ya sé que esto resulta bastante obvio para la mayoría de los que llegáis a este post, pero intento hacer un tutorial lo más completo posible para aquellos que no han tenido tanto contacto con la electrónica. Bueno, seguimos…

    Tras insertar el micro, cargamos el nuevo código en la placa abriéndolo desde el propio IDE y subiéndolo a nuestro Arduino (vamos, como hemos hecho siempre para cargar programas). Yo he empleado un código que enciende y apaga atenuadamente un LED conectado al pin 9 (os dejo el código al final del post). Verificamos que el programa funcione y extraemos el micro desconectando previamente Arduino del PC. Con esto el chip ya se quedará programado. Podemos volver a insertar nuestro antiguo chip en el Arduino, no lo necesitaremos más.
       
  5. Realizar el montaje autónomo. Por último, sólo hay que preparar una protoboard (o breadboard) con los requisitos mínimos que necesita el micro para mantener su funcionamiento. El esquema mínimo a realizar se recoge en la siguiente figura:

    Montaje Basico ATMega


    Como vemos, sólo hay que mantener el cristal entre las patillas 9 y 10, la resistencia de pull-up para el RESET en el pin 1 y alimentarlo de forma externa. Existen numerosas formas de alimentarlo, quizás la más elegante en términos de montaje sea una batería (pila de 9V, por ejemplo), seguida de un regulador de tensión para bajar la tensión a 5V. Yo en mi caso, aunque cuento con reguladores LM317, voy a emplear un método más cutre pero más eficaz (no requiere estar cambiando pilas): un cargador USB como el de los smartphones, que pelado nos permite extraer 5V y tierra. Todo depende ya del uso que vayáis a darle a vuestro nuevo Arduino “autónomo”.

    Se emplee el método que se emplee se debe insertar un condensador de 100µF entre alimentación y tierra, lo más cerca posible del microcontrolador. De esta forma suavizaremos el voltaje continuo de entrada, evitando posibles picos que nos quemen el micro.

    Es opcional, sin embargo, mantener los condensadores de 22pF que instalamos previamente en la etapa de carga del bootloader. Se recomienda mantenerlos, aunque no habrá problema si deseamos eliminarlos del montaje.
       
  6. Realizar el montaje para nuestro circuito. Ahora hay que trabajar sobre el montaje anterior, añadiendo las partes de nuestro circuito. En mi caso, cuando mi programa corría sobre Arduino, debía conectar un LED en el pin 9 para lograr su intermitencia, por tanto eso es todo lo que hay que añadir al circuito previo. Pero MUY IMPORTANTE: El pin 9 de Arduino UNO no es equivalente al pin 9 en el ATMega 328P-PU. Para saber a qué pin del micro le corresponde el pin 9 de Arduino, tendremos que hacer una búsqueda en internet. De allí extraemos una figura como la que vemos a continuación:

    ATmega328_pinout

    Como podemos ver, el pin digital 9 de Arduino equivale a la patilla número 15 de nuestro micro. Será por tanto a la patilla 15 donde deberemos conectar nuestro LED, quedando el circuito mínimo de la siguiente forma:

    Montaje Completo ATMega

    Realizando este montaje es posible ver cómo nuestro nuevo Arduino casero mantiene su funcionamiento de manera autónoma.
Bueno, hasta aquí este tutorial. Os dejo también a continuación el código que empleé. Es algo simple puesto que va destinado a la iluminación de una maqueta, pero también podéis realizar montajes más complejos y comprobar que efectivamente también funcionan. Espero que esto os haya servido de ayuda y también espero no haberme dejado nada por el camino.

Código:

#define PINLED 9   //Pin donde estara el LED a atenuar
#define TIEMPO 9500000  //Tiempo de atenuacion en microseg.

//Funcion que implementa la atenuacion, ya sea creciente o decreciente
//t: tiempo de atenuacion en us, creciente = true -> de apagado a encendido, pin: numero de pin donde producir la atenuacion PWM
void atenuacion(double t, bool creciente, int pin){
 if (creciente){
  for (int j = 0; j <= 255; j++){
   analogWrite(pin, j);
   delayMicroseconds(t / 255);
  }
 }

 else{
  for (int j = 255; j >= 0; j--){
   analogWrite(pin, j);
   delayMicroseconds(t / 255);
  }
 }
}

void setup()
{
 pinMode(PINLED, OUTPUT);

}

void loop()
{
 atenuacion(TIEMPO, true, PINLED);
 delay(700);
 atenuacion(TIEMPO, false, PINLED);
 delay(3000);

}



Os dejo también este vídeo, que junto con la web de Arduino y el foro son las fuentes bibliográficas que he consultado:


Y nada más.

Salu2.

sábado, 15 de agosto de 2015

Reproducción de melodía con buzzer pasivo


Hola de nuevo. Después de tanto tiempo he vuelto a tener la osadía de asomar la cabeza por el blog, como prometí en su momento en la cuenta de twitter.

Todos estos días he estado ocupado –distraído, mejor dicho– con temas de universidad, trabajo, etcétera etcétera. Pero me complace mucho volver con la noticia de que estreno nueva sección. Como anuncié en su momento, adquirí por internet un pack de “aprendizaje” con la placa Arduino UNO. Pues bien, ha llovido desde entonces. Lo que parecía un caprichito pasajero se ha convertido en una inmersión total en el mundo de electrónica. Condensadores, resistencias, integrados, transistores, diodos, etc. Todo eso y más son las cosas que he comprado, víctima de mi nueva enfermedad: la adicción a la electrónica.

Prometí una serie de sketches de Arduino bastante simples, que en su momento pensaba que eran… ¿como decirlo? ¿Currados? No sé.

El caso es que desde aquel post he realizado gran cantidad de proyectos diferentes y de distintas magnitudes, por supuesto no tan simples como estos primeros. Es más, no únicamente he trabajado con Arduino. También trabajé con las placas MSP430 de Texas Instruments, Intel Galileo, Waspmote de Libelium, etc. Así que obviamente no publicaré los proyectos simples. Aunque de esa primera partida inicial sí que hay un proyecto que me gustaría compartir con vosotros. No sé si es por que estoy orgulloso de ello o porque al estar íntimamente relacionado con mi infancia Nintendero-gamer me despierta gran simpatía. El caso es que este podría decirse que fue, de los primeros, el proyecto más completo que hice. Todo en un único fichero .ino, pero empleando funciones y con una estructura plenamente desarrollada por mí. Y con un trabajillo de investigación detrás.

Os hablo de la reproducción de una melodía con un buzzer pasivo. La melodía en concreto es la de Pueblo Paleta de las versiones Amarillo, Rojo y Azul de Pokémon. Qué nostalgia.

Como muchos de vosotros sabréis, el buzzer pasivo consiste literalmente en un zumbador que, al recibir cierto nivel de tensión, emite un pitido. En este caso funciona bajo 5V, como la mayoría de accesorios que se conectan a Arduino. Pero, ¿cómo emitir melodías si este zumbador únicamente emite un pitido? La respuesta es sencilla: con simplemente producir el pitido a una frecuencia determinada es posible emitir una nota u otra.

Aquí entra el trabajo de investigación.

En primer lugar se investigan las diferentes notas existentes en la escala musical (se va a trabajar en clave de sol). Googleando un poco, se encuentran tablas como la que se muestra a continuación.

notasyfrecsbg

Basta con recordar el valor de frecuencia que corresponde a cada nota para poder reproducir la melodía.

Junto con esto, se busca una partitura con la melodía de Pallet Town, en este caso, para poder conocer todas las notas que la componen. Además se deberán tener en cuenta los silencios entre cada una de las notas.

Un error de novato que tuve al realizar el código fue emplear PWM para modular las notas. Mi intención era variar el ciclo de trabajo para lograr la diferente escala. Pero cuál fue mi sorpresa al probar el código y ver que lo único que variaba era la intensidad de las notas. IMPORTANTE: PWM varía el ciclo de trabajo, es decir, el porcentaje de tiempo de un determinado tiempo fijo que la señal se mantiene en alto. En ningún momento varía la frecuencia. De los errores se aprende, y esto mismo aprendí yo al intentar hacerlo de este modo.

Una vez solucionado esto, se puede ver que se hace necesaria la creación de una función encargada de generar la “vibración”. Para ello se ha diseñado la función reproducirNotas que podéis ver en el código a continuación. Esta función implementa el proceso de vibración. Únicamente se ha de especificar la nota a reproducir (mediante un índice), la duración de la misma y la duración del silencio que la sigue (que de no existir puede ser 0 perfectamente). De esta forma, el formato de la partitura ahora se adapta a un formato de conjuntos nota+silencio que se van sucediendo en el tiempo. Alternando de la forma adecuada es posible lograr con exactitud la melodía que se indica en la partitura.

Y bueno, no tengo mucho más que añadir. Aquí a continuación os dejo el código comentado. Podéis probar con la melodía que os guste, simplemente tenéis que extraer de la partitura la secuencia de pares nota/silencio. Espero que os resulte interesante. Me parece que llegó a ser mi tercer proyecto con Arduino, con lo cual no está nada mal. Aunque hay que dar parte del mérito a Mr.Sandman, que ayudó en el proceso de búsqueda de información y estuvo ahí para supervisar el proceso mecánico de la traducción. Pasaos por su blog, también tiene algunas cosillas muy interesantes.

Código:

int frecuencias[] = {   262,277,294,311,330,349,370,392,415,440,466,494,523,554,587,   622,659,698,740,784,831,880,932,988}; //Array de frecuencias equivalentes a las notas://DO,#DO,RE,#RE,MI,FA,#FA,SOL,#SOL,LA,#LA,SI,DO2,#DO2,RE2,#RE2,//MI2,FA2,#FA2,SOL2,#SOL2,LA2,#LA2,SI2  void setup() {   pinMode(4, OUTPUT); //Determinación del pin 4 como salida (autor del sonido en sí)}   void reproducirNotas(int i,float figura,float silencio){  //i: indice del array de frecuencias; figura: factor a multiplicar según la figura (negra, blanca, corchea...) //silencio: factor a multiplicar según el silencio long j = 0; //indice no entero long semiperiodo = 1000000/(frecuencias[i])/2; //obtención del semiperiodo (en microsegundos, de ahi el 1000000) como mitad del periodo (1/frec) long numCiclos = frecuencias[i]*(500*figura)/1000; //obtencion del numero de ciclos (500 es el tiempo al que se le aplica el factor de figura) while(j<numCiclos){    digitalWrite(4,HIGH); //ciclo en alto durante primer semiperiodo   delayMicroseconds(semiperiodo);    digitalWrite(4,LOW); //ciclo en alto durante segundo semiperiodo   delayMicroseconds(semiperiodo);    j++;  }  silencio=silencio*500; //500 tiempo al que se le aplica el factor de silencio if(silencio>0){ //si existe silencio, aplicarlo   delay(silencio);  } }   void loop() {   //secuencia obtenida para PalletTown  reproducirNotas(14,0.25,0.25);   reproducirNotas(12,0.25,0.25);   reproducirNotas(11,0.25,0.25);   reproducirNotas(9,0.25,0.25);   reproducirNotas(19,0.25,0.25);   reproducirNotas(16,0.25,0.25);   reproducirNotas(18,0.25,0.25);   reproducirNotas(16,0.25,0.25);   reproducirNotas(14,1.25,0.5);   reproducirNotas(11,0.25,0.25);   reproducirNotas(7,0.25,0.25);   reproducirNotas(7,0.25,0.25);   reproducirNotas(9,0.25,0.25);   reproducirNotas(11,0.25,0.25);   reproducirNotas(12,1.75,0.75);   reproducirNotas(6,0.25,0.25);   reproducirNotas(7,0.25,0.25);   reproducirNotas(9,0.25,0.25);   reproducirNotas(11,1.25,0.25);   reproducirNotas(12,0.25,0);   reproducirNotas(11,0.25,0);   reproducirNotas(9,1.75,0.25);   reproducirNotas(14,0.25,0.25);   reproducirNotas(12,0.25,0.25);   reproducirNotas(11,0.25,0.25);   reproducirNotas(14,0.25,0.25);   reproducirNotas(19,0.25,0.25);   reproducirNotas(18,0.25,0.25);   reproducirNotas(17,0.25,0.25);   reproducirNotas(19,0.25,0.25);   reproducirNotas(16,1.25,0.25);   reproducirNotas(14,2.25,0.25);   reproducirNotas(12,0.25,0.25);   reproducirNotas(11,0.25,0.25);   reproducirNotas(9,0.25,0.25);   reproducirNotas(7,0.25,0.25);   reproducirNotas(14,0.25,0.25);   reproducirNotas(12,0.25,0.25);   reproducirNotas(11,0.25,0.25);   reproducirNotas(9,0.25,0.25);   reproducirNotas(7,1.75,0.75);   reproducirNotas(7,0.25,0.25);   reproducirNotas(9,0.25,0.25);   reproducirNotas(11,0.25,0.25);   reproducirNotas(12,1.75,0.25);   reproducirNotas(14,1.25,0.25);   reproducirNotas(12,0.25,0.25);   reproducirNotas(11,1.75,0.75);   reproducirNotas(7,0.25,0.25);   reproducirNotas(9,0.25,0.25);   reproducirNotas(11,0.25,0.25);   reproducirNotas(12,0.75,0.25);   reproducirNotas(12,0.75,0.25);   reproducirNotas(14,1.25,0.25);   reproducirNotas(12,0.25,0);   reproducirNotas(14,0.25,0);   reproducirNotas(11,1.75,0.75);   reproducirNotas(11,0.25,0.25);   reproducirNotas(9,0.25,0.25);   reproducirNotas(7,0.25,0.25);   reproducirNotas(9,1.75,0.25);   reproducirNotas(4,0.75,0.25);   reproducirNotas(11,0.75,0.25);   reproducirNotas(9,1.75,0.25);   reproducirNotas(7,0.75,0.25);   reproducirNotas(4,0.75,0.25);   reproducirNotas(6,1.75,0.25);   reproducirNotas(7,0.75,0.25);   reproducirNotas(11,0.75,0.25);   reproducirNotas(11,1.75,0.25);   reproducirNotas(9,1.75,0.25);   delay(250); //250 ms entre reproducciones}
Y bueno, os paso también una imagen de cómo realizar el conexionado para que el código os funcione a la primera. Aunque en este caso no sea de una complejidad elevada, pero bueno… Nunca está de más documentar un poco.

PalletTownBuzzer_bb

La verdad es que tengo que reconocer que me encanta formar parte de esta comunidad opensource de Arduino. Y me complace mucho compartir este código (y los otros muchos que espero publicar) con vosotros, porque igualmente agradezco mucho que exista gran cantidad de código abierto publicado en internet que a mí me puede servir de gran utilidad. Ojalá todas las compañías emplearan esta estrategia porque es la mejor forma, con diferencia, de crear conocimiento colectivo en esta red tan masiva que es internet.

Pero bueno, sermones a parte, me encanta haber compartido esto con vosotros por si os sirve de ayuda. Siento no haber comentado mucho el código en el post, pero el propio código cuenta con mis comentarios, que creo que son suficientes. De todas formas, si tuvierais alguna duda más sobre el tema me la podéis hacer llegar a wemento@gmail.com, a la cuenta de Twitter o escribirlo en este mismo post en un comentario. Intentaré responder con la mayor brevedad y precisión posibles.

Espero que os guste. Yo, personalmente, estoy encantado de comenzar esta nueva sección del blog.

Salu2.