Facciamo un gioco

per Nello79
intendi tra l'inizio e la fine della parte dedicata alla trasmessione Morse?

non sarebbe costante, con l'oscilloscopio non lo vedresti

ad esempio come fai tu, una IF con tanti OR

con la valutazione di corto circuito avresti "periodi" velocissimi alternati a periodi più lenti
microsecondi, concordo, forse meno, ma sono sicuro che si sentirebbero....

questo è un altro che ho fatto per prova
l'algoritmo non è mio , ma di Sulimarco

unsigned long int conta;
unsigned long int t;
#define PUNTO 250
uint8_t PrevTime = 0;
uint8_t Step = 0;



void setup(void)
{
   pinMode(13, OUTPUT);
   Serial.begin(9600);
   t = micros();
}

void loop(void)
{
   if (((uint8_t)(millis() - PrevTime)) >= PUNTO)
   {
      PrevTime += PUNTO;
      Step++;

      if ((Step < 28) && (Step & 0x01) && (Step != 7) && (Step != 21) || (Step == 10) || (Step == 14) || (Step == 18))
      {
         digitalWrite(LED_BUILTIN, HIGH);
      }
      else
      {
         digitalWrite(LED_BUILTIN, LOW);
      }

      if (Step > 33)
      {
         Step = 0;
      }
   }

   if (100000UL == ++conta)
   {
      Serial.println(micros() - t);
      conta = 0;
      t = micros();
   }
}

compila in 2220 byte 198 byte di variabili e fa da 308132 a 308140 microsecondi per centomila giri di loop

questo è un altro che ho fatto per prova

Secondo me il test di velocita e' concettualmente corretto.
Non dipende dalla durata del tempo di PUNTO.
Se provi a mettere #define PUNTO 200 vedrai che il risultato cambia pochissimo.
L'unica cosa e' che farei un tempo di test piu' lungo mettendo __if (1000000UL == ++conta) __

Marco

Concordo

Scusate cosa significa quel UL nell' IF

Unsigned Long

Scusate se posto la domanda qui (se da fastidio la elimino), ma e' sorta dal programmino stupido che avevo postato qui (e poi qui e' pieno di programmatori, perche' non approfittarne ? :P) ... avete presente, quello che avevo scritto sbagliato col notepad non avendo ancora reinstallato l'ide ...

Ora che ho rimesso l'ide mi era venuta voglia di controllarlo, l'ho corretto, e alla verifica mi dice che l'array che dichiaravo e' troppo piccolo ... e qui c'e' il punto che non mi quadra ...

Io avevo dichiarato un'array da 34 elementi (da 0 a 33) perche' i valori da metterci erano 34 (si, li ho ricontati 3 volte :P) ... e l'ide alla verifica mi dice "error: too many initializers for 'int [33]' ..." ...

la cosa mi sembra strana, pero' provo a cambiarlo in un'array da 35 elementi (da 0 a 34), e l'errore sparisce ...

Ora, forse sono stupido io, ma com'e' che 34 valori non ci stanno in un'array da 34 posizioni ?

L'array è da 33 elementi da 0-32 tu hai valorizzato 34 valori.

No ... "int posiz[33] ..." secondo me e' da 34, dato che comincia con zero (lascia perdere quello che avevo postato, l'ho corretto tutto con l'ide installato, ed e' un'array da 34 che mi da errore con 34 elementi)

byte pinled = 10;
int posiz[33] = {1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0};
byte posnum = 0;
byte tempo = 1;
... eccetera ...

EDIT: Aspetta, il numero fra parentesi quadre non e' l'indice ma il numero degli elementi ? ... ho davvero fatto un'errore cosi stupido ? ... o_o

... vado a comperare i ceci ... chi di voi mette su la Corazzata Potiomkin ? ...

No è da 33 elementi! L'indice va da 0 a 32.

Ho come l'impressione che ci sia qualcosa che non quadra nel sistema di misura. Ho provato a sostituire i digitalWrite con l'impostazione diretta dei registri di uscita e facendogli compiere 1000000 di volte il loop ma il tempo non cambia. Secondo voi da cosa può dipendere?

unsigned long int conta;
unsigned long int t;
#define PUNTO 250
uint8_t PrevTime = 0;
uint8_t Step = 0;



void setup(void)
{
   pinMode(13, OUTPUT);
   Serial.begin(9600);
   t = micros();
}

void loop(void)
{
   if (((uint8_t)(millis() - PrevTime)) >= PUNTO)
   {
      PrevTime += PUNTO;
      Step++;

      if ((Step < 28) && (Step & 0x01) && (Step != 7) && (Step != 21) || (Step == 10) || (Step == 14) || (Step == 18))
      {
         //digitalWrite(LED_BUILTIN, HIGH);
         PORTB |= 0b00100000;
      }
      else
      {
         //digitalWrite(LED_BUILTIN, LOW);
         PORTB &= 0b11011111;
      }

      if (Step > 33)
      {
         Step = 0;
      }
   }

   if (1000000UL == ++conta)
   {
      Serial.println(micros() - t);
      conta = 0;
      t = micros();
   }
}

edit: Forse ho capito, in così poco tempo il numero delle volte che entra all'interno della funzione è troppo basso per poter essere rilevato....

Non so se ho capito bene il problema, perchè all'inizio non avevo proprio ben capito che si volesse cadenzare di 250ms, l'avevo inteso come un valore di riferimento...
Comunque, che 250ms sia!

La mia soluzione è questa:

#define TIME 250
#define MAX 34
uint64_t sos = 11336911488; // 10101 000 11101110111 000 10101 0000000
uint8_t pos = 0;
uint8_t prevMillis = 0;
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  if (millis() - prevMillis >= TIME) {
    digitalWrite(LED_BUILTIN, bitRead(sos, pos));
    prevMillis += TIME;
    pos = ++pos % MAX;
  }
}

che poi, dopo averla fatta mi sono andato a vedere le altre soluzioni dei vari post, e si è rivelata essere una copia di quella di ORSO :cry:
Non l'ho testata per mancanza di un arduino sotto mano, quindi ci potrebbe essere qualche piccolo errorino.

Compatta è compatta!

Ora per misurarne la velocità di esecuzione servirebbero due contatori, il primo che conti il numero di giri di loop, il secondo, gestito da interrupt, che conti il numero di switch sul fronte di salita di LED_BUILTIN.
Quando viene contato il sedicesimo, a parte il pirmo giro che non viene correttamente inizializzato, avremmo il numero di loop tra un sos e l'altro, poi resettiamo i contatori ripartendo da uno per i fronti di salita (visto che stiamo elaborando il primo del nuovo giro) e da zero per i loop.
Il contatore dei loop va incrementato alla fine del loop.

In questo modo, più loop si contano e più è veloce il codice.

Maurizio

EDIT:
Visto che il C non è il mio linguaggio e sono perennemente arrugginito, non sono sicurissimo dell'ordine di esecuzione dei vari pezzi della riga:

pos = ++pos % MAX;

Per evitare rischi la si può riscrivere in

pos = (pos + 1) % MAX;

Quello sketch purtroppo impegna molta più memoria però è molto più intuitivo.

Il % mi sembra che sia un bel mattone...

Datman:
Il % mi sembra che sia un bel mattone...

Mi cogli impreparato, dici che non è una primitiva?
Nel caso si ricorre al test classico di raggiungimento del massimo con una bella e classica if.
Ora vado a darmi un po' di antiruggine in merito :wink:

Maurizio

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