Arduino qui plante lors de l'appui sur un bouton

Bonjour,

J'ai fait le montage suivant : 4 boutons, 4 led, 1 encodeur rotatif (avec bouton poussoir intégré), et 2 potentiomètres.

Le principe est le suivant lorsqu'on appuie sur un bouton, la led correspondante s'allume et l'arduino envoie une note en midi, on coupe la note en appuyant sur le même bouton, et la led s'éteint. Les potentiomètres envoient des messages CC en midi, et l'encodeur rotatif permet d'avoir 3 banques de 4 notes différentes, ce qui permet de jouer 12 notes avec seulement 4 boutons. Le bouton de l'encodeur permet de stopper toutes les notes d'un coup.

Tout fonctionne bien, sauf lorsque j'appuie sur l'encodeur, cela stoppe bien toutes les notes, mais le problème, c'est que cela fait planter l'arduino, il n'est même plus visible dans la liste des ports, j'ai testé les composants 1 par 1, j'ai essayé avec un autre arduino, et ça me fait la même chose.

C'est sans doute mon code qui ne va pas, mais je ne vois pas l'erreur

#include <midi_serialization.h>
#include <usbmidi.h>
#include <Bounce2.h>
#include <Arduino.h>
#include <BasicEncoder.h>

// See midictrl.png in the example folder for the wiring diagram,
// as well as README.md.

void sendCC(uint8_t channel, uint8_t control, uint8_t value) {
  USBMIDI.write(0xB0 | (channel & 0xf));
  USBMIDI.write(control & 0x7f);
  USBMIDI.write(value & 0x7f);
}

void sendNote(uint8_t channel, uint8_t note, uint8_t velocity) {
  USBMIDI.write((velocity != 0 ? 0x90 : 0x80) | (channel & 0xf));
  USBMIDI.write(note & 0x7f);
  USBMIDI.write(velocity & 0x7f);
}

void voyant(int pin, bool etat) {
  if (etat) {
    digitalWrite(pin, HIGH);
  }
  else {
    digitalWrite(pin, LOW);
  }
}


const int ANALOG_PIN_COUNT = 1;
const int BUTTON_PIN_COUNT = 4;
const int LED_PIN_COUNT = 4;
const int NB_MEM = 3;

// Change the order of the pins to change the ctrl or note order.
int rotaryPinA = 11;
int rotaryPinB = 12;
int stopPin = 2;
int analogPins[ANALOG_PIN_COUNT] = { A0 };
int buttonPins[BUTTON_PIN_COUNT] = { 7, 8, 9, 10 };
int ledPin[LED_PIN_COUNT] = { 3, 4, 5, 6 };
bool ledState[NB_MEM][LED_PIN_COUNT] = {
  { false, false, false, false },
  { false, false, false, false },
  { false, false, false, false },
};

int gamme[NB_MEM][BUTTON_PIN_COUNT] = {
  { 64, 67, 70, 73 },
  { 74, 77, 80, 83 },
  { 84, 87, 90, 93 },
};
//int brillance[LED_PIN_COUNT] = { 40, 25, 40, 25 };

int ccValues[ANALOG_PIN_COUNT];
int buttonDown[BUTTON_PIN_COUNT];
int memoire = 0;
//int bouton[BUTTON_PIN_COUNT];

Bounce bouton[BUTTON_PIN_COUNT] = Bounce();
Bounce stopBouton = Bounce();
BasicEncoder encoder(rotaryPinA, rotaryPinB);

int readCC(int pin) {
  // Convert from 10bit value to 7bit.
  return analogRead(pin) >> 3;
}

void setup() {
  //Serial.begin(9600);
  for (int i = 0; i < LED_PIN_COUNT; ++i) {
    pinMode(ledPin[i], OUTPUT);
    voyant(ledPin[i], true);
    delay(100);
    voyant(ledPin[i], false);
  }

  for (int i = 0; i < ANALOG_PIN_COUNT; ++i) {
    pinMode(analogPins[i], INPUT);
    ccValues[i] = readCC(analogPins[i]);
  }

  for (int i = 0; i < BUTTON_PIN_COUNT; ++i) {
    bouton[i].attach(buttonPins[i], INPUT_PULLUP);
    bouton[i].interval(5);
    //    buttonDown[i] = isButtonDown(i);
  }
  stopBouton.attach(stopPin, INPUT_PULLUP);
  stopBouton.interval(5);
}

void loop() {
  //Handle USB communication
  USBMIDI.poll();

  while (USBMIDI.available()) {
    // We must read entire available data, so in case we receive incoming
    // MIDI data, the host wouldn't get stuck.
    u8 b = USBMIDI.read();
  }
  encoder.service();
  int encoder_change = encoder.get_change();
  if (encoder_change) {
    memoire = abs(encoder.get_count() % 3);
    for (int i = 0; i < BUTTON_PIN_COUNT; ++i) {
      voyant(ledPin[i], ledState[memoire][i]);
      //Serial.println(memoire);
    }
  }
  stopBouton.update();
  if (stopBouton.fell()) {
    for (int i = 0; i < BUTTON_PIN_COUNT; ++i) {
      voyant(ledPin[i], false);
    }
    for (int i = 0; i < NB_MEM; ++i) {
      for (int j = 0; j < BUTTON_PIN_COUNT; ++i) {
        ledState[i][j] = false;
        sendNote(0, gamme[i][j], 0);
        delay(1);
        //Serial.println(ledState[i][j]);
      }
    }
  }
  for (int i = 0; i < ANALOG_PIN_COUNT; ++i) {
    int value = readCC(analogPins[i]);
    // Send CC only if th has changed.
    if (ccValues[i] != value) {
      sendCC(0, i, value);
      ccValues[i] = value;
    }
  }
  for (int i = 0; i < BUTTON_PIN_COUNT; ++i) {
    bouton[i].update();
    if ( bouton[i].fell()) {
      Serial.println("appuyé");
      ledState[memoire][i] = !ledState[memoire][i];
      voyant(ledPin[i], ledState[memoire][i]);
      sendNote(0, gamme[memoire][i], ledState[memoire][i] ? 120 : 0 );
    }
  }

  // Flush the output.
  USBMIDI.flush();
}

vous avez des résistances de limitation de courant pour les LEDs ?
un schéma des branchements serait utile

à mon avis cette ligne doit vous donner un warning à la compilation

Bounce bouton[BUTTON_PIN_COUNT] = Bounce();

et créer ensuite bien des soucis..

oui, j'ai des résistances, et aucun warnings à la compilation

activez les warnings étendus dans les préférences

image

je les ai activé, il n'y a pas de warnings

on devrait écrire

Bounce bouton[BUTTON_PIN_COUNT] = {Bounce()};

sinon le compilateur devrait dire
warning: array must be initialized with a brace-enclosed initializer [-fpermissive]

mais il semblerait que le compilateur fasse ce qu'il faut quand même

comment est câblé l'encodeur (et son bouton) ?

J'ai soudé la masse du bouton, et celle de l'encodeur ensemble, mais je ne pense pas que cela vienne de là, j'ai testé l'encodeur seul, et ça ne plante pas.

bon, maintenant, l'arduino est toujours reconnue, mais j'ai remarqué que la led TX reste allumé lorsque la carte plante

Visiblement le problème vient de cette partie du code, car lorsque je la commente, ça ne plante plus.

    for (int i = 0; i < NB_MEM; ++i) {
      for (int j = 0; j < BUTTON_PIN_COUNT; ++i) {
        ledState[i][j] = false;
        sendNote(0, gamme[i][j], 0);
        delay(5);
        //Serial.println(ledState[i][j]);
      }
    }

Bonjour jojo_monk

Encore une victime du copier/coller :wink:

for (int j = 0; j < BUTTON_PIN_COUNT; ++J)
// Est mieux que
for (int j = 0; j < BUTTON_PIN_COUNT; ++i)

Avec cette erreur, i dépassait le maximum NB_MEM et j ne bougeait pas.
Invoquer un indice de tableau en au-delà de la déclaration ...

Cordialement
jpbbricole

Ah merci, j’ai cherché des heures, et je l’avais même pas vu…. La prochaine fois je mets a et b a la place de i et j, je repèrerais peut-être mieux l’erreur

@jpbbricole oeil de lynx encore une fois :slight_smile:

Bonjour jojo_monk

Pourquoi pas MEM et BUTTON, c'est encore plus claire et "ça ne mange pas de pain".

Bonne journée
Cordialement
jpbbricole

Oui c’est vrai, en cherchant à économiser quelques lettres à taper, on perd des heures en déboggage…

Bonjour jojo_monk

Tu peux toujours te rassurer, tu n'est pas le seul à qui c'est arrivé, loin s'en faut.

En même temps, un Arduino qui plante dans la situation telle qu'exposée dans le post #9, me dit rapidement, indice de tableau qui dépasse les limites indiquées, chose qui est rédhibitoire dans ce type de langage.

Cordialement
jpbbricole

Oui ça sentait le débordement de tableau / mémoire mais en lisant le code sur mon iPhone j'avais raté le souci d'indice :slight_smile:

généralement on met les variables en minuscule (camelCase)

par exemple

for (int buttonIndex = 0; buttonIndex < BUTTON_PIN_COUNT; buttonIndex++) {...}