Pages: 1 ... 3 4 [5]   Go Down
Author Topic: Nuova libreria 74HC595 per controllo display LCD ed uscite digitali  (Read 7387 times)
0 Members and 1 Guest are viewing this topic.
Majano (UD)
Offline Offline
Newbie
*
Karma: 6
Posts: 34
Stefano Smania
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Come vi avevo promesso ho fatto dei test per vedere se è possibile incrementare ulteriormente la velocità della libreria, anche se francamente dai test che avevo fatto non ne sentivo il bisogno.
Come test ho usato l'esempio incluso nella libreria che non fa altro che settare il cursore e scrivere un carattere su un display lcd ad ogni ciclo. Senza fare alcuna modifica, con la libreria così come la trovate in rete, ho ottenuto un tempo di esecuzione di 7268 microsecondi. Andando a modificare la Send595 affinchè non usi la digitalWrite ma, come vi accennavo, una versione modificata che ignora la disattivazione del pwm e la disattivazione / riattivazione degli interrupt, ottengo 7244microsecondi. Un ulteriore miglioramento è ottenibile con la manipolazione diretta delle porte (7192us) , ma come vi dicevo in un post precedente andrei a perdere la possibilità di usare qualunque pin e la certezza di compatibilità con schede più sofisticate / recenti della Uno. A questo punto ho creato una versione modificata della ShiftOut che si affida alla digitalWrite modificata. Il risultato è notevole, il tempo di esecuzione scende a 4984 con un miglioramento prestazionale di circa il 30%.
Visto il risultato a breve avrete una nuova versione della libreria ed una piccola grande sorpresa a cui ho pensato, ma mi ci vuole qualche giorno per scrivere il codice e verificare che tutto funzioni a dovere.
Logged

Majano (UD)
Offline Offline
Newbie
*
Karma: 6
Posts: 34
Stefano Smania
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Dopo un duro lavoro di ottimizzazioni eccomi qui con la nuova implementazione della mia libreria. Come detto nei precedenti post ho lavorato, grazie ai vostri consigli, sull'ottimizzazione della velocità e devo dire la verità che con l'uso dei display la differenza è notevole. C'è però una scelta da fare che volevo discutere con tutti voi. Ho infatti lavorato su due versioni distinte, non perchè sia impazzito, ma perchè ad un certo punto del lavoro ho notato che introducendo ulteriori ottimizzazioni del codice cpp, la velocità complessiva della sketch diminuiva invece che aumentare. Ho perciò pensato che fosse un problema dovuto all'incapacità del compilatore ad ottimizzare correttamente il codice cpp per cui ho scitto anche una versione in C che come presunto si è dimostrata più veloce. Ma non basta. Oltre ad usare i due linguaggi, ho usato sia codice ottimizzato all'interno della libreria, sia mi sono appoggiato ad una nuova microlibreria scritta apposta per l'occasione. Questa seconda opzione ha ovviamente il vantaggio di essere utilizzabile in qualsiasi altra vostra sketch o libreria. In entrambi i casi NON ho gestito in modo diretto le porte ma ho sfruttato le funzioni di basso livello di Arduino digitalPinToBitMask e portOutputRegister che sicuramente non permettono di raggiungere le massime velocità possibili ma dovrebbero garantire totale compatibilità con qualunque clone Arduino.
Vi riporto qui sotto le due sketch d'esempio, la prima in cpp, la seconda in c. La libreia Memoryfree che vedete mi serve solo a calcolare la memoria residua della Uno per ottimizzare anche quell'aspetto
Code:
// versione scritta in Cpp

#include <FastArduino.h>
#include <hc595.h>
#include <MemoryFree.h>

unsigned char Leds;
unsigned long time1,time2;

hc595 My595(12,11,13,2); // latch,clock,data,number of 74hc595


void setup()
{
 Leds=0;
  My595.DisplayReset(LCD595_BASIC_DISPLAY_INIT | LCD595_MORELINES ,0); // multiline display
 My595.SetCursor(0,0,1,0); // cursor at 0,0, display type 1 on first 595
 My595.DisplayWrite("Setup is OK...",0); // Write string
 delay(1500); // waiting for...
 My595.DisplayClean(0); // clear display
Serial.begin(9600);
}

void loop()
{
    time1 = micros();
  My595.SetCursor(Leds%13,Leds%2,1,0);
  My595.DisplayChar(32+Leds%96,0);
   time2 = micros();

  Serial.println(time2-time1);
   Serial.print("freeMemory()=");
  Serial.println(freeMemory());
  Leds++;
  delay(500);
}

 
Code:
// versione scritta in C
#include <FastArduino.h>
#include <hc595c.h>
#include <MemoryFree.h>

unsigned char Leds;
unsigned long time1,time2;

void setup()
{
 hc595_hc595(12,11,13,2); // latch,clock,data,number of 74hc595
 Leds=0;
 hc595_DisplayReset(LCD595_BASIC_DISPLAY_INIT | LCD595_MORELINES ,0); // multiline display
 hc595_SetCursor(0,0,1,0); // cursor at 0,0, display type 1 on first 595
 hc595_DisplayWrite("Setup is OK...",0); // Write string
 delay(1500); // waiting for...
 hc595_DisplayClean(0); // clear display
 Serial.begin(9600);

 
}

void loop()
{
    time1 = micros();
  hc595_SetCursor(Leds%13,Leds%2,1,0);
  hc595_DisplayChar(32+Leds%96,0);
   time2 = micros();

  Serial.println(time2-time1);
   Serial.print("freeMemory()=");
  Serial.println(freeMemory());
  Leds++;
  delay(500);
}

 
I risultati che ho ottenuto sono i seguenti:
Con codice ottimizzato all'interno della libreria hc595:
C       -len: 5178- speed: 4864- ram: 1763 (aggiornato dopo aver postato)
CPP - len: 5474 - speed: 5180- ram: 1761

e con libreria esterna FastArduino:
C   -    len: 5378 - speed: 4908- ram: 1763
CPP - len: 5670 - speed: 4932- ram: 1761

Con len si intende la lunghezza della sketch, speed i microsecondi medi per l'esecuzione e ram la memoria disponibile. L'utilizzo della ram risulta sostanzialmente uguale nelle varie "incarnazioni". Per quanto riguarda la grandezza della sketck in entrambi i casi la scrittura in C fa risparmiare circa 290 bytes ed altri 200 vengono risparmiati passando dall'uso della libreria esterna al codice bulti-in. L'estremo massimo si ha dalla scrittura in cpp con libreria esterna, al codice C builtin con risparmio di 480 bytes.
Anche la velocità di esecuzione porta ad alcune riflessioni. La versione in C è sempre la più veloce ed il codice built-in ottimizzato è di quasi l'1% più veloce rispetto alla libreria esterna. Usando il cpp invece si ha lo strano fenomeno che vi descrivevo all'inizio, ossia l'uso della libreria esterna MENO ottimizzata è paradossalmente più veloce di quasi il 5% nonostante il maggior numero di chiamate a funzioni e calcoli da eseguire. L'unica spiegazione che ho è appunto la scarsa capacità del compilatore ad ottimizzare il codice cpp rispetto il codice c puro, infatti se guardiamo la sola versione con codice built-in in cui il codice è fortemente più ottimizzato, vediamo che il divario fra la versione c e cpp è nettamente più marcato passando da meno dello 0.5% a quasi il 6%.
Dopo questa lunghissima ma necessaria introduzione la domanda è: che libreia terreste? Qualla in C con codice builtin o quella cpp con libreria esterna? Rispetto alla sketch d'esempio, la prima è dell'1% più veloce, fa risparmiare 480bytes in flash e 2 in ram, la seconda è leggermente più lenta, occupa più spazio in sketch ma essendo in cpp è più semplice da gestire / mantenere e si basa su una libreiria esterna su cui possiamo basare anche altre sketch che necessitino di un aumento prestazionale senza rischiare di pregiudicare la compatibilità con altre schede.
Voi cosa scegliereste?
« Last Edit: October 13, 2013, 08:02:36 am by smania2000 » Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Atroce dubbio... l'ho vissuto anch'io durante lo sviluppo del leOS.
Quei (pochi) utenti avanzati che l'hanno provata mi hanno suggerito forti trasformazioni verso il lato OOP che in parte ho implementato ed in parte no perché usando in modo intensivo gli oggetti e tutto il supporto offerto dal C++ arrivavo ad avere una libreria più semplice da gestire lato utente, sicuramente più "advanced" a livello di codice ma senz'altro più pesa.
Gli Atmel, come molte MCU ad 8 bit, sono ottimizzati per il C.

La scelta è doppia: o lasci la lib in C++ senza sfruttare però troppo le caratteristiche di questo linguaggio, ottenendo quindi un bilancio fra velocità ed occupazione di codice medio, ma rendendo la lib più agevole da gestire agli utenti (considerando che la stragrande maggioranza delle lib per Arduino è scritta in C++ e che quindi sono già abituati ad includere una lib e ad istanziarla) oppure ti appoggi al C, sfruttandone i vantaggi in termini di peso/prestazioni, richiedendo però all'utente un pò di impegno in più per gestirla.

Uh... bella scelta...  smiley-sweat
Logged


Majano (UD)
Offline Offline
Newbie
*
Karma: 6
Posts: 34
Stefano Smania
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ehi ragazzi non scannatevi a rispondere....se non fosse per Leo72 mi farei le domande e darei le risposte da solo :-) Comunque sia ho preso una decisione. Sono riuscito a spingere ancora un po' le prestazioni del codice cpp per cui alla fine la libreria resta per l'utente sostanzialmente identica, in più avete una libreria nuova chiamata FastArduino in cui avete le due funzioni FastdigitalWrite e FastshiftOut che funzionano allo stesso modo delle funzioni Arduino originali ma sono più veloci. Dettagli maggiori li trovate nel sito dove potete scaricare e testare la nuova versione.
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 110
Posts: 6984
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Libreria molto interessante.  smiley-wink
Hai provato ad associarla alla classe print per sfruttarne i metodi come fanno le classiche librerie per LCD?
Anche perché il quel modo, a parte l'istanza di classe, il codice sarebbe riusabile anche se si cambi metodo di collegamento del display.
« Last Edit: October 18, 2013, 10:21:31 am by PaoloP » Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Offline Offline
Jr. Member
**
Karma: 0
Posts: 87
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

scusa la mia assenza dopo aver postato la domande per le prestazioni, pensavo fosse attivo il Notify ma invece non lo era, comunque, secondo me è meglio lasciare la versione C++ (come hai già fatto) in quanto arduino viene usato da tanti che di programmazione ne sanno abbastanza poco ed è più facile gestirla a livello di OOP

P.S: gentilmente, se puoi e se non hai ancora cancellato la versione c, mi invieresti una copia? giusto per prendere spunto, questi giorni sono abbastanza impegnato e non sono riuscito ad andare avanti con il mio progetto e se avrei qualche spunto su come velocizzare la comunicazione spi sarei molto felice, ti ringrazio anticipatamente smiley
Logged

Majano (UD)
Offline Offline
Newbie
*
Karma: 6
Posts: 34
Stefano Smania
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Recuperata appena in tempo dal cestino   smiley-grin. Qui non mi pare ci sia qualche pulsantino per mettere allegati, ma se mi passi una mail ti invio la libreria in C. Mentre scrivevo ho fatto dei test in quanto volevo rispondere anche a PaoloP. Quel che volevo dire era che l'uso della print avrebbe rallentato la mia libreria e che comunque derivando la classe era possibile eseguire comunque tale operazione. A questo punto ho fatto dei test e mi accorgo che la Liquidcrystal segnava dei tempi migliori rispetto alla mia libreria, anche se non di tantissimo. Ho fatto un'analisi del codice e mi sono accorto di un baco da principiante, in un pezzo di codice ho scambiato nanosecondi con microsecondi smiley-confuse . Messo a posto il baco la mia libreria è diventata più veloce di 4 volte diventando 3 volte più veloce della LiquidCrystal. A questo punto due considerazioni: per LeonidRusnac puoi tranquillamente usare la versione in cpp che rispetto allla prima versione scritta è 7 volte più veloce ed annulla tutti i deficit prestazionali rispetto alla versione C. Per PaoloP se ti servono funzioni aggiuntive dovrebbe essere sufficiente creare una classa derivata, appena ho un attimo comunque faccio dei test così magari scrivo una sketch d'esempio per mostrare come fare.
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 110
Posts: 6984
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Qui non mi pare ci sia qualche pulsantino per mettere allegati
Punto 8 -->  http://forum.arduino.cc//index.php?topic=149082.0
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Majano (UD)
Offline Offline
Newbie
*
Karma: 6
Posts: 34
Stefano Smania
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

 smiley-grin smiley-grin smiley-grin smiley-grin   ....si vede vero che non ho scritto molto sul forum ? Allora allego qui la versione in C, tenete conto che l'ho presa nel cestino così com'era

* hc595c.zip (4.64 KB - downloaded 27 times.)
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 87
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie mille smiley
Logged

Majano (UD)
Offline Offline
Newbie
*
Karma: 6
Posts: 34
Stefano Smania
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao ragazzi. Dall'ultima volta ci sono stati numerosi sviluppi ma non vi voglio annoiare con quelli, li trovate sul mio blog. Volevo segnalare che l'utente ogrenero ha individuato un problema con la IDE 1.5.5-r2, nello specifico non gli comparivano gli esempi della SS_hc595 e cercando di importare la libreria con l'apposita funzione gli compariva il messaggio "Trovata libreria non valida in C:\Program Files (x86)\Arduino\libraries\Ss_hc595: Missing 'architectures' from library". Ho indagato brevemente. La causa è il file library.properties che trovate nella relativa cartella.
Devo indagare sull'esatta origine del problema, comunque un semplice Work-around per sistemare il problema è cancellare quel file. Nel frattempo cercherò di capire la causa del problema.
Logged

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 521
Posts: 12325
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao, forse sarebbe bene segnalare questa cosa nel Topic di PaoloP in cui si parla specificatamente della versione 1.5.x ed è tenuto costantemente aggiornato, magari qualcuno potrebbe decidere di segnalare la cosa agli sviluppatori. Grazie.
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Majano (UD)
Offline Offline
Newbie
*
Karma: 6
Posts: 34
Stefano Smania
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ho fatto come mi hai suggerito, prima però ho fatto delle prove per vedere se scoprivo la causa ma per ora nulla di fatto. E' comunque utile sapere che se qualcuno incorre nello stesso problema, anche con altre librerie, basta eliminare il file library.properties.
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Credo dipenda dal fatto che il ramo 1.5.x è sotto pesante sviluppo e le specifiche cambiano anche radicalmente da rilascio a rilascio.
Ti quoto questo, preso dal changelog dell'IDE 1.5:
Quote
ARDUINO 1.5.5 BETA 2013.11.28

NOTICE:
The 1.5 library format is under heavy review on the Arduino Developers mailing list.
We suggest to delay the adoption of the new format until a stable 1.5.x is released.
Il formato delle librerie, a partire dalla 1.5.5 è oggetto di cambiamento (la R2 è solo un rilascio per correggere un problema con i driver certificati per Windows).
Logged


Pages: 1 ... 3 4 [5]   Go Up
Jump to: