J'ai viré tout le "code Leds" pour ne laisser que le "code MIDI", si quelque chose vous saute aux yeux.
Si il s'agit d'une bande de led adressable, le temps d'écriture sur la bande pourrait bien être trop long pour gérer
correctement le midi.
En gardant le code que tu as posté ici, peux-tu tester en allumant ardLed quand la vélocité > 0 et en l'éteignant quand la vélocité vaut 0 et essayer
avec ton piano si ardLed suit bien la pression d'une touche ?
Ce sont 2 bandes de LED RVB, elle "consomment" 6 analogWrite par tour de boucle, penses-tu que cela peut perturber le MIDI ?
Voici mon "truc" avec le code LED, qui utilise une ch'tite librairie maison :
#include "LedRVB.h"
#define ardLed 13
// Serial reading data
LedRVB ledStripL(3,5,6), ledStripR(9,10,11);
void setup()
{
pinMode(ardLed,OUTPUT);
Serial.begin(31250); // Begin Serial MIDI
ledStripL.setVal(NOIR);
ledStripR.setVal(NOIR);
digitalWrite(ardLed,LOW);
}
// Data for MIDI words
byte state=0;
byte msgTyp=0;
byte charTmp,cmd,newMsg;
// RGB led values & Timeout
int note,velo,lR,lG,lB,rR,rG,rB;
unsigned long lastMid,lastMsg;
void loop()
{
if (Serial.available() > 0) { // Only if serial data arrived...
digitalWrite(ardLed,HIGH);
lastMid=millis();
charTmp = Serial.read(); // Read the first char...
if (charTmp==0xF8 || charTmp==0xFE) { // ...If it is a RealTimeClock Message...
// ...just ignore it
}
else // But if it is NOT a RTC-M...
{
switch(state){
case 2:
velo=charTmp; // Save the velocity byte
newMsg=1;
rB=1;
break;
case 1:
note=charTmp; // Save the note byte
state=2;
rG=1;
break;
case 0:
cmd=charTmp; // Save the command byte
state=1;
rR=1;
break;
}
}
}
if (newMsg==1) {
lastMsg=millis();
newMsg=0;
state=0;
if (cmd==0x90) msgTyp=1;
else{
if (cmd==0xB0 && note==0x40) msgTyp=2;
else msgTyp=0;
}
switch(msgTyp){
case 2:
if (velo>0) lB=50;
else lB=1;
break;
case 1:
if (velo>0) lG=50;
else lG=1;
break;
case 0:
if (velo>0) lR=50;
else lR=1;
break;
}
}
// Normal LOOP CODE
if (millis()>lastMid+5) digitalWrite(ardLed,LOW);
if (millis()>lastMsg+1000) { // If there is no MIDI word since 1 second, switch off the leds
rR=0;
rG=0;
rB=0;
lR=0;
lG=0;
lB=0;
}
ledStripL.setVal(lR,lG,lB);
ledStripR.setVal(rR,rG,rB);
}
EDIT : J'ajoute que dans tous les tests que je fais, le premier messages MIDI reçu juste après un reboot de l'Arduino est bien pris en compte (NoteOn & SustainOn, y compris avec la bonne vélocité et la bonne note)... surprenant non ?
EDIT 2 : Pour aider à la compréhension du code, les bandes de Led sont en mode "DEBUG" :
Celle de gauche est censée s'allumer "VertFort" quand elle reçoit un NoteOn, VertFaible quand elle reçoit un "NoteOff", BleuFort/Faible en fontction du Sustain et Rouge si le message n'est pas reconnu.
Celle de droite elle s'allume Rouge quand elle reçoit un cmd, Vert quand elle reçoit une note, et Bleu quand elle reçoit une vélocité, elle doit donc toujours s'allumer "R+V+B"
Ce sont 2 bandes de LED RVB, elle "consomment" 6 analogWrite par tour de boucle, penses-tu que cela peut perturber le MIDI ?
Le plus simple c'est de mesurer avec micros() avant et après l'appel à ledStripL.setVal();
Tu as 320 microsecondes à disposition par tour de boucle pour "consommer" ce qui arrive sur ton port série MIDI en entrée. Si tu suis pas
le rythme, le buffer d'entrée série (dont j'ignore la longueur) va simplement déborder et tu perds des données.
Pour le moment ton code passe le plus clair de son temps à faire ledStripL.setVal(); si ce code dépasse 320 microsecondes ça expliquerai le problème.
Peux-tu faire cette mesure stp ? ou donner la référence à la librairie que tu utilises ?
La librairie je l'ai crée moi-même, voici ce que fait cette fonction :
Je vais effectivement mesurer la durée (micros) de cette fonction dans la main loop, c'est une information intéressante et je peux le faire sans être connecté en MIDI (l'Arduino ne peut pas débugger par moniteur serie & écouter du MIDI en même temps en HardSerial).
Toutefois, je ne pense sincèrement pas que ça puisse venir de la, après une courte recherche sur le net, un analogWrite devrait prendre entre 2µs a 7µs, donc en exagérant au pire, ma fonction devrait durer dans les 60µs, reste à voir les constrain() mais j'y crois pas trop non-plus.
PS : J'attends avec impatiente, l'arrivée de mon shield LCD-I2C pour débugger tout ça en local, par exemple en exportant vers l'écran le nombre de caractères dans le buffer, ou le dernier mot reçu
En fait mon piano n'envoi pas forcément la commande NoteOn ou SustainOn si plusieurs messages de ce même type se suivent, exemple :
NoteOn de la note 23 avec vélocité 50, suivi d'un NoteOff de la même note :
0x902350
0x2300
Du coup, au lieu de remettre mon state à 0 je le met à 1 (prêt à lire une nouvelle note) :
if (newMsg==1) {
newMsg=0;
state=1;
....
Et si c'est une commande, je le remet à 0 :
if (charTmp==0x90 || charTmp==0xB0) state=0; //...if it is a command...
Merci à tous !
PS : Pour y arriver j'ai monté un SoftSerial pour écouter le MIDI de mon piano, et l'Arduino renvoyait les valeurs vers le moniteur Arduino (par le "hard"serial).