Remplissage de cuve à distance via module Lora

Bonjour à tous,

Je suis en train de mettre en place sur mon terrain un système pour me permettre de lancer l’allumage d’une pompe (qui est située chez mon voisin à une centaine de m) à distance soit manuellement (interrupteur on/off) soit automatiquement (2 capteurs de niveau d’eau à flotteur dans la cuve).

Le montage récepteur branché sur le 220v coté pompe:

  • un pro mini chinois (5v 16mhz)
  • un module LoRa (sx1276) UART pour Arduino (réception, données pour 3000m en champs libre)
  • un relais 5v/10A pour allumer la pompe
  • un bouton poussoir + écran LCD pour afficher le nombre d’heure d’utilisation de la pompe (et payé l’elec du voisin en question…)
  • un transfo (récup par encore faite, j’en suis au test sur l’ordi pour l’instant) 220v vers 5 à 12v pour alimenter l’Arduino

le code qui va avec le boitier de réception:

#include <SoftwareSerial.h>
#include <EEPROM.h>
#include "EEPROMAnything.h"
#include <Wire.h> // Library for I2C communication
#include <LiquidCrystal_I2C.h> // Library for LCD
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);
#define relais  4
#define ecranOn  6
 
int compteur = 0;       // un compteur
int etatRelais;         // L'état du relais
float heureFonct = 0;   //compteur en heure de fonctionnement

SoftwareSerial loraSerial(2, 3); // TX, RX

void setup() {
  pinMode(relais, OUTPUT);
  pinMode(ecranOn, INPUT_PULLUP);
  Serial.begin(9600);
  loraSerial.begin(9600);
  digitalWrite(relais, HIGH); 
  lcd.init();
  EEPROM_readAnything(0, heureFonct);

}

void loop() { 

  
  if(loraSerial.available() > 1){
    String input = loraSerial.readString();
    Serial.println(input);  
    if(input == "on") {
      digitalWrite(relais, LOW);  
    } 
    if(input == "off") {
      digitalWrite(relais, HIGH
      );
    }
  }
  delay(20);
   // lecture de l'état du relay
    etatRelais = digitalRead(relais);
 
     // Si le relay a un état  "haut"
    if (etatRelais == LOW) {
        compteur ++;            
    delay(1000);         
      Serial.print ("compteur seconde    ");
      Serial.println (compteur);
       
    }

    
     if  (compteur == 3600){
           EEPROM_readAnything(0, heureFonct);
           heureFonct = heureFonct + 1;
           EEPROM_writeAnything(0, heureFonct);
    
      Serial.print ("nombre d'heure de fonctionnement  ");
      Serial.println (heureFonct);
      compteur = 0;   
   
     }
      if(digitalRead(ecranOn) == 0) {
        lcd.backlight();
        lcd.setCursor(0, 0);
        lcd.print("Heures utilisees");
        lcd.setCursor(2, 1); //Set the cursor on the third column and the second row (counting starts at 0!).
        lcd.print(heureFonct);
        delay(5000);
        lcd.clear();
        lcd.noBacklight();
    
    while(digitalRead(ecranOn) == 0);
    delay(50);
  }

}

le montage émetteur coté jardin/cuve:

  • un seeeduino stalker v2.3 (équivalent micro pro 3.3v 8mhz mais équipé d’une entrée solaire + panneau, entrée batterie + batterie, module horloge ds3231, carte sd, le boitier étanche qui va bien etc…)
  • un module LoRa (sx1276) UART pour Arduino (en émission)
  • un interrupteur on/off
  • 2 capteurs de niveau d’eau à flotteur
  • une batterie li-ion 3.7v 1A/h
  • un panneau solaire (Typical voltage: 5.5V - Typical current: 100mA - Open-circuit voltage: 8.2 V - Maximum load voltage: 6.4V) voir un autre plus grand en 170mA

et le code qui va avec ce boitier émetteur:

#include <SoftwareSerial.h>
#include <avr/sleep.h>

const int pompe = 3;
const int flotBas = 2; 
const int flotHaut = 6;  
const int led = 7;
volatile int etatflotBas;
volatile int etatflotHaut;


SoftwareSerial loraSerial(12, 13); // TX, RX

String turnOn = "on";
String turnOff = "off";


void setup() {
  pinMode(pompe, INPUT_PULLUP);
  pinMode(flotBas, INPUT_PULLUP);
  pinMode(flotHaut, INPUT_PULLUP);
  pinMode(led, OUTPUT);
  Serial.begin(9600);
  loraSerial.begin(9600);
  digitalWrite(led, LOW);
  
}

void modeManuel()
{
   sleep_disable();
   digitalWrite(led, HIGH);
    loraSerial.print(turnOn);
    while(digitalRead(pompe) == LOW);
  


  if(digitalRead(pompe) == HIGH) {
    loraSerial.print(turnOff);
  
  }
  detachInterrupt (1);
}

void modeAuto() {
  
  sleep_disable();
  digitalWrite(led, HIGH);
 
    loraSerial.print(turnOn);  
    while(digitalRead(flotHaut) != 1);
    
 

  if(digitalRead(flotHaut) == 1)
  {
    loraSerial.print(turnOff);  
 
  }
  detachInterrupt (0);
}
  void loop(){
  delay(500);
  digitalWrite(led, LOW);
  etatflotBas = digitalRead(flotBas);
  etatflotHaut = digitalRead(flotHaut);
  Serial.print ("etatflotBas");
  Serial.println (etatflotBas);
  Serial.print ("etatflotHaut");
  Serial.println (etatflotHaut);
  delay(500);
  
  // disable ADC
  ADCSRA = 0;  
  
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_enable();

  // Do not interrupt before we go to sleep, or the
  // ISR will detach interrupts and we won't wake.
  noInterrupts ();
  
  // will be called when pin D2 goes low  
  attachInterrupt(0, modeAuto, LOW);
  EIFR = bit (INTF0);  // clear flag for interrupt 0
  attachInterrupt(1, modeManuel, LOW);
  EIFR = bit (INTF1);  // clear flag for interrupt 1

 
  // turn off brown-out enable in software
  // BODS must be set to one and BODSE must be set to zero within four clock cycles
  MCUCR = bit (BODS) | bit (BODSE);
  // The BODS bit is automatically cleared after three clock cycles
  MCUCR = bit (BODS); 
  
  // We are guaranteed that the sleep_cpu call will be done
  // as the processor executes the next instruction after
  // interrupts are turned on.
  interrupts ();  // one cycle
  sleep_cpu ();   // one cycle
 
  }

il s’agit de la version de test, je virerais tous les serials et LED inutiles une fois le bousin en prod…

Tel quel l’ensemble fonctionne à la maison devant l’ordi, cela dit étant un “arduiniste occasionnel”, je me doute que mon code est farci de grossières erreurs et autre inepties propre au statut décrit précédemment…

  • Première coquille sur le boitier émetteur, lorsque j’appelle l’interruption déclenché par mon interrupteur (fonction modeManuel), le premier appui on/off ne fonctionne pas, en revanche les suivants fonctionnent eux comme prévu.

  • autre question concernant les rebonds d’un bouton poussoir, ce souci s’applique t’il aussi à un interrupteur on/off 2 positions (bloquées) et s’applique-t’il aussi à mes inters à flotteur

et si c’est le cas, je ne vais pas relancer l’éternel débat et souhaiterais supprimer le problème de manière physique en ajoutant des condensateurs aux interrupteurs concernés.
Il se trouve que je n’ai à disposition que des condensateurs électrolytique radial polarisés (je recopie pour être sûr de pas dire de conneries…), est ce que ça peut faire l’affaire et si oui comment les placés par rapport à mes interr, en parallèle je vois mais c’est plus vis à vis de la polarisation que je suis pas sûr sachant que mes interr sont reliés au gnd d’un coté et à une pin de l’arduino (avec pull-up) de l’autre.

  • Autre question concernant la nécessité (d’un point de vue conso) de virer le seeeduino pour passer à un atmega 328P nu, qu’en pensez-vous sachant que ce montage ne me sert qu’au printemps/été/début d’automne à Millau (très ensoleillé…) et que selon la doc du seeeduino l’autonomie est déjà au rendez-vous en l’utilisant tel quel http://wiki.seeedstudio.com/Seeeduino_Stalker_v2.3/#a-note-on-power-consumption

  • Concernant le transfo de récup que je compte utiliser pour alimenter l’arduino coté réception, que me conseillez-vous en tension de sortie pour le pro mini?

  • Enfin n’hésitez pas à me soumettre toutes les améliorations hardware/software qui vous semblent évidentes voir indispensables…

D’avance, merci à ceux qui participeront à ce post.

Mathieu

un petit up avant que je mette ça en boite et en prod

Bonjour, de mon côté j'ai déjà rencontré des problèmes dans la gestion de bouton pour effectuer une commande avec un appui pas toujours pris en compte et c'était du à l'utilisation de la fonction delay() qui stop le programme. Utilise plutôt la fonction millis() pour créer des temporisations qui elle n'est pas bloquante

je viens de purger mon code des serials et delay (dans les interruptions) et également finaliser mon circuit (soudure au lieu de dupont/breadboard) et il semble que ça ait résolu le problème du premier appui dans les choux, cela dit je note ta remarque concernant milis() pour la suite.
merci