En varios artículos sobre Arduino encontré referencias a la velocidad en ciclos de CPU de algunas instrucciones y me preguntaba si ese seria un calculo puramente teórico y como podría hacer para reproducir (si es posible) dichos valores.
Se me ocurrió un método que pongo a consideración de Uds para un debate al respecto.
La idea es dejar operar al Arduino durante un tiempo fijo (digamos 5 segundos) y contar el numero de veces que se ejecuta la instruccion. Luego comparar el numero de vueltas. Logicamente numero mas altos corresponderían a instrucciones que se ejecutan mas rápido.
El boceto básico es este:
int n;
void setup(){
Serial.begin(115200);
pinMode(13, OUTPUT);
}
void loop(){
digitaWrite(13, !digitalRead(13)); //Instrucción a probar
n++;
if (millis() > 5000){
Serial.println(n); //598 124
while (1);
}
}
Para mis pruebas yo use SimulIDE, pero supongo que si uso físicamente un Arduino los resultados deberían ser proporcionales.
Mi segunda prueba fue:
int n;
bool x;
void setup(){
Serial.begin(115200);
pinMode(13, OUTPUT);
}
void loop(){
digitaWrite(13, x); //Instrucción a probar
x = !x;
n++;
if (millis() > 5000){
Serial.println(n); //787 629
while (1);
}
}
Mi tercera prueba fue:
int n;
void setup(){
Serial.begin(115200);
pinMode(13, OUTPUT);
}
void loop(){
PORTB = PORTB ^ 32; //Instrucción a probar
n++;
if (millis() > 5000){
Serial.println(n); //1446 372
while (1);
}
}
Imagino que se pueden hacer muchas mas pruebas, pero en principio este post es para discutir la validez del método.
digitaWrite(13, !digitalRead(13)); //Instrucción a probar
debe ser
digitalWrite(13, !digitalRead(13)); //Instrucción a probar
Pero al correrlo me da un número negativo, por lo que cambie int n; por
unsigned long n;
Resultado
598014
corrido en un NANO Atmega328
Lo que coincide con tu código.
Bien, tengo una alternativa aunque no mide loops sino tiempos. Me interesa saber el tiempo que le lleva a una macro instrucción realizar su tarea.
Primero lo hice con una sola instrucción y me daba 8 us y luego se me ocurrió repetir 10 veces la instrucción requerida para minimizar la influcencia de la lectura del tiempo.
#define LOOPCOUNT 10000
void setup(){
Serial.begin(115200);
pinMode(13, OUTPUT);
}
void loop(){
unsigned long micros1,micros2,sum;
sum = 0;
for(uint16_t cnt=0; cnt<LOOPCOUNT; cnt++) {
micros1 = micros();
digitalWrite(13, !digitalRead(13)); //Instrucción a probar
digitalWrite(13, !digitalRead(13)); //Instrucción a probar
digitalWrite(13, !digitalRead(13)); //Instrucción a probar
digitalWrite(13, !digitalRead(13)); //Instrucción a probar
digitalWrite(13, !digitalRead(13)); //Instrucción a probar
digitalWrite(13, !digitalRead(13)); //Instrucción a probar
digitalWrite(13, !digitalRead(13)); //Instrucción a probar
digitalWrite(13, !digitalRead(13)); //Instrucción a probar
digitalWrite(13, !digitalRead(13)); //Instrucción a probar
digitalWrite(13, !digitalRead(13)); //Instrucción a probar
micros2 = micros();
sum += micros2-micros1;
}
Serial.print("digitalWrite: ");
Serial.print((float) sum/LOOPCOUNT/10.0);
Serial.print(" us\n");
}
Aunque en términos teóricos podría ser un buen ejercicio para ver "cual es la mejor", el poder comparar varias placas respecto al manejo de un set de instrucciones, posibilitaría el contar con una base de datos comparativa entre varias placas compatibles en el entorno arduino. Esto podría orientar al usuario, respecto a cual elegir para el diseño de algún proyecto.
Sería un complemento a términos de búsqueda como numero de pines, tamaño, forma física, etc.
PD: hoy quedé muy sorprendido por las dimensiones del teensy 4, llegó un ejemplar de estos a la mesa de experimentos y creo que hay una gama mas completa para intentar alguno que otro test