Escritura en LCD

Continuamos con el “cursillo” de PIC en C con algo que he conseguido simular hoy. Tan simple como utilizar funciones predefinidas en una librería y tan importante como otra nueva salida al exterior de la información que maneja nuestro PIC. Se trata de escribir en una LCD un par de frases y un relojito. Algo tal que así aunque luego me ocuparé de mejorarlo:

lcd

 

Como no se ve muy bien, he conectado RB0 al pin Enable (6), RB1 a RS(4) y RB2 a RW(5).

La configuración de la alimentación de la LCD es la siguiente: alimentamos directamente VDD y ponemos VSS a tierra. VEE es el control del contraste de nuestra pantalla (que en simulación no funciona). Tomamos de VDD a un potenciómetro (normalmente de 10K Ohm) y conectamos el pin intermedio (el variable) a VEE. El otro extremo del potenciómetro va a tierra.

En programación: hay que declarar qué puerto usar antes de añadir la librería, en éste caso he utilizado la lcd.c que viene por defecto en CCS, aunque existen por internet versiones flex_lcd.c en las que defines los pines uno a uno. Allá vamos. También hay dos formas de controlar el LCD: por 8 o 4 bits. He utilizado la configuración de 8. La LCD es de 2×16. 16 caracteres y 2 líneas.

#include <16f84a.h>
#use delay(clock=4000000)
#fuses NOWDT,NOPROTECT
#define LCD_DATA_PORT getenv("SFR:PORTB") //Se define el puerto B como datos
#include <lcd.c> //incluimos la librería por defecto
int i; //variable que utilizaremos para contar segundos
void main(){
 lcd_init(); //Éste comando inicializa la LCD automáticamente
 delay_ms(20); //*1
 i=0; //inicializamos variable a 0
 while(1){
 lcd_putc("\fHola mundo"); //limpia la pantalla y escribe Hola mundo
 lcd_gotoxy(1,2); //baja a primer caracter segunda linea
 printf(lcd_putc,"By jmth %ds",i); //imprime By jmth y la variable entera i
 delay_ms(1000); //retardo de 1s
 i++; //subimos 1 a la var
 if(i>60) i=0; //si pasa de 1 min que vuelva a 0
 }
}
//*1: En usos reales se deberá hacer un pequeño delay entre cada instrucción
// debido a lo que tarda el controlador de LCD en procesar cada una

También cabe añadir las otras 2 funciones de putc o printf, \b, que retrocede un caracter, y \n, que pasa a la siguiente línea. Si no tenéis la librería lcd.c aquí la dejo:

///////////////////////////////////////////////////////////////////////////////
//// LCD.C ////
//// Driver for common LCD modules ////
//// ////
//// lcd_init() Must be called before any other function. ////
//// ////
//// lcd_putc(c) Will display c on the next position of the LCD. ////
//// The following have special meaning: ////
//// \f Clear display ////
//// \n Go to start of second line ////
//// \b Move back one position ////
//// ////
//// lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1) ////
//// ////
//// lcd_getc(x,y) Returns character at position x,y on LCD ////
//// ////
//// CONFIGURATION ////
//// The LCD can be configured in one of two ways: a.) port access or ////
//// b.) pin access. Port access requires the entire 7 bit interface ////
//// connected to one GPIO port, and the data bits (D4:D7 of the LCD) ////
//// connected to sequential pins on the GPIO port. Pin access ////
//// has no requirements, all 7 bits of the control interface can ////
//// can be connected to any GPIO using several ports. ////
//// ////
//// To use port access, #define LCD_DATA_PORT to the SFR location of ////
//// of the GPIO port that holds the interface, -AND- edit LCD_PIN_MAP ////
//// of this file to configure the pin order. If you are using a ////
//// baseline PIC (PCB), then LCD_OUTPUT_MAP and LCD_INPUT_MAP also must ////
//// be defined. ////
//// ////
//// Example of port access: ////
//// #define LCD_DATA_PORT getenv("SFR:PORTD") ////
//// ////
//// To use pin access, the following pins must be defined: ////
//// LCD_ENABLE_PIN ////
//// LCD_RS_PIN ////
//// LCD_RW_PIN ////
//// LCD_DATA0 ////
//// LCD_DATA1 ////
//// LCD_DATA2 ////
//// LCD_DATA3 ////
//// LCD_DATA4 ////
//// ////
//// Example of pin access: ////
//// #define LCD_ENABLE_PIN PIN_E0 ////
//// #define LCD_RS_PIN PIN_E1 ////
//// #define LCD_RW_PIN PIN_E2 ////
//// #define LCD_DATA0 PIN_D4 ////
//// #define LCD_DATA1 PIN_D5 ////
//// #define LCD_DATA2 PIN_D6 ////
//// #define LCD_DATA3 PIN_D7 ////
//// ////
///////////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2009 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
///////////////////////////////////////////////////////////////////////////
typedef struct 
{ // This structure is overlayed
 BOOLEAN enable; // on to an I/O port to gain
 BOOLEAN rs; // access to the LCD pins.
 BOOLEAN rw; // The bits are allocated from
 BOOLEAN unused; // low order up. ENABLE will
 int data : 4; // be LSB pin of that port.
 #if defined(__PCD__) // The port used will be LCD_DATA_PORT.
 int reserved: 8;
 #endif
} LCD_PIN_MAP;
#if defined(__PCB__)
 // these definitions only need to be modified for baseline PICs.
 // all other PICs use LCD_PIN_MAP or individual LCD_xxx pin definitions.
/* EN, RS, RW, UNUSED, DATA */
 const LCD_PIN_MAP LCD_OUTPUT_MAP = {0, 0, 0, 0, 0};
 const LCD_PIN_MAP LCD_INPUT_MAP = {0, 0, 0, 0, 0xF};
#endif
#ifndef LCD_ENABLE_PIN
 #define lcd_output_enable(x) lcdlat.enable=x
 #define lcd_enable_tris() lcdtris.enable=0
#else
 #define lcd_output_enable(x) output_bit(LCD_ENABLE_PIN, x)
 #define lcd_enable_tris() output_drive(LCD_ENABLE_PIN)
#endif
#ifndef LCD_RS_PIN
 #define lcd_output_rs(x) lcdlat.rs=x
 #define lcd_rs_tris() lcdtris.rs=0
#else
 #define lcd_output_rs(x) output_bit(LCD_RS_PIN, x)
 #define lcd_rs_tris() output_drive(LCD_RS_PIN)
#endif
#ifndef LCD_RW_PIN
 #define lcd_output_rw(x) lcdlat.rw=x
 #define lcd_rw_tris() lcdtris.rw=0
#else
 #define lcd_output_rw(x) output_bit(LCD_RW_PIN, x)
 #define lcd_rw_tris() output_drive(LCD_RW_PIN)
#endif
#ifndef LCD_DATA_PORT
 #if defined(__PCB__)
 #define LCD_DATA_PORT 0x06 //portb
 #define set_tris_lcd(x) set_tris_b(x)
 #elif defined(__PCM__)
 #define LCD_DATA_PORT getenv("SFR:PORTD") //portd
 #elif defined(__PCH__)
 #define LCD_DATA_PORT getenv("SFR:PORTD") //portd
 #elif defined(__PCD__)
 #define LCD_DATA_PORT getenv("SFR:PORTD") //portd
 #endif 
#endif
#if defined(__PCB__)
 LCD_PIN_MAP lcd, lcdlat;
 #byte lcd = LCD_DATA_PORT
 #byte lcdlat = LCD_DATA_PORT
#elif defined(__PCM__)
 LCD_PIN_MAP lcd, lcdlat, lcdtris;
 #byte lcd = LCD_DATA_PORT
 #byte lcdlat = LCD_DATA_PORT
 #byte lcdtris = LCD_DATA_PORT+0x80
#elif defined(__PCH__)
 LCD_PIN_MAP lcd, lcdlat, lcdtris;
 #byte lcd = LCD_DATA_PORT
 #byte lcdlat = LCD_DATA_PORT+9
 #byte lcdtris = LCD_DATA_PORT+0x12
#elif defined(__PCD__)
 LCD_PIN_MAP lcd, lcdlat, lcdtris;
 #word lcd = LCD_DATA_PORT
 #word lcdlat = LCD_DATA_PORT+2
 #word lcdtris = LCD_DATA_PORT-0x02
#endif
#ifndef LCD_TYPE
 #define LCD_TYPE 2 // 0=5x7, 1=5x10, 2=2 lines
#endif
#ifndef LCD_LINE_TWO
 #define LCD_LINE_TWO 0x40 // LCD RAM address for the second line
#endif
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
 // These bytes need to be sent to the LCD
 // to start it up.

BYTE lcd_read_nibble(void);
BYTE lcd_read_byte(void)
{
 BYTE low,high;
#if defined(__PCB__)
 set_tris_lcd(LCD_INPUT_MAP);
 #else
 #if (defined(LCD_DATA0) && defined(LCD_DATA1) && defined(LCD_DATA2) && defined(LCD_DATA3))
 output_float(LCD_DATA0);
 output_float(LCD_DATA1);
 output_float(LCD_DATA2);
 output_float(LCD_DATA3);
 #else
 lcdtris.data = 0xF;
 #endif
 #endif
 
 lcd_output_rw(1);
 delay_cycles(1);
 lcd_output_enable(1);
 delay_cycles(1);
 high = lcd_read_nibble();
 
 lcd_output_enable(0);
 delay_cycles(1);
 lcd_output_enable(1);
 delay_us(1);
 low = lcd_read_nibble();
 
 lcd_output_enable(0);
#if defined(__PCB__)
 set_tris_lcd(LCD_INPUT_MAP);
 #else
 #if (defined(LCD_DATA0) && defined(LCD_DATA1) && defined(LCD_DATA2) && defined(LCD_DATA3))
 output_drive(LCD_DATA0);
 output_drive(LCD_DATA1);
 output_drive(LCD_DATA2);
 output_drive(LCD_DATA3);
 #else
 lcdtris.data = 0x0;
 #endif
 #endif
return( (high<<4) | low);
}
BYTE lcd_read_nibble(void)
{
 #if (defined(LCD_DATA0) && defined(LCD_DATA1) && defined(LCD_DATA2) && defined(LCD_DATA3))
 BYTE n = 0x00;
/* Read the data port */
 n |= input(LCD_DATA0);
 n |= input(LCD_DATA1) << 1;
 n |= input(LCD_DATA2) << 2;
 n |= input(LCD_DATA3) << 3;
 
 return(n);
 #else
 return(lcd.data);
 #endif
}
void lcd_send_nibble(BYTE n)
{
 #if (defined(LCD_DATA0) && defined(LCD_DATA1) && defined(LCD_DATA2) && defined(LCD_DATA3))
 /* Write to the data port */
 output_bit(LCD_DATA0, BIT_TEST(n, 0));
 output_bit(LCD_DATA1, BIT_TEST(n, 1));
 output_bit(LCD_DATA2, BIT_TEST(n, 2));
 output_bit(LCD_DATA3, BIT_TEST(n, 3));
 #else 
 lcdlat.data = n;
 #endif
 
 delay_cycles(1);
 lcd_output_enable(1);
 delay_us(2);
 lcd_output_enable(0);
}
void lcd_send_byte(BYTE address, BYTE n)
{
 lcd_output_rs(0);
 while ( bit_test(lcd_read_byte(),7) ) ;
 lcd_output_rs(address);
 delay_cycles(1);
 lcd_output_rw(0);
 delay_cycles(1);
 lcd_output_enable(0);
 lcd_send_nibble(n >> 4);
 lcd_send_nibble(n & 0xf);
}
void lcd_init(void) 
{
 BYTE i;
#if defined(__PCB__)
 set_tris_lcd(LCD_OUTPUT_MAP);
 #else
 #if (defined(LCD_DATA0) && defined(LCD_DATA1) && defined(LCD_DATA2) && defined(LCD_DATA3))
 output_drive(LCD_DATA0);
 output_drive(LCD_DATA1);
 output_drive(LCD_DATA2);
 output_drive(LCD_DATA3);
 #else
 lcdtris.data = 0x0;
 #endif
 lcd_enable_tris();
 lcd_rs_tris();
 lcd_rw_tris();
 #endif
lcd_output_rs(0);
 lcd_output_rw(0);
 lcd_output_enable(0);
 
 delay_ms(15);
 for(i=1;i<=3;++i)
 {
 lcd_send_nibble(3);
 delay_ms(5);
 }
 
 lcd_send_nibble(2);
 for(i=0;i<=3;++i)
 lcd_send_byte(0,LCD_INIT_STRING[i]);
}
void lcd_gotoxy(BYTE x, BYTE y)
{
 BYTE address;
if(y!=1)
 address=LCD_LINE_TWO;
 else
 address=0;
 
 address+=x-1;
 lcd_send_byte(0,0x80|address);
}
void lcd_putc(char c)
{
 switch (c)
 {
 case '\f' : lcd_send_byte(0,1);
 delay_ms(2);
 break;
 
 case '\n' : lcd_gotoxy(1,2); break;
 
 case '\b' : lcd_send_byte(0,0x10); break;
 
 default : lcd_send_byte(1,c); break;
 }
}
 
char lcd_getc(BYTE x, BYTE y)
{
 char value;
lcd_gotoxy(x,y);
 while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
 lcd_output_rs(1);
 value = lcd_read_byte();
 lcd_output_rs(0);
 
 return(value);
}

Entrada digital

El otro día nos iniciamos en la programación en C de un PIC, para ser concretos en la salida digital de datos, haciendo rotar y parpadear un bit en el puerto B.

Hoy os voy a enseñar a darle juego a vuestro PIC controlando las entradas. Utilizaremos el PIC16F84A (con ésto ya tendremos entre un 30% y un 50% de las utilidades de éste pequeño, no da más de sí) y el puerto A como entrada de datos digitales, asignando a TRISA el valor 0xFF, es decir, 8 bytes en estado alto binario, aunque éste dispositivo sólo tiene 5 pines. El siguiente paso será comprobar si el pin que nos interesa está en 1 o 0 mediante un if y entonces, realizar la acción que nos interesa. Éste programa en concreto enciende el puerto B cuando detecte el pin A0 en estado alto y después bajo y lo apagará cuando vuelva a ocurrir.

Allá va el programa:

#include <16f84A.h>
#FUSES NOWDT,RC,NOPROTECT // *1
#use delay(clock=13300)
#byte trisa=getenv("SFR:TRISA") //asignamos bytes de puertos a sus nombres
#byte trisb=getenv("SFR:TRISB")
#byte porta=0x05
#byte portb=0x06
#bit b0=0x06.0 //Le ponemos nombre a unos cuantos pines
#bit b1=0x06.1
#bit b2=0x06.2
#bit a0=0x05.0 //Éste será el de entrada en el puerto A
int led; //Utilizaré ésta variable como indicador de estado
void main(){
 trisa=0xff; //configuramos el puerto A como entrada
 trisb=0; //y el puerto B como salida
 porta=0; //limpiamos los puertos
 portb=0;
 led=0; //inicializamos la variable a 0
 while(1){
 if(a0==1){ //Si el PIC detecta que el pin está en estado alto
 while(a0==1) delay_ms(5); // *2
 if(led==0){ //Si la variable indicadora es 0
 portb=0xff; //enciende el puerto B
 led=1; //Pone la variable a 1
 }
 else if(led==1){ // PERO si la variable está en 1
 portb=0x00; //apaga el puerto B
 led=0; //Pone la variable a 0
 } //Vuelve a esperar a que el pin esté en estado alto
 }
 }
}
// *1: Como he utilizado el programa para probar el programador de PIC
// he utilizado RC (oscilador resistencia-condensador) y NOPROTECT para poder
// borrar el código de la memoria y probar más programas
//
// 2*: Ésto es un truco que se usa cuando puede haber un pequeño "rebote" que
// haga parecer que han habido 2 pulsos cuando solo hemos dado 1. Cuando pulsamos
// un botón, tardamos algo en soltarlo, lo que haría al programa dar vueltas y 
// descontrolarse
//
// Como veis simplemente se basa en testear en qué estado está el pin y entonces
// llevar a cabo la acción. También podríamos usar las otras entradas para
// copiar 4 bits y llevarlos al puerto B, como un buffer

PIC and EEPROM programmer

Testeado y funcionando con PIC16F84A, PIC16F877A

Programado con PICPgm

Éste finde (si contamos el jueves como finde), he estado haciendo éste “pequeño” proyecto para ver si paso de la simulación al manejo de PICs a mano y en casa. Quizás el curso de arduino haya sido un incentivo porque, sin lugar a dudas, uno empieza a pensar cuántas cosas se pueden hacer y se lia.

Empezaré por el 16F84A, tampoco es un avance muy fuerte…

Bien, al caso, he estado haciendo éste juguetito que extraje de ésta web que a su vez salió de una web inglesa que figura al final…

http://www.elotrolado.net/hilo_programador-de-pics-12-16-18-y-eeproms-24cxx_1505958

Tiene una lista ENORME de PICs y EEPROMs que puede programar. Es un programador tipo JDM, debe ser muy bueno, aún lo tengo por probar porque me falta el cable de puerto serie. Se utiliza con los programas ICPROG y WinPIC PICPgm (que vale para W7, es menos pesado y más independiente). Si alguien quiere hacerlo y no tiene puerto serie, puede comprar un adaptador de USB a serie, pero se advierte que el funcionamiento puede no ser correcto.

Mi objetivo sería programar PICs para jugar y practicar y por último hacer un programador USB cuya interface sea otro PIC.

Comentar que en la web está el archivo descargable con los pdf del bottom, top y jumpers de la placa, y un esquemático. Cuando lo vayáis a imprimir, el bottom ya está con efecto espejo, imprimir y aplicar, pero el top, que es la capa de componentes, no.

Hace falta tener cierta experiencia con el taladro y el soldador porque es complicado hacer los agujeros rectos y que luego no se junten varios pines. Yo lo he conseguido por los pelos.

A mí no me ha quedado tan bonito porque no he cortado la placa pero allá va:

Realimentación negativa, amplificador

Es una forma de realimentar un Amplificador Operacional para que trabaje en un régimen lineal más extenso.

En los AO ideales, con realimentación negativa (por la entrada inversora), la tensión en las entradas inversora y no inversora se igualan.

El resultado de ésto es que la salida se puede expresar en función de la entrada como V- = BVs

El circuito básico para la realimentación negativa es éste:

Aquí se pueden ver las corrientes de cada rama. Obviemos la carga a la salida.

Desarrollando las fórmulas de teoría de circuitos:

Vs=Av*(Ve-B*Vs)

Vs+Av*B*Vs=Av*Ve

Vs*(Av*B+1)=Av*Ve

Vs/Ve=Av/(Av*B+1)

Vs/Ve=1/B=(R1+R2)/R1

Gv=1+(R2/R1)

Vs=tensión de salida

Ve=tensión de entrada

Aquí tenemos el amplificador no inversor con ganancias mayores que 1.

En las resistencias se utilizan valores del orden de kilo ohmios para evitar que se pierda corriente y que el AO se sature, ya que tiene una capacidad limitada.

Ahora veamos el amplificador inversor.

Éste funciona poniendo a masa la entrada no inversora y con Ve a R1. Aplicaremos en ésta ocasión que las tensiones en las dos entradas son iguales (serán 0 por estar la no inversora a masa), que las corrientes de entrada son nulas, y las leyes de Kirchoff. Así pues:

(Ve-V-)/Rin=(V- -Vs)/Rf

Ésto es porque tenemos una corriente I1 que atraviesa Rin y otra I2 que circula por Rf, que son iguales. La I1 es igual a la tensión de entrada menos la que cae por la entrada inversora, dividido por la resistencia “Rin”, y I2 es la tensión que cae por la entrada inversora menos la de salida, dividido por la resistencia “Rf”. Ahora desarrollemos más:

V-=0, así que sencillamente…

Vs=-(R2/R1)Ve

La función de transferencia en éste caso es inversa a la que vimos en el anterior post, lo que indica que cualquier entrada la amplifica y la vuelve negativa.

Vaya mente debía tener el que inventó el cacharro éste ¿eh? Pues aún queda…

Un pequeño anexo: cuando ponemos una resistencia de carga, la corriente que atraviesa Rf se bifurca, de forma que la corriente que pasa por la carga puede saturar el AO, por no poder éste otorgar suficiente corriente para toda la carga y la demanda que tiene.

AO: Generalidades, bucle abierto

Como en las próximas semanas voy a trabajar el amplificador operacional, es necesario una introducción para conocer qué es ése pequeño que tan complejo ha sido siempre de entender.

Bien, el amplificador operacional es un componente activo, que necesita un aporte externo de energía para funcionar. Suelen estar compuestos de materiales semiconductores. Su símbolo es éste:

Como vemos tiene 2 entradas: inversora y no inversora, 2 patillas de alimentación, para alimentación simétrica, y una salida. Los pines del integrado donde se encuentra cada una de éstas viene definido por el fabricante, el ejemplo más común es el 741:

La salida, definida mediante la función de transferencia, cuando trabaja en bucle abierto es:

Vs=Av*(V+ – V-)

Donde Av es la ganancia diferencial del amplificador operacional. La función de transferencia que vemos en ésta tabla es la de un AO ideal: no existe una región lineal entre el punto más alto o el más bajo porque la ganancia es infinita. Cuando la diferencia entre entradas no inversora e inversora es positiva, se satura positivamente, y cuando es negativa, se satura negativamente. Normalmente la tensión de saturación será siempre algo menor a la tensión de alimentación. En éste modo de operación se suele utilizar como comparador de tensiones.

Otra característica importante de los AO es su altísima impedancia de entrada, por lo que se puede considerar que la entrada de corriente es nula. A su vez tienen muy baja impedancia de salida aunque su corriente sea bastante limitada.

Aunque el ancho de banda varía según su utilidad, los que se usan a nivel de estudiante, sonido y aplicaciones no profesionales trabajan entre los 0 y 20 kHz aproximadamente.

Ahora veamos la función de transferencia de un AO real:

Aquí se ve la región lineal, cuyo rango normalmente es bastante más pequeño, del orden de microvoltios, antes de saturar. Si por ejemplo tenemos un AO alimentado a +-15V y con una Av de 10^6 v/v, veremos que satura positivamente a partir de los 15 microvoltios, es decir, en total tiene una región lineal de 30 microvoltios.

Ésto es todo lo que hay que saber para iniciarse, si queda algún cabo suelto o cualquier duda podéis preguntar mediante un comentario.

También tengo que comentar que el curso nos lo están dando basado en el libro “Teoría de circuitos y dispositivos electrónicos” de Robert L. Boylestad, décima edición, que podéis encontrar en freelibros.com, entre muchos otros.

Starter Kit de Arduino

Como vamos a hacer un cursillo de introducción a lo “básico” de Arduino, necesitábamos un kit o por lo menos tener las piezas en casa. Los organizadores pedían 25 euros por el cursillo pero por unos 35 más te traen éste:

http://www.aliexpress.com/snapshot/260781748.html

Ahora mismo su precio se sitúa por los 39’90 US$ (aprox. 30€) por pack, envío gratis como suele ocurrir con éstas páginas chinorris que, si bien el producto es bueno, el tiempo de llegada puede ser desesperante (20 a 40 días). Incluye:

  • Placa Arduino Uno Rev. 3
  • Mini placa de pruebas con base
  • Placa de pruebas de 830 puntos
  • Caja para componentes
  • 15 LEDs rojos, amarillos y verdes (5 de cada)
  • 2 Buzzers (uno pasivo)
  • 4 interruptores
  • 2 dígitos LED
  • 2 interruptores de vuelco “tilt switch”
  • 3 fotoresistores
  • 1 potenciometro
  • 1 sensor de llamas
  • 1 receptor infrarrojo
  • Resistencias de 220, 1K y 10K (5 de cada)
  • Sensor de temperatura LM35
  • 1 cable USB
  • 30 cables jumper
  • 1 porta pilas de 9V
  • 1 control remoto infrarrojo
  • Pantalla LCD 1602
  • 1 servomotor 9G
  • 1 motor paso a paso 5V + placa driver ULN2003
  • 1 74HC595 (shift register, para manejar matriz de LEDs)
  • 1 Matriz de LEDs 8×8

Como se ve, vale la pena y esperamos que el producto sea de gran calidad como ha llegado en otras ocasiones. Ellos se ocuparán de testearlo antes de dar el cursillo, que empezará, si no hay retrasos en el envío, el 28 de septiembre.

En todo caso para más info y mis agradecimientos a MakersVLC.

Habrán más ediciones si ésta resulta buena.