Mesure de distance Ultra-Sonique

Utilisation d’un ESP32-C6 Zero pour la mesure de distance

Composants:

ESP32-C6 Zero

HC-SR04

Montage)

Le principe de fonctionnement d’un HC-SR04:

Un emetteur envoit un signal ultrasonique de fréquence de 40 kHz (inaudible) Un récepteur capte le signal de retour On mesure le temps mis par le signal pour faire un aller-retour entre l’émetteur et le récepteur. Connaissant la vitesse du son dans l’air (+/- 340 mètres par seconde), nous pouvons donc calculer la distance parcourue par le signal sonore.

Si le signal revient… la sortie passe au niveau haut durant toute la période où l’onde voyage vers l’objet et revient après avoir été réfléchie par ce dernier. La distance évaluée = temps durant lequel le signal de sortie est au niveau haut x la vitesse du son (340m/s) / 2. Si le temps d’impulsion de sortie est inférieur à 60ms, vous pouvez également utiliser la formule simplifié distance_en_cm = temps_impulsion_µS / 58.

Caractéristiques techniques

  • Tension de fonctionnement: 5 V continu
  • Consoomation (en fonctionnement): 15mA
  • Fréquence de fonctionnement: 40Hz
  • Distance Minimale: 2cm
  • Distance maximale: 400cm (4m) (dans de bonnes conditions)
  • Angle de mesure: 15 degrés
  • Signal d’entrée - trig: déclenchement de la mesure: impulsion 10µS TTL
  • Signal de sortie - echo: impulsion lorsque l’écho est reçu: signal TTL (dépend de la distance mesurée)

Câblage:

HC-SR04 ESP32-C6 Zero
VCC 5 Volts
Trig 1
Echo 0
Gnd Gnd

Le code Arduino IDE: Nécéssite les librairies suivantes

  • Zigbee
  • ESPCPUTemp
  • FastLED

CODE

// 
// Configure USC CDC on boot to Enabled
// partition scheme zigbee 4 MB with spiffs
// configure the Zigbee to ED (end device) in the IDE tools


#ifndef ZIGBEE_MODE_ED
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
#endif

#include "Zigbee.h"
#include <ESPCPUTemp.h>
#include <FastLED.h>


#define LED_BUILTIN 13 //blue LED user conrolable
#define RGB_LED 8 //controlable RGB LED
#define NUM_LEDS 1
#define DATA_PIN 8
#define BRIGHTNESS 16


ESPCPUTemp tempSensor;

#define DELAY_DISTANCE 250 // delay between consecutive distance measurements in milliseconds 

#define ANALOG_DEVICE_ENDPOINT_NUMBER 1
#define TEMP_SENSOR_ENDPOINT_NUMBER 2

ZigbeeAnalog zbAnalogDevice = ZigbeeAnalog(ANALOG_DEVICE_ENDPOINT_NUMBER);
ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER);

CRGB leds[NUM_LEDS];

uint8_t button = BOOT_PIN;
const int trigPin = 0;
const int echoPin = 1;

//define sound speed in cm/uS
#define SOUND_SPEED 0.034
#define CM_TO_INCH 0.393701

long duration;
float distanceCm;
float distanceInch;
float temp;
float oldt;
int count;
char retval[256];

/********************* DISTANCE sensor measure **************************/

static void distance_sensor_value_update(void *arg) {

for (;;) {
    // read the raw analog value from the sensor
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    // Sets the trigPin on HIGH state for 10 micro seconds
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    
    // Reads the echoPin, returns the sound wave travel time in microseconds
    duration = pulseIn(echoPin, HIGH);
    
    // Calculate the distance
    distanceCm = duration * SOUND_SPEED/2;
    int distance_raw = int(distanceCm);    
    
    // Prints the distance in the Serial Monitor
    //Serial.print("Distance (cm): ");
    //Serial.println(distance_raw);
    sprintf(retval,"Duration: %d\tDistance %d", int(duration), distance_raw );
    //Serial.println(retval);
    //Serial.println(distanceInch);
    zbAnalogDevice.setAnalogInput(distance_raw);  // send distance in cm to zigBee
    // Analog input supports reporting
    zbAnalogDevice.reportAnalogInput();
    delay(DELAY_DISTANCE);  // reduce delay (in ms), if you want your device to react more quickly
  }
}


/****************** routine that measures the CPU temperature and reports it ************/

static void temp_sensor_value_update(void *arg) {
for (;;) {
    // Read temperature sensor value
    float tsens_value = tempSensor.getTemp();
    //Serial.printf("Updated temperature sensor value to %.2f°C\r\n", tsens_value);
    // Update temperature value in Temperature sensor EP
    zbTempSensor.setTemperature(tsens_value);
    delay(5000); // take a measure every 5 seconds
}
}

void onAnalogOutputChange(float analog_output) {
Serial.printf("Received analog output change: %.1f\r\n", analog_output);
Serial.println(retval);
}


/********************* Setup the bits and blobs **************************/

void setup() {
Serial.begin(115200);


FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

// Init button for factory reset
pinMode(button, INPUT_PULLUP);
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input

leds[0] = CRGB::Green;    //RGB LED RED whe starting, on the zero Red and green are inverted !!!
FastLED.setBrightness(BRIGHTNESS);
FastLED.show(); // swith the RGB LED on

zbAnalogDevice.setManufacturerAndModel("on4kch", "ZigbeeDistance");

// Add analog clusters to Zigbee Analog according your needs
zbAnalogDevice.addAnalogInput();  //define an analog input entry to sned the distance
zbAnalogDevice.addAnalogOutput(); //define an analog output entry to get parameters from outside

zbAnalogDevice.onAnalogOutputChange(onAnalogOutputChange);    //define the routine that wil process the outside requests

Zigbee.addEndpoint(&zbAnalogDevice); // add the Analog endpoint

// define the CPU temp. sensor endpoint parameters

// Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement)
zbTempSensor.setMinMaxValue(10, 60);

// Optional: Set tolerance for temperature measurement in °C (lowest possible value is 0.01°C)
zbTempSensor.setTolerance(1);

// Add endpoint to Zigbee Core
Zigbee.addEndpoint(&zbTempSensor);


/*************************** start the zigbee *************************/

Serial.println("Starting Zigbee...");
// When all EPs are registered, start Zigbee in End Device mode
if (!Zigbee.begin()) {
    Serial.println("Zigbee failed to start!");
    Serial.println("Rebooting...");
    ESP.restart();
} else {
    Serial.println("Zigbee started successfully!");
}
Serial.println("Connecting to network");
while (!Zigbee.connected()) {
    Serial.print(".");
    delay(100);
}

leds[0] = CRGB::Red;
FastLED.show();
Serial.println();

// Start distance and temperature sensor reading task
xTaskCreate(distance_sensor_value_update, "distance_sensor_update", 2048, NULL, 10, NULL);
xTaskCreate(temp_sensor_value_update, "temp_sensor_update", 2048, NULL, 10, NULL);

// Set reporting schedule for illuminance value measurement in seconds, must be called after Zigbee.begin()
// min_interval and max_interval in seconds, delta
// if min = 1 and max = 0, delta = 1000, reporting is sent when raw illuminance value changes by 1000, but at most once per second
// if min = 0 and max = 10, delta = 1000, reporting is sent every 10 seconds or if raw illuminance value changes by 1000
// if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of illuminance change
// Note: On pairing with Zigbee Home Automation or Zigbee2MQTT the reporting schedule will most likely be overwritten with their default settings

zbAnalogDevice.setAnalogInputReporting(0, 0, 5);  // report immediately if value changes by 5 cm

zbTempSensor.setReporting(0, 0, 1);

if (tempSensor.begin()) {
    Serial.println("Temperature sensor initialized successfully");
} else {
    Serial.println("Failed to initialize temperature sensor");
}
}

/********************* Main loop **************************/
void loop() {
// Checking button for factory reset if pressed more then 3 seconds, reset zigbee, will need to be included again.
if (digitalRead(button) == LOW) {  // Push button pressed
    // Key debounce handling
    delay(100);
    int startTime = millis();
    while (digitalRead(button) == LOW) {
    delay(50);
    if ((millis() - startTime) > 3000) {
        // If key pressed for more than 3 secs, factory reset Zigbee and reboot
        Serial.println("Resetting Zigbee to factory and rebooting in 1s");
        delay(1000);
        Zigbee.factoryReset();
    }
    }
    // force report of distance when button is pressed
    Serial.println("Report AnalogInput ");
    zbAnalogDevice.reportAnalogInput();
}

Le external converter à insérer dans zigbee2mqtt

import * as m from "zigbee-herdsman-converters/lib/modernExtend";
const defaultReporting = {min: 0, max: 3600, change: 0};

export default {
    zigbeeModel: ["ZigbeeDistance"],
    model: "ZigbeeDistance",
    vendor: "ON4KCH",
    description: "Automatically generated definition",
    extend: [
        m.deviceEndpoints({endpoints: {1: 1, 2: 2, 9: 9}}),
        m.temperature({endpointNames: ["2"]}),
        m.numeric({
            name: "Distance",
            unit: "cm",
            scale: 1,
            cluster: "genAnalogInput",
            attribute: "presentValue",
            description: "Measured distance",
            access: "STATE",
            endpointNames: ["1"],
            precision: 2,
            reporting: defaultReporting,
        }),
    ],
    meta: {multiEndpoint: true, friendly_name: "ON4KCH's Distance"},
};