Ultrason + Télécommande IR + Action

a marqué ce sujet comme résolu.

Je copie colle mon problème que j'ai déjà écris sur le blog de Eskimon (qui m'a d'ailleurs proposé de venir ici pour en parler plus facilement)

Bonjour, j’utilise une arduino avec un capteur ultrason, j’ai mis delay de 1s entre chaque prise de mesure mais je trouve que le délai entre chaque mesure est trop court, j’ai donc voulu réduire le temps mais cela me pause des problèmes. J’utilise une télécommande IR, sauf que lorsque j’appuie sur le bouton pour stopper les mesures, la pause se lance une fois sur 10 car le capteur n’a pas le temps de capter à cause du capteur ultrason. Je voulais savoir comment faire pour que l’appui du bouton soit repéré immédiatement ? C’est a dire que lorsque j’appuie sur un bouton, cela agit quoi qu’il arrive, même si le capteur fait ses mesures. J’espère avoir été clair car c’est difficile d’expliquer :/

Je rajouterai , car je viens d'y penser, que le capteur ultrason doit fonctionner sans bloquer les autres commande car il sert de détecteur d'obstacle donc lorsque les moteurs tournent s'il détecte un objet trop prêt cela ralentis la vitesse de rotation sauf que que le programme ne peut pas utiliser le capteur et en même temps réduire la vitesse, et c'est pareil avec la télécommande .

Je vous met aussi le code actuel

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include <Ultrasonic.h>
#include <IRremote.h>
#include <Servo.h>
#include <LiquidCrystal.h>

//Déclaration constante
  //LCD
LiquidCrystal lcd(41,40,30,31,28,29,26,27,24,25);
char message[16] = "";

  //LED
const int rouge = 7; //la LED à la broche 7
const int orange = 8; //la LED à la broche 8
const int vert = 9; //la LED à la broche 9

  //Ultrason
const int trig = 11;     // pin "Trig" du HC-SR04 connectée à pin 11 de l'Arduino
const int echo = 12;     // pin "Echo" du HC-SR04 connectée à pin 12 de l'Arduino
long lecture_echo; 
long cm;                // variable pour stocker la distance de l'objet en cm
Ultrasonic HCSR04(trig,echo);
decode_results results;

  //IR
int RECV_PIN = 10;
IRrecv irrecv(RECV_PIN);

  //Servo
Servo myservo;
int pos =90;

int arret ;
int nnn=0;

void setup()
{
    //Ecran LCD
  lcd.begin(16, 2);
  lcd.setCursor(3,0);
  lcd.print("Bienvenue");
  lcd.noBlink(); //pas de clignotement
  lcd.noCursor(); //pas de curseur
  lcd.noAutoscroll(); //pas de défilement
  
    //Sorties
  pinMode(rouge, OUTPUT); //la led est une sortie
  pinMode(orange, OUTPUT); //la led est une sortie
  pinMode(vert, OUTPUT); //la led est une sortie
  pinMode(trig, OUTPUT);
  
    //Entrées
  pinMode(echo, INPUT);
    
    //Initialisation
  arret = HIGH;
  digitalWrite(trig, LOW);
  irrecv.enableIRIn(); // Start the receiver
  myservo.attach(4);
  myservo.write(pos);              // tell servo to go to position in variable 'pos' 
  delay(2515);                       // waits 15ms for the servo to reach the position  
  Serial.begin(9600);
  lcd.clear();  
}

void dump(decode_results *results) {
  int count = results->rawlen;
  if (results->decode_type == NEC) {
    switch (results->value) 
    {
        case 0xFFC23D:
          if (nnn == 1)
          {
            arret = HIGH;
            digitalWrite(rouge,HIGH);
            lcd.setCursor(0,0);
            lcd.print("Mode automatique");
            delay(1500);
            nnn=0; 
          }
          else if (nnn == 0)
          {
            arret = LOW;
            digitalWrite(rouge,LOW);
            digitalWrite(orange,HIGH);
            digitalWrite(vert,HIGH);
            delay(1000);
            nnn = 1;
          }
          break;
    }
    if (arret == LOW)
    {
      switch (results->value) 
      {
           
          case 0xFF02FD:
            pos += 30;
            if (pos >=180)
            {
              pos =179;
            }  
            myservo.write(pos);              // tell servo to go to position in variable 'pos'
            lcd.setCursor(5,1);
            lcd.print("Gauche"); 
            delay(15);                       // waits 15ms for the servo to reach the position 
            break;
          case 0xFF22DD:
            pos-=30;
            if (pos <=0)
            {
              pos =1;
            }                 
            myservo.write(pos);              // tell servo to go to position in variable 'pos'
            lcd.setCursor(5,1);
            lcd.print("Droite"); 
            delay(15);                       // waits 15ms for the servo to reach the position 
            break;
      }
    }
  delay(500);
  lcd.clear();
  if (arret == LOW)
  {
    lcd.setCursor(2,0);
    lcd.print("Mode Manuel");
  }  
  }
}

void loop()
{
  if (irrecv.decode(&results)) 
  {
    dump(&results);
    irrecv.resume(); // Receive the next value
  }
  delay(100);
  while (arret == HIGH)
  {
    lcd.clear();
    if (irrecv.decode(&results)) 
    {
    dump(&results);
    irrecv.resume(); // Receive the next value
    }
  
    digitalWrite(trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(trig, LOW);
    lecture_echo = pulseIn(echo, HIGH);
    cm = lecture_echo / 58;
  
    sprintf(message,"Obstacle: %2d cm",cm);
    lcd.home();
    lcd.setCursor(0,0);
    lcd.print(message);
    
    if (cm <= 5)
    {
      digitalWrite(rouge,LOW);
      digitalWrite(orange,HIGH);
      digitalWrite(vert,HIGH);
      lcd.setCursor(4,1);
      lcd.write("Arret !");
    }
    else if (cm > 5 && cm <13)
    {
      digitalWrite(rouge,HIGH);
      digitalWrite(orange,LOW);
      digitalWrite(vert,HIGH);
      lcd.setCursor(1,1);
      lcd.write("Vitesse lente");
    }
    else if (cm >= 13)
    {
      digitalWrite(vert,LOW);
      digitalWrite(orange,HIGH);
      digitalWrite(rouge,HIGH);
      lcd.setCursor(2,1);
      lcd.write("Vitesse max");   
    }
    delay(1500);
    if (irrecv.decode(&results)) 
    {
      dump(&results);
      irrecv.resume(); // Receive the next value
    }
  }
}

Je n'ai pas regardé en détail, mais je vois des delays dans le code. delay() étant une fonction bloquante, lorsque tu as un delay, tu ne pourras rien traiter d'autre. Ton arduino attends. Ligne 182 par exemple, tu bloques ton arduino pendant une seconde et demi. N'utilises pas de delay(), préfère la fonction millis().

J'ai mis un delay pour limiter les mesures du capteur, donc comment faire avec la fonction millis pour stopper les mesures et seulement les mesures ?

EDIT: Je viens de regarder la doc j'ai compris ce qu'elle fait mais je ne vois pas comment elle fonctionne. En gros je doit définir debuttemps =0, par exemple, pour commencer et soustraire de debuttemps par le temps actuel du programme qui est géré par la fonction millis ? C'est comme avec la fonction time en python en gros si j'ai bien compris

Mais du coup si je fait ça, il n'y a plus de delay donc cela ne bloque plus, mais admettons que lorsque j'appuie sur le bouton de la télécommande au moment ou il fait sa mesure, cela ne va pas récupérer l'info de la télécommande du coup ?

En attendant vos réponses je vais faire mes tests et peut être cela répondra à mes questions

+0 -0

Comme l'explique AmarOk, les fonctions bloquantes sont a bannir si tu veux etre en mesure de reagir tout le temps. Ainsi, les delay() ou le pulseIn() ne sont pas les bienvenus puisqu'elles bloqueront le microcontrôleur.
Il faudra donc faire en sorte d’éviter cela en utilisant autre chose comme millis() par exemple (qui fonctionne comme time en python effectivement)

+0 -0

Effectivement je viens de remplacer la plupart de mes delay et on voit vite la différence ^^ Mais du coup, comment remplacer le pulseIn de

1
lecture_echo = pulseIn(echo, HIGH);

Et j'ai une question, comment faire pour lui dire de faire une action si et seulement si la valeur cm a changé d'intervalle ? car la il fait cette action toute les 1s apres avoir pris les mesures sauf que la valeur cm ne change pas forcement d'intervalle donc pas besoin de changer l'action, sa permettrai de rendre encore plus fluide les actions du coup ^^ Et aussi est ce qu'un téléphone peut faire des interférences sur la carte ou le capteur ? car à chaque fois qu'un téléphone est posé à coté, il ne respecte plus le temps et se met à faire des actions à n'importe quel moment ^^

Pour pulseIn(), je ne suis pas sur mais regarde du côté de cette librairie : http://playground.arduino.cc/Main/PinChangeInt
Pour cm, pourquoi ne pas passer par une variable temporaire. Et après tu fais la différence entre ta variable temporaire et le cm précédent.
Enfin pour ton téléphone, c'est possible. Ton matériel peut être sensible au bruit. Si c'est grave, tu peux penser à une sorte de "blindage", mais je doute que ce soit utile.

Et j'ai une question, comment faire pour lui dire de faire une action si et seulement si la valeur cm a changé d'intervalle ? car la il fait cette action toute les 1s apres avoir pris les mesures sauf que la valeur cm ne change pas forcement d'intervalle donc pas besoin de changer l'action, sa permettrai de rendre encore plus fluide les actions du coup

Utilise une autre variable last_distance qui stocke ta distance au temps $ t-1 $ . Si les deux distances sont suffisamment différente (a toi de décider ce qui est "suffisant") alors tu rentres dans le choix d'actions, sinon tu le zappes..

Mais du coup, comment remplacer le pulseIn

Le pulseIn mesure la duree d'un signal a un etat precis. Si ta boucle principale est completement sans fonction bloquante tu peux le faire avec millis() aussi.
Ca ferait un truc du genre :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
long tempshaut;
bool mesuring;

void loop() {
   if(digitalRead(echo) && !mesuring) { //demarre la mesure
      temphaut = millis();
      mesuring = true;
   } else if(mesuring && !digitalRead(echo)) { //arrete la mesure
      temphaut = millis()-temphaut;
      mesuring = false;
      // Ici tu as la valeur de ta distance normalement
   }
}

Codé a l'arrache donc sans garanti !

+0 -0

Pour last_distance, cela fonctionne bien et ne fait plus clignoter l'afficheur chaque seconde donc c'est parfait , merci ^^ . Par contre le code pour les mesures ne fonctionne pas, j'ai même essayer de voir pourquoi mais je n'ai pas trouvé (tu as d'ailleurs oublié les "s" a tempshaut ^^).

Quand je lance l'onde avec digitalWrite(trig, HIGH) cela fonctionne, en revanche quand il la reçois il ne fait pas les mesures.

Et dans ton code je ne comprend pas une partie, quand tu démarres la mesure, tu envoie l'onde ? car je ne vois pas de "trig".

Par contre j'ai le même problème de dérèglement des mesures et pourtant je n'ai rien à coté pouvant interférer .. :/

EDIT: j'ai, je crois, réussi à régler le problème qui déréglais les mesures. J'avais mis :

1
long intervalMesure = 1500;

J'ai juste rajouté "const" pour lui dire que c'est une constante et il ne me fait plus ce qu'il a fait. Donc je pense que quelque chose a changé la valeur en cours de route d’où les prises de mesure n'importe quand. Après pourquoi cela a fait ça ..

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte