Mi sono messo a giocare coi tempi

e per provare a vedere cosa esce da un argomento che ci ha un po' interessato nello spamm bar
https://forum.arduino.cc/t/italiano-lo-spamm-bar-part-2/847652/5441?u=standardoil

Premesso che l'idea stessa è un po' "strana", visto che misura con micros() (che dipende dal clock del processore) la velocità di un programma che a sua volta dipende dallo stesso clock
sarebbe come cercare di capire se un orologio va avanti leggendo l'ora esatta dallo stesso orologio

ma tant'è, le prove servono proprio per provare

ecco il programma base, leggermente modificato:

#define TEST_PIN 10

void setup()
{
   Serial.begin(9600);
   pinMode(TEST_PIN, OUTPUT);
   unsigned long timeBegin = micros();

   for (int i = 0; i < 500; i++)
   {
      digitalWrite(TEST_PIN, HIGH);
      digitalWrite(TEST_PIN, LOW);
   }

   unsigned long timeEnd = micros();
   unsigned long duration = timeEnd - timeBegin;
   Serial.println(duration);
}

void loop()
{
}

il valore ottenuto?
4528
in decimi di milionesimi di secondo

adesso cominciamo le prove vere...

cominciamo ad usare variabili come argomenti della digitalwrite...

#define TEST_PIN 10

int I = 1;
int O = 0;

void setup()
{
   Serial.begin(9600);
   pinMode(TEST_PIN, OUTPUT);
   unsigned long timeBegin = micros();

   for (int i = 0; i < 500; i++)
   {
      digitalWrite(TEST_PIN, I);
      digitalWrite(TEST_PIN, O);
   }

   unsigned long timeEnd = micros();
   unsigned long duration = timeEnd - timeBegin;
   Serial.println(duration);
}

void loop()
{
}

risultato?

ancora 4528, sembra che usare una variabile intera al posto di una costante letterale sia la stessa cosa

ecco che arriva la sorpresa:

#define TEST_PIN 10

volatile int I = 1;
volatile int O = 0;

void setup()
{
   Serial.begin(9600);
   pinMode(TEST_PIN, OUTPUT);
   unsigned long timeBegin = micros();

   for (int i = 0; i < 500; i++)
   {
      digitalWrite(TEST_PIN, I);
      digitalWrite(TEST_PIN, O);
   }

   unsigned long timeEnd = micros();
   unsigned long duration = timeEnd - timeBegin;
   Serial.println(duration);
}

void loop()
{
}

4716

la parola chiave "volatile" obbliga a lettura in ram della variabile, e "magia" adesso si "paga" il tempo di accesso alla RAM
4716-4528 fa 188 microsecondi
per 1000 letture
meno di 2 decimi di microsecondo a lettura
grosso modo (ma non è preciso) sembra tre cicli di clock a lettura

usando variabili byte abbiamo invece 4592
un ciclo di clock a lettura...

interessante
anche se bisognerebbe sapere se cambia anche il tempo di esecuzione esplicita della digitalwrite cambiando il tipo del suo argomento...

Sempre dal sito linkato, ma questa volta questo tutorial: https://roboticsbackend.com/arduino-fast-digitalwrite/

In questo caso pare faccia anche una media, dovrebbe essere interessante

ecco cosa succede con char

volatile char I = 1;
volatile char O = 0;

4592
"quindi char o byte per me pari sono
a quant’altre d’intorno mi vedo;
del mio core l’impero non cedo"

e proviamo a capire quanto influenzano la for e i test e il jump

#define TEST_PIN 10


void setup()
{
   Serial.begin(9600);
   pinMode(TEST_PIN, OUTPUT);
   unsigned long timeBegin = micros();

   for (int i = 0; i < 500; i++)
   {
      digitalWrite(TEST_PIN, HIGH);
      digitalWrite(TEST_PIN, LOW);
      digitalWrite(TEST_PIN, HIGH);
      digitalWrite(TEST_PIN, LOW);
   }

   unsigned long timeEnd = micros();
   unsigned long duration = timeEnd - timeBegin;
   Serial.println(duration/2);
}

void loop()
{
}

risultato 4464 (già diviso per due, fa il doppio delle scritture, ma non il doppio delle iterazioni

quindi
1000 scritture + 500 iterazioni fanno 4528
1000 scritture + 250 iterazioni fanno 4464
quindi 250 iterazioni fanno 4528-4464
64 microsecondi per 16 cicli al microsecondo, diviso 250
un'iterazione dura 4 cicli di clock
un'iterazione fa una somma (i++), un test (i<500) e un jump

proviamo ad aggiungere somme...

volevo provare a mettere volatile I
e per cominciare la ho spostata globale...

#define TEST_PIN 10
int i;

void setup()
{
   Serial.begin(9600);
   pinMode(TEST_PIN, OUTPUT);
   unsigned long timeBegin = micros();

   for (i = 0; i < 500; i++)
   {
      digitalWrite(TEST_PIN, HIGH);
      digitalWrite(TEST_PIN, LOW);
   }

   unsigned long timeEnd = micros();
   unsigned long duration = timeEnd - timeBegin;
   Serial.println(duration);
}

void loop()
{
}

4904

al solo usare una variabile globale per le iterazioni perdiamo circa 0.75 microsecondi a ciclo, ovvero 3 cicli di clock
sembra come un accesso in memoria in più

#define TEST_PIN 10
int i;

void setup()
{
  
   Serial.begin(9600);

   pinMode(TEST_PIN, OUTPUT);
   unsigned long timeBegin = micros();

   for (i = 0; i < 250; i++)
   {
      digitalWrite(TEST_PIN, HIGH);
      digitalWrite(TEST_PIN, LOW);
   }

   unsigned long timeEnd = micros();
   unsigned long duration = timeEnd - timeBegin;
   Serial.println(duration);
}

void loop()
{
}

2440, abbastanza credibile, c'è un'imprecisione ma ci può stare

perché solo 250?
per usare byte come tipo

#define TEST_PIN 10
byte i;

void setup()
{
  
   Serial.begin(9600);

   pinMode(TEST_PIN, OUTPUT);
   unsigned long timeBegin = micros();

   for (i = 0; i < 250; i++)
   {
      digitalWrite(TEST_PIN, HIGH);
      digitalWrite(TEST_PIN, LOW);
   }

   unsigned long timeEnd = micros();
   unsigned long duration = timeEnd - timeBegin;
   Serial.println(duration);
}

void loop()
{
}

2344
ovvero 96 microsecondi in meno
ancora circa sei cicli di clock a iterazione

Interessante quest'ultimo programma

#define TEST_PIN 10
byte i;

void setup()
{
  
   Serial.begin(9600);

   pinMode(TEST_PIN, OUTPUT);
   unsigned long timeBegin = micros();

   for (i = 0; i < 250; i++)
   {
      digitalWrite(TEST_PIN, HIGH);
      digitalWrite(TEST_PIN, LOW); 
      digitalWrite(TEST_PIN, HIGH);
      digitalWrite(TEST_PIN, LOW);
      i++;
   }

   unsigned long timeEnd = micros();
   unsigned long duration = timeEnd - timeBegin;
   Serial.println(duration);
}

void loop()
{
}

2276

esegue 250 digitalwrite + 250 somme + 125 test e jump per 2276 microsecondi
il precedente
esegue 250 digitalwrite + 250 somme + 250 test e jump per 2344 microsecondi
ovvero 125 test e jump durano 68 microsecondi
circa nove cicli di clock per ogni test e jump

adesso credo che possiamo valutare la durata della singola digitalwrite e fare anche un minimo di previsione di cosa succede cambiando tipo dati

ah.. BTW

#define TEST_PIN 10
byte i;

volatile const int  I = 1;
volatile const int O = 0;



void setup()
{
   Serial.begin(9600);
   pinMode(TEST_PIN, OUTPUT);
   unsigned long timeBegin = micros();

   for (i = 0; i < 250; i++)
   {
      digitalWrite(TEST_PIN, I);
      digitalWrite(TEST_PIN, O);
      digitalWrite(TEST_PIN, I);
      digitalWrite(TEST_PIN, O);
      i++;
   }

   unsigned long timeEnd = micros();
   unsigned long duration = timeEnd - timeBegin;
   Serial.println(duration);
}

void loop()
{
}

fa 2368
NON dite più che è meglio usare le const invece delle macro
questo lo smentisce in maniera irrefutabile

e per oggi buona notte

Metti PORT! :slight_smile:
Naturalmente puoi ancora usare una variabile per esprimere il numero della porta:
D0=1
D1=2
D2=4
D3=8
spento=0.

Ma nooo

Lo faccio per misurare

Mica per ottimizzare

Interessanti risultati. Credo che più cose si fanno fare, più le differenze di "qualità di clock" risaltino.

Se qualcuno avesse una Arduino Micro e prova mi fa un piacere. Io lo sketch originario riesco a farlo funzionare solo su una Uno ed una Every.

Beh... Devi aggiungere per forza zavorra?... :slight_smile:

Che zavorra?

Come faresti a misurare l'effetto di un tipo dati più "ciccio" se non lo usi?

Una piccola nota a margine.
Nel caso di scheda con supporto "nativo" usb, leggasi la Micro e la MKR1000 come esempio, i vari sketch proposti "non funzionano", ovvero sul Monitor Seriale appare il "Nulla".
Credo sia una cosa ovvia, ma meglio segnalarlo.

... se c'è una USB nativa DEVI aspettare che essa sia pronta prima di proseguire!

Guglielmo

Beh...

Questa è una ovvietà...

E comunque si parlava di confronto a parità di clock e processore
E qui in particolare si parlava di UNO

Ma no dai, togli il volatile e vedrai.

Ciao.

Se togliessi il volatile il compilatore ottimizzerebbe,
Solo in questo caso però
Perché se lo fai in un programma mediamente complesso non ne avrebbe occasione
Riportando le cose come dico io

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.