Go Down

Topic: Velocità del loop Mega 2560 (Read 10068 times) previous topic - next topic

tuxduino

Secondo me hai capito male. Sto dicendo che sul mega avendo 4 seriali anziché una sola il codice "di sistema" esegue una if(available) su 4 seriali anziché su una sola, e il solo fatto di effettuare questo test comporta (ovviamente) l'esecuzione di (circa) 4x istruzioni macchina rispetto allo stesso controllo su una sola seriale. Se si commentano gli if (available) sulle 3 seriali hw in più rispetto alla UNO, ecco che i tempi ritornano simili a  quanto visto sulla UNO stessa (ma, sempre ovviamente, le 3 seriali aggiuntive non "ricevono" più)

pablos

#76
Jan 09, 2013, 08:36 pm Last Edit: Jan 09, 2013, 08:39 pm by pablos Reason: 1
Non credo sia così, perchè se le voglio attivare tutte devo scrivere

Code: [Select]
Arduino Mega example:

// Arduino Mega using all four of its Serial ports
// (Serial, Serial1, Serial2, Serial3),
// with different baud rates:

void setup(){
  Serial.begin(9600);
  Serial1.begin(38400);
  Serial2.begin(19200);
  Serial3.begin(4800);

  Serial.println("Hello Computer");
  Serial1.println("Hello Serial 1");
  Serial2.println("Hello Serial 2");
  Serial3.println("Hello Serial 3");
}

void loop() {}


altrimenti queste istruzioni che senso avrebbero, in questo caso prendo coscienza che esiste un rallentamento, ma l'ho dichiarato io, quella libreria lo fa senza leggere i begin

http://arduino.cc/en/Serial/Begin
no comment

tuxduino

Le #define vengono valutate a tempo di compilazione, non a tempo di esecuzione, per cui il fatto che venga chiamata o meno Serial1.begin() non ha nessuna influenza sul fatto che la riga if (Serial1.available() > 0) { serial1Event(); } venga inclusa nella compilazione o meno.

Prima di sentenziare oltre però voglio (ri) leggermi bene il sorgente, onde evitare di dare prendere granchi :)

pablos


Le #define vengono valutate a tempo di compilazione, non a tempo di esecuzione

Prima di sentenziare oltre però voglio (ri) leggermi bene il sorgente, onde evitare di dare prendere granchi :)

Vero le define sono considerate in compilazione, nemmeno io voglio sentenziare, per ora siamo in prima istanza :) e lascio la parola agli avvocati più esperti in materia.
Resta il fatto che se mi dai delle istruzioni per attivare a mia scelta 4 cose indistintamente, in teoria mi aspetto che se non le imposto su sketch in compilazione non dovrebbero esserci quelle funzioni. Basterebbe aggiungere qualche debug qua e la per vedere bene cosa succede.
Se vuoi fare qualcosa e darrmelo da provare io sono qui.
Grazie anche a te per il tuo contributo

ciao
no comment

tuxduino

granchi da dare, da prendere, da lanciare... :D vabbè il senso era chiaro :D

tuxduino

Da HardwareSerial.cpp (copio solo il codice relativo alla seriale 3 tanto il resto è uguale)

Code: [Select]

#if defined(USART3_RX_vect) && defined(UDR3)   <<<<<< se è presente la seriale hardware 3
  void serialEvent3() __attribute__((weak));
  void serialEvent3() {}
  #define serialEvent3_implemented    <<<<<<<<<< viene definito il simbolo che varia il contenuto di serialEventRun
  SIGNAL(USART3_RX_vect)
  {
    if (bit_is_clear(UCSR3A, UPE3)) {
      unsigned char c = UDR3;
      store_char(c, &rx_buffer3);
    } else {
      unsigned char c = UDR3;
    };
  }


Code: [Select]

void serialEventRun(void)
{
#ifdef serialEvent_implemented
  if (Serial.available()) serialEvent();
#endif
#ifdef serialEvent1_implemented
  if (Serial1.available()) serialEvent1();
#endif
#ifdef serialEvent2_implemented
  if (Serial2.available()) serialEvent2();
#endif
#ifdef serialEvent3_implemented   <<<<<<<<<<<< ecco il simbolo
  if (Serial3.available()) serialEvent3();
#endif
}


E da main.cpp
Code: [Select]

for (;;) {
loop();
if (serialEventRun) serialEventRun();
}


Quindi la differenza sta nel diverso contenuto di serialEventRun() a seconda del numero di porte serial hardware presenti. Nel caso della UNO il risultato della compilazione condizionale equivale al seguente:

Code: [Select]

void serialEventRun(void)
{
  if (Serial.available()) serialEvent();
}


Nel caso del MEGA il risultato equivale invece a:

Code: [Select]
void serialEventRun(void)
{
  if (Serial.available()) serialEvent();
  if (Serial1.available()) serialEvent1();
  if (Serial2.available()) serialEvent2();
  if (Serial3.available()) serialEvent3();
}


e la funzione Serial::available() richiede un po' di lavoro:
Code: [Select]

int HardwareSerial::available(void)
{
  return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SERIAL_BUFFER_SIZE;
}


Ecco quindi spiegato perché compilando uno sketch vuoto sulla Mega la funzione loop() viene chiamata meno frequentemente rispetto alla UNO.

(disclaimer: non posseggo una Mega)

pablos

#81
Jan 09, 2013, 11:31 pm Last Edit: Jan 10, 2013, 12:01 am by pablos Reason: 1
ok chiaro come il sole, ma:

void serialEventRun(void)
{
 if (Serial.available()) serialEvent();
 if (Serial1.available()) serialEvent1(); >>>> non è Available ..... perchè vai a perdere tempo in serialEvent?
 if (Serial2.available()) serialEvent2(); >>>> non è Available ..... perchè vai a perdere tempo in serialEvent?
 if (Serial3.available()) serialEvent3(); >>>> non è Available ..... perchè vai a perdere tempo in serialEvent?
}

Se non sono available dovrebbe uscire immediatamente dall'if e 3  semplici if falsi non possono rallentare di 3/4 la velocità, magari mi prendono 10 ms ... dico una scemenza, se la dico spara pure, forse mi sfugge qualcosa :)
no comment

tuxduino

Ehm... scusa ma come funziona lo statement if ?

Vediamo:

Code: [Select]

if (condizione)
    istruzione


"istruzione" viene eseguita solo se "condizione" è true.

Quindi non capisco il tuo commento "non è Available ..... perchè vai a perdere tempo in serialEvent?"

Innanzitutto non è "Available" ma "available". E prima che tu faccia della facile ironia sul fatto che sono pignolo :D beh prova a compilare un programma in cui chiami Serial.Available() :DD

La funzione serialEvent() NON viene chiamata se il metodo available() ritorna zero, cioè se non ci sono byte da leggere. Quindi nessun tempo perso, a parte quello per l'esecuzione del metodo available().

tuxduino

Quote
semplici if falsi


E come sai se la condizione dello statement if è vera o falsa ? Devi valutarla, cioè, in questo caso, eseguire il metodo available(). E se vai a vedere il contenuto di quel metodo, non si tratta esattamente di un paio di istruzioni macchina :)

pablos

Non ti ritengo pignolo maiuscola o minuscola ahahahahha, se qui a spiegare ci mancherebbe ... ma si potrebbe trovare un metodo per evitare che il software faccia controlli su qualcosa che non è volontariamente abilitato da sketch?
ciao
no comment

tuxduino

Quote
ma si potrebbe trovare un metodo per evitare che il software faccia controlli su qualcosa che non è volontariamente abilitato da sketch?


Tipo che il metodo begin() setta un flag "enabled" a true poi in serialEventRun hai una roba simile:

Code: [Select]

if (Serial.enabled()) {
    if (Serial.available()) {
        serialEvent();
    }
}


in questo modo il test è sicuramente più veloce (verificare se un boolean è true o false richiede meno istruzioni rispetto ai calcoli del metodo available()).

Forse non è un'idea del tutto peregrina, ma non ne vedo l'utilità, se non come esercizio per diletto personale.

pablos

#86
Jan 10, 2013, 12:40 am Last Edit: Jan 10, 2013, 12:47 am by pablos Reason: 1
Quote
Tipo che il metodo begin() setta un flag "enabled" a true poi in serialEventRun hai una roba simile:

si, esatto una roba simile.

Quote
Forse non è un'idea del tutto peregrina, ma non ne vedo l'utilità, se non come esercizio per diletto personale.

vuoi scherzare :))
Lo sai quanti utenti comprano una mega perchè ha la possibilità di avere piu' pin, più memoria per lo sketch  e connetterla via usb tramite serial0 sui pin 0-1 a un piccolo server che ne gestisce le varie funzioni.....
A me personalmente in questo momento non serve, io le posso tagliare tutte, ma un giorno che vorrò fare una linea 485 dovrò abilitarne una o due al max, io che adesso lo so mi personalizzo la libreria facendo dei tagli, ma per chi non lo sa secondo me è una grave penalizzazione, comunque resta sempre una cosa che funziona con risorse ridotte per errore.

ciao
no comment

lesto

non solo, dato che i buffer sono inizializzati alla creazione di HardwareSerial, che avviene sempre, viene rubatta anche un bel pò di ram (questo sia per il 328 che per la MEGA, anche se per lamega ilproblema è triplo).

Quindi inizializzando i buffer a null, spostando l'inizializzazione vera e propria dei buffer in begin(), e la loro distruzione e risettaggio a null in end(), avremmo risparmiato un pò di ram e in automatico basterebbe controllare che i due buffer siano non null per sapere se la seriale è attiva... ma comunque perdi qualche ciclo macchina per il check.

Non credo esista qualche macro per dirgli di non aggiungere del codice se una classe non è usata, ma magari vengo smentito, non conosco bene le macro.

il check sarebbe
Code: [Select]
bool HardwareSerial::isActive()
{
  return (_rx_buffer!=null && _tx_buffer!=null)?true:false;
}
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

tuxduino

Mah, io continuo a pensare che arrivare a scrivere un programma per la Mega in cui perfino un paio di chiamate in più a SerialX.available() fanno la differenza sarebbe già un bel traguardo di per se. Cioè sarebbe un programma talmente raffinato in tutte le sue parti che non ci sarebbe altro modo per ottimizzarlo ulteriormente se non evitando di compilare il supporto a una o due seriali hw aggiuntive.

Forse sto sottovalutando il problema, ma questo concentrarsi su un paio di istruzioni perché "rallentano" uno sketch vuoto mi fa pensare al contrasto tra ottimizzazione algoritmica e "di basso livello". Tipo che uno tenta di spremere fino all'ultimo ciclo di clock per "velocizzare" una  una funzione il cui tempo di esecuzione cresce con n^2 quando basterebbe cambiare l'algoritmo con uno con tempo proporzionale a (p. es.) n log(n) per ottenere miglioramenti prestazionali molto più robusti e consistenti, lasciando al compilatore il compito di occuparsi dell'assebly.
Mi pare la parola chiave sia "premature optimization" :)

lesto

bhe però sulla RAM stiamo parlando di 128*2 = 256 byte persi se usi solo una seriale.. non pochi no?
ma forse sto andando OT ;)
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Go Up