Electrónica y Programación en Personal
«Si no se soluciona con un script en Python entonces no es viable»

por Yeison Cardona el 05 de octubre de 2012 a las 02:21 UTC
Uno de los «problemas» que se tiene al trabajar con tarjetas de desarrollo (todas) es que están orientadas pensando en el rápido desarrollo (casi en un paradigma funcional, en términos de programación) sacrificando un poco el tiempo de ejecución, pero esto no debería representar mucho problema si saben algunas cosas, las cuales podemos aprender leyendo las bibliotecas de Pinguino.

Centrémonos en dos funciones muy usadas, digitalRead y analogRead:

digitalRead
Vamos a suponer que se está usando Pinguino 18F2550, al explorar el archivo digitalw.c (p8/pinguino/include/core) podemos identificar que el método usado para leer el pin, así:

(PORTB &amp; 1<<0)
para el pin 0
(PORTB &amp; 1<<1) para el pin 1
(PORTB &amp; 1<<2)
para el pin 2
(PORTB &amp; 1<<3)
para el pin 3
(PORTB &amp; 1<<4)
para el pin 4
(PORTB &amp; 1<<5)
para el pin 5
(PORTB &amp; 1<<6)
para el pin 6
(PORTB &amp; 1<<7)
para el pin 7

(PORTC &amp; 1<<6) para el pin 8
(PORTC &amp; 1<<7)
para el pin 9
(PORTC &amp; 1<<0)
para el pin 10
(PORTC &amp; 1<<1)
para el pin 11
(PORTC &amp; 1<<2)
para el pin 12

(PORTA &amp; 1<<0) para el pin 13
(PORTA &amp; 1<<1)
para el pin 14
(PORTA &amp; 1<<2)
para el pin 15
(PORTA &amp; 1<<3)
para el pin 16
(PORTA &amp; 1<<5)
para el pin 17

(PORTA &amp; 1<<4) para el pin 18 (RunLED)

Ahora hagamos una comparación para medir el tiempo acumulado de cada respuesta, para ello podemos usar un simple código que haga 100.000 iteraciones con cada comando y ver que resulta
#define READ_0 (PORTB &amp; 1<<0)

int t0,t1,t2a,t2b;
unsigned int i=0;

void setup() {
    pinMode(0,INPUT);
    }

void loop() {
    //Primer método, directo
    t0=millis();
    for (i=0 ;i<50000 ;i++) READ_0;
    for (i=0 ;i<50000 ;i++) READ_0;
    t1=millis();
    t2a=t1-t0;

    //Segundo método, por defecto Pinguino
    t0=millis();
    for (i=0 ;i<50000 ;i++) digitalRead(0);
    for (i=0 ;i<50000 ;i++) digitalRead(0);
    t1=millis();
    t2b=t1-t0;

    CDC.printf("100.000 datos en %dms-%dms",t2a,t2b);
    }
Y obtendremos algo como:
Pinguino: Pinguino 2550
Proc: 18f2550
Archivo: /home/yeison/Desktop/str/digitalRead.pde
Compilacion completada
code size: 13902 / 24575 bytes (56% used)
0.757531881332 segundos (Tiempo de proceso)
Pinguino found
Bootloader v2.12
Writing ...
digitalRead.hex successfully uploaded
   Conectado: /dev/ttyACM0
   100.000 datos en 42ms-509ms
   100.000 datos en 43ms-508ms
   100.000 datos en 43ms-508ms
   100.000 datos en 42ms-508ms
   100.000 datos en 42ms-508ms
   100.000 datos en 43ms-508ms
   100.000 datos en 42ms-508ms
Pero ¿qué quiere decir éstos datos?, bueno, nos dicen que las 100 mil lecturas las hace con el primer método en 43 milisegundos y usando el comando por defecto de Pinguino nos tardamos 508 milisegundos, es decir, hacemos la misma cantidad de lecturas en tan sólo menos del 9% del tiempo que se logra con digitalRead, podemos aumentar en 10 veces la velocidad de muestreo. analogRead Y lo mismo pasa con analogRead, haciendo el mismo análisis anterior (les dejo el análisis del código a ustedes), con el siguiente código:
#define INIT_ANALOG ADCON1=0x0A;ADCON2=0xBD;
#define READ_13(result) (result)=0;ADCON0=0;ADCON0bits.ADON=1;ADCON0bits.GO=1;while (ADCON0bits.GO);(result)=ADRESH<<8;(result)+=ADRESL;ADCON0bits.ADON=0;
    
u16 valor;

int t0,t1,t2a,t2b;

u32 i=0;

void setup() {
    INIT_ANALOG;
    pinMode(13,INPUT);
    }

void loop() {
    //Primer método, directo
    t0=millis();
    for (i=0 ;i<100000 ;i++) READ_13(valor);
    t1=millis();
    t2a=t1-t0;
    
    //Segundo método, por defecto Pinguino
    t0=millis();
    for (i=0 ;i<100000 ;i++) analogRead(13);
    t1=millis();
    t2b=t1-t0;
    
    CDC.printf("Retardo: %d-%d",t2a,t2b);

    }
para obtener:
Pinguino: Pinguino 2550
Proc: 18f2550
Archivo: /home/yeison/Desktop/str/analogread.pde
Compilacion completada
code size: 14222 / 24575 bytes (57% used)
0.801403045654 segundos (Tiempo de proceso)
Pinguino found
Bootloader v2.12
Writing ...
analogread.hex successfully uploaded
   Conectado: /dev/ttyACM1
   100.000 datos en 54ms-1248ms
   100.000 datos en 55ms-1247ms
   100.000 datos en 54ms-1247ms
   100.000 datos en 55ms-1247ms
   100.000 datos en 55ms-1246ms
   100.000 datos en 55ms-1247ms
   100.000 datos en 55ms-1247ms
   100.000 datos en 54ms-1247ms
En éste caso tenemos el peor escenario con el primer método nos estamos tardando en hacer 100 mil lecturas análogas en sólo 55 milisegundos, pero cuando usamos analogRead nos tardamos hasta 1.2 segundos, estamos multiplicando por 20 la cantidad de lecturas que podemos hacer por unidad de tiempo.

Conclusión
Siempre podemos optimizar nuestro código para que responda mas rápido, si así lo necesita nuestra aplicación, ésto puede resultar muy útil en STR (sistemas de tiempo real), pero si queremos optimizar aún más, siempre podemos usar assembler, incluso dentro de nuestro código Pinguino, pero esa será otra entrada.

También podría interesarte:

Comentarios:
JealGoVa dijo:
5 de octubre de 2012 10:01
Buen dato!......Checare algunas otras...
Responder a JealGoVa
Respuesta de Yeison Cardona:
5 de octubre de 2012 10:21
que bien, si obtienes mas datos o datos diferentes, los compartes ;)
Responder a Yeison Cardona
Jose Luis dijo:
15 de octubre de 2012 07:54
Interesante
¿Como se hace lectura analogica del resto de pines analog?
Responder a Jose Luis
guillenoguera.com.ar dijo:
21 de octubre de 2012 19:53
muy bueno el post, más allá del manejo de tiempos que obviamente es importante cuando de manejo de procesos se trata aún cuando estamos prototipando una solución; lo bueno es que vamos desentrañando al pinguino! :-)
Responder a guillenoguera.com.ar
marlon dijo:
oct. 8, 2013, 5:56 p.m.
buen post, en la ultima parte hablas de usar assembler junto con el codigo del pinguino, quisiera una ayuda de como indicarle al compilador que se esta usando codigo en assembler en tal linea, esto es con el objectivo de poder usar el modulo de generacion de voltaje de referencia. porque este modulo no esta implementado en en ninguna libreria
Responder a marlon
Añadir un nuevo comentario:
Si desean una respuesta para su comentario sólo deben agregarme en G+ y hacer una mención a Yeison Cardona, así les podré responder lo antes posible.