Association informatique libre, solidaire

Forum d'échange entre les membres

Vous n'êtes pas identifié(e).

#1 2018-04-29 16:58:12

Benoît
Administrator
Inscription : 2015-06-21

création sonde profondeur de puits

Salut à tous,

Je vais fabriquer, à base d'arduino, un capteur de profondeur de puits, pour le connecter avec Domoticz en radio 433mhz via un RFLink. J'ai besoin de centraliser les informations, et comme ça peut intéresser certains, je poste ici. Je compléterai au fur et à mesure de mes découvertes, les commentaires et les discussions sont les bienvenues!

Pour info: Domoticz est un logiciel libre de domotique, installable sur un raspberry pi. J'ai raccordé à cela un module RFLink, qui est réalisé à base d'arduino mega (https://easydomoticz.com/rflink-un-modu … -materiel/)
Pas mal de protocoles supportés, très facile à réaliser.

le matériel

  • un capteur de pression avec pression de référence (datasheet )

  • un arduino nano

  • des tuyaux de pompe d'aquarium

  • une bouteille plastique

  • un boitier étanche

  • et tout un tas de trucs, tel que de la colle époxy, du silicone, des piles, un porte pile, je détaille pas plus

le principe
capteur_puit.svg
Une bouteille plastique branchée sur un tuyau, lui même sur le capteur, ça renvoi la pression par rapport à la pression ext. La bouteille est lestée, bien entendu. Je renvoie donc via radio un signal, avec les données: pression au fond, et niveau des piles.
Je vais devoir étalonner le montage, je pense immerger le capteur à une profondeur connue, que j'augmente au fur et à mesure, jusqu'à atteindre le fond, et à chaque fois, je capte les mesures et je fais une moyenne de [3? 4?] mesures à la même profondeur.

[edit] au vu des mesures aléatoires "à vide", j'ai mis le circuit sous pression avant d'immerger la bouteille, ça marche mieux. Et l'étalonnage, effectivement indispensable, m'a permis de corriger les errements du montage[/edit]

les infos utiles

  • un protocole radio pour communiquer avec domoticz

  • le branchement du capteur sur arduino:

et les questions...
Quels sont les types de capteurs que domoticz accepte? existe t-il un capteur de profondeur? (j'ai vaguement idée que non...)
Comment envoyer la mesure des piles à domoticz? Quel est le format qu'il accepte?


La suite plus tard.

Hors ligne

#2 2018-05-15 15:49:10

Benoît
Administrator
Inscription : 2015-06-21

Re : création sonde profondeur de puits

La suite ! La suite !
Oui, ça va j'arrive...

Alors, pour la suite. Petite modif du protocole d'envoi, je passe désormais par la bibliothèque x10rf à récupérer avec le sketch ino là. Je m'en suis assez inspiré, d'ailleurs.

Et, du coup, pour les capteurs: non il n'y a pas de capteur réellement adapté. Domoticz voit ça comme un compteur. Je l'ai passé en "hidden", j'ai un script lua pour récupérer les données, et mettre à jour un capteur virtuel (custom sensor).

Par contre, sur l'arduino, découverte: avec certains nano chinois, pour les programmer, il faut déclarer la carte comme une duemilanove. Sinon, erreurs multiples au téléversement.

Enfin, reste la question du capteur de tension, comment envoyer ça par radio, et là, je sèche. Mais bon, j'ai le temps, c'est pas comme si l'été approchait, avec son lot d'arrosages, de remplissages de piscines olympiques et tutti quanti!

[edit] abandon de la recherche à ce niveau là, après décorticage de la bibliothèque x10rf, je n'ai pas l'impression que ce soit implémenté. J'ai donc un script qui mesure le temps entre deux mesures, et si trop long => alerte [/edit]

Hors ligne

#3 2018-10-03 10:46:03

Benoît
Administrator
Inscription : 2015-06-21

Re : création sonde profondeur de puits

Des nouvelles de ce capteur.
Déjà, j'ai galéré à comprendre pourquoi quand j'envoyais une mesure avec le protocole rfxCom, je ne recevais pas les mêmes infos.
Par exemple, l'arduino relève 310120, il arrive 336200. Étonnement, puis recherche. J'ai cerné que ce qui était envoyé :

void x10rf::RFXmeter(uint8_t rfxm_address, uint8_t rfxm_packet_type, long rfxm_value){
	uint8_t x10buff[5]; // Set message buffer
	x10buff[0] = rfxm_address;
	x10buff[1] = (~x10buff[0] & 0xF0) + (x10buff[0] & 0xF); // Calculate byte1 (byte 1 complement upper nibble of byte0)
	if (rfxm_value > 0xFFFFFF) rfxm_value = 0; 	// We only have 3 byte for data. Is overflowed set to 0	
	// Packet type goed into MSB nibble of byte 5. Max 15 (B1111) allowed
	// Use switch case to filter invalid data types
	switch(rfxm_packet_type) {
		case 0x00: //Normal. Put counter values in byte 4,2 and 3
			x10buff[4] = (uint8_t) ((rfxm_value >> 16) & 0xff);
			x10buff[2] = (uint8_t) ((rfxm_value >> 8) & 0xff);
			x10buff[3] = (uint8_t) (rfxm_value & 0xff);
			break;
	}
	x10buff[5] = (rfxm_packet_type << 4); 		// Packet type goes into byte 5's upper nibble.
	// Calculate parity which
	uint8_t parity = ~(((x10buff[0] & 0XF0) >> 4) + (x10buff[0] & 0XF) + ((x10buff[1] & 0XF0) >> 4) + (x10buff[1] & 0XF) + ((x10buff[2] & 0XF0) >> 4) + (x10buff[2] & 0XF) + ((x10buff[3] & 0XF0) >> 4) + (x10buff[3] & 0XF) + ((x10buff[4] & 0XF0) >> 4) + (x10buff[4] & 0XF) + ((x10buff[5] & 0XF0) >> 4));
	x10buff[5] = (x10buff[5] & 0xf0) + (parity & 0XF);
	SendCommand(x10buff, sizeof(x10buff)); // Send byte to be broadcasted
}

Et oui, l'envoi est modifié par ça, et c'est Denis qui m'a fourni les clefs de compréhension, je le cite:

Denis MUSET DEPERO a écrit :

x10buff[4] = (uint8_t) ((rfxm_value >> 16) & 0xff);

rfxm_value >> 16 = je décale le contenu de rfxm_value de 16 bits vers la droite (ou bien je divise par 65536).

& 0xff = je fais un ET bit à bit avec un masque dont les 8 derniers bits sont à 1. Je ne garde donc que les 8 derniers bits.

(rfxm_value >> 16) & 0xff = En numérotant de droite à gauche à partir de zéro, j'extrais les bits 16 à 23 de rfxm_value.

(uint8_t) = Je force le résultat à être de type uint8_t qui doit sûrement représenter un caractère sur 8 bits non signé. C'est vraisemblablement que x10buff est un tableau de uint8_t.

x10buff[4] = Je mets le résultat sur la cinquième étagère (la première s'appelle zéro)

Bien bien bien. J'ai compris. Soit, je décode en faisant le chemin inverse, soit je travaille avec les données tel qu'elles arrivent. Dont acte, second choix pour moi. Et là: second souci, mon capteur gonflé... se dégonfle! Voir mon puits perdre toute son eau en une nuit m'a mis la puce à l'oreille. Problème d'étanchéité. Diantre. Colère. (Sacré nom de ù*:§ de +°@ù! de capteur de %µ£=)à !).
Du coup, j'ai tout viré. J'ai juste, dans mon puits, le tuyau avec la bouteille qui sert de crépine, je l'ai percée partout dans le fond pour que l'eau rentre.
C'est génial ça marche et c'est beaucoup plus précis!
Pourquoi faire compliqué alors que le simple marche? Certes, ça heurte mon sens de la complication, mais bon, les faits sont têtus, bref, ça fonctionne du tonnerre. D'autant que j'ai branché le capteur et l'arduino sur le secteur, sinon c'était 1 pile 9V par 48h, ça fini par coûter cher. J'ai tenté des deep sleep, mais ça c'est réservé aux ESP-8266 et consorts...

Aller, pour terminer, le code de mon arduino nano

/******************************************
# Script pour envoyer le niveau d'un puit 
# à partir d'un capteur MPX5500
# et envoi par protocole RFXCOM
#
#
# Ce script utiliser la librairie x10rf 
# Les sources sont là :
# https://github.com/p2baron/x10rf
#
/*******************************************/

// including x10rf library
#include <x10rf.h>

// Autres
#define RF_OUT 4 // OUTPUT RF 

x10rf myx10 = x10rf(RF_OUT,0,5);

// les pins et variables pour la mesure
const int analogInPin = A0; // Entrée analogique de la sortie Vout du capteur
int sensorValue = 0; // valeur lue sur le pin
long totEau = 0; // variable de stockage de toutes les mesures

/***************************************************************/
/**             Mise en route du programme                    **/
/***************************************************************/

void setup() {
  // MYX10 INITIALIZATION
  myx10.begin(); 
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
}

void loop() {
    //lecture du capteur MPX5500DP, et envoie des données, 

    mesurePression();
    // wait 5 sec before the next loop
    delay(60000);
}



/****************************************************************/
/**                 Fonctions                                  **/
/****************************************************************/

void mesurePression() {
  //Boucle pour les mesures
  for (int i=0; i<5; i++) {
    // on lit la broche du capteur
    sensorValue = analogRead(analogInPin);
    
    // convertir la lecture en voltage
    float sensorVoltage = sensorValue * (5.0 / 1023.0);
    totEau += (sensorVoltage*10000);
    //si on est en fin de boucle, 5 mesures effectuées, alors on calcule la moyenne et on envoie
    if (i == 4) {
      //on fait la moyenne des cinq mesures, et on calcule la hauteur d'eau en cm
      totEau = (totEau/5);
      // On envoi les données par radio
      Serial.println(totEau,4);
      myx10.RFXmeter(12,0,totEau);
      totEau = 0;
    }
  }
}

Hors ligne

Pied de page des forums