[Résolu] Problème d'horloge connexion USB - Pro Micro

Bonjour,

Je suis en train de réaliser un bouton qui me permet de simuler la touche “espace” de mon clavier.
J’utilise donc un arduino avec un ATmega32U4, le Pro Micro.

J’ai mis une temporisation de 500ms après chaque “espace” pour éviter d’en écrire plus que souhaité en appuyant sur mon bouton.

Tout fonctionne bien juste après la programmation mais du moment où je débranche et je rebranche ma carte de l’ordinateur, les 500ms passent à environ 4 secondes…

Voilà le code :

#include "Keyboard.h"

// set pin number for the button:
const int Bouton = 2;
const int prog = 4;
unsigned long depart;
unsigned long chrono;

void setup() { 
  // initialize the buttons' inputs:
  pinMode(Bouton, INPUT);
  pinMode(prog, INPUT_PULLUP);
  Keyboard.begin();
  depart=millis();
}

void loop() {


  // use the pushbuttons to control the keyboard:
  if (digitalRead(Bouton) == HIGH) {
    Keyboard.write(' ');
    chrono=500;
    depart=millis();
    while((millis()-depart)<=chrono){}
  }
 
  if (digitalRead(prog) == LOW) {
 Keyboard.end();
    while(digitalRead(prog) == LOW){
    }
  Keyboard.begin();    
  }


}

Le problème disparait du moment ou on fait un reset de l’arduino.
Je suis donc tenté de souder un condensateur et une résistance pour faire un reset automatique au branchement mais j’aimerai savoir s’il existe plutôt une solution soft.

Soit une commande qui reglerait l’horloge
Soit un soft reset au branchement ?

Merci d’avance :slight_smile:
Trit

hello

void loop()
{
software_Reset() ;
}


 

void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile ("  jmp 0");  
}

Hello Dfgh,

Merci pour ta réponse,

J’ai essayé plusieurs insertions dans mon prog mais je n’y arrive pas, voilà ce que je pensais correct :

#include "Keyboard.h"

// set pin number for the button:
const int Bouton = 2;
const int prog = 4;
unsigned long depart;
unsigned long chrono;

void setup() { 

  // initialize the buttons' inputs:
  pinMode(Bouton, INPUT);
  pinMode(prog, INPUT_PULLUP);
  Keyboard.begin();
  depart=millis();
}

void loop() {
software_Reset() ;
while(1 == 1){
  // use the pushbuttons to control the keyboard:
  if (digitalRead(Bouton) == HIGH) {
    Keyboard.write(' ');
    chrono=500;
    depart=millis();
    while((millis()-depart)<=chrono){}
  }
 
  if (digitalRead(prog) == LOW) {
 Keyboard.end();
    while(digitalRead(prog) == LOW){
    }
  Keyboard.begin();    
  }
}

}

void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile ("jmp 0");  
}

mais je ne reçois plus d’“espace” quand j’appuie sur mon bouton.

Merci

hello
je ne me suis pas occupé de ton prg.
tu voulais une instruction de reset par soft...........

C’est à dire qu’en mettant soft_Reset() comme première instruction de loop() tu ne peux pas exécuter beaucoup de code puisque tu fais un reset() dès que tu commences ton programme.

Je viens de relire mon code après une nuit de sommeil et en effet, ça reset en permanence...
auriez vous une idée pour faire un reset automatique au démarrage 1 seule fois pour ensuite passer au reste du code ?

Je viens de voir vos réponses en écrivant :slight_smile:

Il faudrait donc mettre une condition pour lancer le reset mais je n'ai pas envie de mettre un interrupteur pour ça... sinon le bouton reset suffirait :smiley:

Cette histoire d'horloge qui change est quand même bizarre. Je n'ai pas souvenir d'avoir vu ce problème exposé sur le forum.
Il y a toujours une solution bourrin, c'est de modifier la temporisation en question.

Oui c'est sûr :slight_smile:

J'ai essayé de mettre :

Serial.begin(9600);

Mais ça n'a rien fait non plus...

Trit:
J'ai essayé de mettre :

Serial.begin(9600);

Je ne vois pas très bien le rapport :o
Je pensais plutôt à

chrono=100;

Oui j’avais bien compris,
J’essaie de trouver une solution sans triche lol

Merci en tout cas

Peut-etre qu'une solution serait de mettre le reset dans une condition en fonction d'une valeur dans l'EEprom qui serait incrémenté au début du programme.
Si c'est pair, on fait reset, si non, on lance le prog.

Qu'en pensez-vous ?
C'est dommage de ne pas trouver la vrai source du probleme mais ça devrait fonctionner...

Hello,

Voilà le programme modifié avec insertion du reset automatique.
L’arduino reset bien à chaque branchement sur l’ordinateur.

/*
Press Espace

Simulateur de Clavier USB
Ecris un "Espace" quand on appuie sur le gros bouton

un petit bouton "prog" est disponible pour quitter le mode USB HID.
 */
#include "Keyboard.h"
#include <EEPROM.h>

// set pin number for the button:
const int Bouton = 2;
const int prog = 4;
unsigned long depart;
unsigned long chrono;
int i = 0;
boolean mem;

void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile ("  jmp 0");  
}  

void setup() { 

  // initialize the buttons' inputs:
  pinMode(Bouton, INPUT);
  pinMode(prog, INPUT_PULLUP);
  Keyboard.begin();
  depart=millis();
  
}

void loop() {
            chrono=500;   // Ligne de test
          depart=millis();   // Ligne de test
          while((millis()-depart)<=chrono){}   // Ligne de test
  Keyboard.print("debut");   // Ligne de test      
      
mem = EEPROM.read(i);
mem = !mem;
EEPROM.write(i, mem);

if (mem == true) {
        while(1){
        // Si le Bouton est activé, on tape un "espace"
        if (digitalRead(Bouton) == HIGH) {
          Keyboard.print(" ");
         // On attend 500ms avant de retester le bouton
          chrono=500;
          depart=millis();
          while((millis()-depart)<=chrono){}
        }

       // Si le bouton de programmation est actif, on stop le mode USB HID.
        if (digitalRead(prog) == LOW) {
       Keyboard.end();
          while(digitalRead(prog) == LOW){
          }
        Keyboard.begin();    
        }
      }
}

Keyboard.print("fin"); // Ligne de test

  software_Reset() ;

}

Malheureusement ce soft-reset ne suffit pas à résoudre le problème…
L’horloge est toujours plus longue que prévu :frowning:

J’ai testé 2 de mes cartes pro micro et 2 ordinateurs différents, problème toujours présent.
Est-ce que la source du problème ne pourrait pas venir des paramètres du compilateur arduino ?

Merci

Est-ce que l'instruction Serial.begin(9600); ne devrait pas régler l'horloge ?

Hello,

en attendant je vais souder un condo et une résistance.
Je vous tiens au courant si je trouve la vrai source du problème.

A+

Mettre ça dans la loop()

mem = EEPROM.read(i);
mem = !mem;
EEPROM.write(i, mem);

va flinguer votre EEPROM (100,000 cycle d'écritures) hyper rapidement...

Quand vous dites

Tout fonctionne bien juste après la programmation mais du moment où je débranche et je rebranche ma carte de l'ordinateur, les 500ms passent à environ 4 secondes...

est-ce que le pro-micro est alimenté séparément ou est-ce qu'en le débranchant vous éteignez le pro-micro?

J-M-L:
Mettre ça dans la loop()

mem = EEPROM.read(i);

mem = !mem;
EEPROM.write(i, mem);



va flinguer votre EEPROM (100,000 cycle d'écritures) hyper rapidement...

Le truc est un peu alambiqué, il n'y passe qu'une fois au démarrage. Il y a un while(1) après. Il fait son propre loop dans loop(). Le code qui teste si le reset a eu lieu aurait du se trouver dans le setup().
De toute façon à mon sens c'est une mauvaise solution pour couvrir un problème dont la cause est non encore identifié.

ah oui je n’avais pas lu la suite :slight_smile:

oui c’est une mauvaise solution…

Ce serait bien de savoir si le Pro Micro reste alimenté ou pas. Une déconnexion et re-connexion USB ne fait pas de reset sur la carte (par opposition à un UNO) → ça déclenche une Serial re-enumeration qui va donc créer un délai avant que le driver virtuel (CDC) de serial port soit établi sur l’ordinateur

d’autre part appeler begin et end ne sert pas à grand chose vu le code de la librairie…

void Keyboard_::begin(void)
{
}

void Keyboard_::end(void)
{
}

ce code là revient juste à faire un delay(500);

         // On attend 500ms avant de retester le bouton
          chrono=500;
          depart=millis();
          while((millis()-depart)<=chrono){}

c’est une attente active aussi, donc pas très utile non plus. autant utiliser delay()…

ce serait intéressant de tester avec ceci:

#include "Keyboard.h"
const byte Bouton = 2;

void setup() {
  pinMode(Bouton, INPUT);
  Serial.begin(115200);
  while (!Serial);  // attends l'établissement de la connexion
  delay(1000);      // pour prendre la main au cas où
  Keyboard.begin(); // pour une future compatibilité si nécessaire
}

void loop() {
  static unsigned long repereTemps = 0;

  // Si le Bouton est activé et qu'on a attendu assez longtemps, on tape un "espace"
  if ((millis() - repereTemps >= 500) && (digitalRead(Bouton) == HIGH)) {
    Keyboard.write(' ');
    repereTemps = millis();
  }
}

Merci J-M-L et fdufnews pour vos réponses.

En Effet, il n'y a pas d'alimentation externe, il y a seulement l'alimentation de l'USB !

Ah oui étonnant ce code dans la librairie du keyboard... ils indiquent même l'utilisation du begin ici :
*Keyboard.begin() - Arduino Reference *

Pour le delay j'utilise cette forme par habitute si besoin de vérifier une entrée pendant l'attente.
Vous pensez que ça consomme plus que la commande delay ?

Je viens de tester votre code, il fonctionne :slight_smile: mais uniquement lorsque j’enlève la ligne

while (!Serial);

Par contre le soucis d'horloge est toujours là quand je débranche/rebranche.
Pensez-vous qu'il est possible de trouver une solution sans ajouter d'alim externe ?

Merci encore.

Trit:
Je viens de tester votre code, il fonctionne :slight_smile: mais uniquement lorsque j’enlève la ligne

while (!Serial);

ce n'est pas normal.
Vous avez le driver qui va bien pour votre arduino pro micro installé sur le PC en question?

Pour le delay j'utilise cette forme par habitute si besoin de vérifier une entrée pendant l'attente.
Vous pensez que ça consomme plus que la commande delay ?

c'est juste que là c'est inutile donc ça alourdit la compréhension du code. plutôt que de faire une attente active à ce niveau là, faites comme je fais, revenez à la boucle principale mais ne resterez le bouton qu'après 500ms - comme cela votre code peut faire autre chose au lieu d'attendre