Oui je voudrais un réveil tous les 24h, ou à la demande mais qui sera rare...
Une EEPROM accepte 100000 écriture par Addresse, donc si tu fais une sauvegarde de ta valeur par jour, tu as de la marge
Par contre tu n'a pas décrit ton porjet
Car la question est pourquoi aurais tu besoin de calculer la différence avec la précédente mesure et de l'envoyer, le destinnataire n'est pas plus amene de le faire ?
Je voudrais faire cette différence pour avoir une visibilité plus rapide du poids, car il y aura l'envoi de 5 esp32 soit 1 SMS avec 5 fois les prises de données, du coup pas simple de rechercher le dernier message et faire la différence pour chaque esp32...
Je voudrais le faire avec préférence comme esp32.
#include <Preferences.h>
Preferences poids;
Void setup() {
poids.begin("balance",false);
float poids_dernier = poids.getFloat("dernier_poids",0);
}
Void loop () {
Serial2.print (poids.getFloat("dernier_poids",0) - Ruche e);
Ruche.e = poids.putFloat("dernier_poids",0);
}
J'ai essayé si je rajoute ça ça peut le faire ?
Code en totalité
#include <esp_now.h>
#include <WiFi.h>
// Définir la structure des données.
typedef struct struct_message {
int a;
float b;
float c;
float d;
float e;
} struct_message;
// Créez un struct_message appelé "Ruche".
struct_message Ruche;
#include <Preferences.h>
Preferences poids;
// Fonction de rappel.
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len)
{
// Obtenir des données entrantes.
memcpy(&Ruche, incomingData, sizeof(Ruche));
// Imprimer sur le moniteur Série.
Serial.print("Ruche n° ");
Serial.println(Ruche.a);
Serial.print("Température INT: ");
Serial.print(Ruche.b);
Serial.println("°C");
Serial.print("Température EXT: ");
Serial.print(Ruche.c);
Serial.println("°C");
Serial.print("Humidité EXT: ");
Serial.print(Ruche.d);
Serial.println("%");
Serial.print("Poids: ");
Serial.print(Ruche.e);
Serial.println("Kg");
Serial.println("");
Serial.println("");
}
void setup() {
Serial.begin(115200);//Initialisation liaison Moniteur série
// Mettre l'ESP32 en mode WIFI temporaire.
WiFi.mode(WIFI_STA);
// Initialiser ESP-NOW.
if (esp_now_init() != 0) {
Serial.println("Erreur d'initialisation...");
return;
}
// Fonction de rappel d'enregistrement.
esp_now_register_recv_cb(OnDataRecv);
poids.begin("balance", false); // ouverture du namespace.
float poids_dernier = poids.getFloat("dernier_poids", 1.0 ); // on récupère la valeur associée à la clé poids_dernier ou 1.0 si elle n'existait pas
Serial2.begin(115200);//Initialisation module SIM900
delay(20000);//Temps de connexion du SIM900 au réseau téléphonique - Ajuster si besoin
Serial2.println("AT");
delay(1000);
updateSerial();
Serial2.println("AT+CMGF=1\r"); //Activation mode Texte
delay(1000);
updateSerial();
Serial2.println("AT+CMGS=\"+33xxxxxxxxx\""); //Numéro du destinataire
delay(1000);
updateSerial();
}
void loop() {
// Message à envoyer.
Serial2.print("Ruche ");
Serial2.println(Ruche.a);
Serial2.print("Temp. INT : ");
Serial2.print(Ruche.b);
Serial2.println(" *C");
Serial2.print("Temp. EXT : ");
Serial2.print(Ruche.c);
Serial2.println(" *C");
Serial2.print("Humid. EXT : ");
Serial2.print(Ruche.d);
Serial2.println("%");
Serial2.print("Poids : ");
Serial2.print(Ruche.e);
Serial2.println("Kg");
Serial2.print("Rapport veille : ");
Serial2.print (poids.getFloat("dernier_poids", 1.0 )- Ruche.e);
Serial2.println("");
Serial2.println("");
delay(1000);
Serial2.write((char)26); //Envoi du message
delay(1000);
Ruche.e = poids.putFloat("dernier_poids", 0 );
}
void updateSerial()
{
delay(500);
while (Serial.available())
{
Serial2.write(Serial.read());
}
while (Serial2.available())
{
Serial.write(Serial2.read());
}
}
Ok, donc le destinataire final est ton téléphone?
le code en plus de ne pas être formaté, ne compile pas
J'ai repris ton code avec quelques questions qui me saute au visage
#include <Preferences.h>
Preferences poids;
Void setup() {
poids.begin("balance",false);
float poids_dernier = poids.getFloat("dernier_poids",0);
//pourquoi sauvegarder dans une variable local non utilisé?
}
Void loop () {
Serial2.print (poids.getFloat("dernier_poids",0) - Ruche.e);
//que vaut Ruche.e la premiére fois que tu rentre dans la fonction loop ?
Ruche.e = poids.putFloat("dernier_poids",0);
//pourquoi mettre 0 dans la sauvegarde ?
//pourquoi affecter Ruche.e avec le nombre d'octet sauvegardé ?
//du coup Ruche.e représente quoi pour toi ?
}
Le langage c++ reste un langage, même s'il sert essentiellement à dialoguer avec processeur, il doit aussi te parler
Une chose qui peut aider quand on commence, c'est de symboliser ton algorithme soit sous forme de graphe ou de phrase suivant avec quoi tu es le plus à l'aise.
Je n'ai pas bien compris ce que tu espères de ton code.
Ta fonction loop envois un SMS à chaque appel de celui-ci, c'est normal ?
Il ne faudrait pas protéger cela ?
De plus tu récupères les données envoyées par ton autre ESP32 en asynchrone, ton suivant ce que fais ton autre ESP32, il y a de forte chance que tu envois des SMS alors que tu n'a pas encore reçu le poids de tes ruches?
Oui, le destinataire sera moi et quelqu'un d'autres
Les données sont envoyées en wifi avec espnow, de l'ESP32 de la balance à l'ESP32 relié à la sim900( suis récolte toutes les données de chaque ruche)
Ruche.e est le poids de la ruche qui est envoyé en wifi
J'ai mis 0 en valeur car j'ai suivi un exemple, après il faut sûrement par mettre ça
L'envoi de SMS était pour le moment un essai, c'est j'aimerais à la fin, que l'envoi soit le matin, à 8h (par exemple) et ensuite à la demande si un jour j'ai besoins de savoir en fin de journée...
Merci
C'est bien ce que je pensais avoir compris, un ESP32(peseur) collecte le poids de 5 ruches et l'envois à un ESP32(émetteur) pour qu'il envoi les valeurs par SMS.
Si Ruche.e contient le poids que tu as recu, il serait logique que cela soit celui-ci que tu donne à la fonction putFloat, si tu veux que celui-ci soit sauvegarder.
La valeur 0 que tu donne à putFloat, est la valeur que tu veux sauvegarder.
Cela est différent de la fonction getFloat.
Oui, mais du coup dans ton essais tu envois des SMS en boucle
et pire tel quel tu fais aussi une écrire sur la Flash en boucle, ce qui n'est pas bon.
dans un premier temps, laisse ta loop vide, crée une fonction avec ton code d'envois de SMS.
ensuite tu veux faire un envois uniquement lorsque tu reçois quelque chose.
Donc l'appel de la fonction d'envois de SMS, devrait ce trouver à la fin de ta fonction de réception de donné.
Est ce que ça va mieux, comme ceci ?
#include <esp_now.h>
#include <WiFi.h>
// Définir la structure des données.
typedef struct struct_message {
int a;
float b;
float c;
float d;
float e;
} struct_message;
// Créez un struct_message appelé "Ruche".
struct_message Ruche;
#include <Preferences.h>
Preferences poids;
// Fonction de rappel.
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len)
{
// Obtenir des données entrantes.
memcpy(&Ruche, incomingData, sizeof(Ruche));
// Imprimer sur le moniteur Série.
Serial.print("Ruche n° ");
Serial.println(Ruche.a);
Serial.print("Température INT: ");
Serial.print(Ruche.b);
Serial.println("°C");
Serial.print("Température EXT: ");
Serial.print(Ruche.c);
Serial.println("°C");
Serial.print("Humidité EXT: ");
Serial.print(Ruche.d);
Serial.println("%");
Serial.print("Poids: ");
Serial.print(Ruche.e);
Serial.println("Kg");
Serial.println("");
Serial.println("");
poids.putFloat("dernier_poids", Ruche.e);
}
void setup() {
Serial.begin(115200);//Initialisation liaison Moniteur série
// Mettre l'ESP32 en mode WIFI temporaire.
WiFi.mode(WIFI_STA);
// Initialiser ESP-NOW.
if (esp_now_init() != 0) {
Serial.println("Erreur d'initialisation...");
return;
}
// Fonction de rappel d'enregistrement.
esp_now_register_recv_cb(OnDataRecv);
poids.begin("balance", false); // ouverture du namespace.
float poids_dernier = poids.getFloat("dernier_poids"); // on récupère la valeur associée à la clé poids_dernier ou 1.0 si elle n'existait pas
Serial2.begin(115200);//Initialisation module SIM900
delay(8000);//Temps de connexion du SIM900 au réseau téléphonique - Ajuster si besoin
Serial2.println("AT");
delay(500);
updateSerial();
Serial2.println("AT+CMGF=1\r"); //Activation mode Texte
delay(500);
updateSerial();
Serial2.println("AT+CMGS=\"+33xxxxxxxxx\""); //Numéro du destinataire
delay(500);
updateSerial();
// Message à envoyer.
Serial2.print("Ruche ");
Serial2.println(Ruche.a);
Serial2.print("Temp. INT : ");
Serial2.print(Ruche.b);
Serial2.println(" *C");
Serial2.print("Temp. EXT : ");
Serial2.print(Ruche.c);
Serial2.println(" *C");
Serial2.print("Humid. EXT : ");
Serial2.print(Ruche.d);
Serial2.println("%");
Serial2.print("Poids : ");
Serial2.print(Ruche.e);
Serial2.println("Kg");
Serial2.print("Rapport veille : ");
Serial2.print (poids_dernier - Ruche.e);
Serial2.println("");
Serial2.println("");
delay(500);
Serial2.write((char)26); //Envoi du message
delay(500);
}
void loop() {
}
void updateSerial()
{
delay(500);
while (Serial.available())
{
Serial2.write(Serial.read());
}
while (Serial2.available())
{
Serial.write(Serial2.read());
}
}
Egalement je dois appuyer sur le bouton du SIM900, afin qu'il trouve le réseau tout seul, y a t-il un code pour qu'il le trouve tout seul?
Oui ca parait plus cohérent.
par contre pour getFloat, tu peux indiquer un deuxième paramètre, avec la valeur retourné par défaut si la clé n'a jamais été enregistrée.
Oui, je crois qu'il y a une commande AT pour ça, par contre je ne sais pas si il peut s'enregistrer sur le premier qu'il trouve.
Tu as regardé du coté de AT+CREG?
Je ne sais plus si c'est @lesept ou @al1fch, mais on a un membre qui utilise ce genre de module, je crois
Pas moi !
float poids_dernier = poids.getFloat("dernier_poids",0);
Comme ceci ?
Serial2.print (poids_dernier - Ruche.e);
L'opération est ok? Je trouverai un résultat positif ou négatif en cas de perte de poids ?
je ne suis pas sûre que se soit @al1fch non plus
oui si "dernier_poids" n'existe pas dans les préférences, cela te retourne 0.
Pas encore tout à fait, comme tu as mis l'envois du SMS dans le setup et que le setup est la première chose qui est appelé, ce que tu demandes dans ton programme c'est :
-initialise ton Arduino (Wifi, communication série)
- positionne une fonction de rappel, pour recevoir des données par le réseau ESPNOW
- envois le SMS, donc sans avoir reçu aucune données de ton autre ESP32
- Si tu reçois des données de ton autre ESP32, afficher les données, sauvegarder la propriétés Ruche.e
Donc il faut modifier ça pour que cela correspond à ce que tu veux vraiment faire.
C'est pour ça que je t'avais préconiser de créer une fonction avec ton code d'envois du SMS.
Ce qui te permet alors d'appeler cette fonction ou tu veux, c'est à dire après la réception des données de ton autre ESP32
void envoisms
Par exemple ? Je le mets dans le setup avec tout le code que j'ai fait
Et dans le loop, je le rappellerai quand j'en ai besoin et aurait avancé dans le programme ?
Je n'ai pas bien compris ce que tu voulais dire
Quelque chose comme ça, si tu cela suffit pour envoyer en boucle des SMS
Cette fonction tu pourras alors l'appeler la ou tu veux, a priori lorsque tu reçois des données de ton autre ESP32
Edit: tout ceci en supposant que ce n'est pas grave de bloquer la réception des données pendant 1s!
void envoiSms() {
// Message à envoyer.
Serial2.print("Ruche ");
Serial2.println(Ruche.a);
Serial2.print("Temp. INT : ");
Serial2.print(Ruche.b);
Serial2.println(" *C");
Serial2.print("Temp. EXT : ");
Serial2.print(Ruche.c);
Serial2.println(" *C");
Serial2.print("Humid. EXT : ");
Serial2.print(Ruche.d);
Serial2.println("%");
Serial2.print("Poids : ");
Serial2.print(Ruche.e);
Serial2.println("Kg");
Serial2.print("Rapport veille : ");
Serial2.print (poids_dernier - Ruche.e);
Serial2.println("");
Serial2.println("");
delay(500);
Serial2.write((char)26); //Envoi du message
delay(500);
}
Pour démarrer le sim900 sans le bouton, j'ai vu il faut souder R13 et brancher en 9 sur un Arduino et sur esp32?
Il n'y a pas une autre solution à part souder?
Alors là cela dépasse mes connaissances, tu as un lien vers la documentation?
Bouclier SIM900 GSM GPRS avec Arduino)%20Ajoutez
ça me mets que "poids_dernier" n'est pas déclaré dans le scope
je mets avant le setup
float poids_dernier;
oui, il faut que la variable soit déclaré global dans ton programme et non au moment ou tu la lit.
Oui exactement.