Creare un metronomo preciso in ambito grafico e temporale!?

Ciao ragazzi, sto cercando di creare un metronomo che si muovera'graficamente da un punto Xstart ad un punto Xend su un pannello processing.
Graficamente sara'una linea verticale e dovra' scorere dal punto Xstart che si trova diciamo a X=0 al punto Xend che si trova diciamo a X=560.

Ecco il mio problema, non riesco ad uscirne.. :

abbiamo una variabile "velocita'metronomo" che inizialmente varra' 1.

Con la velocita'settata a 1, il metronomo dovra' scorrere da X=0 a X=560 in 5 secondi, piu' precisamente in 5000 millisecondi.
Con la velocita'settata a 2, il metronomo dovra' scorrere da X=0 a X=560 in 2500millisecondi
Con la velocita'settata a 3, il metronomo dovra' scorrere da X=0 a X=560 in
1250millisecondi
Con la velocita'settata a 4, il metronomo dovra' scorrere da X=0 a X=560 in
625millisecondi.

Allora non riesco proprio a creare qualcosa di operativo.
come far scorrere una linea verticale su una barra di 560 pixel in un tempo preciso??

Sono arrivato al fatto che se disegno 1pixel ogni 9 millesimi, otterro' 555 pixels in 5000 millisecondi.. ma il mio obiettivo e' che il metronomo scorra per 5000millisecondi toccando nella sua corsa 560 pixels! c'e' qualche proporzione che svolazza nella mia mente ma non l'afferro.

Aiuto sono bloccato!

5000ms / 560 pixel = 8,928571429ms per ogni pixel
2500 / 560 = 4,464285714 = 8,928571429ms / 2
1250 / 560 = 2,232142857 = 8,928571429ms / 4
625 / 560 = 1,116071429 = 8,928571429ms / 8

C'è da vedere se riesci a rispettare le temporizzazione che ovviamente arrotonderai e per cui avrai sempre un errore.

Ciao.

Per migliorare, invece di millis() puoi usare micros() ... l'errore è comunque di +/- 4μsec, dovuto al funzionamento della micros() stessa.

Guglielmo

Ops, ma da 0 a 560 pixel sono 560+1 pixel incluso lo zero per cui dovrebbe essere:
5000 / 561 = ecc

A meno che visualizzi il pixel 0 subito poi temporizzi e accendi l'altro pixel ecc.

Mi sto incasinando pure io.

Ciao.

Maurotec:
Ops, ma da 0 a 560 pixel sono 560+1 pixel incluso lo zero per cui dovrebbe essere:
5000 / 561 = ecc

Magari è veramente da 560 px, da 0 a 559 :wink:

Guglielmo

Maurotec:
5000ms / 560 pixel = 8,928571429ms per ogni pixel
2500 / 560 = 4,464285714 = 8,928571429ms / 2
1250 / 560 = 2,232142857 = 8,928571429ms / 4
625 / 560 = 1,116071429 = 8,928571429ms / 8

C'è da vedere se riesci a rispettare le temporizzazione che ovviamente arrotonderai e per cui avrai sempre un errore.

Ciao.

Ahh benissimo grazie 1000 Mauro! e che cavolo figurati ho scritto qui dopo almeno un paio d'ore in cui mi stavo totalmente incasinando.. ehh il caldo :stuck_out_tongue: :stuck_out_tongue:
Faccio subito delle prove e vi faccio sapere! (considerando anche il discorso del pixel 0)

gpb01:
Per migliorare, invece di millis() puoi usare micros() ... l'errore è comunque di +/- 4μsec, dovuto al funzionamento della micros() stessa.

Guglielmo

Ciao Guglielmo! molto interessante! grazie.
Piu' precisione ottengo meglio è..
io attualmente sto utilizzando la libreria Chrono che mi permette di avere un metodo pronto a mo di metronomo.
Con i millisecondi mi trovo bene, una precisione decente diciamo.. ma con i microsecondi potrei realmente ottenere la precisione che sto cercando.
Piuttosto non so se la precisione che otterrei utilizzando i ms, possa essere gestita e quindi goderne i benefici, dalla MEGA2560..

su un pannello processing

Che vuol dire "pannello processing"?

Ho dato per scontato che il software girava sul PC sotto processing (il linguaggio) e allora sono andato a vedere il reference alla ricerca di micros e non c'è, ma c'è millis. Ora parli della MEGA, come funziona sta cosa?

Ciao.

Ma mi chiedevo una cosa: ce la fa come velocità a disegnare la linea per spostarla? Ossia significa fare 560 spostamenti ossia 2 operazioni (cancella la vecchia posizione e disegna la nuova) per 560 volte in 625ms sono 560*2/0.625 = oltre 1700 aggiornamenti del display al secondo...

Allora, si scusate, sono stato poco chiaro a riguardo;
le operazioni vengono eseguite sulla mega,
e i risultati visualizzati su un pannello programmato su Processing.

In pratica tutto il codice di gestione del metronomo con relativi timers avviene sull'IDE Arduino.
questo codice generera' varie cose tra cui la posizione X della linea del metronomo stesso.

I dati a quel punto vengono spediti in seriale a processing che li visualizza graficamente; in questo caso processing piazzera' la linea del metronomo nella posizione grafica corretta leggendo appunto da seriale la variabile posizione X

Quindi il codice relativo alla VISUALIZZAZIONE della linea, si, quello e' a carico di processing.

ecco l'immagine del pannello:
Il metronomo che scorre da sinistra a destra.
quindi tutta la parte grafica relativa al metronomo è programmata su processing.

aldoz:
Quindi il codice relativo alla VISUALIZZAZIONE della linea, si, quello e' a carico di processing.

Ok.
A questo punto per verificare le performance minima, ti consiglierei solo di verificare bene l'idea, ossia vedere sulla seriale quanti e quali dati passano verso Processing ed a quale velocità.

Per dire, per questo "metronomo" (scusa la curiosità, ma a che serve?) già con soli 4 byte per tick (per indicare la posizione più separatore) siamo sui 7600 byte al secondo, ossia circa 71k baud richiesti solo per questo, a 115200 non è che ti resti poi molta banda per il resto, che tra l'altro essendo una seriale contribuisce a problemi di tempistica.

Inoltre la precisione di questo metronomo quanto è essenziale e di quanto al massimo puoi discostarti?

Scusa, perchè 4 bytes? ... sono 560 pixel (mandi direttamente fino a che pixel accendere, non i micros) ... con un unsigned int (16bit) ci stai dentro ...

Guglielmo

Perché per evitare problemi ci metto sempre anche almeno un marker o separatore. Un unsigned int sono comunque 2 byte, più separatore sono 3, ma immagino che su quel canale non ci passino solo i dati del metronomo, per cui un qualche minimo di "identificazione" ci deve stare, visto anche quel pannello che ha mostrato (e quindi secondo me sono anche ben più di 4 byte per campione).

Se si devono inviare più informazioni si usa un tracciato fisso e i separatori non servono a nulla ... Apertura, streaming, chiusura e volendo un CRC, quindi ... 2 bytes sono più che sufficienti per la posizione :wink:

Guglielmo

Certo, ma tu sai come funziona la comunicazione seriale verso Proceessing e QUEL pannello in particolare?

Io no, lo deve sapere l'OP, che ho quindi avvisato di farsi i conti.

docdoc:
Certo, ma tu sai come funziona la comunicazione seriale verso Proceessing ...

... SI.

Certo, poi cosa c'è su quel pannello e da dove riceva i dati ... è un'alto paio di maniche :smiley: :smiley: :smiley:

Guglielmo

Proprio li volevo arrivare, dove è arrivato docdoc, nel senso che parlare di precisione di timing al microsecondo se poi serializzo verso processing a poco senso, certamente si può vedere di ottimizzare, tarare ecc in modo che il risultato sia accettabile almeno a vista, ma sono scettico riguardo alla precisione.

In alternativa se si vuole coinvolgere la MEGA perché non inviare un dato adesso e uno fra 5 secondi e poi processing si ricava l'intervallo e al posto della barra una lancetta, come nel metronomo tradizionale.

Comunque è interessante, vediamo dove si arriva.

Ciao.

beh, se i tempi sono stretti si può inviare un messaggio ogni 2 o più pixel di spostamento, dubito che l'occhio noti la differenza a quella velocità.
La precisione deve essere sull'intero ciclo, non su ogni singolo spostamento.
Io farei un meccanismo che invia dati periodicamente e all'invio viene calcolata la posizione da inviare, anche se si rischia di far saltare qualche pixel.
Se la comunicazione è troppo lenta, perderò qualche pixel ma la velocità complessiva dovrebbe essere rispettata.

Allora ragazzi, ho seguito la vostra conversazione.
Per quanto mi riguarda, l'importante in tutta questa storia è che il codice che gira sulla Mega sia il piu' preciso possibile.
Tutti i calcoli avverranno nell'Arduino.

Questo metronomo eseguira una "scansione" da un pixel di partenza ad un pixel di arrivo.
La velocita' di questa scansione avverra' con la logica suggeritami da Mauro.
(quando questo metronomo "tocchera' il primo pixel di una zona interna a questa barra, iniziera' a far sollevare un motore per il tempo (pixels) che dura appunto questa zona che avra', per l'appunto, un X di inizio evento ed un X di fine evento)
Vi allego un'immagine per capire meglio.

Vedete come a 1250ms (che equivalgono a 140 pixel dal primo pixel della barra dati) ci sia un evento che inizia e dura fino a 2600ms circa.
Ecco, il metronomo, in base alla sua velocita', (la quale viene ottenuta grazie al suggerimento di Mauro) appena superera' il pixel di inizio e evento, creera' un movimento di un motore che durera' per tutta la durata temporale dell'evento stesso.

Ovviamente tutta questa "visualizzazione grafica" verra' generata da Processing ma visualizzera' i dati che sta ricevendo via seriale (112500) dal codice Arduino.

Che sia li la precisione! cioe' che ci sia precisione nei calcoli; poi il fatto che vengano visualizzati da processing, purtroppo, creera' degli sfasamenti temporali... Pero' ripeto :
l'importante che i dati "RAW" siano i piu' precisi possibili poi nella loro visualizzazione ci sara' probabilmente un ritardo..

Scusa, io non conosco Processing (so cos'è ma non l'ho mai utilizzato finora) ma mi chiedevo perché non rendere Arduino più "stupido" e far fare i timing a Processing il quale si può limitare a mandare al Mega i comandi per eseguire gli eventi. Mi riprometto anche di studiare Processing perché è a volte utile per controllare Arduino da PC (in particolare ho da estendere un controllo di un braccio robotico che comandavo solo in automatico con movimenti predefiniti ad esempio), ma c'è un motivo per cui questa cosa non si possa fare, o almeno non agevolmente?