![]() |
Utilisation du lidar TFMiniPlus |
avril 2024 |
J'ai besoin dans un prochain projet d'un Lidar, alors j'ai investi dans le TFMiniPlus de chez "Benewake".
Je vous livre ici mon test, j'utilise la librairie "TFMPlus.h" qui permet de se concentrer sur l'utilisation, la partie indigeste
de gestion de l'interface série (ou I2C) du lidar étant prise en compte par la librairie (un grand merci aux auteurs !).
Cette librairie prend également en compte la liaison I2C
(il n'y a que quelques lignes à changer, et avec un esp qui n'a qu'une seule interface série, cela peut être intéressant !),
mais dans un premier temps, je me concentre sur l'interface série.
Le LIDAR TFMiniPlusMesure de distance entre 10cm et 12mInterface UART et I2C Précision +/- 5cm jusqu'à 6m / 1% au delà Alimentation en 5 volts Résistant à l'eau IP65 Prix entre 45 et 50 euros Interface par défaut UART. |
![]() |
Le lidar TFMiniPlus comporte deux interfaces UART et I2C (+ une version io, non documentée ici.), perso, je test ici la version UART. Avec le lidar, il est livré un adaptateur USB qui permet en chargeant un programme de faire des tests sous windows, cela ne m'intéresse pas, je me suis donc concentrer sur l'utilisation avec un esp. J'avais sous la main un esp-8266 l'utilisation d'un esp32 aurait été cependant plus simple, car celui ci possède plusieurs ports séries (ce qui n'est pas le cas du 8266). Le câblage du lidar est simple '4 fils' alim et tx/rx de l'uart (ou SCL/SDA avec I2C). Pour l'alim le TFMiniPlus peut être alimenté en 5v ce qui est pratique avec mon module Wemos D1 Mini. Pour les besoins du programme, j'utilise également un bouton pour mémoriser des valeurs à des moments précis, attention, celui-ci doit être polarisé avec le 3v3 dispo sur le module wemos (pas en 5volts sinon bobo !).
Un petit afficheur lcd en I2c oled 1306 est utilisé pour afficher les valeurs mesurées, elles sont également envoyées sur une page HTML sous la forme d'un graphique. Si on appui sur le bouton on fige la mesure une fois sous la forme d'une longueur et une fois sous la forme d'une largeur, cela afin de calculer un périmètre et une surface (histoire de compléter le test d'interface avec la page HTML.) La page HTML est automatiquement rafraichie toutes les 2 secondes (c'est juste pour l'exemple, mais ca doit saturer un peu le reseau local !) afin d'afficher les changements de mesure, sinon il serait nécessaire de rafraichir la page manuellement !!! Pour le graphique le script utilise les graphiques mis à disposition par google qui sont bien pratiques. Voilà en espérant que cela vous aidera, si vous en avez besoin dans votre projet...
|
Remarque : Attention la librairie utilisée pour le lcd oled 1306 est "SSD1306Wire.h" (avec un W majuscule)
elle n'est pas directement disponible dans l'IDE Arduino ou dans VSC.
il faut donc la charger comme un fichier zip (j'explique comment faire sous Visual Studio Code et dans l'IDE Arduino sur ce site dans la partie
"Programmation", voir ici.).
// test_lidar
// https://castoo.fr
// Exemple d'utilisation de la librairie TFMiniPlus pour utiliser le LIDAR TFMiniPlus
// Lecture d'une valeur sur le lidar, mémorisation dans un tableau de 30 valeurs
// qui sont affichées dans un graphique sur la page HTML
// Si le bouton est pressé envoi par wifi sur la page HTML de la valeur
// La mesure est alors interprétée une fois comme une largeur une fois comme une longueur
// Ceci pour afficher un exemple de calcul d'un périmètre et d'une surface
//
// Attention, il faut attendre quelques secondes / minutes avant que le lidar affiche des valeurs cohérentes !
// Ce petit programme permet juste de tester le lidar il utilise une lecture au coup par coup, d'autres options
// sont disponibles comme précisé dans le code ci-dessous.
// Ici l'adresse IP est déterminée en DHCP vous pouvez choisir d'utiliser une IP fixe (voir dans le setup)
//
// Le code est distribué pour Visual Studio Code (main.cpp) si vous utilisez l'IDE Arduino
// renommez le fichier en "truc.ino" et chargez le dans un rep "/truc" L'include "Arduino" n'est dans ce cas plus nécessaire.
//
// Attention pour transferer le code dans l'esp il faut débrancher le lidar car sinon comme l'esp8266
// ne possede qu'un seul port série, celui-ci n'est plus disponible pour charger le code.
//
#include <Arduino.h>
#include <TFMPlus.h>
#include "SSD1306Wire.h"
#include "ESP8266WiFi.h"
#include <ESP8266WebServer.h>
#define ssid "xxxxxxxxxxxxxxxxxxx"
#define password "yyyyyyyyyyyyyyyyyyyyyyyyyyyy"
ESP8266WebServer server(80);
#define PIN_SCL D1 // I2C SCL
#define PIN_SDA D2 // I2C SDA
#define PIN_Bouton D7 // Bouton pour envoyer info par wifi
#define adr_oled 0x3c // Adresse I2C de l'OLED
SSD1306Wire display(adr_oled, PIN_SDA, PIN_SCL); // Declaration de l'objet écran Oled
TFMPlus tfmini; // Declaration de l'objet lidar
int16_t mesure; // Mesure en cm
int16_t tfmini_qualite = 0; // Strength (qualité du signal reçu (< 100 mauvais))
int16_t tfmini_temp = 0; // Température interne du lidar
int mesure_largeur, mesure_longueur;
int t_mesure[31];
int vcpt; // cpt dans tableau
boolean v_m; // Mesure largeur ou hauteur
String const v_css_body = "body { background-color: grey; font-family: Sans-Serif; Color: orange; text-align: center;}";
String const v_css_lien = "a.btn { text-decoration: none; padding: 10px; font-family: arial; font-size: 1em; color: #FFFFFF; background-color: #b2a2c7; border-radius: 24px;-webkit-border-radius: 24px; -moz-border-radius: 24px; border: 4px solid #ffffff; box-shadow: 3px 3px 8px #444444; -webkit-box-shadow: 3px 3px 8px #444444; -moz-box-shadow: 3px 3px 8px #444444; }";
String const v_css_lien_vol = "a.btn:hover { padding: 10px; color: #ffff00; background-color: #5f497a; border: 4px solid #fbd5b5; box-shadow: 1px 1px 4px #777777; -webkit-box-shadow: 1px 1px 4px #777777; -moz-box-shadow: 1px 1px 4px #777777; }";
String page_html(){
String page = "<!DOCTYPE html><html dir='ltr' lang='fr'><head><meta http-equiv='refresh' content='2'/>"; // On demande un rafraichissement de la page toutes les 2 secondes
page += "<meta http-equiv='content-type' content='text/html; charset=UTF-8'><title>Test lidar</title>";
page += "<style> " + v_css_body + v_css_lien + v_css_lien_vol + " </style>";
page += "<script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script>";
page += "<script type='text/javascript'>";
page += "google.charts.load('current', {'packages':['corechart']});";
page += "google.charts.setOnLoadCallback(drawChart);";
page += "function drawChart() { var data = google.visualization.arrayToDataTable([['Jour',";
page += "'Longueur'],";
int vadr=0;
while (vadr <= 29){
page += "['*', ";
page += String(t_mesure[vadr]) + "],";
vadr++;
}
page += "['*', " + String(t_mesure[vadr]) + "]";
page += "]); var options = {title: 'Les trente dernières mesures du LIDAR Testé avec Modèle : TFMiniPlus', titleTextStyle: {color: '#FF0000'},";
page += "curveType: 'function',legend: { position: 'bottom' }}; ";
page += "var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));";
page += "chart.draw(data, options);}</script></head><body><div align='center'><div id='curve_chart' style='width: 900px; height: 500px'></div>";
page += "<br><p align='center'><a class='btn' href='/' target='_self'>Retour Accueil</a> ";
page += " <a class='btn' href='https://www.castoo.fr' target='_blank'>Visiter le site https://www.castoo.fr</a></p>";
page += "<h3>Lecture : " + String(mesure) + " </h3><p>";
page += "<h3>Largeur : " + String(mesure_largeur) + " cm Longueur : " + String(mesure_longueur) + " cm </h3><p>";
page += "<h3>Périmètre : " + String((mesure_largeur + mesure_longueur)*2) + " cm Surface : " + String(mesure_largeur * mesure_longueur) + " cm² </h3><p>";
page += "</div></body></html>";
return page;
}
void setup() {
Serial.begin(115200); // L'esp8266 n'a qu'un seul port serie il va donc être utilisé pour le lidar
pinMode(PIN_Bouton, INPUT); // Bouton appel wifi
/* Pour une adresse IP fixe :
IPAddress ip(192, 168, 1, 86); // Declaration adr IP fixe 192.168.1.86
IPAddress dns(192,168,1,254);
IPAddress gateway(192,168,1,254);
IPAddress subnet(255, 255, 255, 0);
WiFi.config(ip, dns, gateway, subnet);
*/
WiFi.begin ( ssid, password );
while ( WiFi.status() != WL_CONNECTED ) { delay ( 500 ); }
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.clear();
String adr_ip = WiFi.localIP().toString();
display.drawString(64, 22, adr_ip); // Affichage de l'adresse IP utile si pas IP fixe
display.display();
delay(1000);
tfmini.begin(&Serial);
while (!tfmini.sendCommand( HARD_RESET, 0)){ // Retour aux parametres d'usine, suite à un plantage, cela s'est revelé être utile !
display.clear();
display.drawString(64, 12, "tfmini ERREUR");
display.drawString(64, 22, "parametres usine");
display.display();
delay(500);
}
display.clear();
display.drawString(64, 22, "tfmini OK");
display.display();
tfmini.sendCommand( SET_BAUD_RATE, BAUD_115200); // Vitesse émission du lidar
delay(100);
tfmini.sendCommand( STANDARD_FORMAT_CM, 0 ); // Les mesures seront renvoyées en cm
delay(100);
tfmini.sendCommand( SET_FRAME_RATE, FRAME_0); // Frame à 0 donc il faudra commander la mesure (si par exemple 100 il y aura 100 mesures/seconde)
delay(100);
tfmini.sendCommand( SAVE_SETTINGS, 0);
delay(300);
server.on("/", [](){ server.send(200, "text/html", page_html()); });
server.begin();
display.setFont(ArialMT_Plain_24);
vcpt=0;
v_m = false;
}
void loop() {
server.handleClient();
tfmini.sendCommand( TRIGGER_DETECTION, 0); // On declenche la lecture
if ( tfmini.getData( mesure, tfmini_qualite, tfmini_temp) ) { // Si lecture ok
if(tfmini_qualite > 100){ // Lecture fiable (si <100 la lecture n'est pas fiable)
display.clear();
display.drawString(64, 22, String(mesure)); // Affichage valeur sur le LCD Oled
display.display();
t_mesure[vcpt]= mesure;
vcpt++; if(vcpt>29) vcpt=0;
if ( digitalRead( PIN_Bouton ) == HIGH ) { // Lecture du bouton
delay( 100 ); // Pour éviter les rebonds
if ( digitalRead( PIN_Bouton ) == HIGH ) {
display.clear();
display.drawString(64, 22, "Envoi WiFi");
display.display();
if (v_m) mesure_largeur = mesure; else mesure_longueur = mesure;
v_m = !v_m;
}
}
delay(300); // Limite entre deux lectures du Lidar
}
}
}