Communication avec mon Automate

Bonjour à tous , j'arrive tout doucement à la fin de mon projet mais j'ai encore 2 problèmes sur lesquels je me casse beaucoup la tête et pour lesquels je n'arrive pas à trouver de solutions adéquates, peut-être que vous aurez des idées.

LE PROJET:
Le but est d'ouvrir et fermer une fenêtre , un peu le même principe qu'une porte de poulailler. Donc je dois piloter, avec une télécommande, mon moteur ( DC 24V 12W) pour qu'il puisse ouvrir ou fermer la fenêtre avec certaines commandes de sécurité, etc... Comme principe , lorsque l'utilisateur appuie sur le Bouton "A" , la porte s'ouvre et sur Bouton "B" la porte se ferme. Le tout sur batteries rechargeables ( 24 V 3Ah) car cette fenêtre est montable et démontable en permanence.

Tout est fonctionnel mais voici les 2 soucis :

  1. La portée de communication de mon récepteur est médiocre. J'utilise pour le moment ce type de récepteur en 433 Mhzs à qui j'envoie des données avec ce type de télécommande.

Récepteur : récepteur

Télécommande : Télécommande

En effet, pour le moment , j'ai une porté d'environs 4m. et j'aimerais pouvoir communiquer à une portée de 40 -50m.

  1. Je n'ai pas assez d'autonomie de batterie , mon automate tient pour le moment 2 jours et après ça, les batteries sont trop déchargées pour pouvoir refermer la fenêtre en cas de besoin. Tout ça est du aux différents modules installés sur l'arduino pour la communications, la sécurité, pilotage du moteur, etc.. Dans l'idéal , l'automate devrait pouvoir tenir 1 semaine à 10 jours. Dans cet esprit, je comptais mettre mon arduino en mode veille dès que l'utilisateur aterminé une commande. Et pour sortir de ce mode veille , faire une interruption externe grâce au signal envoyé par la télécommande. En gros, l'utilisateur appuie sur un des boutons, l'arduino se réveille et ensuite l'utilisateur peut faire sa commande jusqu'à ce que le programme remette en veille l'arduino et ainsi économise énormément de batterie.
    Pour le moment et avec ce récepteur , les Pins n'envoies que des "DATA" et je ne peux pas faire une interruptions avec ça.

C'est pour ça que je viens vers vous et demande si vous connaissez un moyen de communication ( bluetooth, Radio fréquence,... consommant le moins possible) qui permettrait d'augmenter considérablement la portée du signal et de plus permettrait d'agir comme interruption externe ?

Les modules wifi et infrarouges ne sont pas possibles dans cette application. Et j'ai essayé les modules LoRa mais ceux-ci coûtent trop cher et ont une application avec une portée trop importante pour la simple application que je fais.

Voici le code que j'utilise pour mes tests si ça peut vous aider:

#include <RCSwitch.h>
#include "EmonLib.h" // Inclure la bibliothèque pour le capteur ACS712 et la lecture de courant
#include <EEPROM.h>
#include <virtuabotixRTC.h>// inclure la bibliothèque de l'horloge RTC DS1302
#define ENA 10
#define INA 12

virtuabotixRTC myRTC(4, 5, 6); // définir l'horloge RTC DS1302
// SCLK -> 4, I/O -> 5, CE -> 6
// CLK -> 4 , DAT -> 5, Reset -> 6
RCSwitch mySwitch = RCSwitch();// définir la télécommande
// Data -> 2
EnergyMonitor emon1; // définition de la classe Energymonitor 

const int analogInPin = A2;  // Broche analogique utilisée pour la lecture de tension
const int courantPin = A0;  // broche analogique utilisée pour lire le courant

// Valeurs des boutons de la première télécommande
unsigned long boutonA_1 = 12451858;
unsigned long boutonB_1 = 12451860;
// Valeurs des boutons de la deuxième télécommande
unsigned long boutonA_2 = 10813458;
unsigned long boutonB_2 = 10813460;

bool ouverture = false; // Indique si l'ouverture a été effectuée 
bool fermeturefinale = false; // Indique lorsque la fermeture fianle du au seuil de tension a été effectué.
// variables  pour la lecture de la tension de la batterie
float tensionBatterie = 0.0;// définition de la variable Tension batterie
float voltageDividerRatio = 6.0;  // rapport de division de tension (10k / (2k + 10k))
float seuilTension = 22.0; // Seuil de tension en volts

// Variables pour la lecture du courant
float seuilCourant = 2.0; // Seuil de courant en ampères
// Variables pour l'heure 
int address_day = 0;
int address_month = address_day + sizeof(int);
int address_year = address_month + sizeof(int);
int address_hours = address_year + sizeof(int);
int address_minutes = address_hours + sizeof(int);
int address_seconds = address_minutes + sizeof(int);
  
// Les différentes fonctions appelées dans le programme
// Fonction pour lire la tension de la batterie
float lireTensionBatterie() {
  int sensorValue = analogRead(analogInPin);  // Lecture de la valeur analogique
  float tensionBatterie = sensorValue * (5.0 / 1023.0) * voltageDividerRatio; // Calcul de la tension réelle
  
  return tensionBatterie;
}
// Fonction pour lire le courant
double lireCourant() {
  double courant = emon1.calcIrms(1480);  // Passer une valeur à calcIrms pour spécifier le nombre d'échantillons
  return courant;
}
void sauvegarderheure(){
  EEPROM.put(address_day, myRTC.dayofmonth);
  EEPROM.put(address_month, myRTC.month);
  EEPROM.put(address_year, myRTC.year);
  EEPROM.put(address_hours, myRTC.hours);
  EEPROM.put(address_minutes, myRTC.minutes);
  EEPROM.put(address_seconds, myRTC.seconds);
}
//fonction pour afficher l'heure
void afficherheure(){
  EEPROM.get(address_day, myRTC.dayofmonth);
  EEPROM.get(address_month, myRTC.month);
  EEPROM.get(address_year, myRTC.year);
  EEPROM.get(address_hours, myRTC.hours);
  EEPROM.get(address_minutes, myRTC.minutes);
  EEPROM.get(address_seconds, myRTC.seconds); 
  Serial.print("Date / Heure de la fermeture définitive: ");
        Serial.print(myRTC.dayofmonth);
        Serial.print("/");
        Serial.print(myRTC.month);
        Serial.print("/");
        Serial.print(myRTC.year);
        Serial.print(" ");
        Serial.print(myRTC.hours);
        Serial.print(":");
        Serial.print(myRTC.minutes);
        Serial.print(":");
        Serial.println(myRTC.seconds);

}

// Fonction pour avancer
void avancer() {
  unsigned long startTime = millis(); // utillisation d'une fonction non bloquante pour ouvrir la fenêtre d'environs 18o mm
  digitalWrite(INA, HIGH);  // Avancer 
  analogWrite(ENA, 255);
   while (millis() - startTime < 7000) { //( 25 secondes = 180 mm)
    double courant = lireCourant(); // Lecture du courant
    Serial.println(courant); // juste pour debuggage
    // Vérifier si le courant dépasse le seuil
    if (courant >= seuilCourant) {
      // Arrêter complètement le moteur pour éviter la surcharge
      analogWrite(ENA, 0); // arrêt
      Serial.println("Alerte : Courant de surcharge détecté. Le moteur est arrêté.");
      ouverture = true;
      return; // Sortir de la fonction reculer() si le courant dépasse le seuil
    }
  }
  analogWrite(ENA, 0);
  ouverture = true;
}

// Fonction pour reculer
void reculer() {
  digitalWrite(INA, LOW);  // Reculer
  analogWrite(ENA, 255);
  while (true) {
    double courant = lireCourant(); // Lecture du courant
    Serial.println(courant); // juste pour débuggage
    // Vérifier si le courant dépasse le seuil
    if (courant >= seuilCourant) {
      // Arrêter complètement le moteur pour éviter la surcharge
      analogWrite(ENA, 0); // arrêt
      myRTC.updateTime();
      sauvegarderheure();
      Serial.println("Alerte : Courant de surcharge détecté. Le moteur est arrêté.");
      ouverture = false;
      return; // Sortir de la fonction reculer() si le courant dépasse le seuil
    }
  }
}

void setup() {
  pinMode(ENA, OUTPUT);  // Pin de vitesse
  pinMode(INA, OUTPUT);   // Pin de direction
  Serial.begin(9600);     // Initialisation de la communication série
  mySwitch.enableReceive(0);  // Activer la réception sur le pin 0
  // Initialisation de l'instance de la classe EnergyMonitor pour mesurer le courant
  emon1.current(courantPin, 30);  // La valeur 30 représente la sensibilité du capteur (185mV/A pour l'ACS712)
 if (Serial){
  afficherheure();
 }
}

void loop() {
while(!fermeturefinale){
  tensionBatterie = lireTensionBatterie(); // Lecture de la tension de la batterie
  //Serial.println(tensionBatterie); // juste pour débuggage
  
  
  if (tensionBatterie <= seuilTension) {
    // Effectuer un dernier retour avant d'arrêter la boucle
    reculer(); 
    fermeturefinale = true;
  }
  if(fermeturefinale){
    return;
  }
  
  if (mySwitch.available()) {
    unsigned long valeurTelecommande = mySwitch.getReceivedValue();
    if (!ouverture) {
      if (valeurTelecommande == boutonA_1 || valeurTelecommande == boutonA_2) {
        double courant = lireCourant(); // Lecture du courant
        Serial.println(courant); // juste pour débuggage
        avancer();
      }
    }
    else {
      if (valeurTelecommande == boutonB_1 || valeurTelecommande == boutonB_2) {
         double courant = lireCourant(); // Lecture du courant
        Serial.println(courant); // juste pour débuggage
        reculer();
        myRTC.updateTime();
        sauvegarderheure();
        Serial.print("Date / Heure de la fermeture définitive: ");
        Serial.print(myRTC.dayofmonth);
        Serial.print("/");
        Serial.print(myRTC.month);
        Serial.print("/");
        Serial.print(myRTC.year);
        Serial.print(" ");
        Serial.print(myRTC.hours);
        Serial.print(":");
        Serial.print(myRTC.minutes);
        Serial.print(":");
        Serial.println(myRTC.seconds);
        //delay(300000); // éviter que l'utilisateur joue trop avec les télécommandes , délais de 5 minutes
      }
    mySwitch.resetAvailable();
    }
  }
}
while(fermeturefinale){
  analogWrite(ENA, 0); // arrêt
}
}

Merci beaucoup d'avance !

J'ai un montage approchant.

D'abord il faut bien sûr soigner les alimentations. utilisez un abaisseur de tension efficace pour alimenter l'électronique en 5V ou 3.3V depuis votre batterie. ➜ lire l'article de @hbachetti Convertisseurs STEPUP & STEPDOWN

Ensuite il faut couper toute consommation inutile (moteurs etc) quand le système est en veille. Sur mon arduino j'ai un power switch qui me sert à à cela. ça consomme 0.01 μA en mode veille.

Pour la partie radio j'ai utilisé un HC12. En ligne de vue directe et environnement non bruité (dans mon jardin) j'ai plusieurs centaines de mètres de portée avec ce HC12 et sa petite antenne spirale.

Le HC12 a un mode basse consommation (mode FU2 - 80μA) en réception. Je configure le HC12 sur ce mode économie et configure mon arduino pour être réveillé sur l'entrée série (PCINT) et je mets mon arduino en sommeil profond.

Quand la 'télécommande' envoie un message, le HC12 émet un octet (0b10101010 pour avoir une alternance de fronts) sur la pin Rx du port série ce qui réveille l'arduino. Ce premier octet "de réveil" est perdu (il ne faut pas coder une commande avec cet octet) mais la télécommande le sait et envoie donc seulement ensuite la vraie commande.

Une fois que l'arduino récepteur a traité la commande, il coupe les circuits d'alimentation et se remet en veille profonde.

Un article aussi à lire:

Merci , je vais commander le HC 12 de suite et je reviens vers vous.

En gros, là , j'ai une batterie qui alimente en même temps mon moteur en 24V et l'arduino via un convertisseur de tension en 9V.
Est connecté au 5V de l'arduino aussi un shield moteur L298P , un capteur de courant , un diviseur de tension( 10 k ohms, 2kOhms, pour lire la tension) et un module RF 433 Mhzs ( pour mes tests , il y a l'horloge RTC aussi mais qui ne devrais pas y figurer à la finition)
On est bien d'accord que si je le mets en sleepmode , l'arduino ne consommera presque plus rien et augmentera l'autonomie de mes batteries ? même avec la configuration que je viens d'expliquer ?
ce power switch va permettre de tout couper mais du coup mon émetteur qui est branché sur l'arduino ne sera plus alimenté non plus ?
j'ai du mal à visuliser comment je peux faire le montage de tout cela ?
Ce récepteur HC12 serait compatible avec des télécommandes de type ouverture de barrière, garage , etc.. ?

Merci beaucoup pour votre réponse rapide !

Si vous continuez d'alimenter le moteur, vous ne verrez pas beaucoup de gain... et le L298P est peu efficient...

De même si votre convertisseur de tension en 9V est de mauvaise qualité vous allez tirer en permanence sur la batterie... Et pourquoi 9V alors que votre arduino sans doute en a besoin de 5V ? vous allez demander à votre Arduino de dissiper les 4V d'écart (multiplié par le courant consommé) sous forme de chaleur... ➜ perte d'énergie

Techniquement parlant il faut couper toute consommation parasite quand vous n'en avez pas besoin et optimise chacune des parties matérielles.

Le HC12 n'est qu'une petite partie de la solution et cette partie radio n'est pas forcément là où se pose le souci de consommation actuel de votre montage.

le montage c'est batterie -> step down efficace vers 5V --> HC12 et Arduino comme premier circuit. Un second circuit alimente le power switch qui est piloté par l'arduino (activation, désactivation quand nécessaire). C'est ce power switch qui alimente tout le reste des équipements de manière à ce que l'Arduino puisse décider de couper l'intégralité de la consommation des autres appareils (moteurs, drivers, capteurs, ...)

Merci beaucoup !
Le power switch , c'est bien un module composé de Mosfet . Parceque , il y en a avec des boutons poussoirs et d'autres non , sont 'il tous compatibles pour être pilotés par une sortie arduino ?
celui-ci serait-il compatible ?
switch sans bouton
Ou alors celui ci ?
Sur amazon

En fait la livraison serait 4x le prix du module .. si je prends chez Polulu , connaissez-vous une alternative ?

Je comprends mieux le fonctionnement , ce qui ferait que à la fin, lorsque arduino est en veille , il n'y aurait plus que l'arduino + HC-12 + Power switch qui consommerait ( et cela reste très peu) ?

Dernière petite question , si je comprends bien pour ue mon arduino consomme le moins , mon converisseur de tension VMA404 de chez Vellememan devrait convertir 24 V en 5V ( assez pour alimenter l'arduino sur la prise jack , je vois que ce serait mieux de 7V - 12V??) , ce qui permettrait par la même occasion via le OUT + et le OUT - du convertisseur d'alimenter le HC-12 en 5V et le Power switch ?

merci

avant d'acheter quoi que ce soit il faut que vous regardiez exactement les besoins.

est-ce que le moteur (quel est sont type ??) doit rester sous tension dans votre montage. Si on coupe le courant, il n'a plus de couple par exemple.

pour le mosfet, il faut un design qui ne consomme "rien". Ceux de pololu sont bien fichus et pré-cablés pour cela mais rien ne vous empêche en effet de concevoir un circuit à base de mosfet vous même.

Pour savoir lequel choisir, il faut connaitre la puissance à contrôler.

si vous voulez alimenter par le Jack, oui il faut au moins 7V.
Si vous mettez un convertisseur régulé qui donne 5V vous pourriez rentrer directement sur vos modules

Oui donc nécessaire d'avoir 2 step down , un pour Arduino qui convertit en 7V et un pour les modules que je convertit en 5V.
Ne serait-il pas plus simple que je laisse 1 seul Step down en 5V rentrer en USB au lieu du jack ?
Le moteur est un moteur a courant continu , et sans tension , il reste juste bloqué , donc ça me convient très bien.

J'ai tout commandé , merci beaucoup , je reviendrai surement vers vous prochainement.

Rebonjour , je n'arrive pas à communiquer avec ma télécommande et le module HC-12 en mode récepteur .. Communiquiez-vous avec une télécommande ?

Non je pensais que vous aviez compris - il faut deux HC-12 - un maître et un esclave

C'est ce que j'ai cru comprendre en essayant de communiquer ..
comment puis-je faire pour que mon arduino puisse recevoir des données d'une télécommande ( soit on appuye sur A , soit on appuie sur B , en fonction de ça , il fait une action) avec une portée acceptable ?

ça doit exister non ?

Je n'arrive pas à touver de solutions adéquates ..

Je ne sais pas qui sont A et B mais il faut que l'émetteur (votre télécommande) soit assez puissant et que vous ayez une antenne adaptée en réception.

hello
ce genre là ?

j'en ignore la portée

Bonjour , peut -être une idée à développer.
merci .

Rebonjour , donc pour le moment , j'utilise donc les récepteurs que j'ai reçu avec ma télécommande où j'ai facilement 50m de portée même dans une boite métallique , donc idéal pour mon application. Car il permettrait de faire une interruption pour sortir du sleep mode et en plus commander mon moteur (soit quand j'appuie sur A , soit quand j'appuie sur B)
C'est ce type là: récepteur avec 4 fils ( 2 IN ( alim) 2 OUT ( sorties)).
Je l'utilise comme ça :
Je l'alimente en 5V et il m'offre, lorsque j'appuie sur le bouton, 5V.
Sinon il a 0 V voir une petite tension résiduelle. Ca c'est quand je le teste au multimètre.

Mais il ne réagit pas pareil avec l'arduino, il ne passe pas de 0 à 5V mais envoie toujours une certaine tension..
Par exemple , si je le branche à une PIN digitale, , il reste toujours en HIGH , ça je pourrais comprendre que ce soit dû à la petite tension résiduelle.
Donc j'ai essayé de le brancher sur une PIN Analogique pour lire la tension et voir ce qu'il envoie comme tension et c'est effectivement très aléatoire sans que je ne fasses rien l'arduino lit des tensions allant de 0 à 5V complètement aléatoirement..
Donc j'utilise ce code et je fais allumer une led pour simuler les actions de mon projet

const int ledPin = 13; // Broche de la LED
const int receiverPin = A3; // Broche de réception du signal du récepteur 433 MHz

void setup() {
  // Initialisation de la communication série
  Serial.begin(9600);

  // Initialisation de la broche de la LED en mode de sortie
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // Lecture de la tension sur la broche analogique
  int sensorValue = analogRead(receiverPin);
  // Conversion de la valeur analogique en tension (0-5V)
  float voltage = sensorValue * (5.0 / 1023.0);
  
  // Si la tension est supérieure à 2.5V, cela signifie qu'un signal a été détecté
  if (voltage > 2.5) {
    // Allumer la LED
    digitalWrite(ledPin, HIGH);
  } else {
    // Éteindre la LED
    digitalWrite(ledPin, LOW);
  }

  // Affichage de la tension pour le débogage
  Serial.print("Tension : ");
  Serial.print(voltage);
  Serial.println(" V");
  delay(500);
  
}

et j'ai ça comme info sans appuyer sur quoi que ce soit :
Capture
Vous savez à quoi cela peut être dû et comment le régler pour que je puisse l'utiliser comme une impulsion comme lue sur le multimètre ?

Merci beaucoup d'avance.

ce n'est qu'une seule sortie - le + et le - d'après le schéma, capable d'alimenter un circuit

Il faudrait mettre un petit coup d'ohmmètre pour savoir si c'est le plus ou le moins qui est commun entre l'entrée et la sortie.
Généralement, sur ce genre de truc, pour des raisons de facilité, c'est le plus qui est commun et la sortie se fait sur un collecteur ouvert (ou un drain ouvert si c'est un mosFET).
Si c'est bien le cas alors, il faut raccorder la sortie OUT- sur une entrée de l'arduino et configurer l'entrée en INPUT_PULLUP Et tu devrais avoir des états HIGH et LOW stables.

Bonjour, effectivement , c'est IN + et OUT+ qui est commun et c'est un mofset de type 20N06:
20n06.pdf (1,1 Mo)
Voilà le code que j'utilise sur une board elegoo UNO R3 :

const int ledPin = 12; // Broche de la LED
const int receiverPin = 2; // Broche de réception du signal du récepteur 433 MHz

void setup() {
  // Initialisation de la communication série
  Serial.begin(9600);

  // Initialisation de la broche de la LED en mode de sortie
  pinMode(ledPin, OUTPUT);
  pinMode(receiverPin, INPUT);
  pinMode(receiverPin, HIGH);
}

void loop() {
  
  int currentState = digitalRead(receiverPin);
 
  // Si la tension est supérieure à 2.5V, cela signifie qu'un signal a été détecté
 if (currentState == HIGH) { 
    digitalWrite(ledPin, HIGH);
    delay(5000); // Attendre 5 secondes
    digitalWrite(ledPin, LOW); // Éteindre la LED
  }

}

comme c'est là , ça fonctionne bien quand je branche comme suit :

  • 5V ( + alimentation extérieure de arduino) sur IN + du récepteur
  • (- alimnetation extérieur ) sur IN- du récepteur
  • OUT + vers PIN 2 digitale
  • OUT - sur GRD Arduino
  • Digital PIN 12 de arduino vers résistance 220 Ohms sur cathode LED
  • Anode LED sur GRD Arduino

Là , si je ne l'utilise que comme ça , ça fonctionne bien , par contre , j'ai besoin de pouvoir utiliser les 2 bouton donc les 2 récepteurs.
J'ai donc essayé de faire la même chose avec une 2ème LED et le deuxième récepteur évidemment sur d'autres entrées et sorties, le bouton A fait réagir les 2 LEDS , le bouton B , pareil , je n'arrive pas à faire 2 actions distinctes .. Je ne comprends pas la logique , comme si lorsque j'envoie le signal , ça met toutes les sorties en HIGH d'un coup , je ne sais pas ..

Si je fais comme vous dites et que je mets (pinMode(receiverPin, INPUT_PULLUP); , ma LED reste allumée non stop. , y aurait-il un problème dans la connectique , je n'arrive pas à comprendre ce qui fait que j'ai ce résultat..

C'est contradictoire car si IN+ et OUT+ sont reliés cela veut dire que tu appliques en permanence +5V sur la PIN2.
Si comme tu le dis IN + et OUT+ sont communs, le branchement devrait être

  • 5V ( + alimentation extérieure de arduino) sur IN + du récepteur
  • (- alimentation extérieur ) sur IN- du récepteur et GND Arduino
  • OUT + inutilisé
  • OUT - sur PIN 2
  • Digital PIN 12 de arduino vers résistance 220 Ohms sur cathode LED

Merci beaucoup , effectivement, ça va beaucoup mieux mais que quand c'est l'arduino qui alimente mon récepteur .. j'imagine que c'est des problèmes de mise à la terre mal respectée ..?

Maintenant , je suis sur le problème de de la mise en veille de mon arduino ,je veux le mettre en mode veille profond et pouvoir le réveiller à la fois grâce aux interruptionset à la fois périodiquement. j'arrive bien à faire mes interruptions externes sur les PIN 2 et 3 mais j'aimerais bien que mon arduino se réveille aussi périodiquement( par exemple toutes les 10 minutes, pour, dans mon application, surveiller la tension de ma batterie et une fois que c'est fait , se remettre en veille .. Avez-vous une idée si c'est possible ?

Oui c’est possible avec un timer sur 8s Pas sur 10 minutes directement donc vous avez un compteur et seulement au bout de 75 réveils vous verifiez la batterie (75x8s = 10 minutes) sinon vous vous rendormez aussitôt.

Regardez Low-Power - Arduino Reference