Composants:
)
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.
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
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"},
};