HELP - Compréhension sur bug au démarrage du code

Bonjour à tous,
Sam, technicien son, DIYer a mes heures perdues (nombreuses depuis mars dernier)
J'ai fait pas mal d'électronique (fabrication préamps/compresseurs/eq/amplis à lampes/switcher/pédales/maintenance) et je débute en arduino (depuis février 2020)
Je me suis lancé dans un switcher de boucles pour guitare, j'ai "créé" un code en m'inspirant de ce que j'ai pu voir/trouver/utiliser par le passé.
Il comporte 17 "boucles" et 2x10 presets (Eeprom)
Il est basé sur l'arduino Mega (pro mini pour la version finale pour la place dans le boitier)
Mon code fonctionne à l'exception d'une chose que je n'arrive pas à comprendre.
J'ai prototypé le tout sur breadboard, et à chaque allumage, ce qui est nommé RELAY 10 s'allume sans que je comprenne pourquoi.
J'avais mis une lecture de mémoire qui rappelait un preset enregistré sur lequel TOUT les relais étaient éteints ainsi que toutes les leds des switchs de presets. Seul le relai 10 s'allume.
Je pense que ça a à voir entre le nombre de presets (10 boutons - int J) et le nombre de boucle (17 - int i) mais je ne comprends pas pourquoi.
Les boutons qui commandent les relais sont gérés avec un toggle, l'enregistrement et le rappel des presets sont gérés avec un "keypad".
Voici le code que j'utilise :

#include <EEPROM.h>
#include <Keypad.h>

const byte rows = 10; //numbers of preset switches
const byte cols = 4; //selector for write/read/banks
char keys[rows][cols] = {
{'a','k','A','K'},
{'b','l','B','L'},
{'c','m','C','M'},
{'d','n','D','N'},
{'e','o','E','O'},
{'f','p','F','P'},
{'g','q','G','Q'},
{'h','r','H','R'},
{'i','s','I','S'},
{'j','t','J','T'}
};
byte rowPins[rows] = {A4,A5,A6,A7,A8,A9,A10,A11,A12,A13}; //input of the preset switches
byte colPins[cols] = {A0,A1,A2,A3}; //input of the selector
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);

//variable will not change//

const int numberOfPedal = 17; //enter the number of loop you need
const int numberOfPresetButton = 10; // enter the number of preset button you need
const int buttonPin[17] = {12,14,15,16,17,18,19,2,3,4,5,6,7,8,9,10,11}; //define the Inputs of your arduino
const int relayPin[17] = {20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52}; //define the Outputs of your arduino
const int presetLedPin[10] = {21,23,25,27,29,31,33,35,37,39}; //define the Outputs of your arduino
boolean buttonPressed = false;
boolean Toggle = false;

//variable will change//

int i; // use for pedal number
int j; // use for preset number
int debounce =0;

////////////////////////////////////////////////////////////////////////////////////

void memory(int addr, int led)
{
  resetAllLeds();
  for(i=0; i<numberOfPedal; i++)
    {
      EEPROM.write((addr) + i, digitalRead(relayPin[i]));
      }
delay(100);
digitalWrite(presetLedPin[led], HIGH);
delay(100);
digitalWrite(presetLedPin[led], LOW);
delay(100);
digitalWrite(presetLedPin[led], HIGH);
delay(100);
digitalWrite(presetLedPin[led], LOW);
delay(100);
digitalWrite(presetLedPin[led], HIGH);
delay(100);
digitalWrite(presetLedPin[led], LOW);
delay(100);
digitalWrite(presetLedPin[led], HIGH);
delay(100);
digitalWrite(presetLedPin[led], LOW);
delay(100);
digitalWrite(presetLedPin[led], HIGH);
delay(100);
}

////////////////////////////////////////////////////////////////////////////////////

void readPreset(int addr, int pcNum, int led)
{
  resetAllLeds();
  for(i=0; i<numberOfPedal; i++)
  {
    digitalWrite(relayPin[i], EEPROM.read((addr)+i));
    digitalWrite(presetLedPin[led], HIGH);
    }
}

////////////////////////////////////////////////////////////////////////////////////

void resetAllLeds()
{
  for(int j=0; j<numberOfPresetButton; j++)
  {
    digitalWrite(presetLedPin[j], LOW);
  }
  
}

////////////////////////////////////////////////////////////////////////////////////

void resetAllRelays()
{
  for(int i=0; i<numberOfPedal; i++)
  {
    digitalWrite(relayPin[i], LOW);
  }
}

////////////////////////////////////////////////////////////////////////////////////

void toggle()
{
  resetAllLeds();
  digitalWrite(relayPin[i], !digitalRead(relayPin[i]));
}

////////////////////////////////////////////////////////////////////////////////////

void updateButtons()
{
  for(i=0; i<numberOfPedal; i++)
  {
    if(digitalRead(buttonPin[i])==HIGH)
    {
      debounce++;
    }else
    {
      debounce = 0;
      buttonPressed = false;
      Toggle = false;
    }
    if(debounce >= 1200)
    {
      buttonPressed = true;
    }
    if(buttonPressed == true && Toggle == false)
    {Toggle = true;
    toggle();
    }
  }
}

////////////////////////////////////////////////////////////////////////////////////

void updatePresets()
{
    char key = keypad.getKey();
if(key) // Check for a valid key.
  {
   switch (key)
    {
     
/****************************** STORE PRESET MODE (EEProm address,led number)*/
     case 'a':
      memory(12,0);
      break;
     case 'b':
      memory(32,1);
      break;
     case 'c':
      memory(52,2);
      break;
     case 'd':
      memory(72,3);
      break;
     case 'e':
      memory(92,4);
      break;
     case 'f':
      memory(112,5);
      break;
     case 'g':
      memory(132,6);
      break;
     case 'h':
      memory(152,7);
      break;
     case 'i':
      memory(172,8);
      break;
     case 'j':
      memory(192,9);
      break;
     case 'k':
      memory(212,0);
      break;
     case 'l':
      memory(232,1);
      break;
     case 'm':
      memory(252,2);
      break;
     case 'n':
      memory(272,3);
      break;
     case 'o':
      memory(292,4);
      break;
     case 'p':
      memory(312,5);
      break;
     case 'q':
      memory(332,6);
      break;
     case 'r':
      memory(352,7);
      break;
     case 's':
      memory(372,8);
      break;
     case 't':
      memory(392,9);
      break;
/****************************** READ PRESET MODE (EEProm address,PcNum,led number)*/
     case 'A':
      readPreset(12, 1, 0); 
      break;
     case 'B':
      readPreset(32, 2, 1);
      break;
     case 'C':
      readPreset(52, 3, 2);
      break;
     case 'D':
      readPreset(72, 4, 3);
      break;
     case 'E':
      readPreset(92, 5, 4);
      break;
     case 'F':
      readPreset(112, 6, 5);
      break;
     case 'G':
      readPreset(132, 7, 6);
      break;
     case 'H':
      readPreset(152, 8, 7);
      break;
     case 'I':
      readPreset(172, 9, 8);
      break;
     case 'J':
      readPreset(192, 10, 9);
      break;
     case 'K':
      readPreset(212, 1, 0); 
      break;
     case 'L':
      readPreset(232, 2, 1);
      break;
     case 'M':
      readPreset(252, 3, 2);
      break;
     case 'N':
      readPreset(272, 4, 3);
      break;
     case 'O':
      readPreset(292, 5, 4);
      break;
     case 'P':
      readPreset(312, 6, 5);
      break;
     case 'Q':
      readPreset(332, 7, 6);
      break;
     case 'R':
      readPreset(352, 8, 7);
      break;
     case 'S':
      readPreset(372, 9, 8);
      break;
     case 'T':
      readPreset(392, 10, 9);
      break;
      }
    } 
}

////////////////////////////////////////////////////////////////////////////////////

void setup() {
  for(i=0; i<numberOfPedal; i++)
  {
    pinMode(buttonPin[i], INPUT_PULLUP);
    pinMode(relayPin[i], OUTPUT);
    digitalWrite(relayPin[i],HIGH); //pullup all relay outputs in case off low level relayboard
    delay (25);
    digitalWrite(relayPin[i], LOW);
  }
  
  for(j=0; j<numberOfPresetButton; j++)
  {
    pinMode(presetLedPin[j], OUTPUT);
    digitalWrite(presetLedPin[j], HIGH);
    delay (25);
    digitalWrite(presetLedPin[j], LOW);
  }
  //readPreset(12, 1, 0);
}

////////////////////////////////////////////////////////////////////////////////////
 
void loop() { 
if(numberOfPedal !=0) updateButtons();
if(numberOfPresetButton !=0) updatePresets();
}

////////////////////////////////////////////////////////////////////////////////////

Ligne 290 : //readPreset(12, 1, 0);
J'ai mis les // parce que même s'il charge le preset #1, le relai #10 s'allume, même si la mémoire est vide.
Je ne suis pas programmeur, je n'ai jamais étudié sérieusement le code (base C je crois ? - enfin je ne sais pas de quoi je parle...) mais j'ai essayé de saisir comment ça marche et j'ai tenté de faire un code à peu près propre.
Déclaration des variables
Déclaration des fonctions
Déclaration du setup
Déclaration du programme en lui-même.

Bref, je sèche... Bon ce n'est pas non plus vital vu que le code fonctionne, et je vous remercie si vous êtes arrivé jusqu'ici.
Si quelqu'un a une piste, je suis preneur, sinon, je ferai avec.
Une bonne journée/soirée à ceux qui passent par là.

L’EEPROM s’use. Si vous l’avez beaucoup sollicité en écriture (100,000 fois ça arrive vite si une boucle est mal écrite) une case mémoire peut être grillée. Avez vous fait une petit code qui lit et affiche réellement ce qui est en eeprom ?

Pour éviter de griller prématurément l’eeprom on fait attention quand on y écrit et on utilise put() au lieu de write (et get pour lire)

Pour passer sur pro mini ça semble compromis vu le nombre de pins utilisées

Dans la fonction readPreset(int addr, int pcNum, int led), le paramètre pcNum n’est pas utilisé.

Dans cette fonction:

void readPreset(int addr, int pcNum, int led)
{
  resetAllLeds();
  for (int i = 0; i < numberOfPedal; i++) {
    digitalWrite(relayPin[i], EEPROM.read((addr) + i));
    digitalWrite(presetLedPin[led], HIGH); 
  }
}

pourquoi mettez vous à HIGH presetLedPin[led] à tous les tours de boucle for .

Dans le code j’ai vu cela qui n’est pas terrible

void toggle()
{
  resetAllLeds();
  digitalWrite(relayPin[i], !digitalRead(relayPin[i]));
}

vous utilisez i dans cette fonction qui n’est pas défini particulièrement et donc sera égal à une valeur de l’indice utilisé dans une boucle ailleurs avant l’appel de cette fonction. En regardant l’usage de cette fonction vous ne l’avez qu’une fois donc ça devrait aller mais le mieux serait de passer le bon index en paramètre.

On évite aussi d’utiliser i et j en variables globale car si une fonction qui fait une boucle sur i appelle une autre fonction qui fait aussi une boucle avec i ça met le bazar. Déclarez l’index juste localement dans la boucle

for(int i=0; i<3; i++) {…}

Votre code de debounce va dépendre de la vitesse du microprocesseur. En pratique pour des interface humaine il suffit de rajouter un court délai après la détection du changement d’état de la pin pour absorber la période des rebonds (15ms suffisent souvent et ne sont pas vraiment visibles au niveau ergonomie)


j'ai nettoyé un peu votre code, ça donne cela

#include <EEPROM.h>
#include <Keypad.h>

const byte rows = 10; //numbers of preset switches
const byte cols = 4; //selector for write/read/banks
char keys[rows][cols] = {
  {'a', 'k', 'A', 'K'},
  {'b', 'l', 'B', 'L'},
  {'c', 'm', 'C', 'M'},
  {'d', 'n', 'D', 'N'},
  {'e', 'o', 'E', 'O'},
  {'f', 'p', 'F', 'P'},
  {'g', 'q', 'G', 'Q'},
  {'h', 'r', 'H', 'R'},
  {'i', 's', 'I', 'S'},
  {'j', 't', 'J', 'T'}
};
byte rowPins[rows] = {A4, A5, A6, A7, A8, A9, A10, A11, A12, A13}; //input of the preset switches
byte colPins[cols] = {A0, A1, A2, A3}; //input of the selector
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);

//constant will not change
const int EEPROMStart = 12;
const byte numberOfPedal = 17; //enter the number of loop you need
const byte buttonPin[numberOfPedal] = {12, 14, 15, 16, 17, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; //define the Inputs of your arduino
const byte relayPin[numberOfPedal] = {20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52}; //define the Outputs of your arduino

const byte numberOfPresetButton = 10; // enter the number of preset button you need
const byte presetLedPin[numberOfPresetButton] = {21, 23, 25, 27, 29, 31, 33, 35, 37, 39}; //define the Outputs of your arduino

byte previousButtonState[numberOfPedal] ;

////////////////////////////////////////////////////////////////////////////////////

void resetAllLeds()
{
  for (byte j = 0; j < numberOfPresetButton; j++)
    digitalWrite(presetLedPin[j], LOW);
}

void resetAllRelays()
{
  for (byte i = 0; i < numberOfPedal; i++)
    digitalWrite(relayPin[i], LOW);
}

////////////////////////////////////////////////////////////////////////////////////

void memory(int addr, byte led)
{
  resetAllLeds();
  for (byte i = 0; i < numberOfPedal; i++) {
    byte valeur = digitalRead(relayPin[i]);
    EEPROM.put(EEPROMStart + addr + i, valeur);
  }

  // blink led et reste allumée
  for (byte i = 0; i < 4; i++) {
    digitalWrite(presetLedPin[led], HIGH); delay(100);
    digitalWrite(presetLedPin[led], LOW);  delay(100);
  }
  digitalWrite(presetLedPin[led], HIGH);
}

void readPreset(int addr, int pcNum, byte led)
{
  resetAllLeds();
  digitalWrite(presetLedPin[led], HIGH);
  for (byte i = 0; i < numberOfPedal; i++)
    digitalWrite(relayPin[i], EEPROM.read(EEPROMStart + addr + i)); // pourquoi ne pas utiliser pcNum ??
}

////////////////////////////////////////////////////////////////////////////////////

void updateButtons()
{
  for (byte i = 0; i < numberOfPedal; i++)  {
    int etat = digitalRead(buttonPin[i]);
    if (previousButtonState[i] == HIGH && etat == LOW) {      // appui bouton
      resetAllLeds();
      digitalWrite(relayPin[i], !digitalRead(relayPin[i])); // toggle
      delay(15); // anti rebond
    }
    previousButtonState[i] = etat;
  }
}

void updatePresets()
{
  char key = keypad.getKey();
  if (key) { // Check for a valid key.
    switch (key)  {
      /****************************** STORE PRESET MODE (EEProm address,led number)*/
      case 'a' ... 't': memory((key - 'a') * 20, (key - 'a') % 10);  break;
      /****************************** READ PRESET MODE (EEProm address,PcNum,led number)*/
      case 'A' ... 'T': readPreset((key - 'A') * 20, 1 + (key - 'A') % 10, (key - 'A') % 10);
      default: break;
    }
  }
}

////////////////////////////////////////////////////////////////////////////////////

void setup() {
  for (byte i = 0; i < numberOfPedal; i++) {
    pinMode(buttonPin[i], INPUT_PULLUP);
    previousButtonState[i] = HIGH; // par défaut bouton relâché
    pinMode(relayPin[i], OUTPUT);
    digitalWrite(relayPin[i], HIGH); //pullup all relay outputs in case off low level relayboard
    delay (25);
    digitalWrite(relayPin[i], LOW);
  }

  for (byte j = 0; j < numberOfPresetButton; j++) {
    pinMode(presetLedPin[j], OUTPUT);
    digitalWrite(presetLedPin[j], HIGH);
    delay (25);
    digitalWrite(presetLedPin[j], LOW);
  }
  //readPreset(12, 1, 0); // LA PREMIERE FOIS VOUS NE SAVEZ PAS CE QUI EST EN EEPROM...
}

void loop() {
  updateButtons();
  updatePresets();
}

la première fois que vous allez faire tourner ce code sur une nouvelle carte vous ne savez cependant pas ce qui est stocké en EEPROM, ça peut être n'importe quoi.

Bonjour et merci de votre réponse.

L'EEPROM s'use. Si vous l'avez beaucoup sollicité en écriture (100,000 fois ça arrive vite si une boucle est mal écrite) une case mémoire peut être grillée. Avez vous fait une petit code qui lit et affiche réellement ce qui est en eeprom ?

Négatif, je vais regarder ça de suite et vérifier l'EEPROM de ma carte actuelle.

Pour passer sur pro mini ça semble compromis vu le nombre de pins utilisées

Je suis parti sur ce genre de carte :
Mega 2560 Pro Mini

Dans la fonction readPreset(int addr, int pcNum, int led), le paramètre pcNum n'est pas utilisé.

C'est pour une implémentation midi, je n'en ai pas besoin sur ce projet, je pourrais en effet enlever cette partie.

pourquoi mettez vous à HIGH presetLedPin[led] à tous les tours de boucle for .

Pour allumer la led correspondant au footswitch enclenché.

vous utilisez i dans cette fonction qui n'est pas défini particulièrement et donc sera égal à une valeur de l'indice utilisé dans une boucle ailleurs avant l'appel de cette fonction. En regardant l'usage de cette fonction vous ne l'avez qu'une fois donc ça devrait aller mais le mieux serait de passer le bon index en paramètre.

Donc si je comprends bien, j'aurai dû rajouter dans mon code :

void toggle()
{
for(int i=0; i<numberOfPedal; i++)
{[color=#222222][/color]
  resetAllLeds();[color=#222222][/color]
  digitalWrite(relayPin[i], !digitalRead(relayPin[i]));
}[color=#222222][/color]
}

On évite aussi d'utiliser i et j en variables globale car si une fonction qui fait une boucle sur i appelle une autre fonction qui fait aussi une boucle avec i ça met le bazar. Déclarez l'index juste localement dans la boucle

Noté.

Ca par contre, je n'avais pas encore vu.

switch (key)  {
      /****************************** STORE PRESET MODE (EEProm address,led number)*/[color=#222222][/color]
      case 'a' ... 't': memory((key - 'a') * 20, (key - 'a') % 10);  break;

Je crois que j'ai saisi le pourquoi du comment, juste un doute sur le signe %, il est utilisé comme division ?

Merci pour le clean du code en tout cas, ça me rappelle quand un pote me ramène un ampli et qu'il me dit qu'il marche mais qu'il buzz, et que je lui refais le câblage tout propre.

Merci pour le clean

:wink:

le % c'est modulo, le reste de la division. Par exemple 14 % 10 = 4 (car 14 divisé par 10 ça fait 1 et il reste 4)

Pour le case 'a' ... 't':ça permet de grouper d'un coup toutes les valeurs entre 'a' et 't' (puisqu'elles se suivent en ASCII) et comme la chose à effectuer c'est en gros tout le temps pareil mais avec une petite modification, j'ai rajouté des formules qui calculent ce qui va bien en fonction de key

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.