Fråga:
Programvara Serien är för långsam för MIDI?
Michel Keijzers
2017-05-20 06:06:16 UTC
view on stackexchange narkive permalink

Jag försökte använda SoftwareSerial-biblioteket för MIDI (med 47 effekter), men det verkar som om jag får regelbundet skadade / oväntade meddelanden.

Kretsen jag använder fungerar perfekt när jag ansluter den till HardwareSerial-lösning (så problemet måste ligga i programvara).

Vad jag ser är:

  • När jag trycker på anteckningar och släpper anteckningar tänds och släcks LED 13 korrekt.
  • När jag använder Serial.print för felsökning får jag korrekta meddelanden. I exemplet nedan tog jag dock bort utskriftsuttalanden för att ha ett minimalt exempel).
  • När jag använder SoftwareSerial tänds och släcks LED 13 för varje anteckning korrekt. Men när jag skickar många meddelanden (till exempel genom aftertouch / pitch bend som skickar många meddelanden på kort tid) märkte jag att Obs På / Av-kommandon med "slumpmässiga" värden skickas.

Vissa källor säger att SoftwareSerial borde fungera för MIDI, men hittills är det långt ifrån perfekt. Gör jag något misstag?

(btw, MIDIs baudrate är 31.250 bps, när jag använder pitchband skickas flera hundra byte per sekund, så långt inom MIDI-specifikationen).

Skissen jag använder är:

  #include <MIDI.h> // Add Midi Library # include <SoftwareSerial.h>SoftwareSerial swSerial (2, 11); // RX, TXMIDI_CREATE_INSTANCE (SoftwareSerial, swSerial, midiSw1); # define LED 13 // Arduino Board LED lyser på Pin 13void setup () {pinMode (LED, OUTPUT); // Ställ in Arduino-kortstift 13 för att mata ut midiSw1.begin (MIDI_CHANNEL_OMNI); midiSw1.setHandleNoteOn (MyHandleNoteOn); midiSw1.setHandleNoteOff (MyHandleNoteOff);} void loop () {midiSw1.read ();} void MyHandleNoteOn (byte channel, byte pitch, byte speed) {digitalWrite (LED, HIGH); // Slå på lysdioden} ogiltig MyHandleNoteOff (byte kanal, byte tonhöjd, byte hastighet) {digitalWrite (LED, LOW); // Stäng av lysdioden}  
Jag har upplevt exakt samma problem. Enligt min erfarenhet är SoftwareSerial inte tillräckligt snabbt för att hantera snabba, successiva MIDI-meddelanden. Jag hittade att jag fick de bästa resultaten genom att använda hårdvaruserien för MIDI och använda SoftwareSerial + en annan Arduino för felsökning. Även om detta var den bästa installationen, var det fortfarande inte perfekt. Även hårdvaruserien tappade / skadade meddelanden då och då.
"digitalWrite" kan vara för långsam. Försök att ersätta den med `PORTB | = 0x20;` och `PORTB & = ~ 0x20;`. Men det finns inget mycket du kan göra för att påskynda all MIDI-hanteringskod.
@Mazaryk ... Jag använder redan en Mega som har 4 hårdvaruserier, hittills använder jag 3 för MIDI, en för felsökning (för tillfället kan senare vara den 4: e MIDI). Och när den fjärde används för MIDI kommer jag antagligen att använda en annan Arduino som felsökning. Jag gjorde en hel del testning och hittills fick jag aldrig tappade / skadade meddelanden ... och CL föreslog att använda de ännu bättre H11L1 optokopplarna istället för 6N138 som jag använder nu.
@CL: Tack ... allt för att påskynda kan vara bra ... men eftersom hårdvaruserielösningen fungerade bra med digitalWrite och mjukvaruserien inte, tycker jag fortfarande att det är för oförutsägbart om jag måste använda sådana "knep" .. .. senare vill jag också göra ytterligare bearbetning som kan göra programvarulösningen omöjlig (igen).
Ett svar:
Majenko
2017-05-20 16:53:46 UTC
view on stackexchange narkive permalink

Problemet med SoftwareSerial är att medan den tar emot ett paket kan Arduino inte göra någonting annat - det inkluderar läsbyte från RX-bufferten, så det kommer lätt att flöda om du skickar saker för snabbt. Med HardwareSerial kan du läsa från bufferten medan den tar emot data, så överflöd är ett mindre problem.

Så snart START-biten i ett paket tas emot kommer den in i en ISR och läser var och en av återstående 9 bitar data (inklusive stoppbit) i en tät slinga. Den ISR avslutas inte förrän hela paketet har tagits emot och lagrats i RX-bufferten. Om en annan byte skickas direkt går det lite tid mellan ISR-avslutningen och att den utlöses igen. Resten av koden, inklusive MIDI-parsningsrutiner som läser data från RX-bufferten, svälts sedan ut av CPU-cykler och kan inte köras ordentligt. Skicka för många byte tillsammans och den begränsade RX-bufferten (64 byte) fylls och flödar över, så förlorar du data.

Ett annat problem med SoftwareSerial är att den måste fånga START-biten när den anländer. Varje försening i att fånga den kanten kommer att resultera i en drift i bitprovtagningstimingen. Om det finns något annat som använder avbrott samtidigt (såsom millis () -timern) fördröjs utlösningen av PCINT-avbrottet som används för START-bitdetektering. Även SoftwareSerial-avbrottet har en viss tid efter att det har tagit emot paketet där det lagras i RX-bufferten och återvänder från avbrottsrutinen. Om nästa paket anländer före är ISR redo att betjäna det kommer det att finnas en fördröjning - och någon fördröjning är dålig.

Personligen är jag av den uppfattningen att SoftwareSerial aldrig borde vara används för någonting någonsin. Om du behöver fler seriella portar behöver du antingen ett kraftfullare chip eller så behöver du mer än ett chip och få dem att kommunicera tillsammans via en annan hårdvarukanal med högre hastighet (SPI eller I2C, till exempel).

SoftwareSerial är endast lämpligt för att skicka korta utbrott av data (eftersom det blockeras helt under sändning) eller ta emot mycket korta meddelanden som sänds sällan.

Mycket hjälpsam information (som alltid) ... Jag försökte göra bufferten 128 byte men jag såg ingen förbättring. Naturligtvis kan jag göra det 256 till kanske 512, men förmodligen "fördröjer" det tiden innan jag får problem om jag läser din förklaring.
Om du skickar massor mycket hela tiden så ja, allt du kommer att göra är att fördröja tiden innan du ser problem. Det finns också alltid chansen att om nästa paket kommer för snabbt kommer ISR inte att kunna svara tillräckligt snabbt och du kan förlora början på nästa paket, vilket utlöser delvis igenom nästa fallande kant inom det.
Kanske i framtiden (om mitt projekt kommer att växa) kan jag behöva gå till en annan tavla (ge mig 8 hårdvaruserier). För närvarande använder jag en SD-skärm, planerar att använda en WIFI-skärm och eventuellt en USB (värd) -sköld, behöver också ett prototypkort för ytterligare komponenter (flera optokopplare etc). Så kanske 2 Mega skulle vara bra :-)
Kanske till och med tre;) Du kan aldrig ha för många. Det kan vara bra att dela upp ett projekt i komponentblock och få dem att styras och hanteras separat. Kanske ha en central huvudkontroll än att berätta för alla andra vad de ska göra.
Ja låter helt klart för mig :-) ... Jag vet inte om du är bekant med MIDI, men notera på / av kommer inte att ge ett problem, men CC-meddelanden (som pitchbending / aftertouch resulterar i många byte, väl inom baudrate för MIDI som är 31250 bps, men förmodligen för långsam för SoftwareSerial).
Det låter också som en väldigt cool idé ... men kom ihåg att det här är det första Arduino-projektet jag gör :-) ... å andra sidan om projektet långsamt växer är det väldigt bra att lära sig mycket om Arduinos / mikrokontroller och elektronik.
Ja, jag känner MIDI ganska bra. Som jag nämnde i en kommentar ovan är det inte bara mängden som kan vara ett problem utan klyftan mellan på varandra följande paket. Till och med bara två paket som skickas för nära varandra kan vara problematiska.
Och "problemet" är att jag inte bryr mig om att förlora ett CC-meddelande, men ett anteckningsmeddelande som inte hanteras resulterar i en anteckning som låter för alltid (såvida inte ljudet ändras på en synth) ... det här är helt oacceptabelt i en levande musik situation.
Absolut. Det kan vara användbart att programmera en "kill switch" som stoppar alla ljud i en nödsituation. För säkerhets skull.
En kill-switch är inte något som också är praktiskt (i mitt fall) ... Jag vill låta MIDI-rutan (som jag kallar det) för att svara på misstag från syntar och bearbeta dem och skicka tillbaka meddelanden ... så boxen kan vara utom synhåll för mig själv när jag spelar, men jag kan göra ett MIDI-meddelande som resulterar i en sådan dödfunktion (anteckningar).
Ja, det behöver inte vara en fysisk knapp direkt ansluten - det är därför jag använde citat;) Bara någon signal som kan skickas för att säga "håll käften". Kanske få det att svara på en ton du aldrig spelar (C8 eller något) så det är precis framför dig hela tiden på tangentbordet. Du kan till och med sluta införliva det i dina föreställningar;)
Låt oss [fortsätta denna diskussion i chatt] (http://chat.stackexchange.com/rooms/59042/discussion-between-michel-keijzers-and-majenko).


Denna fråga och svar översattes automatiskt från det engelska språket.Det ursprungliga innehållet finns tillgängligt på stackexchange, vilket vi tackar för cc by-sa 3.0-licensen som det distribueras under.
Loading...