Sto lavorando a un progetto che invia dati seriali per controllare l'animazione di luci a LED, che devono rimanere sincronizzati con un motore di animazione. Sembra esserci un grande buffer di scrittura seriale (dispositivo seriale USB chipset OSX (POSIX) + FTDI), quindi senza limitare manualmente le chiamate a write(), il software può ottenere diversi secondi prima delle luci.Seriale: write() throttling?
Attualmente mi sto limitando manualmente la velocità di scrittura seriale alla velocità di trasmissione (telaio di serie 8N1 = 10 byte per byte di dati 8, 19200 bps seriali -> 1920 byte al secondo max), ma io sto avendo un problema con l'animazione alla deriva fuori sincrono con le luci nel tempo - inizia bene, ma dopo 10 minuti c'è un ritardo notevole (100ms +) tra l'animazione e le luci.
Questo è il codice che limitano la velocità di scrittura seriale (chiamato una volta per frame di animazione, 'trascorso' è la durata del frame corrente, 'baud' è il bps (19200)):
void BufferedSerial::update(float elapsed)
{
baud_timer += elapsed;
if (bytes_written > 1024)
{
// maintain baudrate
float time_should_have_taken = (float(bytes_written)*10)/float(baudrate);
float time_actually_took = baud_timer;
// sleep if we have > 20ms lag between serial transmit and our write calls
if (time_should_have_taken-time_actually_took > 0.02f)
{
float sleep_time = time_should_have_taken - time_actually_took;
int sleep_time_us = sleep_time*1000.0f*1000.0f;
//printf("BufferedSerial::update sleeping %i ms\n", sleep_time_us/1000);
delayUs(sleep_time_us);
// subtract 128 bytes
bytes_written -= 128;
// subtract the time it should have taken to write 128 bytes
baud_timer -= (float(128)*10)/float(baudrate);
}
}
}
Chiaramente c'è qualcosa che non va, da qualche parte.
Un approccio molto migliore sarebbe quello di essere in grado di determinare il numero di byte attualmente nella coda di trasmissione, e cercare di mantenerlo al di sotto di una soglia fissa, ma non riesco a capire come farlo su un OSX (POSIX).
Qualsiasi consiglio è gradito.
La sincronizzazione tra i buffer è qualcosa che POSIX è generalmente inadatto a gestire; i primi tentativi di audio e video sincronizzati su tutti i sistemi operativi dei consumatori sono un buon esempio di quanto male. Potrebbe essere necessario scrivere direttamente alla UART seriale o trovare o scrivere un driver che permetta l'ioctli plesiocrono come "emettere questo byte non prima del tempo _n_ – msw
Hai il controllo del motore di animazione? –
Il framerate dell'animazione è fisso? –