Condition -> alors afficher

Bonjour,

Nous sommes un groupe et avons pour projet de faire une boite à livre intelligente. Chacun a sa partie (forme, énergie, numérique). Un collègue et moi avons pour tâche de détecter si un livre a été ajouté ou non. Pour cela après plusieurs réflexions nous avons décidé de faire un système arduino avec un capteur à ultrasons, un émetteur/récepteur 433mhz, un lcd 2 lignes, ainsi que des breadboards.

Après avoir réussi (en s’inspirant) à mesurer la distance entre deux points, et la transmettre, nous voulons intégrer une condition permettant d’afficher si un livre a été ajouté ou non. Cette condition serait plus ou moins:
si la distance change négativement, alors afficher momentanément “un livre a été ajouté”, si la distance change positivement alors afficher “un livre a été retiré”. Seulement on ne sait pas trop comment s’y prendre. C’est pourquoi nous venons chercher des pistes de réflexions ou réponses.

Dans l’espoir de résoudre ce problème, salutations.

Code pour transmetteur:

#include <VirtualWire.h>
#include <NewPing.h>

#define TRIGGER_PIN  9  
#define ECHO_PIN     8  
#define MAX_DISTANCE 200 
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); 

void setup() {
vw_setup(2000);
vw_set_tx_pin(12);
Serial.begin(9600);
}
void loop()
{
char *pamel = "Distance : ";
int fikri = sonar.ping_cm();
char mss[20];     
           sprintf(mss, "%s%02d", pamel,fikri);
           vw_send((uint8_t *)mss, strlen(mss));
           vw_wait_tx();
           Serial.println(mss);
           delay(200);       
}

Code pour récepteur:

#include <VirtualWire.h>
#include  <LiquidCrystal.h>

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

void setup()
{
lcd.begin(16,2);
lcd.setCursor(1,1);
lcd.print("Boite à lire");
Serial.begin(9600);
vw_setup(2000);
vw_set_rx_pin(11);
vw_rx_start();
}
void loop()
{
byte message[VW_MAX_MESSAGE_LEN];
byte messageLength = VW_MAX_MESSAGE_LEN;
if (vw_get_message(message, &messageLength))
{
lcd.setCursor(1,0);
for (int i = 0; i < messageLength; i++)
{
Serial.write(message[i]);
lcd.write(message[i]);
}
Serial.println();
}
}

Déjà, est-ce que tes codes fonctionnent ?

Je pense que tu n’as pas besoin de transmettre un message si compliqué, seule la valeur de la distance mesurée est nécessaire : ça simplifiera le décodage à la réception.

Détection d’un changement :
Dans ton code récepteur, tu dois utiliser une valeur de distance courante, pour la comparer avec la valeur reçue :

  • si dist_cour < dist_recue : alors tu affiches qu’un livre vient d’être ajouté,
  • si les deux distances sont égales : rien
  • si dist_cour > dist_recue : tu affiches qu’un livre vient d’être retiré
    Il faut prendre en compte le fait que la mesure est peu précise, en posant une tolérance sur la mesure : tol = 0.5 cm par exemple
    Donc tu calcules abs((dist_recue - dist_cour)-tol) : si c’est non nul, c’est qu’il s’est passé quelque chose, et tu fais tes tests.
    Après l’affichage, tu assignes la nouvelle valeur de distance à l’ancienne et c’est terminé.

On voit qu’il faut initialiser la valeur de dist_cour. Moi, je lui mettrais 0 dans le setup et lorsqu’une mesure arrive, je ferais deux cas :

  • si dist_cour = 0 : c’est la première mesure, donc on affecte cette valeur à dist_cour et rien d’autre
  • sinon, on fais les tests précédents

Est-ce clair ?
Si oui, à toi de jouer…

Mille mercis, c'est un peu plus clair. Seulement il y a problème, le programme que tu nous propose nous permet de faire ça pour un livre. Puisque la distance courante change à chaque ajout de livre. Il faudrait donc faire varier la distance courante. Tu nous conseilles de faire comment? Merci

avec une temporisation ? par exemple si la distance n'a pas varié pendant un temps donné, alors la nouvelle distance courante devient la value lue par la capteur

barbare:
Seulement il y a problème, le programme que tu nous propose nous permet de faire ça pour un livre. Puisque la distance courante change à chaque ajout de livre. Il faudrait donc faire varier la distance courante. Tu nous conseilles de faire comment? Merci

Non, la distance courante est mise à jour avec la nouvelle mesure à chaque changement, comme je l'indiquais plus haut :

Après l'affichage, tu assignes la nouvelle valeur de distance à l'ancienne et c'est terminé.

Le code exécute la loop en boucle, comme son nom l'indique : à la fin de la loop, il redémarre au début.

La loop fait ceci:

  • Si la distance courante est nulle (on n'a pas encore mesuré) : faire une mesure et assigner la valeur à la distance courante
  • Faire une mesure
  • Vérifier si la distance a changé
  • Si oui : voir dans quel sens et afficher si on a jouté ou ôté un livre, assigner la nouvelle valeur à la distance courante
    Et ça recommence au début
    Pour plus de précision, tu peux faire plusieurs mesures et prendre la moyenne

lesept:
Non, la distance courante est mise à jour avec la nouvelle mesure à chaque changement, comme je l’indiquais plus haut :

Après l'affichage, tu assignes la nouvelle valeur de distance à l'ancienne et c'est terminé.

Le code exécute la loop en boucle, comme son nom l’indique : à la fin de la loop, il redémarre au début.

La loop fait ceci:

  • Si la distance courante est nulle (on n’a pas encore mesuré) : faire une mesure et assigner la valeur à la distance courante
  • Faire une mesure
  • Vérifier si la distance a changé
  • Si oui : voir dans quel sens et afficher si on a jouté ou ôté un livre, assigner la nouvelle valeur à la distance courante

Et ça recommence au début
Pour plus de précision, tu peux faire plusieurs mesures et prendre la moyenne

Salut,
Avec le code du transmetteur on arrive à voir sur le moniteur série si un livre a été ajouté ou non, mais on n’arrive pas à le transmettre. On est carrément bloqué. Ci-joint le code…

Code pour transmetteur:

#include <VirtualWire.h>
#include <NewPing.h>

#define TRIGGER_PIN  9 
#define ECHO_PIN     8  
#define MAX_DISTANCE 200 

char *tr;
char *msg;
int pass;
int un;

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

void setup() {
vw_setup(2000);
vw_set_tx_pin(12);
Serial.begin(9600);
}
void loop()
{
int un = sonar.ping_cm();
Serial.println(un);
delay(5000);
int deux = sonar.ping_cm();
Serial.println(deux);
delay(1000);
char *tr = "a";
  if(un > deux){
char *tr = "livre ajouter";   
           sprintf("%s%02d",un,tr);
           vw_send((uint8_t *)tr, strlen(tr));
           vw_wait_tx();
           Serial.println(tr);
           delay(200);       
  }
  else if(deux==un){

  }
  else if(un<deux){
char *tr = "livre enlever";    
           sprintf("%s%02d", un,tr);
           vw_send((uint8_t *)tr, strlen(tr));
           vw_wait_tx();
           Serial.println(tr);
           delay(200); 
  }
  else{
  }
}

Code pour récepteur:

#include <VirtualWire.h>
#include  <LiquidCrystal.h>

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

void setup()
{
lcd.begin(16,2);
lcd.setCursor(1,1);
lcd.print("boite a lire");
Serial.begin(9600);
vw_setup(2000);
vw_set_rx_pin(11);
vw_rx_start();
}
void loop()
{
byte message[VW_MAX_MESSAGE_LEN];
byte messageLength = VW_MAX_MESSAGE_LEN;
if (vw_get_message(message, &messageLength))
{
lcd.setCursor(1,0);
for (int i = 0; i < messageLength; i++)
{
Serial.write(message[i]);
lcd.write(message[i]);
}
Serial.println();
}
}

Il faut éviter de se compliquer la vie lorsque ce n’est pas nécessaire ::slight_smile: : au lieu d’envoyer un message compliqué, envoie simplement ‘0’ pour ‘livre ajouté’ et ‘1’ pour ‘livre enlevé’ (par exemple), ce sera plus facile à décoder. Les choses envoyées peuvent être des char ou des byte (‘0’ ou 0)

Tu devrais faire un sketch dédié à la communication, enfin deux sketches

  • Celui du transmetteur envoie ‘1’ attends 2 secondes puis envoie ‘0’ (par exemple)
  • Celui du récepteur affiche ce qu’il reçoit.

Selon ce lien :

Exemple de code du transmetteur (un peu modifié) :

#include <VirtualWire.h>

void setup() {
  Serial.begin(9600);
  vw_setup(2000); 
  Serial.println("Go !"); 
}
 
void loop() {
  byte valeur = 0;
  vw_send((byte *) &valeur, sizeof(valeur));
  vw_wait_tx(); 
}

et exemple de code du récepteur:

#include <VirtualWire.h>

void setup() {
  Serial.begin(9600);
  vw_setup(2000);
  vw_rx_start(); 
  Serial.println("Go !"); 
}

void loop() {
  byte valeur;
  byte taille_message = sizeof(byte);

  /* 
   La variable "taille_message" doit impérativement être remise à 
   la taille de la variable avant de pouvoir recevoir un message. 
   Le plus simple est d'utiliser une variable locale pour ne pas
   avoir à réassigner la valeur à chaque début de loop().
   */

  vw_wait_rx();
  if (vw_get_message((byte *) &valeur, &taille_message)) {
    Serial.println(valeur);
  }
}

Est-ce que ça marche ?