Aide sur fonction millis

Bonjour à tous,

Pouvez vous m'aider sur un soucis de mise en œuvre d'une fonction millis, que j'ai du mal à assimiler.

Voici ma fonction avec le delay :

void Debrayage() {
  
  analogWrite(Valeur_canal_A, 50);                       // Routine de débrayage du tracteur
   analogWrite(Valeur_canal_B, 209);
  
Etat_inter_debrayage = digitalRead(inter_debrayage);

 if(Etat_inter_debrayage == LOW) {

  digitalWrite(Relais_electro_frein, LOW);
  delay(2000);
  digitalWrite(Relais_canal_A_B_debrayage, LOW);
  digitalWrite(led_test_debrayage, HIGH);
}
 else {
  digitalWrite(Relais_electro_frein, HIGH);
  delay(2000);
  digitalWrite(Relais_canal_A_B_debrayage, HIGH);
  digitalWrite(led_test_debrayage, LOW);
 }
}

Voici comment je ferais mais j'ai pas l'impression de bien m'y prendre :

unsigned long heure_actuelle = 0;
unsigned long heure_precedente = 0;

void loop() {

analogWrite(Valeur_canal_A, 50);                       // Routine de débrayage du tracteur
   analogWrite(Valeur_canal_B, 209);
  
Etat_inter_debrayage = digitalRead(inter_debrayage);

 if(Etat_inter_debrayage == LOW) {

  digitalWrite(Relais_electro_frein, LOW);
  digitalWrite(led_test_debrayage, HIGH);
  
  heure_actuelle = millis();
  if(heure_actuelle - heure_precedente) >= 2000 {
    heure_precedente = heure_actuelle;
    
  digitalWrite(Relais_canal_A_B_debrayage, LOW);
  
  }
}
 else {
  digitalWrite(led_test_debrayage, LOW);
  digitalWrite(Relais_electro_frein, HIGH);

  if(heure_actuelle - heure_precedente) >= 2000 {
    heure_precedente = heure_actuelle;
    
  digitalWrite(Relais_canal_A_B_debrayage, HIGH);
  
 }
   
}

Merci d'avance pour votre analyse.

Ludovic

Il faudrait savoir ce que tu veux faire exactement : un code avec un delay peut-être parfaitement correct et utile si on se satisfait que le µcontrôleur soit bloqué pendant le temps du delay.

Remplacer le delay par une boucle n'est utile que si on veut que le µC fasse autre chose en attendant. Dans ton cas, je ne vois pas l'intérêt.

En général, le principe est le suivant :

  1. au démarrage, on stocke la valeur de millis(), l'instant de départ
  2. on boucle tant que la durée depuis ce départ ne dépasse pas une certaine valeur
  3. pendant ce temps, on fait d'autres choses
  4. lorsque la durée est dépassée, on passe à la suite

Ca se traduit comme ça (par exemple) :

unsigned long depart = millis(); // étape 1
while (millis() - depart < duree) // étape 2
{
// faire des choses (étape 3)
}
// la suite maintenant (étape 4)

Merci pour la réponse, dans mon cas, la fonction millis va servir à laisser tourner une autre partie du programme qui fait monter et descendre des vitesses via un encodeur et le delay cité plus haut fait faire une pause de 2 secondes dans la routine de montée et descente de cette vitesse ce qui handicape cette dernière.

Dans l'exemple dont je me suis inspiré " BLINK " sur le site anacorp, on voit le code suivant :

void loop() {
  currentTime=millis();
  if((currentTime-previousTime)>200){
    previousTime=currentTime;
    ledState=!ledState;
    digitalWrite(13,!ledState);
    Serial.print(F("LED State : "));Serial.println(ledState);
  }
}

Je ne comprend pas la ligne : ledState=!ledState

Mon essai de premier poste vous parait bon ?

La nouvelle valeur de ledState est le complement de la valeur actuelle.
donc:

  • si ledState était true, il devient false
  • si ledState était false, il devient true

Merci, je vais tenter mon code plus haut et voir se que ça donne.

Effectivement, tu sembles ne pas bien t'y prendre. Car si tu relâches le bouton tu n'attendras pas 2s.
Le problème c'est que cette fonction n'est qu'une partie de ton programme et on n'a aucune vue d'ensemble de ce que tu veux faire.
Lorsqu'on utilises millis() pour éviter d'avoir des portions de code bloquantes il faut architecturer le logiciel en conséquence. On ne peut pas le faire comme ça juste au milieu d'une fonction.

Il faut avoir dans loop()

  • une fonction qui observe les entrées sorties et qui lance les "tâches" liées au temps.
  • une fonction qui appelle régulièrement les "tâches" liées au temps tant qu'elle n'ont pas expiré
  • une (ou des) fonction(s) qui gère(nt) les tâches de fond, affichages par exemple. Ces fonctions ne doivent pas être bloquantes pour ne pas perturber le déroulement des tâches liées au temps.

Les "tâches" liées au temps contiennent:

  • une partie initialisation de la tâche
    • stockage du temps de début de la tâche
    • positionnement des sorties
    • positionnement d'un drapeau qui dit que la tâche est en cours
  • si la tâche est en cours
    • une partie surveillance du déroulement de la tâche
      • est-ce qu'il y a une demande d'arrêt de la tâche avant la fin
      • est-ce que le temps d'exécution de la tâche est arrivé à expiration
    • fin de la tâche
      • positionnement des sorties
      • positionnement du drapeau qui indique que la tâche est terminée

Voici le code complet du montage :

[code]

/* ------------------------------------------------  Déclaration de l'encodeur virtuel  ------------------------------------*/

const int Pin_Signal_un = 2;   //  pin de simulation encoder par l'Arduino
const int Pin_Signal_deux = 4; //  pin de simulation encoder par l'Arduino

const int inter_monter = 9;  //  Poussoir de relais du récepteur n°2 en haut
int Etat_inter_monter;

const int inter_descente = 10;  //  Poussoir de relais du récepteur n°3 en haut
int Etat_inter_descente;

const int Relais_monter_descente = 7;




/*  -----------------------------------------------  Déclaration du débrayage  ---------------------------------------------*/

const int inter_debrayage = 11;  // Poussoir de relais du récepteur n°1 en haut
int Etat_inter_debrayage;

const int Relais_electro_frein = 3;
const int Relais_canal_A_B_debrayage = 12;


const int Valeur_canal_A = 5;
const int Valeur_canal_B = 6;

/* ------------------------------------------------  Déclaration des leds test   -----------------------------------------*/

const int led_test_montee_descente = 13;
const int led_test_debrayage = 8;
/* _______________________________________________________  SETUP  ___________________________________________________________*/

void setup() {

  Serial.begin(9600);

  /*  ---------------------------------------------  Initialisation de l'encodeur  ------------------------------------------*/

  pinMode(Pin_Signal_un, OUTPUT);
  pinMode(Pin_Signal_deux, OUTPUT);


  pinMode(inter_monter, INPUT);
  Etat_inter_monter = 0;

  pinMode(inter_descente, INPUT);
  Etat_inter_descente = 0;

  digitalWrite(Pin_Signal_un, LOW);
  digitalWrite(Pin_Signal_deux, LOW);

  pinMode(Relais_monter_descente, OUTPUT);



  /*  ---------------------------------------------  Initialisation du débrayage  ----------------------------------------*/

  pinMode(inter_debrayage, INPUT);

  pinMode(Relais_electro_frein, OUTPUT);
  // digitalWrite(Relais_electro_frein, HIGH);

  pinMode(Relais_canal_A_B_debrayage, OUTPUT);
  //digitalWrite(Relais_canal_A_B_debrayage, HIGH);

  pinMode(Valeur_canal_A, OUTPUT);
  pinMode(Valeur_canal_B, OUTPUT);

  /*  --------------------------------------------  Initialisation des leds test  ----------------------------------------*/

  pinMode(led_test_montee_descente, OUTPUT);
  pinMode(led_test_debrayage, OUTPUT);
}

/* ___________________________________________________________  LOOP  _______________________________________________________________________*/


void loop() {


  /* -------------------  Routine de montée descente des vitesses  -----------------------*/


  digitalWrite(Relais_monter_descente, HIGH);


  Etat_inter_monter = digitalRead(inter_monter);        // Routine de montée / descente des vitesses encodeur AutoPower
  Etat_inter_descente = digitalRead(inter_descente);

  if (Etat_inter_monter == LOW) {
    Monter_vitesse();
    digitalWrite(led_test_montee_descente, HIGH);
  } else {
    digitalWrite(led_test_montee_descente, LOW);
  }

  if (Etat_inter_descente == LOW) {
    Descente_vitesse();
    digitalWrite(led_test_montee_descente, HIGH);
  } else {
    digitalWrite(led_test_montee_descente, LOW);
  }

  /*  ------------------  Routine de débrayage  ---------------------------------*/

  analogWrite(Valeur_canal_A, 50);                       // Routine de débrayage du tracteur
  analogWrite(Valeur_canal_B, 209);

  Etat_inter_debrayage = digitalRead(inter_debrayage);

  if (Etat_inter_debrayage == LOW) {

    digitalWrite(Relais_electro_frein, LOW);
    digitalWrite(led_test_debrayage, HIGH);
    delay(2000);
    digitalWrite(Relais_canal_A_B_debrayage, LOW);
  } else {
    digitalWrite(led_test_debrayage, LOW);
    digitalWrite(Relais_electro_frein, HIGH);
    delay(2000);
    digitalWrite(Relais_canal_A_B_debrayage, HIGH);

  }
}
/* _________________________________________________________________  FONCTION(S) _____________________________________________________________*/


void Monter_vitesse() {

  digitalWrite(Pin_Signal_un, LOW);
  digitalWrite(Pin_Signal_deux, LOW);

  delay(200);

  digitalWrite(Pin_Signal_un, HIGH);

  delay(200);

  digitalWrite(Pin_Signal_deux, HIGH);

  delay(200);

  digitalWrite(Pin_Signal_un, LOW);

  delay(200);

}

void Descente_vitesse() {

  digitalWrite(Pin_Signal_un, LOW);
  digitalWrite(Pin_Signal_deux, LOW);

  delay(200);

  digitalWrite(Pin_Signal_deux, HIGH);

  delay(200);

  digitalWrite(Pin_Signal_un, HIGH);

  delay(200);

  digitalWrite(Pin_Signal_deux, LOW);

  delay(200);

}

Sur ce programme, le souci est que les fonctions Monter_vitesse(); et Descente_vitesse();
prend la pause de 2 secondes qui se trouve dans ma condition de fonction de débrayage.

Le delay(2000); est nécessaire pour ne pas se retrouver avec un véhicule en roue libre pendant se laps de temps.
Je souhaiterais que la partie débrayage contenue dans le loop ne perturbe pas les fonctions d'augmentation ou diminution de la vitesse.
J'ai tenté pas mal de chose avec millis mais ça ne fonctionne pas.

Pouvez vous m'apporter une aide ?

Merci par avance,
Ludovic

hello
j'ai voulu regarder ton code,
mais il manque des explications. que veux tu faire?
un changement de vitesses ( 1ere, 2ème) un changement de sens de déplacement ( avant/arrière), ( montée/descente) ?
en commentaire, il y a le mot tracteur..........
un encodeur simulé...
ensuite, les termes choisit pour désigner tes composants n'aident pas
les inters deviennent poussoirs : inter_monter ===>Poussoir de relais du récepteur n°2 en haut
faut il comprendre fin de course?
Relais_canal_A_B_debrayage ?????

difficile de t'aider dans ces conditions :worried: :disappointed_relieved:

expliques ce que tu veux faire. ton application, mets nous dans le contexte...

Autant pour moi, mon projet est de piloter un tracteur sans conducteur à une vitesse de 300 mètres / h et maximum 2 km/h grâce à une radio-commande, je dois pour se faire gérer via mon arduino un potentiomètre de pédale de débrayage et un encodeur qui augmente ou diminue la vitesse de déplacement du véhicule.

Le potentiomètre du tracteur est géré par deux canaux ( A et B ) qui émet un pourcentage au calculateur du tracteur soit :

  • pédale embrayée : valeur canal A : 85 / : valeur canal B : 15

  • pédale débrayée : valeur canal A : 15 / valeur canal B : 85

L'encodeur du tracteur se sert deux signaux ( signal 1 / signal 2 )

Le fonctionnement :

Je commute via un interrupteur principale le démarrage de la carte arduino + platine relais ainsi que l'émetteur / récepteur qui fait la commande de l'ensemble.

Lorsque j'appuie sur le bouton 1 de la radio ( en mode poussoir ), je monte la vitesse d'avancement.

Lorsque j'appuie sur le bouton 2 de la radio ( en mode poussoir ), je descend la vitesse d'avancement.

Lorsque j'appuie sur le bouton 3 de la radio ( en mode poussoir avec maintient jusqu'à réinpulsion ), je pilote une électrovanne qui freine le tracteur et deux seconde plus tard, deux relais qui simulent le débrayage ( canal A et B du potentiomètre) pour stopper le tracteur. Ce principe évite au tracteur de partir un court instant en roue libre.

Pour le faire repartir, il faut ré appuyer sur le bouton 3 pour ré exécuter à l'inverse la séquence.

Les valeurs retournées des canaux A et B sont simulées par l'arduino sur des pins PWM afin d'éviter de lever des codes de diagnostique du calculateur de boite de vitesse du tracteur.

Tout est fonctionnel sur ce principe avec mon délai de 2 secondes sur la phase de débrayage / embrayage mais lorsque j'appuie sur mon bouton de monter ou descente, la vitesse d'avancement intègre ce délai et empêche une montée / descente " linéaire " ( ça monte un peu / une pause de deux secondes / ça monte un peu / une pause de deux secondes ... )

J'espère avoir été plus complet, n'hésitez pas à me poser des questions si des choses restent flou.

Ludovic

hello
c'est un peu plus clair
donc.
le tracteur doit varier sa vitesse de 300 à 2000 m par heure
sa pédale d'embrayage actionne un potentiomètre double pistes A et B
pédale relâchée, position embrayée,piste A = 85 et piste B=15
pédale enfoncée, position débrayée,piste A=15 et piste B=85

le tracteur est équipé d'un encodeur. je suppose qu'il s'agit de vérifier sa vitesse
l'encodeur retourne deux signaux. Signal 1 et signal 2

Télécommande:
BP1: accélère
BP2: ralenti
BP3: actionne une EV pour freiner puis après une tempo de 2 secondes, débraye d' ou : A=15 et B=85
BP3: actionne une EV pour lâcher les freins puis après une tempo de 2 secondes, embraye d' ou : A=85 et B=15
c'est l'arduino qui simule le potentiomètre , donc A 15/85 et B 85/15 et les envoie vers le calculateur de la boite .

c'est bien ça?

Oui, c'est tout à fait ça.
D'origine sur le tracteur, lorsque l'on tourne la molette d'encodeur du tracteur dans un sens ou dans l'autre, nous venons augmenter ou diminuer la vitesse du tracteur.
Dans mon cas, l'arduino simule la séquence de l'encodeur avec les deux fonctions Monter_vitesse(); et Descente_vitesse(); lorsque l'on appui sur BP1 ou BP2

hello
pas sur d'avoir tout compris, veux tu tester ce programme.
les principes de tempos par millis() sont ok, j'ai un doute sur les actions pour faire les différentes commandes.
testé sur UNO et avec un bout de fil pour faire les contacts de télécommande
à toi de vérifier avec les serial.print sur moniteur
attention, moniteur à mettre en 115200 bauds
tiens nous au courant. :grinning:
tracteur_seul.zip (3,2 Ko)

Merci pour ton aide, je test ça dès que possible ( boitier en cours de fabrication )

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