Relay Bypass: code final

A la suite de la campagne de crowdfunding, j'ai décidé d'améliorer le code du Relay Bypass.

En effet, le premier code du relay bypass ne s'active que quand on relâche le switch, ce qui n'est pas toujours évident et pratique. De plus, je voulais implémenter un switch permettant de choisir entre une activation "classique" et une activation "temporaire" de l'effet, que j'utilise notamment dans le Montagne Tremolo.


Ici, je vais donc vous présenter mes avancées en détaillant un peu chaque section du code.

Si vous n'avez pas encore lu mon article sur le Relay Bypass, je vous conseille de le lire avant de vous lancer dans celui ci. J'y présente toutes les bases et outils nécessaires pour se lancer avec les microcontrôleurs PIC.

 Astuce ! Le code complet est disponible sur Github. Avec les fichiers relayonpress.c et header.h et vous aurez tous les fichiers nécessaires pour coder ou graver vos chips.

Si vous avez un compte Github, n'hésitez pas à mettre une "Star" au projet pour suivre son évolution, ou à utiliser le "Fork" pour faire votre propre version !

Allez, c'est parti !




Quel schéma pour ce bypass ?

J'ai donc décidé d'ajouter certaines fonctions en plus. Le code du Relay bypass, mais qui s'active lorsqu'on appuie sur le switch, mais aussi une option pour rendre l'activation temporaire avec un switch supplémentaire. Enfin, j'ai aussi voulu utiliser mon système "anti pop" qui permet d'avoir un bypass complètement silencieux, le système de bypass idéal en quelque sorte !

Pour cela, il faut donc ajouter un switch senseur en plus, et bien entendu le photoFET utilisé pour le système anti pop. On a donc un schéma de circuit suivant :
Tous le circuit tourne autour du microcontrôleur, qui va être le "chef d'ochestre" du circuit.

On utilise toujours notre bon vieux PIC12F675, le relay NA5WK et le photoFET TLG222A. Le switch 2 permet de sentir si on est en mode "temporaire" ou "standard". Dès que le switch 1 est activé, il va alors activer la LED, le photoFET pour éliminer le "pop" et le relay pour activer l'effet.


Comment on code ça ?

Allez, passons au dur : le code !

Comme d'habitude, je vous conseille d'utiliser MPLabX (avec le compilateur XC8) pour écrire / modifier le code en C, puis d'utiliser le PicKit2 pour graver le code au format .hex dans le PIC12F675.

Pour plus de précisions, je vous invite à relire l'article original sur le relay bypass si vous avez oublié tout ça.


Header : configuration bits

Alors, ici on va reprendre la configuration classique.
On utilise donc l'horloge interne du PIC, pas de protection pour le code et on utilise toutes les pattes comme GPIOs. On a donc le code suivant :

// CONFIG
#pragma config FOSC = INTRCIO // Oscillator Selection bits (Internal clock)
#pragma config WDTE = OFF // Watchdog Timer Enable bit
#pragma config PWRTE = OFF // Power-Up Timer Enable bit
#pragma config MCLRE = OFF // GP3/MCLR pin function select
#pragma config BOREN = OFF // Brown-out Detect Enable bit
#pragma config CP = OFF // Code Protection bit
#pragma config CPD = OFF // Data Code Protection bit

// Define Internal clock frequency
#define _XTAL_FREQ 4000000

(c'est le fichier "header.h" du dossier Github)


Le code principal

On va toujours utiliser MPLabX pour pouvoir coder en C, ce qui est quand même plus simple à comprendre et à lire que l'Assembleur !

Le code est séparé en plusieurs parties . On va les voir une par une, puis j'afficherai le code complet. N'oubliez pas que vous pouvez aussi le lire et le télécharger sur GitHub.

Librairies
On doit inclure dans le code quelques librairies nécessaires au bon fonctionnement du code, et bien entendu le fichier header :

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <xc.h>
#include "header.h"

Initialisation
On arrive dans le code à proprement parler (fonction main() ). Commençons par initialiser tous les GPIOs. Nous n'avons pas besoin de GPIOs analogiques, donc on va en profiter pour couper les convertisseurs. On va donc définir lesquels seront des input (sentent un signal en mesurant un état haut ou bas - 5V ou 0V) ou des outputs (envoient une tension de 5V ou 0V)

// Initialization
void main(void) {
  ANSEL = 0; // no analog GPIOs
  CMCON = 0x07; // comparator off
  ADCON0 = 0; // Analog to Digital and Digital to Analog convertors off
  TRISIO0 = 0; // output LED
  TRISIO1 = 1; // input footswtich
  TRISIO2 = 0; // output TGP222A
  TRISIO5 = 0; // output activation relay
  TRISIO4 = 0; // output ground relay
  TRISIO3 = 1; // input temporary switch

  GPIO = 0; // set outputs as low level (0V)

Jusque là, ça ressemble en tout point au code qu'on a déjà fait. On a juste un input de plus pour sentir le switch qui permet de choisir entre mode d'activation temporaire ou normal. Enfin, on reset tous les GPIOs à 0 lorsqu'on démarre.

Définition des variables
On a besoin de plusieurs variables de type entier. On a donc la variable "state" qui définir l'état de la pédale (1 = "on", 0 = "off), la variable "changestate" qui permet de faire la séquence d'allumage du photoFET pour éliminer les "pop".

Par rapport aux codes précédents, on a 2 nouvelles variables, "temporary" qui définit le mode d'activation de la pédale, et "press_switch" qui va jouer le rôle de compteur et nous permettre d'activer la pédale quand on appuie et pas lorsqu'on relâche.

  // Variables definition
  uint8_t state; // on-off state of the pedal (1 = on, 0 = off)
  state = 0;

  uint8_t changestate; // to change status of the pedal
  changestate = 0;

  uint8_t temporary; // define the mode of the pedal : classic or temporary activation
  temporary = 0;

  uint8_t press_switch; // variable to detect if the switch is pressed
  press_switch = 0;

Toutes ces variables ont initialement une valeur de 0, ce qui définit un état suivant pour la pédale à l'allumage : état off (state = 0), pas de changement d'état (la pédale reste off car changestate = 0), mode d'activation "standard" par défaut (temporary = 0) et switch non pressé bien sûr par défaut (press_switch = 0). On va voir un peu plus en détail ce que font ces variables plus bas.

Temporary / Normal mode
La variable temporary sert à savoir si on est en mode temporaire ou classique. Pour définir cela, on a un switch externe, et selon la position de ce switch, la pédale sera en mode temporaire ou normal. On va donc capter l'état du switch (soit relié à la masse, soit en +5V) et modifier la variable temporary en fonction.

  // Main loop
  while(1) {
    if(GP3 == 0) { // By default: normal mode
      temporary = 0;
    }
    else { // If the "hold" mode is activated through the switch
       temporary = 1;
    }


Normal mode : détection du switch
Cette partie du code détecte l'activation du switch et fait changer la pédale d'état quand il est pressé.

Voici le code :

    // Normal mode
    if(temporary == 0) {
       if(GP1 == 0) { // footswitch pressed
         __delay_ms(15); // debouncing
         if(GP1 == 0) {
         press_switch = press_switch + 1; // switch is on
       if(press_switch>10) {
         press_switch = 10; // max value for press_switch
       }
      }
    }
        if(press_switch == 1) { // switch is pressed : lets turn the pedal on or off
          changestate = 1;
          press_switch = 2; // avoid bug if press_switch stays at 1
        }
        if(GP1 == 1) {
          __delay_ms(15); // debouncing
          if(GP1 == 1) {
            press_switch = 0;
          }
        }
      }

Quand on appuie sur le switch, il y a d'abord un debouncing pour vérifier que l'utilisateur a bien appuyé sur le switch avec un __delay_ms(15). Ensuite, si l'utilisateur a bien appuyé sur le switch, on incrémente la variable press_switch.

Le code suivant définit un maximum de 10 pour press_switch. Sans cela, le code ne marche pas car press_switch devient trop grande et ne peut pas être stockée dans la mémoire du PIC !

Lorsque press_switch est égal à 1, on fait passer changestate à 1 pour signaler que la pédale doit changer d'état. L'incrémentation de press_switch nous évite que la pédale change toute le temps d'état si on laisse le pied appuyé sur le footswitch ! De même, on fait passer press_switch à 2 immédiatement pour éviter que la pédale change continuellement d'état si press_switch reste à 1.

Enfin, lorsqu'on détecte que le switch est relâché (GP1 == 1), on reset la valeur de press_switch à 0.


Mode d'activation temporaire
Cette partie suit un mode de fonctionnement similaire à celle présentée ci dessus, sauf que l'état de la pédale est reset à 0 (off) quand on lâche le switch.

      // Temporary mode
      if(temporary == 1) {
        if(GP1 == 0) { // if switch is pressed : temporary activation
          __delay_ms(15); // debouncing
          if(GP1 == 0) {
            press_switch = press_switch + 1; // switch is on
            if(press_switch>10) {
              press_switch = 10; // max value for press_switch
            }
          }
        }
        if(GP1 == 1) { // if switch is not pressed, turn it off
          __delay_ms(15); // debouncing
          if(GP1 == 1) {
            state = 0;
            press_switch = 0;
          }
        }
        if(press_switch == 1) {
          changestate = 1; // if switch is pressed, turn the pedal on
          press_switch = 2; // avoids bug
        }
      }



Changer l'état de la pédale
Cette étape permet de changer l'état de la pédale (passer de on à off ou l'inverse). C'est lors de cette étape que le photoFET va être activé. C'est totalement similaire à ce que j'avais présenté dans mon article sur l'utilisation du photoFET pour enlever les "pop"

      // Changing state of the pedal
      if(changestate == 1) {
        if(state == 0) { // change to on
          GP2 = 1; // photoFET on
          __delay_ms(20);
          GP0 = 1; // LED on
          GP5 = 1; // relay on
          GP4 = 0;
          __delay_ms(20);
          GP2 = 0; // photoFET off
          state = 1;
        }
        else { // change to off
          GP2 = 1;
          __delay_ms(20);
          GP0 = 0; // LED off
          GP5 = 0; // relay off
          GP4 = 0;
          __delay_ms(20);
          GP2 = 0;
          state = 0;
        }
      __delay_ms(10);
      changestate=0; // reset changestate
    }

A noter que c'est cette partie qui est responsable du (très) léger délai d'ativation de la pédale. Après je vous rassure, à l'oreille cela ne s'entend pas du tout !


Etat on ou off de la pédale
Une fois que la pédale a changé d'état (on ou off), on la maintien dans cet état avec les lignes de code suivantes :

    // To let the pedal in the good state (on or off)
    if (state == 1) { // effect on
      GP0 = 1; // LED on
      GP5 = 1; // relay on
      GP4 = 0;
    }
     else { // effect off
      GP0 = 0; // LED off
      GP5 = 0; // relay off
      GP4 = 0;
    }
  }
}



Code complet

Voici le code au complet. Vous pouvez aussi le lire directement sur GitHub (ce sera peut être un peu plus lisible).

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <xc.h>
#include "header.h"

// Initialization
void main(void) {
  ANSEL = 0; // no analog GPIOs
  CMCON = 0x07; // comparator off
  ADCON0 = 0; // Analog to Digital and Digital to Analog convertors off
  TRISIO0 = 0; // output LED
  TRISIO1 = 1; // input footswtich
  TRISIO2 = 0; // output TGP222A
  TRISIO5 = 0; // output activation relay
  TRISIO4 = 0; // output ground relay
  TRISIO3 = 1; // input temporary switch

  GPIO = 0; // set outputs as low level (0V)

  // Variables definition
  uint8_t state; // on-off state of the pedal (1 = on, 0 = off)
  state = 0;

  uint8_t changestate; // to change status of the pedal
  changestate = 0;

  uint8_t temporary; // define the mode of the pedal : classic of temporary activation
  temporary = 0;

  uint8_t press_switch; // variable to detect if the switch is pressed
  press_switch = 0;

  // Main loop
  while(1) {
    if(GP3 == 0) { // By default: normal mode
      temporary = 0;
    }
    else { // If the "hold" mode is activated through the switch
       temporary = 1;
    }

    // Normal mode
    if(temporary == 0) {
       if(GP1 == 0) { // footswitch pressed
         __delay_ms(15); // debouncing
         if(GP1 == 0) {
         press_switch = press_switch + 1; // switch is on
       if(press_switch>10) {
         press_switch = 10; // max value for press_switch
       }
      }
    }
        if(press_switch == 1) { // switch is pressed : lets turn the pedal on or off
          changestate = 1;
          press_switch = 2; // avoid bugs if press_switch stays at 1
        }
        if(GP1 == 1) {
          __delay_ms(15); // debouncing
          if(GP1 == 1) {
            press_switch = 0;
          }
        }
      }

      // Temporary mode
      if(temporary == 1) {
        if(GP1 == 0) { // if switch is pressed : temporary activation
          __delay_ms(15); // debouncing
          if(GP1 == 0) {
            press_switch = press_switch + 1; // switch is on
            if(press_switch>10) {
              press_switch = 10; // max value for press_switch
            }
          }
        }
        if(GP1 == 1) { // if switch is not pressed, turn it off
          __delay_ms(15); // debouncing
          if(GP1 == 1) {
            state = 0;
            press_switch = 0;
          }
        }
        if(press_switch == 1) {
          changestate = 1; // if switch is pressed, turn the pedal on
          press_switch = 2; // avoids bug
        }
      }

      // Changing state of the pedal
      if(changestate == 1) {
        if(state == 0) { // change to on
          GP2 = 1; // photoFET on
          __delay_ms(20);
          GP0 = 1; // LED on
          GP5 = 1; // relay on
          GP4 = 0;
          __delay_ms(20);
          GP2 = 0; // photoFET off
          state = 1;
        }
        else { // change to off
          GP2 = 1;
          __delay_ms(20);
          GP0 = 0; // LED off
          GP5 = 0; // relay off
          GP4 = 0;
          __delay_ms(20);
          GP2 = 0;
          state = 0;
        }
      __delay_ms(10);
      changestate=0; // reset changestate
    }

    // To let the pedal in the good state (on or off)
    if (state == 1) { // effect on
      GP0 = 1; // LED on
      GP5 = 1; // relay on
      GP4 = 0;
    }
     else { // effect off
      GP0 = 0; // LED off
      GP5 = 0; // relay off
      GP4 = 0;
    }
  }
}

 Astuce ! N'oubliez pas que le code complet est disponible sur Github. Avec les fichiers relayonpress.c et header.h et vous aurez tous les fichiers nécessaires pour coder ou graver vos chips.

Si vous avez un compte Github, n'hésitez pas à mettre une "Star" au projet pour suivre son évolution, ou à utiliser le "Fork" pour faire votre propre version !


Et voilà ! Si cet article vous a été utile, n'hésitez pas à liker la page Facebook Coda Effects ou l'Instagram Coda Effects pour suivre l'actualité du blog.
Si vous avez des questions ou une remarque, postez un commentaire !
Previous
Next Post »
1 Commentaire
avatar

Hello !
Mission accomplie, j'ai fait une petite modif de code pour obtenir un "flexi-switch" (comme sur les EQD), à savoir qu'un appui court change l'état et un appui long (250ms, mais c'est paramétrable bien entendu)change l'état le temps de l'appui.
Je vais tenter de comprendre comment github marche et mettre ça dessus !

Répondre