contrôler Servos en MIDI

Bonjour,
Je suis en train de travailler sur un projet assez conséquent, il s’agit d’une chorale de 24 cranes de corbeaux en resine animés par des servo SG90 pilotés en MIDI via un arduino Mega.
une petite vidéo pour expliquer le projet:

je suis novice en code, je me suis basé sur le code de “notes and volts” CC light show, malheureusement je rencontre déjà pas mal de soucis alors que je n’ai que 2 servos branchés.

mon premier souci est que la course des servo n’est absolument pas linéaire, j’ai des soubresauts, des retours en arrière, etc…

mon deuxième souci est que mon CC23 (censé contrôler uniquement le servo 2) contrôle également mon servo 1 (en CC22 pourtant…)

Le problème ne vient pas du hardware, j’ai testé le montage avec l’exemple “servo” de arduino ainsi qu’avec le connection kit de max for live et les mouvement sont bien fluide.

Voilà voilà… Si quelqu’un est chaud de jeter un oeil au code le voici:

    /*
        MIDI CC Light Show
        by Notes and Volts
        www.notesandvolts.com
    */
    ​
    #include <MIDI.h>  // Add Midi Library
    #include <Servo.h>
    Servo myservo1;  // create servo object to control a servo
    Servo myservo2;  // create servo object to control a servo
    ​
    ​
    //Create an instance of the library with default name, serial port and settings
    MIDI_CREATE_DEFAULT_INSTANCE();
    ​
    void setup() {
    myservo1.attach(2);  // attaches the servo on pin 2 to the servo object
    myservo2.attach(3);  // attaches the servo on pin 3 to the servo object
    ​
      MIDI.begin(MIDI_CHANNEL_OMNI); // Initialize the Midi Library.
      // OMNI sets it to listen to all channels.. MIDI.begin(2) would set it
      // to respond to notes on channel 2 only.
      MIDI.setHandleControlChange(MyCCFunction); // This command tells the MIDI Library
      // the function you want to call when a Continuous Controller command
      // is received. In this case it's "MyCCFunction".
    }
    ​
    void loop() { // Main loop
      MIDI.read(); // Continuously check if Midi data has been received.
    }
    ​
    // MyCCFunction is the function that will be called by the Midi Library
    // when a Continuous Controller message is received.
    // It will be passed bytes for Channel, Controller Number, and Value
    // It checks if the controller number is within the 22 to 27 range
    // If it is, light up the corresponding LED with the PWM brightness equal to the Value byte
    void MyCCFunction(byte channel, byte number, byte value) {
      switch (number) {
       
        case 22:
    myservo1.write(value * 1.417);                  // sets the servo position according to the scaled value
                break;
         case 23:
    myservo2.write(value * 1.417);                  // sets the servo position according to the scaled value
                break;
      }
    }

merci!

Bonjour,

Il me semble que servo.write() préfère un int comme paramètre.
Cast ton résultat de calcul en int pour voir...
(sympa les crânes de corbeaux)

merci pour la réponse!
j'ai oublié de préciser que je suis une grosse quiche en programmation, je débute à fond en arduino, pourriez vous me donner un exemple pour utiliser la fonction int comme variable?

j'ai changé ça dans le code:

void MyCCFunction(byte channel, byte number, int value) {

mais mon servo est toujours aussi gogol...
C'etait bien ça l'idée?

Ayant précisé que tu débutais, j'ai pris les devants dans ma réponse.
Le mot 'cast' de mon dernier message est un lien. Clique dessus :wink:

Non, c'est le résultat de ta multiplication que tu dois caster car cela retourne un 'double', pas un 'int'.

Bonjour,

Non, il ne faut pas changer le type des paramètres de la fonction callback. Le compilateur aurait du te signaler une erreur.
Ce que Zlika avait voulu dire c'était de convertir explicitement le paramètre en int.

myservo1.write((int)(value * 1.417));

Ce n'est pas faux, mais ça ne sert à rien, le compilateur le fait implicitement.

ok! je viens de tester en rajoutant le (int) mais c'est toujours la crise de gogolite pour mon servo...

Il faudrait savoir à quelle cadence les commandes midi sont envoyées car si tu envoies une nouvelle commande avant la fin de déplacement du servo ça risque de faire des choses bizarres.

Comment savoir cette fameuse cadence?

Par contre, la commande du servo se fait avec une valeur comprise entre 0 et 180.
Donc si tu pars d'une valeur de 0 à 255 provenant de ton contrôleur, il faut diviser par 1.417 et pas multiplier.

La fonction map est utile pour se genre de convertion mais dans ton cas, il n'y a pas de translation donc une simple division suffit.

je pars d'une valeur de 0 à 127 (norme Midi) et 127 x 1.417 = 179,95, donc la dessus je pense que je ne me suis pas loupé :wink:

guscac:
Comment savoir cette fameuse cadence?

Comment sont envoyées les commandes midi? Tu dois bien savoir quelles sont les commandes envoyées et à quelle cadence.

Les commandes midi sont envoyées par ableton via une interface usb/midi, je controle ableton avec un potentiometre. même en le bougeant par tous petits pas ça fait n'importe quoi.

Oups :-X, oui désolé. J'étais rester sur un Byte et avait oublié que le Bit de poids fort était utilisé pour autre chose.

Vu le nom du callback, je ne pense pas qu'il s'agisse d'un problème de répétition de la trame.
Peut-être qu'il faut mieux filtrer avec le paramétrage du channel lors de l'initialisation du midi...

je ne crois que ça vienne de là, je viens de me regler sur un canal midi (9) plutôt qu'en OMNI et ça ne change rien...

Il faudrait afficher les valeurs reçues au niveau du ‘case’ dans le moniteur pour isoler un peu plus le problème.

Si la valeur varie de façon aléatoire, il faut regarder côté contrôleur.
Sinon il faut appeler un exorciste pour le servomoteur.

guscac:
je pars d'une valeur de 0 à 127 (norme Midi) et 127 x 1.417 = 179,95, donc la dessus je pense que je ne me suis pas loupé :wink:

bonjour

l'argument ne gere pas les valeurs decimales

Le résultat à été caster en int mais ça ne change rien apparemment.

bon, j'ai testé d'ajouter Serial.begin(9600); dans le void setup et Serial.println(); dans le void loop,
ça m'affiche du language exta terrestre à base carrés (au fait mon moniteur est bien sur 9600 baud) et ça met le soft arduino en pls (obligé de débrancher l'arduino pour le debloquer...)