Go Down

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

tuxduino

Quote
il rallentamento indotto dalla creazione delle classi è minimo


No, è nullo.

pablos

#106
Jan 10, 2013, 12:24 pm Last Edit: Jan 10, 2013, 12:26 pm by pablos Reason: 1
Tuxduino, non avevo proprio guardato la main.cpp sei stato geniale :), però mi chiedevo ....
Adesso che le ISR di ricezione seriale vengono eseguite solo quando arrivano dei byte, cosa implica l'aver tolto quella linea? perchè se è stata messa un motivo c'era ... o no?
Tra l'altro hai reso più veloce anche la UNO, non ho provato ma dovrebbe essere così

ciao
no comment

leo72



Nel 1° caso escludi il setup delle seriali, quindi escludi check sui buffer e interrupt.
Nel 2° caso togli solo i check per verificare se ci sono byte nei buffer, quindi il guadagno prestazionale è minore dato che  hai le ISR a rallentare lo sketch.

(se ho capito bene a quali porzioni di codice ti stai riferendo)


Le ISR di ricezione seriale vengono eseguite solo quando arrivano dei byte. Il solo fatto che siano attive non consuma cicli di CPU.

Vero anche questo....

MauroTec

Io non uso più il core Arduino da tanto, ne uso il C++, ma solo C e strutture usate a mò di oggetti. Poi uso una specie di pseudo tipo per raggruppare i registri da passare alle funzioni e altre cose che mi permettono di andare alla massima velocità.

Il codice seguente attiva la seriale 0 e scrive qualcosa:
Code: [Select]

#include <mio.h>
#include <uart.h>
#include <stdio.h>


FILE uart_str;
// seriale numero 0
// questa define si trova in ogni file header dipendente dalla MCU, header che viene incluso dal file "mio.h"
// vedi anche USART_T
// #define USART0 &UCSR0A, &UCSR0B, &UCSR0C, &UBRR0, TXEN0, RXEN0

int
main(void) {
    usart_init(USART0, 230400, USART_CK_DOUBLE, &uart_str);
    while (1) {
        fprintf(&uart_str, "test uart");
        fprintf(&uart_str, "%d", UBRR0 );
    }
}


La funzione usart_init:
Code: [Select]

// USART_T è un pseudo tipo, ma è meglio dire che si tratta di un'accorpamente di dichiarazione di variabili
// che si trova nel file header dipendente dalla MCU.
// nel file atmega48.h c'è questa define:
// #define USART_T volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *ucsrc,\
//                volatile uint16_t *ubrr, volatile uint8_t tx_en, volatile uint8_t rx_en
// pertanto i parametri passati a usart_init possono essere in numero deciso dall'header della MCU


void
usart_init(USART_T, uint32_t baud, const uint8_t ck_serial_mode, struct __file *strm);

void
usart_init(USART_T, uint32_t baud, const uint8_t ck_serial_mode, struct __file *strm)
{

    if (ck_serial_mode == USART_CK_DOUBLE) {
        /* Usart clock double */
        *ucsra _bit_set(UCSRA_U2X);
        *ubrr = USART_UBRR_2X(baud);
    } else {
        *ucsra _bit_unset(UCSRA_U2X);
        *ubrr = USART_UBRR_1X(baud);
    }
    *ucsrb = _BV(tx_en) | _BV(rx_en); /* tx/rx enable */


    fdev_setup_stream(strm, uart_putchar, uart_getchar, _FDEV_SETUP_WRITE);
}



Come si vede non scrivo molto, ma c'è un ma, per usare fprint per qualunque dato devo abilitare dei flag di compilazione che in arduino sono disabilitati, questo nel mio caso incrementa la dimensione dell'eseguibile.

Anche se sono poche righe di codice, un principiante non saprebbe scriverle e arduino è vincente per questo. Io non ho trovato modo per coniugare
l'efficenza e semplicità di uso. Ho anche provato altre librerie C++ nelle quali si è fatto qualcosa di efficente, ma per salvare l'efficenza si è compromesso la semplicità di uso. Per questo considero la semplicità e l'efficenza le due facce della medaglia, cioè o l'una o l'altra ma mai entrambe.

Comunque anche la complicata iniziazializzazione che uso ha risvolti negativi, uno tra questi il numero elevato di argomenti di funzione.

L'unico modo che conosco per scrivere codice efficiente e quello di non usare librerie automatizzate e usare direttamente i registri.

Una funzione specifica di  usart_init si avvantagerebbe dell'uso dei registri senza che queste debbano essere passati come argomento.

creare più funzioni di libreria con nome usart0_init, usart1_init ecc risolverebbe ma il programmatore non ha davanti sempre le stesse api.
Usare le strutture compilandole con gli indirizzi dei registri occupa memoria ram.

A proposito di ram, il compilatore dovrebbe fare pulizia se non c'è un riferimento ad una istanza, quindi anche l'array visto che non c'è codice che lo usa dovrebbe essere spazzato via e quindi non occupare memoria.

Ragazzi mi manca la volonta è il tempo per studiare asm, chi conosce bene asm può verificare cosa fa il compilatore tutti gli altri devono stare in fiducia.

Ciao.

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

lesto

se cerchi bene in giro puoi usare la printf senza bisogno di modificare nulla, l'ho usato personalmente ma non ho uppato il codice... ma l'avevo trovato facilmente con google.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

MauroTec


se cerchi bene in giro puoi usare la printf senza bisogno di modificare nulla, l'ho usato personalmente ma non ho uppato il codice... ma l'avevo trovato facilmente con google.


Esatto, la printf & company scrivono già nella prima seriale, cioè su USART0, ma il codice che ho postato vale anche per le altre seriali. Inoltro con lo stesso sistema scrivo sul display con fptrintf 20x4.

In genere qualunque funzionalità mi serva tendo ad usare cio che già offre la avr-libc, sempre che sia possibile.
Più in la dovrei riscrivere il codice per il display 64128 usando sempre lo stesso sistema, in questo modo riutilizzo più volte sempre lo stesso codice fornito dalla avr-libc
diversamente usando molte librerie il codice si gonfia rapidamente. Poi è quello che viene fatto anche nel core di Arduino, dove la print viene usata anche per altre cose, almeno così mi ricordo.

Ciao.
AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

tuxduino


Tuxduino, non avevo proprio guardato la main.cpp sei stato geniale :), però mi chiedevo ....


:)


Adesso che le ISR di ricezione seriale vengono eseguite solo quando arrivano dei byte, cosa implica l'aver tolto quella linea? perchè se è stata messa un motivo c'era ... o no?


Ho risposto qualche commento fa. Ripeto brevemente: serialEventRun fa sostanzialmente questo (pseudocodice per essere più chiari):

if (ci sono byte nel buffer di ricezione della seriale) then
   chiama la funzione serialEvent
endif

Nel caso della UNO lo fa per la sola Serial, nel caso della Mega lo fa per Serial, 1, 2, 3. A prescindere dal fatto che all'utente servano o meno.
Commentando quella riga, l'utente non dovrà più implementare la funzione serialEvent() (una per ogni seriale che usa), ma dovrà esplicitamente scrivere:

Code: [Select]

if Serial.available() {
   fai qualcosa
}


per le seriali che usa.


Tra l'altro hai reso più veloce anche la UNO, non ho provato ma dovrebbe essere così

ciao


Appunto, appena hai tempo e voglia fai una prova. :)

pablos

#112
Jan 10, 2013, 06:34 pm Last Edit: Jan 10, 2013, 06:56 pm by pablos Reason: 1
Quote
fa sostanzialmente questo (pseudocodice per essere più chiari):

if (ci sono byte nel buffer di ricezione della seriale) then
   chiama la funzione serialEvent
endif

Nel caso della UNO lo fa per la sola Serial, nel caso della Mega lo fa per Serial, 1, 2, 3. A prescindere dal fatto che all'utente servano o meno.
Commentando quella riga, l'utente non dovrà più implementare la funzione serialEvent() (una per ogni seriale che usa), ma dovrà esplicitamente scrivere:

Code:

if Serial.available() {
   fai qualcosa
}

Ok, chiaro

Quote
Appunto, appena hai tempo e voglia fai una prova. smiley

Non ho provato perchè non ce l'ho io ahahahha  (non avevo specificato), tu ce l'hai  :smiley-mr-green:

riguardo a un appunto che hai fatto a pag 5 che mi era sfuggito
Quote
A proposito dell'influenza della seriale sulle prestazioni, vorrei sottolineare i risultati che ho ottenuto nel mio sketch di prova: tra baud rate di 9600 e 115200 c'è una differenza significativa.
Va ricordato però che nelle ultime versioni di Arduino anche la trasmissione seriale è fatta via interrupt, e diventa bloccante solo nel momento in cui il buffer di trasmissione è pieno, quindi in realtà se si trasmettono "pochi" (1) byte alla volta, l'impatto complessivo dovrebbe essere molto limitato.

ho rifatto i test prima con baud rate 9600 e 115200, non ho rilevato nessuna differenza

ciao
no comment

tuxduino

Quote
ho rifatto i test prima con baud rate 9600 e 115200, non ho rilevato nessuna differenza


Sì ma con quale codice ? Inviavi caratteri oppure era solo uno sketch vuoto con un argomento diverso passato alla begin() ?

pablos

inviavo caratteri, ma c'era un errore nello sketch  :D , confermo c'è un abisso tra i 2 baud rate. 
no comment

Testato

- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

leo72

L'ultimo messaggio è di 6 mesi fa, credo che sia abbastanza "morta" come discussione  ;)

pablos

Si direi anche conclusa con un ottimizzazione dello speed sia della mega che della uno.
no comment

Go Up