Radar : Mesure de vitesse avec Arduino et TF02-Pro Lidar

Bonjour à tous,
Je suis en train de réaliser un radar pédagogique avec un Arduino uno, un lidar TF02-Pro et deux grands afficheurs à LED. Je me suis inspiré d'un projet avec un autre capteur mais qui est bien trop cher pour moi. Toute la partie physique est faite et j'ai (avec l'aide précieuse d'un copain) adapté le code d'origine. ça fonctionne à peu près mais je dois modifier le code pour passer de milles/heure en Kilometres/heure, ça je ne suis pas très inquiet je vais m'en sortir. Par contre j'aurais souhaité avoir un coup de main pour voir si le code auquel je suis arrivé n'est pas trop sale. En gros est-ce que mes modifications ne compliquent pas trop le code ou si tout est bien de la bonne pratique. Est-ce que vous pensez que quelqu'un serait assez alaise pour que ça ne lui prenne pas trop de temps et pourrait jeter un œil ?

Je me rend compte que j'ai été un peu ambitieux et qu'il me faudrait bien plus d'expérience pour faire ça bien.

Je suis conscient que c'est difficile pour un novice mais je ne sais pas ce que ça représente pour un habitué c'est pour cela que je me permet de demander. Maintenant je vous demande d'être le plus directe possible aves moi. Si vous estimez que ma demande est trop complexe n'hésitez pas à m'en informer.

Merci pour votre retour.

Je posterais le code ci quelqu'un me propose son aide car le code fait quand même quelques lignes.

postez le et vous verrez bien (et nous aussi) :slight_smile:

OK J-M-L, j'espère que c'est bien ici que je dois le coller :

#include <Wire.h> //Used for I2C

#include <avr/wdt.h> //We need watch dog for this program

#define    LIDARLite_ADDRESS   0x10 // Default I2C Address of LIDAR-Lite.

char i = 0;
byte rx_buf[9] = {0}; // Déclare une var de type octet (8 bits)

//GPIO declarations
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

byte statLED = 13; //On board status LED
byte en_LIDAR = A0; //Low makes LIDAR go to sleep

byte segmentLatch = 5; //Display data when this pin goes high
byte segmentClock = 6; //Clock one bit on each rising/falling edge
byte segmentSerial = 7; //Serial data in

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

long lastTime = 0;
long lastReading = 0;
int lastDistance = 265;
float newDistance;

const byte numberOfDeltas = 8; //  déclare une constante
float deltas[numberOfDeltas];  // déclare une variable à virgule flotante
byte deltaSpot = 0; //Keeps track of where we are within the deltas array 

//This controls how quickly the display updates
//Too quickly and it gets twitchy. Too slow and it doesn't seem like it's responding.
#define LOOPTIME 50

int maxMPH = 0; //Keeps track of what the latest fastest speed is
long maxMPH_timeout = 0; //Forget the max speed after some length of time

#define maxMPH_remember 3000 //After this number of ms the system will forget the max speed

void setup()
{
  wdt_reset(); //Pet the dog
  wdt_disable(); //We don't want the watchdog during init

  Serial.begin(115200);
  Serial.println("Speed Trap");

  Wire.begin();

  pinMode(segmentClock, OUTPUT);
  pinMode(segmentLatch, OUTPUT);
  pinMode(segmentSerial, OUTPUT);

  digitalWrite(segmentClock, LOW);
  digitalWrite(segmentLatch, LOW);
  digitalWrite(segmentSerial, LOW);

  pinMode(statLED, OUTPUT);

  Serial.println("Coming online"); //affiche("Coming online")

   enableLIDAR();
   while (readLIDAR() == 0) // tant que l'expression est vraie
    {
     Serial.println("Failed LIDAR read");
     delay(100);
    }

  showSpeed(42); //Test pattern

  delay(500);

  wdt_reset(); //Pet the dog
  wdt_enable(WDTO_250MS); //Unleash the beast
}

void loop()
{
  wdt_reset(); //Pet the dog

  //Each second blink the status LED
  if (millis() - lastTime > 1000)
  {
    lastTime = millis();

    if (digitalRead(statLED) == LOW)
      digitalWrite(statLED, HIGH);
    else
      digitalWrite(statLED, LOW);
  }

  //Take a reading every 50ms
  if (millis() - lastReading > (LOOPTIME - 1)) // 49)
  {
    lastReading = millis();

    //Every loop let's get a reading
    newDistance = readLIDAR(); //Go get distance in cm
    Serial.print("newDistance=");
    Serial.print("\r\n");
    
    
    //Error checking
    if (newDistance > 1200) newDistance = 0;

    int deltaDistance = lastDistance - newDistance;
    lastDistance = newDistance;

    //Scan delta array to see if this new delta is sane or not
    boolean safeDelta = true;
    for (int x = 0 ; x < numberOfDeltas ; x++)
    {
      //We don't want to register jumps greater than 30cm in 50ms;
      //But if we're less than 1000cm then maybe;
      //30 works well
      if ( abs(deltaDistance - deltas[x]) > 40) safeDelta = false;
      safeDelta = true;
    }

    //Insert this new delta into the array
    if (safeDelta)
    {
      Serial.print("Insert this new delta into the array");
      Serial.print(deltaDistance);
      deltas[deltaSpot++] = deltaDistance;
      if (deltaSpot > numberOfDeltas) deltaSpot = 0; //Wrap this variable
    }

    //Get average of the current deltas array
    float avgDeltas = 0.0;
    for (byte x = 0 ; x < numberOfDeltas ; x++)
      avgDeltas += (float)deltas[x];
    avgDeltas /= numberOfDeltas;

    //22.36936 comes from a big coversion from cm per 50ms to mile per hour
    float instantMPH = 22.36936 * (float)avgDeltas / (float)LOOPTIME;

    instantMPH = abs(instantMPH); //We want to measure as you walk away

    ceil(instantMPH); //Round up to the next number. This is helpful if we're not displaying decimals.

    if (instantMPH > maxMPH)
    {
      showSpeed(instantMPH);

      maxMPH = instantMPH;
      maxMPH_timeout = millis();
    }
    else //maxMPH is king
    {
      showSpeed(maxMPH);
    }

    if (millis() - maxMPH_timeout > maxMPH_remember)
    {
      maxMPH = 0;
      showSpeed(0);
    }

    Serial.print("raw: ");
    Serial.print(newDistance);
    Serial.print(" delta: ");
    Serial.print(deltaDistance);
    Serial.print(" cm distance: ");
    Serial.print(newDistance * 0.0328084, 2); //Convert to ft
    Serial.print(" ft delta:");
    Serial.print(abs(avgDeltas));
    Serial.print(" speed:");
    Serial.print(abs(instantMPH), 2);
    Serial.print(" mph");
    Serial.println();
  }
}



//A watch dog friendly delay
void petFriendlyDelay(int timeMS)
{
  long current = millis();

  while (millis() - current < timeMS)
  {
    delay(1);
    wdt_reset(); //Pet the dog
  }
}

//Get a new reading from the distance sensor
int readLIDAR(void)
{
  int distance = 0;

  Wire.beginTransmission((int)LIDARLite_ADDRESS); // transmit to LIDAR-Lite
  // Wire.write((int)RegisterMeasure); // sets register pointer to  (0x00)
  //  Wire.write((int)MeasureValue); // sets register pointer to  (0x00)
  Wire.write(0x5A); // see product mannual table 11:Obtain Data Frame
  Wire.write(0x05); //
  Wire.write(0x00); //
  Wire.write(0x01); //
  Wire.write(0x60); //
  Wire.endTransmission(); // stop transmitting

  delay(20); // Wait 20ms for transmit 
  wdt_reset(); //Pet the dog

  // Wire.beginTransmission((int)LIDARLite_ADDRESS); // transmit to LIDAR-Lite
  // Wire.write((int)RegisterHighLowB); // sets register pointer to (0x8f)

  //Wire.endTransmission(); // stop transmitting

  // delay(20); // Wait 20ms for transmit
  // wdt_reset(); //Pet the dog

  Wire.requestFrom((int)LIDARLite_ADDRESS, 9); // request 9 bytes from LIDAR-Lite

enableLIDAR(); 

while ( Wire.available())
{
  rx_buf[i] = Wire.read(); // received one byte
  Serial.print("0x");
  Serial.print(rx_buf[i], HEX);
  Serial.print(";");
  i++;
  if (i >= 9)
  {
    i = 0;
    Serial.print("---------->");
    Serial.print("Distance=");
    Serial.print(rx_buf[3] * 256 + rx_buf[2]);
    Serial.print(";");
    Serial.print("Strength=");
    Serial.print(rx_buf[5] * 256 + rx_buf[4]);
    distance = rx_buf[3] * 256 + rx_buf[2];
  }
}
Serial.print("\r\n"); // fait un retour chariot et une nouvelle ligne.
Serial.print("readLidarTerminé");
return (distance);
}

//Takes a speed and displays 2 numbers. Displays absolute value (no negatives)
void showSpeed(float speed)
{
  int number = abs(speed); //Remove negative signs and any decimals

  for (byte x = 0 ; x < 2 ; x++)
  {
    int remainder = number % 10;

    postNumber(remainder, false);

    number /= 10;
  }

  //Latch the current segment data
  digitalWrite(segmentLatch, LOW);
  digitalWrite(segmentLatch, HIGH); //Register moves storage register on the rising edge of RCK
}

//Given a number, or '-', shifts it out to the display
void postNumber(byte number, boolean decimal)
{
  //    -  A
  //   / / F/B
  //    -  G
  //   / / E/C
  //    -. D/DP

#define a  1<<0
#define b  1<<6
#define c  1<<5
#define d  1<<4
#define e  1<<3
#define f  1<<1
#define g  1<<2
#define dp 1<<7

  byte segments;

  //This method uses 7946 bytes
  switch (number)
  {
    case 1: segments = b | c; break;
    case 2: segments = a | b | d | e | g; break;
    case 3: segments = a | b | c | d | g; break;
    case 4: segments = f | g | b | c; break;
    case 5: segments = a | f | g | c | d; break;
    case 6: segments = a | f | g | e | c | d; break;
    case 7: segments = a | b | c; break;
    case 8: segments = a | b | c | d | e | f | g; break;
    case 9: segments = a | b | c | d | f | g; break;
    case 0: segments = a | b | c | d | e | f; break;
    case ' ': segments = 0; break;
    case 'c': segments = g | e | d; break;
    case '-': segments = g; break;
  }

  if (decimal) segments |= dp;

  for (byte x = 0 ; x < 8 ; x++)
  {
    digitalWrite(segmentClock, LOW); // digitalWrite(broche, valeur) Met au niveau logique(broche de valeur segmentClock, au niveau LOW)
    digitalWrite(segmentSerial, segments & 1 << (7 - x));
    digitalWrite(segmentClock, HIGH); //Data transfers to the register on the rising edge of SRCK
  }
}

//Sometimes the LIDAR stops responding. This causes it to reset
  void disableLIDAR()
  {
  digitalWrite(en_LIDAR, LOW);
  }

  void enableLIDAR()
  {
  digitalWrite(en_LIDAR, HIGH);
  }


//Takes an average of readings on a given pin
//Returns the average
int averageAnalogRead(byte pinToRead)
{
  byte numberOfReadings = 8;
  unsigned int runningValue = 0;

  for (int x = 0 ; x < numberOfReadings ; x++)
    runningValue += analogRead(pinToRead);
  runningValue /= numberOfReadings;

  return (runningValue);
}

Merci

oui c'est bien ici et bon point pour avoir mis les balises de code.

le code se lit correctement.

Quelques remarques:

tout ce qui concerne le temps doit être en unsigned long ➜

unsigned long lastTime = 0;
unsigned long lastReading = 0;

donnez des noms "parlants" aux variables globales.

char i = 0;

ici il s'agit de la position dans le buffer de réception du lidar, appelez le rxIndex ou rxLidarIndex par exemple. ce sera plus simple à suivre

de plus comme il n'est utilisé que dans le fonction readLIDAR() vous pourriez le déclarer comme une variable statique de cette fonction et le type habituel pour un index est size_t ou quand on sait qu'il est petit, on peut prendre un byte

int readLIDAR(void)
{
  static byte  rxLidarIndex = 0;
  int distance = 0;
...

Ne faites pas les maths 2 fois, ça ralentit pour rien:

      Serial.print("Distance=");
      Serial.print(rx_buf[3] * 256 + rx_buf[2]);
      Serial.print(";");
      Serial.print("Strength=");
      Serial.print(rx_buf[5] * 256 + rx_buf[4]);
      distance = rx_buf[3] * 256 + rx_buf[2];

pour économiser de la SRAM, mettez tous les textes imprimés en utilisant la macro F("") qui va ranger le texte en mémoire flash. par exemple

  Serial.print(F("readLidar Terminé"));

pas la peine d'appeler wdt_reset() en début de loop. Si vous êtes revenu là c'est que vous êtes passé juste avant par le main() qui fait ce qu'il faut. On fait plutôt cela en cours de route si une opération est longue et bloque la loop() trop longtemps


vous faites

    newDistance = readLIDAR(); //Go get distance in cm

avec newDistance qui est un float mais la fonction retourne un int. Si vous pouvez éviter les calculs en virgule flottante le code sera plus efficace.


ce commentaire n'est pas clair. mettez plutôt la formule qui explique

    //22.36936 comes from a big coversion from cm per 50ms to mile per hour

1 cm / 50ms <=> 72000 cm/h <=> 0.720 km / h <=> 0.720 / 1,60934 mile/h <=> 0,4473883704 mile/h

On en prend la moitié pour compter que le signal a fait un aller retour

0,4473883704 / 2 = 0,2236941852

expliquez pourquoi vous le multipliez par 100


petFriendlyDelay() ni averageAnalogRead() ne sont pas appelées, autant les virer du code

accessoirement, enableLIDAR() est appelée plusieurs fois mais jamais disableLIDAR()


tous les print des debugs pourraient être mis en optionnel en utilisant une macro. J'utilise souvent ceci

#define DEBUG 1    // SET TO 0 OUT TO REMOVE TRACES

#if DEBUG
#define D_SerialBegin(...) Serial.begin(__VA_ARGS__);
#define D_print(...)    Serial.print(__VA_ARGS__)
#define D_write(...)    Serial.print(__VA_ARGS__)
#define D_println(...)  Serial.println(__VA_ARGS__)
#else
#define D_SerialBegin(bauds)
#define D_print(...)
#define D_write(...)
#define D_println(...)
#endif

au lieu de faire

    Serial.print("0x");
    Serial.print(rx_buf[i], HEX);
    Serial.print(";");

vous écrivez

    D_print("0x");
    D_print(rx_buf[i], HEX);
    D_print(";");

et si vous changez le niveau de debug à 0

#define DEBUG 0

alors toutes les impressions vont être virées du code ce qui fait gagner du temps et de la mémoire


je ne suis pas sûr que la gestion du watchdog soit nécessaire.

voilà quelques pistes

Merci beaucoup J-M-L Jackson (je ne comprend pas pourquoi J-M-L apparait en gras et Jackson pas?),

Toutes vos indications vont énormément me servir et je vais m'atteler à la tache dès que possible.

Comme je vous le disais, je ne suis absolument pas programmeur mais je dois m'imposer cette phase d'apprentissage pour espérer réaliser des programmes fonctionnels et propres. Merci vraiment beaucoup pour votre aide. Je n'ai plus qu'à me mettre au boulot.

J-M-L c'est son pseudo
jackson c'est une espèce de "grade" lié à l'activité/expérience sur le forum. Si tu regardes ton profil, actuellement tu es newbie et bien J-M-L il est jackson.

1 Like

Merci fdufnews,

Cela tombe bien je suis aussi proche du newbie en terme de C/C++. Mais j'espère progresser rapidement.
Pourrais-tu me dire où je pourrais trouver des informations sur les messages de la console de débuggage de l'IDE, notamment lorsqu'elle me retourne : 182:29: warning:...., de ce que je comprend le problème vient de la ligne 182 de mon programme mais que signifie 29 ?

Merci

29ème caractère de la ligne. Pas toujours vrai, à prendre avec des pincettes. L'erreur (ou le warning) peut être en amont mais a été détectée à ce niveau.

1 Like

C'est ce que je m'étais dit mais ça ne se vérifiait pas tout le temps, d'où ma question.

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