Bonjour,
J’ai fait un montage pour controler le niveau de l’eau dans un bassin de jardin
en utilisant un capteur à ultrasons et déclencher l’ouverture d’une electrovanne 9V à impulsion quand le niveau baisse pour remplir.
Mon code est censé faire une moyenne de 30 mesures pour éviter de se déclencher au moindre remous à la surface mais j’ai essayé différentes méthodes de calcul de cette moyenne des mesures et j’arrive toujours à faire la même erreur.
Quand le cycle de mesures repart la valeur de la moyenne n'est plus dans la continuité du reste, la première mesure de la série de 30 le calcul de la moyenne est faussée car elle se base sur la mesure n1/1 et donc ça déclenche l’ouverture de la vanne.
La moyenne au lieu d'etre "glissante" progressivement sur les 30 dernières valeurs se fait par bloc de 30 mesures puis repart sur un nouvel ensemble de 30 mesures.
Quelque chose de surement très basique m’échappe… la programmation n’est pas mon fort. :-[
Voici mon code.
Celui ci contient en plus de la partie gestion du niveau, une partie qui me permet de calibrer le niveau à respecter en appuyant sur un bouton et stocker la valeur dans l’eeprom, une partie pour un capteur de température car je compte ajouter un capteur de température de l'eau
et la partie série me sert à faire à remonter avec un ESP12 avec espeasy les infos à ma solution domotique.
Je vous remercie.
// ---------------------------------------------------------------------------
// Capteur Niveau Ultrasons
// ---------------------------------------------------------------------------
#include <NewPing.h>
#include <EEPROM.h>
#include <SoftwareSerial.h>
#include <OneWire.h> //Librairie du bus OneWire
#include <DallasTemperature.h> //Librairie du capteur
OneWire oneWire(11); //Bus One Wire sur la pin 2 de l'arduino
DallasTemperature sensors(&oneWire); //Utilistion du bus Onewire pour les capteurs
DeviceAddress sensorDeviceAddress; //Vérifie la compatibilité des capteurs avec la librairie
SoftwareSerial ESPserial(4, 3); // RX | TX
int valvePin_a = 6;
int valvePin_b = 7;
#define TRIGGER_PIN 9 // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN 10 // Arduino pin tied to echo pin on the ultrasonic sensor.
#define valvePin 13// Arduino pin tied to valve pin.
#define setdistPin 12 // Arduino pin tied to calibration pin.
#define MAX_DISTANCE 250 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
int addr = 0; // EEPROM Address
int measuredDist = 0; // Sensor Distance
int buttonState = 0; // variable for reading the pushbutton status
int valve_state=0;
int calibrationDist = 0;
int lastButtonState = 0; // previous state of the button
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance
unsigned long previousMillis = 0; // last time measure was updated
unsigned long cal_previousMillis = 0; // last time calibration measure was updated
unsigned long fill_previousMillis = 0; // last time refill measure was updated
long interval = 2000; // interval at which to measure distance
long interval_measurement = 1000; // interval at which to measure distance
long interval_refill = 500; // interval at which to measure distance
const long cal_interval = 500; // debounce calibration
int MeasurementsToAverage = 30;
int average = 0; // the average
int lastaverage = 0; // previous state of the button
void setup() {
Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
// initialize the LED pin as an output:
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
ESPserial.begin(57600);
pinMode(valvePin, OUTPUT);
pinMode(valvePin_a, OUTPUT);
pinMode(valvePin_b, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(setdistPin, INPUT);
calibrationDist = EEPROM.read(addr);
Serial.println("-----------------------");
Serial.println("Pond Refill");
Serial.println("-----------------------");
digitalWrite(valvePin_a, LOW);
digitalWrite(valvePin_b, LOW);
}
void loop() {
if ( ESPserial.available() ) { Serial.write( ESPserial.read() ); }
// listen for user input and send it to the ESP8266
if ( Serial.available() ) { ESPserial.write( Serial.read() ); }
buttonState = digitalRead(setdistPin);
if (buttonState == HIGH) {
set_distance();
}
else {
measure_timer();
refill();
}
}
// Solenoid Open-Close functions
void open_valve()
{
digitalWrite(valvePin_a, HIGH);
digitalWrite(valvePin_b, LOW);
delay (100);
digitalWrite(valvePin_a, LOW);
digitalWrite(valvePin_b, LOW);
valve_state=1;
Serial.println("Valve");
Serial.print(valve_state);
}
void close_valve()
{
digitalWrite(valvePin_a, LOW);
digitalWrite(valvePin_b, HIGH);
delay (100);
digitalWrite(valvePin_a, LOW);
digitalWrite(valvePin_b, LOW);
valve_state=0;
Serial.println("Valve");
Serial.print(valve_state);
}
//mesure du niveau
int measure_distance(){
measuredDist = sonar.ping_cm();
for(int i = 0; i < MeasurementsToAverage; ++i)
{
average += measuredDist;
}
average /= MeasurementsToAverage;
Serial.println(average);
if (average != lastaverage) {
String StrTsk1 = "TaskValueSet,1,1,";
String StrAverage = StrTsk1 + average ;
ESPserial.println(StrAverage);
delay(50);
}
lastaverage = average;
}
int measure_timer(){
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
measure_distance();
}
}
//calibration
int set_distance(){
buttonState = digitalRead(setdistPin);
// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (buttonState == HIGH) {
unsigned long currentMillis = millis();
if (currentMillis - cal_previousMillis > cal_interval) {
// save the last time you checked water level
cal_previousMillis = currentMillis;
// turn LED on:
digitalWrite(valvePin, HIGH);
EEPROM.write(addr, measuredDist);
calibrationDist = EEPROM.read(addr);
digitalWrite(valvePin, LOW);
Serial.println("Calibration");
Serial.println(calibrationDist);
}
}
else {
}
}
//remplissage
void refill(){
// if the distance is higher than average start refill
if (average > calibrationDist) {
interval = interval_refill;
if (valve_state < 1){
Serial.println(valve_state);
open_valve();
}
unsigned long currentMillis = millis();
if (currentMillis - fill_previousMillis >= cal_interval) {
// save the last time you checked water level
fill_previousMillis = currentMillis;
}
}
else {
if (valve_state > 0){
Serial.println(valve_state);
close_valve();
interval = interval_measurement;
}
}
}
//lecture température
void temperature_read(){
sensors.requestTemperatures(); //Demande la température aux capteurs
Serial.print("La température est: ");
Serial.print(sensors.getTempCByIndex(0)); //Récupération de la température en celsius du capteur n°0
Serial.println(" C°");
}