Domanda:
SoftwareSerial troppo lento per il MIDI?
Michel Keijzers
2017-05-20 06:06:16 UTC
view on stackexchange narkive permalink

Ho provato a utilizzare la libreria SoftwareSerial per MIDI (da 47 effetti), ma sembra che riceva regolarmente messaggi corrotti / imprevisti.

Il circuito che sto usando funziona perfettamente quando lo collego con il Soluzione HardwareSerial (quindi il problema deve risiedere nel software).

Quello che vedo è:

  • Quando premo note e note di rilascio, il LED 13 si accende e si spegne correttamente.
  • Quando uso Serial.print per il debug ricevo messaggi corretti. Tuttavia, nell'esempio seguente ho rimosso le istruzioni print per avere un esempio minimo).
  • Quando uso SoftwareSerial, il LED 13 si accende e si spegne correttamente per ogni nota. Tuttavia, quando invio molti messaggi (ad esempio tramite aftertouch / pitch bend che inviano molti messaggi in breve tempo), ho notato che vengono inviati comandi Note On / Off con valori "casuali".

Alcune fonti dicono che SoftwareSerial dovrebbe funzionare per MIDI, tuttavia, finora è tutt'altro che perfetto. Faccio qualche errore?

(btw, il baudrate del MIDI è 31.250 bps, quando uso la banda del passo vengono inviate diverse centinaia di byte al secondo, fino ad ora all'interno delle specifiche MIDI).

Lo schizzo che utilizzo è:

  #include <MIDI.h> // Aggiungi libreria Midi # include <SoftwareSerial.h>SoftwareSerial swSerial (2, 11); // RX, TXMIDI_CREATE_INSTANCE (SoftwareSerial, swSerial, midiSw1); # define LED 13 // Arduino Board LED is on Pin 13void setup () {pinMode (LED, OUTPUT); // Imposta il pin 13 della scheda Arduino per emettere midiSw1.begin (MIDI_CHANNEL_OMNI); midiSw1.setHandleNoteOn (MyHandleNoteOn); midiSw1.setHandleNoteOff (MyHandleNoteOff);} void loop () {midiSw1.read ();} void MyHandleNoteOn (canale byte, passo byte, velocità byte) {digitalWrite (LED, HIGH); // Accendi il LED} void MyHandleNoteOff (canale byte, passo byte, velocità byte) {digitalWrite (LED, LOW); // Spegni il LED}  
Ho riscontrato lo stesso identico problema. Nella mia esperienza SoftwareSerial non è abbastanza veloce per gestire messaggi MIDI rapidi e successivi. Ho trovato i migliori risultati utilizzando la seriale hardware per MIDI e utilizzando SoftwareSerial + un altro Arduino per il debug. Sebbene questa fosse la migliore configurazione, non era ancora perfetta. Anche il seriale hardware ha lasciato cadere / danneggiato i messaggi di tanto in tanto.
"digitalWrite" potrebbe essere troppo lento. Prova a sostituirlo con "PORTB | = 0x20;" e "PORTB & = ~ 0x20;". Ma non c'è molto che puoi fare per accelerare tutto il codice di gestione MIDI.
@Mazaryk ... Uso già un Mega che ha 4 seriali hardware, finora ne uso 3 per il MIDI, uno per il debug (per ora, dopo può essere il 4 ° MIDI). E quando il 4 ° viene utilizzato per il MIDI, probabilmente userò un altro Arduino come debug. Ho fatto molti test e finora non ho mai ricevuto messaggi persi / danneggiati ... e CL ha proposto di utilizzare gli accoppiatori ottici H11L1 ancora migliori invece del 6N138 che uso ora.
@CL: Grazie ... tutto per accelerare potrebbe essere buono ... tuttavia, poiché la soluzione seriale hardware ha funzionato bene con digitalWrite e il software seriale no, penso ancora che sia troppo imprevedibile se devo usare questi 'trucchi' .. .. in seguito voglio fare anche un'elaborazione aggiuntiva che potrebbe rendere la soluzione software inattuabile (di nuovo).
Una risposta:
Majenko
2017-05-20 16:53:46 UTC
view on stackexchange narkive permalink

Il problema con SoftwareSerial è che mentre sta ricevendo un pacchetto, Arduino non è in grado di fare nient'altro, inclusa la lettura di byte dal buffer RX, quindi andrà facilmente in overflow se invii le cose troppo rapidamente. Con HardwareSerial sei in grado di leggere dal buffer mentre riceve i dati, quindi l'overflow è un problema minore.

Non appena il bit START di un pacchetto viene ricevuto, entra in un ISR e legge ciascuno dei i restanti 9 bit di dati (compreso il bit di stop) in un ciclo stretto. Quell'ISR non esce finché l'intero pacchetto non è stato ricevuto e memorizzato nel buffer RX. Se un altro byte viene inviato immediatamente, c'è poco tempo tra la fine dell'ISR e il suo nuovo trigger. Il resto del codice, comprese le routine di analisi MIDI che leggono i dati dal buffer RX, sono quindi prive di cicli della CPU e non possono essere eseguite correttamente. Invia troppi byte insieme e il buffer RX limitato (64 byte) si riempie e trabocca e perdi i dati.

Un altro problema con SoftwareSerial è che deve catturare il bit START nel momento in cui arriva. Qualsiasi ritardo nella cattura di quel fronte risulterà in una deriva nella temporizzazione del campionamento dei bit. Se c'è qualcos'altro che sta usando interrupt allo stesso tempo (come il timer millis () ) ritarderà l'attivazione dell'interrupt PCINT usato per il rilevamento del bit START. Anche lo stesso interrupt SoftwareSerial ha una certa quantità di tempo dopo aver finito di ricevere il pacchetto dove lo memorizza nel buffer RX e ritorna dalla routine di interrupt. Se il prossimo pacchetto arriva prima che l'ISR è pronto per il servizio, ci sarà un ritardo e qualsiasi ritardo è negativo.

Personalmente sono dell'opinione che SoftwareSerial non dovrebbe mai essere usato per qualsiasi cosa, mai. Se hai bisogno di più porte seriali, allora hai bisogno di un chip più potente o hai bisogno di più di un chip e farli comunicare insieme attraverso un altro canale hardware a velocità più elevata (SPI o I2C, per esempio).

SoftwareSerial è adatto solo per inviare brevi raffiche di dati (poiché si blocca completamente durante l'invio) o per ricevere messaggi molto brevi inviati di rado.

Informazioni molto utili (come sempre) ... Ho provato a rendere il buffer di 128 byte ma non ho visto alcun miglioramento. Ovviamente posso farlo 256 o forse 512, ma probabilmente sta solo "ritardando" il tempo prima di entrare nei problemi se leggo la tua spiegazione.
Se invii sempre lotti e lotti, sì, tutto ciò che farai sarà ritardare il tempo prima di vedere problemi. Inoltre c'è sempre la possibilità che se il pacchetto successivo arriva troppo velocemente, l'ISR non sarà in grado di rispondere abbastanza velocemente e potresti perdere l'inizio del pacchetto successivo, innescandosi a metà strada sul successivo fronte di caduta al suo interno.
Forse in futuro (se il mio progetto crescerà) potrei dover passare a un'altra scheda (dandomi 8 seriali hardware). Attualmente utilizzo uno scudo SD, progettando di utilizzare uno scudo WIFI e possibilmente uno scudo USB (host), inoltre ho bisogno di una scheda prototipo per componenti aggiuntivi (diversi accoppiatori ottici, ecc.). Quindi forse 2 Mega andrebbero bene :-)
Forse anche tre;) Non puoi mai averne troppe. Può essere utile suddividere un progetto in blocchi di componenti e controllarli e gestirli separatamente. Forse avere un controller principale centrale che dice a tutti gli altri cosa fare.
Sì suona perfettamente chiaro per me :-) ... non so se hai familiarità con il MIDI, ma le note on / off non daranno problemi, ma i messaggi CC (come il pitchbending / aftertouch danno come risultato molti byte, ben entro il baudrate del MIDI che è 31250 bps, ma probabilmente troppo lento per SoftwareSerial).
Anche questa suona come un'idea molto interessante ... ma ricorda, questo è il primo progetto Arduino che faccio :-) ... d'altra parte se il progetto crescerà lentamente è molto bello imparare molto su Arduino / microcontrollori e elettronica.
Sì, conosco abbastanza bene il MIDI. Come ho detto in un commento sopra non è solo la quantità che può essere un problema, ma il divario tra i pacchetti successivi. Anche solo due pacchetti inviati troppo vicini possono essere problematici.
E il `` problema '' è che non mi dispiace perdere un messaggio CC, ma un messaggio di nota off non gestito risulta in una nota che suona per sempre (a meno che non cambi i suoni su un synth) ... questo è totalmente inaccettabile in un situazione di musica dal vivo.
Assolutamente. Può essere utile programmare un "kill switch" che interrompe tutti i suoni in caso di emergenza. Nel caso in cui.
Anche un kill switch non è qualcosa che è utile (nel mio caso) ... Voglio che il MIDI box (come lo chiamo io) risponda ai missaggi provenienti dai sintetizzatori e li elabori e invii messaggi indietro ... box potrebbe anche essere fuori dalla vista per me stesso mentre gioco, ma potrei creare un messaggio MIDI che si traduca in tale funzionalità di kill (note).
Sì, non deve essere un pulsante fisico collegato direttamente - ecco perché ho usato le virgolette;) Solo un segnale che può essere inviato per dire "stai zitto". Forse fai in modo che risponda a una nota che non suoni mai (C8, o qualcosa del genere), quindi è sempre lì davanti a te sulla tastiera. Potresti anche finire per incorporarlo nelle tue performance;)
Cerchiamo di [continuare questa discussione in chat] (http://chat.stackexchange.com/rooms/59042/discussion-between-michel-keijzers-and-majenko).


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...